diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 9 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 6 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 40 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_SYNPROXY.c | 1 | ||||
-rw-r--r-- | net/ipv6/ping.c | 3 | ||||
-rw-r--r-- | net/ipv6/protocol.c | 4 | ||||
-rw-r--r-- | net/ipv6/raw.c | 5 | ||||
-rw-r--r-- | net/ipv6/route.c | 34 | ||||
-rw-r--r-- | net/ipv6/sit.c | 56 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcpv6_offload.c | 32 | ||||
-rw-r--r-- | net/ipv6/udp.c | 5 |
14 files changed, 125 insertions, 76 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 12c97d8aa6bb..d5fa5b8c443e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2613,7 +2613,7 @@ static void init_loopback(struct net_device *dev) | |||
2613 | if (sp_ifa->rt) | 2613 | if (sp_ifa->rt) |
2614 | continue; | 2614 | continue; |
2615 | 2615 | ||
2616 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); | 2616 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false); |
2617 | 2617 | ||
2618 | /* Failure cases are ignored */ | 2618 | /* Failure cases are ignored */ |
2619 | if (!IS_ERR(sp_rt)) { | 2619 | if (!IS_ERR(sp_rt)) { |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a454b0ff57c7..93b1aa34c432 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -73,7 +73,6 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
73 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 73 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
74 | if (flowlabel == NULL) | 74 | if (flowlabel == NULL) |
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | usin->sin6_addr = flowlabel->dst; | ||
77 | } | 76 | } |
78 | } | 77 | } |
79 | 78 | ||
@@ -318,7 +317,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) | |||
318 | /* | 317 | /* |
319 | * Handle MSG_ERRQUEUE | 318 | * Handle MSG_ERRQUEUE |
320 | */ | 319 | */ |
321 | int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | 320 | int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) |
322 | { | 321 | { |
323 | struct ipv6_pinfo *np = inet6_sk(sk); | 322 | struct ipv6_pinfo *np = inet6_sk(sk); |
324 | struct sock_exterr_skb *serr; | 323 | struct sock_exterr_skb *serr; |
@@ -369,6 +368,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
369 | &sin->sin6_addr); | 368 | &sin->sin6_addr); |
370 | sin->sin6_scope_id = 0; | 369 | sin->sin6_scope_id = 0; |
371 | } | 370 | } |
371 | *addr_len = sizeof(*sin); | ||
372 | } | 372 | } |
373 | 373 | ||
374 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 374 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
@@ -377,6 +377,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
377 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 377 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
378 | sin->sin6_family = AF_INET6; | 378 | sin->sin6_family = AF_INET6; |
379 | sin->sin6_flowinfo = 0; | 379 | sin->sin6_flowinfo = 0; |
380 | sin->sin6_port = 0; | ||
380 | if (skb->protocol == htons(ETH_P_IPV6)) { | 381 | if (skb->protocol == htons(ETH_P_IPV6)) { |
381 | sin->sin6_addr = ipv6_hdr(skb)->saddr; | 382 | sin->sin6_addr = ipv6_hdr(skb)->saddr; |
382 | if (np->rxopt.all) | 383 | if (np->rxopt.all) |
@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error); | |||
423 | /* | 424 | /* |
424 | * Handle IPV6_RECVPATHMTU | 425 | * Handle IPV6_RECVPATHMTU |
425 | */ | 426 | */ |
426 | int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) | 427 | int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, |
428 | int *addr_len) | ||
427 | { | 429 | { |
428 | struct ipv6_pinfo *np = inet6_sk(sk); | 430 | struct ipv6_pinfo *np = inet6_sk(sk); |
429 | struct sk_buff *skb; | 431 | struct sk_buff *skb; |
@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) | |||
457 | sin->sin6_port = 0; | 459 | sin->sin6_port = 0; |
458 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; | 460 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; |
459 | sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; | 461 | sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; |
462 | *addr_len = sizeof(*sin); | ||
460 | } | 463 | } |
461 | 464 | ||
462 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); | 465 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index e27591635f92..3fd0a578329e 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -122,7 +122,11 @@ out: | |||
122 | static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) | 122 | static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) |
123 | { | 123 | { |
124 | struct rt6_info *rt = (struct rt6_info *) arg->result; | 124 | struct rt6_info *rt = (struct rt6_info *) arg->result; |
125 | struct net_device *dev = rt->rt6i_idev->dev; | 125 | struct net_device *dev = NULL; |
126 | |||
127 | if (rt->rt6i_idev) | ||
128 | dev = rt->rt6i_idev->dev; | ||
129 | |||
126 | /* do not accept result if the route does | 130 | /* do not accept result if the route does |
127 | * not meet the required prefix length | 131 | * not meet the required prefix length |
128 | */ | 132 | */ |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 59df872e2f4d..e6f931997996 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -116,8 +116,8 @@ static int ip6_finish_output2(struct sk_buff *skb) | |||
116 | } | 116 | } |
117 | rcu_read_unlock_bh(); | 117 | rcu_read_unlock_bh(); |
118 | 118 | ||
119 | IP6_INC_STATS_BH(dev_net(dst->dev), | 119 | IP6_INC_STATS(dev_net(dst->dev), |
120 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 120 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
121 | kfree_skb(skb); | 121 | kfree_skb(skb); |
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | } | 123 | } |
@@ -1193,11 +1193,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1193 | 1193 | ||
1194 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + | 1194 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + |
1195 | (opt ? opt->opt_nflen : 0); | 1195 | (opt ? opt->opt_nflen : 0); |
1196 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); | 1196 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - |
1197 | sizeof(struct frag_hdr); | ||
1197 | 1198 | ||
1198 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { | 1199 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { |
1199 | if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { | 1200 | unsigned int maxnonfragsize, headersize; |
1200 | ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); | 1201 | |
1202 | headersize = sizeof(struct ipv6hdr) + | ||
1203 | (opt ? opt->tot_len : 0) + | ||
1204 | (dst_allfrag(&rt->dst) ? | ||
1205 | sizeof(struct frag_hdr) : 0) + | ||
1206 | rt->rt6i_nfheader_len; | ||
1207 | |||
1208 | maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ? | ||
1209 | mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN; | ||
1210 | |||
1211 | /* dontfrag active */ | ||
1212 | if ((cork->length + length > mtu - headersize) && dontfrag && | ||
1213 | (sk->sk_protocol == IPPROTO_UDP || | ||
1214 | sk->sk_protocol == IPPROTO_RAW)) { | ||
1215 | ipv6_local_rxpmtu(sk, fl6, mtu - headersize + | ||
1216 | sizeof(struct ipv6hdr)); | ||
1217 | goto emsgsize; | ||
1218 | } | ||
1219 | |||
1220 | if (cork->length + length > maxnonfragsize - headersize) { | ||
1221 | emsgsize: | ||
1222 | ipv6_local_error(sk, EMSGSIZE, fl6, | ||
1223 | mtu - headersize + | ||
1224 | sizeof(struct ipv6hdr)); | ||
1201 | return -EMSGSIZE; | 1225 | return -EMSGSIZE; |
1202 | } | 1226 | } |
1203 | } | 1227 | } |
@@ -1222,12 +1246,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1222 | * --yoshfuji | 1246 | * --yoshfuji |
1223 | */ | 1247 | */ |
1224 | 1248 | ||
1225 | if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP || | ||
1226 | sk->sk_protocol == IPPROTO_RAW)) { | ||
1227 | ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); | ||
1228 | return -EMSGSIZE; | ||
1229 | } | ||
1230 | |||
1231 | skb = skb_peek_tail(&sk->sk_write_queue); | 1249 | skb = skb_peek_tail(&sk->sk_write_queue); |
1232 | cork->length += length; | 1250 | cork->length += length; |
1233 | if (((length > mtu) || | 1251 | if (((length > mtu) || |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3512177deb4d..300865171394 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1277,6 +1277,9 @@ skip_linkparms: | |||
1277 | ri->prefix_len == 0) | 1277 | ri->prefix_len == 0) |
1278 | continue; | 1278 | continue; |
1279 | #endif | 1279 | #endif |
1280 | if (ri->prefix_len == 0 && | ||
1281 | !in6_dev->cnf.accept_ra_defrtr) | ||
1282 | continue; | ||
1280 | if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) | 1283 | if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) |
1281 | continue; | 1284 | continue; |
1282 | rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, | 1285 | rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, |
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index f78f41aca8e9..a0d17270117c 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c | |||
@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par) | |||
446 | static struct xt_target synproxy_tg6_reg __read_mostly = { | 446 | static struct xt_target synproxy_tg6_reg __read_mostly = { |
447 | .name = "SYNPROXY", | 447 | .name = "SYNPROXY", |
448 | .family = NFPROTO_IPV6, | 448 | .family = NFPROTO_IPV6, |
449 | .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD), | ||
449 | .target = synproxy_tg6, | 450 | .target = synproxy_tg6, |
450 | .targetsize = sizeof(struct xt_synproxy_info), | 451 | .targetsize = sizeof(struct xt_synproxy_info), |
451 | .checkentry = synproxy_tg6_check, | 452 | .checkentry = synproxy_tg6_check, |
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 8815e31a87fe..a83243c3d656 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = { | |||
57 | 57 | ||
58 | 58 | ||
59 | /* Compatibility glue so we can support IPv6 when it's compiled as a module */ | 59 | /* Compatibility glue so we can support IPv6 when it's compiled as a module */ |
60 | static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | 60 | static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, |
61 | int *addr_len) | ||
61 | { | 62 | { |
62 | return -EAFNOSUPPORT; | 63 | return -EAFNOSUPPORT; |
63 | } | 64 | } |
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index 22d1bd4670da..e048cf1bb6a2 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c | |||
@@ -36,10 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol | |||
36 | } | 36 | } |
37 | EXPORT_SYMBOL(inet6_add_protocol); | 37 | EXPORT_SYMBOL(inet6_add_protocol); |
38 | 38 | ||
39 | /* | ||
40 | * Remove a protocol from the hash tables. | ||
41 | */ | ||
42 | |||
43 | int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol) | 39 | int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol) |
44 | { | 40 | { |
45 | int ret; | 41 | int ret; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index e24ff1df0401..b6bb87e55805 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -466,10 +466,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
466 | return -EOPNOTSUPP; | 466 | return -EOPNOTSUPP; |
467 | 467 | ||
468 | if (flags & MSG_ERRQUEUE) | 468 | if (flags & MSG_ERRQUEUE) |
469 | return ipv6_recv_error(sk, msg, len); | 469 | return ipv6_recv_error(sk, msg, len, addr_len); |
470 | 470 | ||
471 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | 471 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) |
472 | return ipv6_recv_rxpmtu(sk, msg, len); | 472 | return ipv6_recv_rxpmtu(sk, msg, len, addr_len); |
473 | 473 | ||
474 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 474 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
475 | if (!skb) | 475 | if (!skb) |
@@ -792,7 +792,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
792 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 792 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
793 | if (flowlabel == NULL) | 793 | if (flowlabel == NULL) |
794 | return -EINVAL; | 794 | return -EINVAL; |
795 | daddr = &flowlabel->dst; | ||
796 | } | 795 | } |
797 | } | 796 | } |
798 | 797 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7faa9d5e1503..4b4944c3e4c4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -84,6 +84,8 @@ static int ip6_dst_gc(struct dst_ops *ops); | |||
84 | 84 | ||
85 | static int ip6_pkt_discard(struct sk_buff *skb); | 85 | static int ip6_pkt_discard(struct sk_buff *skb); |
86 | static int ip6_pkt_discard_out(struct sk_buff *skb); | 86 | static int ip6_pkt_discard_out(struct sk_buff *skb); |
87 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
88 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
87 | static void ip6_link_failure(struct sk_buff *skb); | 89 | static void ip6_link_failure(struct sk_buff *skb); |
88 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | 90 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, |
89 | struct sk_buff *skb, u32 mtu); | 91 | struct sk_buff *skb, u32 mtu); |
@@ -234,9 +236,6 @@ static const struct rt6_info ip6_null_entry_template = { | |||
234 | 236 | ||
235 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 237 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
236 | 238 | ||
237 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
238 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
239 | |||
240 | static const struct rt6_info ip6_prohibit_entry_template = { | 239 | static const struct rt6_info ip6_prohibit_entry_template = { |
241 | .dst = { | 240 | .dst = { |
242 | .__refcnt = ATOMIC_INIT(1), | 241 | .__refcnt = ATOMIC_INIT(1), |
@@ -1565,21 +1564,24 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1565 | goto out; | 1564 | goto out; |
1566 | } | 1565 | } |
1567 | } | 1566 | } |
1568 | rt->dst.output = ip6_pkt_discard_out; | ||
1569 | rt->dst.input = ip6_pkt_discard; | ||
1570 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; | 1567 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; |
1571 | switch (cfg->fc_type) { | 1568 | switch (cfg->fc_type) { |
1572 | case RTN_BLACKHOLE: | 1569 | case RTN_BLACKHOLE: |
1573 | rt->dst.error = -EINVAL; | 1570 | rt->dst.error = -EINVAL; |
1571 | rt->dst.output = dst_discard; | ||
1572 | rt->dst.input = dst_discard; | ||
1574 | break; | 1573 | break; |
1575 | case RTN_PROHIBIT: | 1574 | case RTN_PROHIBIT: |
1576 | rt->dst.error = -EACCES; | 1575 | rt->dst.error = -EACCES; |
1576 | rt->dst.output = ip6_pkt_prohibit_out; | ||
1577 | rt->dst.input = ip6_pkt_prohibit; | ||
1577 | break; | 1578 | break; |
1578 | case RTN_THROW: | 1579 | case RTN_THROW: |
1579 | rt->dst.error = -EAGAIN; | ||
1580 | break; | ||
1581 | default: | 1580 | default: |
1582 | rt->dst.error = -ENETUNREACH; | 1581 | rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN |
1582 | : -ENETUNREACH; | ||
1583 | rt->dst.output = ip6_pkt_discard_out; | ||
1584 | rt->dst.input = ip6_pkt_discard; | ||
1583 | break; | 1585 | break; |
1584 | } | 1586 | } |
1585 | goto install_route; | 1587 | goto install_route; |
@@ -1903,9 +1905,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, | |||
1903 | else | 1905 | else |
1904 | rt->rt6i_gateway = *dest; | 1906 | rt->rt6i_gateway = *dest; |
1905 | rt->rt6i_flags = ort->rt6i_flags; | 1907 | rt->rt6i_flags = ort->rt6i_flags; |
1906 | if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == | 1908 | rt6_set_from(rt, ort); |
1907 | (RTF_DEFAULT | RTF_ADDRCONF)) | ||
1908 | rt6_set_from(rt, ort); | ||
1909 | rt->rt6i_metric = 0; | 1909 | rt->rt6i_metric = 0; |
1910 | 1910 | ||
1911 | #ifdef CONFIG_IPV6_SUBTREES | 1911 | #ifdef CONFIG_IPV6_SUBTREES |
@@ -2144,8 +2144,6 @@ static int ip6_pkt_discard_out(struct sk_buff *skb) | |||
2144 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); | 2144 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); |
2145 | } | 2145 | } |
2146 | 2146 | ||
2147 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2148 | |||
2149 | static int ip6_pkt_prohibit(struct sk_buff *skb) | 2147 | static int ip6_pkt_prohibit(struct sk_buff *skb) |
2150 | { | 2148 | { |
2151 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); | 2149 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); |
@@ -2157,8 +2155,6 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb) | |||
2157 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); | 2155 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); |
2158 | } | 2156 | } |
2159 | 2157 | ||
2160 | #endif | ||
2161 | |||
2162 | /* | 2158 | /* |
2163 | * Allocate a dst for local (unicast / anycast) address. | 2159 | * Allocate a dst for local (unicast / anycast) address. |
2164 | */ | 2160 | */ |
@@ -2168,12 +2164,10 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2168 | bool anycast) | 2164 | bool anycast) |
2169 | { | 2165 | { |
2170 | struct net *net = dev_net(idev->dev); | 2166 | struct net *net = dev_net(idev->dev); |
2171 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL); | 2167 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, |
2172 | 2168 | DST_NOCOUNT, NULL); | |
2173 | if (!rt) { | 2169 | if (!rt) |
2174 | net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n"); | ||
2175 | return ERR_PTR(-ENOMEM); | 2170 | return ERR_PTR(-ENOMEM); |
2176 | } | ||
2177 | 2171 | ||
2178 | in6_dev_hold(idev); | 2172 | in6_dev_hold(idev); |
2179 | 2173 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1b4a4a953675..c87482252577 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -478,14 +478,44 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
478 | dev_put(dev); | 478 | dev_put(dev); |
479 | } | 479 | } |
480 | 480 | ||
481 | /* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH | ||
482 | * if sufficient data bytes are available | ||
483 | */ | ||
484 | static int ipip6_err_gen_icmpv6_unreach(struct sk_buff *skb) | ||
485 | { | ||
486 | const struct iphdr *iph = (const struct iphdr *) skb->data; | ||
487 | struct rt6_info *rt; | ||
488 | struct sk_buff *skb2; | ||
489 | |||
490 | if (!pskb_may_pull(skb, iph->ihl * 4 + sizeof(struct ipv6hdr) + 8)) | ||
491 | return 1; | ||
492 | |||
493 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
494 | |||
495 | if (!skb2) | ||
496 | return 1; | ||
497 | |||
498 | skb_dst_drop(skb2); | ||
499 | skb_pull(skb2, iph->ihl * 4); | ||
500 | skb_reset_network_header(skb2); | ||
501 | |||
502 | rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0); | ||
503 | |||
504 | if (rt && rt->dst.dev) | ||
505 | skb2->dev = rt->dst.dev; | ||
506 | |||
507 | icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); | ||
508 | |||
509 | if (rt) | ||
510 | ip6_rt_put(rt); | ||
511 | |||
512 | kfree_skb(skb2); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
481 | 516 | ||
482 | static int ipip6_err(struct sk_buff *skb, u32 info) | 517 | static int ipip6_err(struct sk_buff *skb, u32 info) |
483 | { | 518 | { |
484 | |||
485 | /* All the routers (except for Linux) return only | ||
486 | 8 bytes of packet payload. It means, that precise relaying of | ||
487 | ICMP in the real Internet is absolutely infeasible. | ||
488 | */ | ||
489 | const struct iphdr *iph = (const struct iphdr *)skb->data; | 519 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
490 | const int type = icmp_hdr(skb)->type; | 520 | const int type = icmp_hdr(skb)->type; |
491 | const int code = icmp_hdr(skb)->code; | 521 | const int code = icmp_hdr(skb)->code; |
@@ -500,7 +530,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
500 | case ICMP_DEST_UNREACH: | 530 | case ICMP_DEST_UNREACH: |
501 | switch (code) { | 531 | switch (code) { |
502 | case ICMP_SR_FAILED: | 532 | case ICMP_SR_FAILED: |
503 | case ICMP_PORT_UNREACH: | ||
504 | /* Impossible event. */ | 533 | /* Impossible event. */ |
505 | return 0; | 534 | return 0; |
506 | default: | 535 | default: |
@@ -545,6 +574,9 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
545 | goto out; | 574 | goto out; |
546 | 575 | ||
547 | err = 0; | 576 | err = 0; |
577 | if (!ipip6_err_gen_icmpv6_unreach(skb)) | ||
578 | goto out; | ||
579 | |||
548 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 580 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |
549 | goto out; | 581 | goto out; |
550 | 582 | ||
@@ -892,7 +924,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
892 | if (tunnel->parms.iph.daddr && skb_dst(skb)) | 924 | if (tunnel->parms.iph.daddr && skb_dst(skb)) |
893 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | 925 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); |
894 | 926 | ||
895 | if (skb->len > mtu) { | 927 | if (skb->len > mtu && !skb_is_gso(skb)) { |
896 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 928 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
897 | ip_rt_put(rt); | 929 | ip_rt_put(rt); |
898 | goto tx_error; | 930 | goto tx_error; |
@@ -919,7 +951,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
919 | if (!new_skb) { | 951 | if (!new_skb) { |
920 | ip_rt_put(rt); | 952 | ip_rt_put(rt); |
921 | dev->stats.tx_dropped++; | 953 | dev->stats.tx_dropped++; |
922 | dev_kfree_skb(skb); | 954 | kfree_skb(skb); |
923 | return NETDEV_TX_OK; | 955 | return NETDEV_TX_OK; |
924 | } | 956 | } |
925 | if (skb->sk) | 957 | if (skb->sk) |
@@ -934,8 +966,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
934 | tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); | 966 | tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); |
935 | 967 | ||
936 | skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); | 968 | skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); |
937 | if (IS_ERR(skb)) | 969 | if (IS_ERR(skb)) { |
970 | ip_rt_put(rt); | ||
938 | goto out; | 971 | goto out; |
972 | } | ||
939 | 973 | ||
940 | err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, | 974 | err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, |
941 | ttl, df, !net_eq(tunnel->net, dev_net(dev))); | 975 | ttl, df, !net_eq(tunnel->net, dev_net(dev))); |
@@ -945,7 +979,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
945 | tx_error_icmp: | 979 | tx_error_icmp: |
946 | dst_link_failure(skb); | 980 | dst_link_failure(skb); |
947 | tx_error: | 981 | tx_error: |
948 | dev_kfree_skb(skb); | 982 | kfree_skb(skb); |
949 | out: | 983 | out: |
950 | dev->stats.tx_errors++; | 984 | dev->stats.tx_errors++; |
951 | return NETDEV_TX_OK; | 985 | return NETDEV_TX_OK; |
@@ -985,7 +1019,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb, | |||
985 | 1019 | ||
986 | tx_err: | 1020 | tx_err: |
987 | dev->stats.tx_errors++; | 1021 | dev->stats.tx_errors++; |
988 | dev_kfree_skb(skb); | 1022 | kfree_skb(skb); |
989 | return NETDEV_TX_OK; | 1023 | return NETDEV_TX_OK; |
990 | 1024 | ||
991 | } | 1025 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0740f93a114a..f67033b4bb66 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -156,7 +156,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
156 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 156 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
157 | if (flowlabel == NULL) | 157 | if (flowlabel == NULL) |
158 | return -EINVAL; | 158 | return -EINVAL; |
159 | usin->sin6_addr = flowlabel->dst; | ||
160 | fl6_sock_release(flowlabel); | 159 | fl6_sock_release(flowlabel); |
161 | } | 160 | } |
162 | } | 161 | } |
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index c1097c798900..6d18157dc32c 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c | |||
@@ -37,34 +37,32 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | |||
37 | { | 37 | { |
38 | const struct ipv6hdr *iph = skb_gro_network_header(skb); | 38 | const struct ipv6hdr *iph = skb_gro_network_header(skb); |
39 | __wsum wsum; | 39 | __wsum wsum; |
40 | __sum16 sum; | 40 | |
41 | /* Don't bother verifying checksum if we're going to flush anyway. */ | ||
42 | if (NAPI_GRO_CB(skb)->flush) | ||
43 | goto skip_csum; | ||
44 | |||
45 | wsum = skb->csum; | ||
41 | 46 | ||
42 | switch (skb->ip_summed) { | 47 | switch (skb->ip_summed) { |
48 | case CHECKSUM_NONE: | ||
49 | wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb), | ||
50 | wsum); | ||
51 | |||
52 | /* fall through */ | ||
53 | |||
43 | case CHECKSUM_COMPLETE: | 54 | case CHECKSUM_COMPLETE: |
44 | if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, | 55 | if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, |
45 | skb->csum)) { | 56 | wsum)) { |
46 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 57 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
47 | break; | 58 | break; |
48 | } | 59 | } |
49 | flush: | 60 | |
50 | NAPI_GRO_CB(skb)->flush = 1; | 61 | NAPI_GRO_CB(skb)->flush = 1; |
51 | return NULL; | 62 | return NULL; |
52 | |||
53 | case CHECKSUM_NONE: | ||
54 | wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, | ||
55 | skb_gro_len(skb), | ||
56 | IPPROTO_TCP, 0)); | ||
57 | sum = csum_fold(skb_checksum(skb, | ||
58 | skb_gro_offset(skb), | ||
59 | skb_gro_len(skb), | ||
60 | wsum)); | ||
61 | if (sum) | ||
62 | goto flush; | ||
63 | |||
64 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
65 | break; | ||
66 | } | 63 | } |
67 | 64 | ||
65 | skip_csum: | ||
68 | return tcp_gro_receive(head, skb); | 66 | return tcp_gro_receive(head, skb); |
69 | } | 67 | } |
70 | 68 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 81eb8cf8389b..089c741a3992 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -393,10 +393,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
393 | bool slow; | 393 | bool slow; |
394 | 394 | ||
395 | if (flags & MSG_ERRQUEUE) | 395 | if (flags & MSG_ERRQUEUE) |
396 | return ipv6_recv_error(sk, msg, len); | 396 | return ipv6_recv_error(sk, msg, len, addr_len); |
397 | 397 | ||
398 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | 398 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) |
399 | return ipv6_recv_rxpmtu(sk, msg, len); | 399 | return ipv6_recv_rxpmtu(sk, msg, len, addr_len); |
400 | 400 | ||
401 | try_again: | 401 | try_again: |
402 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), | 402 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), |
@@ -1140,7 +1140,6 @@ do_udp_sendmsg: | |||
1140 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 1140 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1141 | if (flowlabel == NULL) | 1141 | if (flowlabel == NULL) |
1142 | return -EINVAL; | 1142 | return -EINVAL; |
1143 | daddr = &flowlabel->dst; | ||
1144 | } | 1143 | } |
1145 | } | 1144 | } |
1146 | 1145 | ||