diff options
Diffstat (limited to 'net/ipv4/tcp.c')
| -rw-r--r-- | net/ipv4/tcp.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5c7ed147449c..032a96d78c99 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -2277,6 +2277,38 @@ static inline bool tcp_can_repair_sock(const struct sock *sk) | |||
| 2277 | ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED)); | 2277 | ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED)); |
| 2278 | } | 2278 | } |
| 2279 | 2279 | ||
| 2280 | static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int len) | ||
| 2281 | { | ||
| 2282 | struct tcp_repair_window opt; | ||
| 2283 | |||
| 2284 | if (!tp->repair) | ||
| 2285 | return -EPERM; | ||
| 2286 | |||
| 2287 | if (len != sizeof(opt)) | ||
| 2288 | return -EINVAL; | ||
| 2289 | |||
| 2290 | if (copy_from_user(&opt, optbuf, sizeof(opt))) | ||
| 2291 | return -EFAULT; | ||
| 2292 | |||
| 2293 | if (opt.max_window < opt.snd_wnd) | ||
| 2294 | return -EINVAL; | ||
| 2295 | |||
| 2296 | if (after(opt.snd_wl1, tp->rcv_nxt + opt.rcv_wnd)) | ||
| 2297 | return -EINVAL; | ||
| 2298 | |||
| 2299 | if (after(opt.rcv_wup, tp->rcv_nxt)) | ||
| 2300 | return -EINVAL; | ||
| 2301 | |||
| 2302 | tp->snd_wl1 = opt.snd_wl1; | ||
| 2303 | tp->snd_wnd = opt.snd_wnd; | ||
| 2304 | tp->max_window = opt.max_window; | ||
| 2305 | |||
| 2306 | tp->rcv_wnd = opt.rcv_wnd; | ||
| 2307 | tp->rcv_wup = opt.rcv_wup; | ||
| 2308 | |||
| 2309 | return 0; | ||
| 2310 | } | ||
| 2311 | |||
| 2280 | static int tcp_repair_options_est(struct tcp_sock *tp, | 2312 | static int tcp_repair_options_est(struct tcp_sock *tp, |
| 2281 | struct tcp_repair_opt __user *optbuf, unsigned int len) | 2313 | struct tcp_repair_opt __user *optbuf, unsigned int len) |
| 2282 | { | 2314 | { |
| @@ -2604,6 +2636,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
| 2604 | else | 2636 | else |
| 2605 | tp->tsoffset = val - tcp_time_stamp; | 2637 | tp->tsoffset = val - tcp_time_stamp; |
| 2606 | break; | 2638 | break; |
| 2639 | case TCP_REPAIR_WINDOW: | ||
| 2640 | err = tcp_repair_set_window(tp, optval, optlen); | ||
| 2641 | break; | ||
| 2607 | case TCP_NOTSENT_LOWAT: | 2642 | case TCP_NOTSENT_LOWAT: |
| 2608 | tp->notsent_lowat = val; | 2643 | tp->notsent_lowat = val; |
| 2609 | sk->sk_write_space(sk); | 2644 | sk->sk_write_space(sk); |
| @@ -2860,6 +2895,28 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
| 2860 | return -EINVAL; | 2895 | return -EINVAL; |
| 2861 | break; | 2896 | break; |
| 2862 | 2897 | ||
| 2898 | case TCP_REPAIR_WINDOW: { | ||
| 2899 | struct tcp_repair_window opt; | ||
| 2900 | |||
| 2901 | if (get_user(len, optlen)) | ||
| 2902 | return -EFAULT; | ||
| 2903 | |||
| 2904 | if (len != sizeof(opt)) | ||
| 2905 | return -EINVAL; | ||
| 2906 | |||
| 2907 | if (!tp->repair) | ||
| 2908 | return -EPERM; | ||
| 2909 | |||
| 2910 | opt.snd_wl1 = tp->snd_wl1; | ||
| 2911 | opt.snd_wnd = tp->snd_wnd; | ||
| 2912 | opt.max_window = tp->max_window; | ||
| 2913 | opt.rcv_wnd = tp->rcv_wnd; | ||
| 2914 | opt.rcv_wup = tp->rcv_wup; | ||
| 2915 | |||
| 2916 | if (copy_to_user(optval, &opt, len)) | ||
| 2917 | return -EFAULT; | ||
| 2918 | return 0; | ||
| 2919 | } | ||
| 2863 | case TCP_QUEUE_SEQ: | 2920 | case TCP_QUEUE_SEQ: |
| 2864 | if (tp->repair_queue == TCP_SEND_QUEUE) | 2921 | if (tp->repair_queue == TCP_SEND_QUEUE) |
| 2865 | val = tp->write_seq; | 2922 | val = tp->write_seq; |
| @@ -2969,8 +3026,18 @@ static void __tcp_alloc_md5sig_pool(void) | |||
| 2969 | return; | 3026 | return; |
| 2970 | 3027 | ||
| 2971 | for_each_possible_cpu(cpu) { | 3028 | for_each_possible_cpu(cpu) { |
| 3029 | void *scratch = per_cpu(tcp_md5sig_pool, cpu).scratch; | ||
| 2972 | struct ahash_request *req; | 3030 | struct ahash_request *req; |
| 2973 | 3031 | ||
| 3032 | if (!scratch) { | ||
| 3033 | scratch = kmalloc_node(sizeof(union tcp_md5sum_block) + | ||
| 3034 | sizeof(struct tcphdr), | ||
| 3035 | GFP_KERNEL, | ||
| 3036 | cpu_to_node(cpu)); | ||
| 3037 | if (!scratch) | ||
| 3038 | return; | ||
| 3039 | per_cpu(tcp_md5sig_pool, cpu).scratch = scratch; | ||
| 3040 | } | ||
| 2974 | if (per_cpu(tcp_md5sig_pool, cpu).md5_req) | 3041 | if (per_cpu(tcp_md5sig_pool, cpu).md5_req) |
| 2975 | continue; | 3042 | continue; |
| 2976 | 3043 | ||
