diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/fib_frontend.c | 8 | ||||
| -rw-r--r-- | net/ipv4/tcp_cong.c | 23 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_mode_beet.c | 4 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 11 | ||||
| -rw-r--r-- | net/ipv6/exthdrs.c | 40 |
5 files changed, 67 insertions, 19 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index fc920f63452b..cac06c43f004 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -776,6 +776,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
| 776 | .nl_u = { .ip4_u = { .daddr = frn->fl_addr, | 776 | .nl_u = { .ip4_u = { .daddr = frn->fl_addr, |
| 777 | .tos = frn->fl_tos, | 777 | .tos = frn->fl_tos, |
| 778 | .scope = frn->fl_scope } } }; | 778 | .scope = frn->fl_scope } } }; |
| 779 | |||
| 780 | frn->err = -ENOENT; | ||
| 779 | if (tb) { | 781 | if (tb) { |
| 780 | local_bh_disable(); | 782 | local_bh_disable(); |
| 781 | 783 | ||
| @@ -787,6 +789,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
| 787 | frn->nh_sel = res.nh_sel; | 789 | frn->nh_sel = res.nh_sel; |
| 788 | frn->type = res.type; | 790 | frn->type = res.type; |
| 789 | frn->scope = res.scope; | 791 | frn->scope = res.scope; |
| 792 | fib_res_put(&res); | ||
| 790 | } | 793 | } |
| 791 | local_bh_enable(); | 794 | local_bh_enable(); |
| 792 | } | 795 | } |
| @@ -801,6 +804,9 @@ static void nl_fib_input(struct sock *sk, int len) | |||
| 801 | struct fib_table *tb; | 804 | struct fib_table *tb; |
| 802 | 805 | ||
| 803 | skb = skb_dequeue(&sk->sk_receive_queue); | 806 | skb = skb_dequeue(&sk->sk_receive_queue); |
| 807 | if (skb == NULL) | ||
| 808 | return; | ||
| 809 | |||
| 804 | nlh = (struct nlmsghdr *)skb->data; | 810 | nlh = (struct nlmsghdr *)skb->data; |
| 805 | if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len || | 811 | if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len || |
| 806 | nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) { | 812 | nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) { |
| @@ -813,7 +819,7 @@ static void nl_fib_input(struct sock *sk, int len) | |||
| 813 | 819 | ||
| 814 | nl_fib_lookup(frn, tb); | 820 | nl_fib_lookup(frn, tb); |
| 815 | 821 | ||
| 816 | pid = nlh->nlmsg_pid; /*pid of sending process */ | 822 | pid = NETLINK_CB(skb).pid; /* pid of sending process */ |
| 817 | NETLINK_CB(skb).pid = 0; /* from kernel */ | 823 | NETLINK_CB(skb).pid = 0; /* from kernel */ |
| 818 | NETLINK_CB(skb).dst_group = 0; /* unicast */ | 824 | NETLINK_CB(skb).dst_group = 0; /* unicast */ |
| 819 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); | 825 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 5c8caf4a1244..34ae3f13483a 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -77,18 +77,19 @@ void tcp_init_congestion_control(struct sock *sk) | |||
| 77 | struct inet_connection_sock *icsk = inet_csk(sk); | 77 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 78 | struct tcp_congestion_ops *ca; | 78 | struct tcp_congestion_ops *ca; |
| 79 | 79 | ||
| 80 | if (icsk->icsk_ca_ops != &tcp_init_congestion_ops) | 80 | /* if no choice made yet assign the current value set as default */ |
| 81 | return; | 81 | if (icsk->icsk_ca_ops == &tcp_init_congestion_ops) { |
| 82 | rcu_read_lock(); | ||
| 83 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | ||
| 84 | if (try_module_get(ca->owner)) { | ||
| 85 | icsk->icsk_ca_ops = ca; | ||
| 86 | break; | ||
| 87 | } | ||
| 82 | 88 | ||
| 83 | rcu_read_lock(); | 89 | /* fallback to next available */ |
| 84 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | ||
| 85 | if (try_module_get(ca->owner)) { | ||
| 86 | icsk->icsk_ca_ops = ca; | ||
| 87 | break; | ||
| 88 | } | 90 | } |
| 89 | 91 | rcu_read_unlock(); | |
| 90 | } | 92 | } |
| 91 | rcu_read_unlock(); | ||
| 92 | 93 | ||
| 93 | if (icsk->icsk_ca_ops->init) | 94 | if (icsk->icsk_ca_ops->init) |
| 94 | icsk->icsk_ca_ops->init(sk); | 95 | icsk->icsk_ca_ops->init(sk); |
| @@ -236,6 +237,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
| 236 | 237 | ||
| 237 | rcu_read_lock(); | 238 | rcu_read_lock(); |
| 238 | ca = tcp_ca_find(name); | 239 | ca = tcp_ca_find(name); |
| 240 | |||
| 239 | /* no change asking for existing value */ | 241 | /* no change asking for existing value */ |
| 240 | if (ca == icsk->icsk_ca_ops) | 242 | if (ca == icsk->icsk_ca_ops) |
| 241 | goto out; | 243 | goto out; |
| @@ -261,7 +263,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
| 261 | else { | 263 | else { |
| 262 | tcp_cleanup_congestion_control(sk); | 264 | tcp_cleanup_congestion_control(sk); |
| 263 | icsk->icsk_ca_ops = ca; | 265 | icsk->icsk_ca_ops = ca; |
| 264 | if (icsk->icsk_ca_ops->init) | 266 | |
| 267 | if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) | ||
| 265 | icsk->icsk_ca_ops->init(sk); | 268 | icsk->icsk_ca_ops->init(sk); |
| 266 | } | 269 | } |
| 267 | out: | 270 | out: |
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index f68dfd8a0f5c..d419e15d9803 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c | |||
| @@ -52,7 +52,7 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 52 | 52 | ||
| 53 | ph = (struct ip_beet_phdr *)skb->h.raw; | 53 | ph = (struct ip_beet_phdr *)skb->h.raw; |
| 54 | ph->padlen = 4 - (optlen & 4); | 54 | ph->padlen = 4 - (optlen & 4); |
| 55 | ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; | 55 | ph->hdrlen = optlen / 8; |
| 56 | ph->nexthdr = top_iph->protocol; | 56 | ph->nexthdr = top_iph->protocol; |
| 57 | if (ph->padlen) | 57 | if (ph->padlen) |
| 58 | memset(ph + 1, IPOPT_NOP, ph->padlen); | 58 | memset(ph + 1, IPOPT_NOP, ph->padlen); |
| @@ -85,7 +85,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 85 | ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1); | 85 | ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1); |
| 86 | 86 | ||
| 87 | phlen = sizeof(*ph) + ph->padlen; | 87 | phlen = sizeof(*ph) + ph->padlen; |
| 88 | optlen = ph->hdrlen * 8 - phlen; | 88 | optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); |
| 89 | if (optlen < 0 || optlen & 3 || optlen > 250) | 89 | if (optlen < 0 || optlen & 3 || optlen > 250) |
| 90 | goto out; | 90 | goto out; |
| 91 | 91 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7552663aa125..452a82ce4796 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -172,6 +172,7 @@ struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
| 172 | #endif | 172 | #endif |
| 173 | #endif | 173 | #endif |
| 174 | .proxy_ndp = 0, | 174 | .proxy_ndp = 0, |
| 175 | .accept_source_route = 0, /* we do not accept RH0 by default. */ | ||
| 175 | }; | 176 | }; |
| 176 | 177 | ||
| 177 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | 178 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { |
| @@ -203,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
| 203 | #endif | 204 | #endif |
| 204 | #endif | 205 | #endif |
| 205 | .proxy_ndp = 0, | 206 | .proxy_ndp = 0, |
| 207 | .accept_source_route = 0, /* we do not accept RH0 by default. */ | ||
| 206 | }; | 208 | }; |
| 207 | 209 | ||
| 208 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | 210 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ |
| @@ -3356,6 +3358,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
| 3356 | #endif | 3358 | #endif |
| 3357 | #endif | 3359 | #endif |
| 3358 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; | 3360 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; |
| 3361 | array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route; | ||
| 3359 | } | 3362 | } |
| 3360 | 3363 | ||
| 3361 | static inline size_t inet6_if_nlmsg_size(void) | 3364 | static inline size_t inet6_if_nlmsg_size(void) |
| @@ -3884,6 +3887,14 @@ static struct addrconf_sysctl_table | |||
| 3884 | .proc_handler = &proc_dointvec, | 3887 | .proc_handler = &proc_dointvec, |
| 3885 | }, | 3888 | }, |
| 3886 | { | 3889 | { |
| 3890 | .ctl_name = NET_IPV6_ACCEPT_SOURCE_ROUTE, | ||
| 3891 | .procname = "accept_source_route", | ||
| 3892 | .data = &ipv6_devconf.accept_source_route, | ||
| 3893 | .maxlen = sizeof(int), | ||
| 3894 | .mode = 0644, | ||
| 3895 | .proc_handler = &proc_dointvec, | ||
| 3896 | }, | ||
| 3897 | { | ||
| 3887 | .ctl_name = 0, /* sentinel */ | 3898 | .ctl_name = 0, /* sentinel */ |
| 3888 | } | 3899 | } |
| 3889 | }, | 3900 | }, |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 28e0c6568272..fb39604c3d09 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -362,10 +362,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
| 362 | struct inet6_skb_parm *opt = IP6CB(skb); | 362 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 363 | struct in6_addr *addr = NULL; | 363 | struct in6_addr *addr = NULL; |
| 364 | struct in6_addr daddr; | 364 | struct in6_addr daddr; |
| 365 | struct inet6_dev *idev; | ||
| 365 | int n, i; | 366 | int n, i; |
| 366 | |||
| 367 | struct ipv6_rt_hdr *hdr; | 367 | struct ipv6_rt_hdr *hdr; |
| 368 | struct rt0_hdr *rthdr; | 368 | struct rt0_hdr *rthdr; |
| 369 | int accept_source_route = ipv6_devconf.accept_source_route; | ||
| 370 | |||
| 371 | if (accept_source_route < 0 || | ||
| 372 | ((idev = in6_dev_get(skb->dev)) == NULL)) { | ||
| 373 | kfree_skb(skb); | ||
| 374 | return -1; | ||
| 375 | } | ||
| 376 | if (idev->cnf.accept_source_route < 0) { | ||
| 377 | in6_dev_put(idev); | ||
| 378 | kfree_skb(skb); | ||
| 379 | return -1; | ||
| 380 | } | ||
| 381 | |||
| 382 | if (accept_source_route > idev->cnf.accept_source_route) | ||
| 383 | accept_source_route = idev->cnf.accept_source_route; | ||
| 384 | |||
| 385 | in6_dev_put(idev); | ||
| 369 | 386 | ||
| 370 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 387 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || |
| 371 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 388 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { |
| @@ -377,6 +394,22 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
| 377 | 394 | ||
| 378 | hdr = (struct ipv6_rt_hdr *) skb->h.raw; | 395 | hdr = (struct ipv6_rt_hdr *) skb->h.raw; |
| 379 | 396 | ||
| 397 | switch (hdr->type) { | ||
| 398 | #ifdef CONFIG_IPV6_MIP6 | ||
| 399 | break; | ||
| 400 | #endif | ||
| 401 | case IPV6_SRCRT_TYPE_0: | ||
| 402 | if (accept_source_route > 0) | ||
| 403 | break; | ||
| 404 | kfree_skb(skb); | ||
| 405 | return -1; | ||
| 406 | default: | ||
| 407 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | ||
| 408 | IPSTATS_MIB_INHDRERRORS); | ||
| 409 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | ||
| 410 | return -1; | ||
| 411 | } | ||
| 412 | |||
| 380 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || | 413 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || |
| 381 | skb->pkt_type != PACKET_HOST) { | 414 | skb->pkt_type != PACKET_HOST) { |
| 382 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 415 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| @@ -434,11 +467,6 @@ looped_back: | |||
| 434 | } | 467 | } |
| 435 | break; | 468 | break; |
| 436 | #endif | 469 | #endif |
| 437 | default: | ||
| 438 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | ||
| 439 | IPSTATS_MIB_INHDRERRORS); | ||
| 440 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | ||
| 441 | return -1; | ||
| 442 | } | 470 | } |
| 443 | 471 | ||
| 444 | /* | 472 | /* |
