aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/addrlabel.c48
-rw-r--r--net/ipv6/icmp.c10
-rw-r--r--net/ipv6/ip6_gre.c5
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/ip6_tunnel.c6
-rw-r--r--net/ipv6/ndisc.c14
-rw-r--r--net/ipv6/raw.c1
-rw-r--r--net/ipv6/sit.c11
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/ipv6/xfrm6_output.c21
-rw-r--r--net/ipv6/xfrm6_state.c1
12 files changed, 79 insertions, 45 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2a66eaad047f..d6ff12617f36 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1022,7 +1022,6 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
1022 unsigned long regen_advance; 1022 unsigned long regen_advance;
1023 int tmp_plen; 1023 int tmp_plen;
1024 int ret = 0; 1024 int ret = 0;
1025 int max_addresses;
1026 u32 addr_flags; 1025 u32 addr_flags;
1027 unsigned long now = jiffies; 1026 unsigned long now = jiffies;
1028 1027
@@ -1068,7 +1067,6 @@ retry:
1068 idev->cnf.temp_prefered_lft + age - 1067 idev->cnf.temp_prefered_lft + age -
1069 idev->cnf.max_desync_factor); 1068 idev->cnf.max_desync_factor);
1070 tmp_plen = ifp->prefix_len; 1069 tmp_plen = ifp->prefix_len;
1071 max_addresses = idev->cnf.max_addresses;
1072 tmp_tstamp = ifp->tstamp; 1070 tmp_tstamp = ifp->tstamp;
1073 spin_unlock_bh(&ifp->lock); 1071 spin_unlock_bh(&ifp->lock);
1074 1072
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index f083a583a05c..b30ad3741b46 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -251,38 +251,36 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net,
251/* add a label */ 251/* add a label */
252static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) 252static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
253{ 253{
254 struct hlist_node *n;
255 struct ip6addrlbl_entry *last = NULL, *p = NULL;
254 int ret = 0; 256 int ret = 0;
255 257
256 ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", 258 ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp,
257 __func__, 259 replace);
258 newp, replace);
259 260
260 if (hlist_empty(&ip6addrlbl_table.head)) { 261 hlist_for_each_entry_safe(p, n, &ip6addrlbl_table.head, list) {
261 hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); 262 if (p->prefixlen == newp->prefixlen &&
262 } else { 263 net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
263 struct hlist_node *n; 264 p->ifindex == newp->ifindex &&
264 struct ip6addrlbl_entry *p = NULL; 265 ipv6_addr_equal(&p->prefix, &newp->prefix)) {
265 hlist_for_each_entry_safe(p, n, 266 if (!replace) {
266 &ip6addrlbl_table.head, list) { 267 ret = -EEXIST;
267 if (p->prefixlen == newp->prefixlen &&
268 net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
269 p->ifindex == newp->ifindex &&
270 ipv6_addr_equal(&p->prefix, &newp->prefix)) {
271 if (!replace) {
272 ret = -EEXIST;
273 goto out;
274 }
275 hlist_replace_rcu(&p->list, &newp->list);
276 ip6addrlbl_put(p);
277 goto out;
278 } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
279 (p->prefixlen < newp->prefixlen)) {
280 hlist_add_before_rcu(&newp->list, &p->list);
281 goto out; 268 goto out;
282 } 269 }
270 hlist_replace_rcu(&p->list, &newp->list);
271 ip6addrlbl_put(p);
272 goto out;
273 } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
274 (p->prefixlen < newp->prefixlen)) {
275 hlist_add_before_rcu(&newp->list, &p->list);
276 goto out;
283 } 277 }
284 hlist_add_after_rcu(&p->list, &newp->list); 278 last = p;
285 } 279 }
280 if (last)
281 hlist_add_after_rcu(&last->list, &newp->list);
282 else
283 hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
286out: 284out:
287 if (!ret) 285 if (!ret)
288 ip6addrlbl_table.seq++; 286 ip6addrlbl_table.seq++;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 73681c227453..eef8d945b362 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -940,6 +940,14 @@ static const struct icmp6_err {
940 .err = ECONNREFUSED, 940 .err = ECONNREFUSED,
941 .fatal = 1, 941 .fatal = 1,
942 }, 942 },
943 { /* POLICY_FAIL */
944 .err = EACCES,
945 .fatal = 1,
946 },
947 { /* REJECT_ROUTE */
948 .err = EACCES,
949 .fatal = 1,
950 },
943}; 951};
944 952
945int icmpv6_err_convert(u8 type, u8 code, int *err) 953int icmpv6_err_convert(u8 type, u8 code, int *err)
@@ -951,7 +959,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err)
951 switch (type) { 959 switch (type) {
952 case ICMPV6_DEST_UNREACH: 960 case ICMPV6_DEST_UNREACH:
953 fatal = 1; 961 fatal = 1;
954 if (code <= ICMPV6_PORT_UNREACH) { 962 if (code < ARRAY_SIZE(tab_unreach)) {
955 *err = tab_unreach[code].err; 963 *err = tab_unreach[code].err;
956 fatal = tab_unreach[code].fatal; 964 fatal = tab_unreach[code].fatal;
957 } 965 }
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index db992a373011..6b26e9feafb9 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -722,6 +722,11 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
722 ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); 722 ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
723 } 723 }
724 724
725 if (likely(!skb->encapsulation)) {
726 skb_reset_inner_headers(skb);
727 skb->encapsulation = 1;
728 }
729
725 skb_push(skb, gre_hlen); 730 skb_push(skb, gre_hlen);
726 skb_reset_network_header(skb); 731 skb_reset_network_header(skb);
727 skb_set_transport_header(skb, sizeof(*ipv6h)); 732 skb_set_transport_header(skb, sizeof(*ipv6h));
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index dd08cfd8999e..3a692d529163 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -213,6 +213,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
213 hdr->saddr = fl6->saddr; 213 hdr->saddr = fl6->saddr;
214 hdr->daddr = *first_hop; 214 hdr->daddr = *first_hop;
215 215
216 skb->protocol = htons(ETH_P_IPV6);
216 skb->priority = sk->sk_priority; 217 skb->priority = sk->sk_priority;
217 skb->mark = sk->sk_mark; 218 skb->mark = sk->sk_mark;
218 219
@@ -1032,6 +1033,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1032 /* initialize protocol header pointer */ 1033 /* initialize protocol header pointer */
1033 skb->transport_header = skb->network_header + fragheaderlen; 1034 skb->transport_header = skb->network_header + fragheaderlen;
1034 1035
1036 skb->protocol = htons(ETH_P_IPV6);
1035 skb->ip_summed = CHECKSUM_PARTIAL; 1037 skb->ip_summed = CHECKSUM_PARTIAL;
1036 skb->csum = 0; 1038 skb->csum = 0;
1037 } 1039 }
@@ -1334,6 +1336,7 @@ alloc_new_skb:
1334 /* 1336 /*
1335 * Fill in the control structures 1337 * Fill in the control structures
1336 */ 1338 */
1339 skb->protocol = htons(ETH_P_IPV6);
1337 skb->ip_summed = CHECKSUM_NONE; 1340 skb->ip_summed = CHECKSUM_NONE;
1338 skb->csum = 0; 1341 skb->csum = 0;
1339 /* reserve for fragmentation and ipsec header */ 1342 /* reserve for fragmentation and ipsec header */
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 55999d923f26..61355f7f4da5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1028,6 +1028,12 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
1028 init_tel_txopt(&opt, encap_limit); 1028 init_tel_txopt(&opt, encap_limit);
1029 ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); 1029 ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
1030 } 1030 }
1031
1032 if (likely(!skb->encapsulation)) {
1033 skb_reset_inner_headers(skb);
1034 skb->encapsulation = 1;
1035 }
1036
1031 skb_push(skb, sizeof(struct ipv6hdr)); 1037 skb_push(skb, sizeof(struct ipv6hdr));
1032 skb_reset_network_header(skb); 1038 skb_reset_network_header(skb);
1033 ipv6h = ipv6_hdr(skb); 1039 ipv6h = ipv6_hdr(skb);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index c4bc7a35cd56..12179457b2cd 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -372,14 +372,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
372 int tlen = dev->needed_tailroom; 372 int tlen = dev->needed_tailroom;
373 struct sock *sk = dev_net(dev)->ipv6.ndisc_sk; 373 struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
374 struct sk_buff *skb; 374 struct sk_buff *skb;
375 int err;
376 375
377 skb = sock_alloc_send_skb(sk, 376 skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
378 hlen + sizeof(struct ipv6hdr) + len + tlen,
379 1, &err);
380 if (!skb) { 377 if (!skb) {
381 ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb, err=%d\n", 378 ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
382 __func__, err); 379 __func__);
383 return NULL; 380 return NULL;
384 } 381 }
385 382
@@ -389,6 +386,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
389 skb_reserve(skb, hlen + sizeof(struct ipv6hdr)); 386 skb_reserve(skb, hlen + sizeof(struct ipv6hdr));
390 skb_reset_transport_header(skb); 387 skb_reset_transport_header(skb);
391 388
389 /* Manually assign socket ownership as we avoid calling
390 * sock_alloc_send_pskb() to bypass wmem buffer limits
391 */
392 skb_set_owner_w(skb, sk);
393
392 return skb; 394 return skb;
393} 395}
394 396
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index c1e533498203..58916bbb1728 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -633,6 +633,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
633 goto error; 633 goto error;
634 skb_reserve(skb, hlen); 634 skb_reserve(skb, hlen);
635 635
636 skb->protocol = htons(ETH_P_IPV6);
636 skb->priority = sk->sk_priority; 637 skb->priority = sk->sk_priority;
637 skb->mark = sk->sk_mark; 638 skb->mark = sk->sk_mark;
638 skb_dst_set(skb, &rt->dst); 639 skb_dst_set(skb, &rt->dst);
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 19abcc9d6a1a..7ee5cb96db34 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -641,11 +641,7 @@ static int ipip_rcv(struct sk_buff *skb)
641 const struct iphdr *iph; 641 const struct iphdr *iph;
642 struct ip_tunnel *tunnel; 642 struct ip_tunnel *tunnel;
643 643
644 if (iptunnel_pull_header(skb, 0, tpi.proto))
645 goto drop;
646
647 iph = ip_hdr(skb); 644 iph = ip_hdr(skb);
648
649 tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, 645 tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
650 iph->saddr, iph->daddr); 646 iph->saddr, iph->daddr);
651 if (tunnel != NULL) { 647 if (tunnel != NULL) {
@@ -655,6 +651,8 @@ static int ipip_rcv(struct sk_buff *skb)
655 651
656 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) 652 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
657 goto drop; 653 goto drop;
654 if (iptunnel_pull_header(skb, 0, tpi.proto))
655 goto drop;
658 return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); 656 return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
659 } 657 }
660 658
@@ -881,6 +879,11 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
881 ttl = iph6->hop_limit; 879 ttl = iph6->hop_limit;
882 tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); 880 tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
883 881
882 if (likely(!skb->encapsulation)) {
883 skb_reset_inner_headers(skb);
884 skb->encapsulation = 1;
885 }
886
884 err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, 887 err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
885 ttl, df, !net_eq(tunnel->net, dev_net(dev))); 888 ttl, df, !net_eq(tunnel->net, dev_net(dev)));
886 iptunnel_xmit_stats(err, &dev->stats, dev->tstats); 889 iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 9acdcedf9a14..5c71501fc917 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1425,7 +1425,7 @@ ipv6_pktoptions:
1425 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) 1425 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
1426 np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; 1426 np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
1427 if (np->rxopt.bits.rxtclass) 1427 if (np->rxopt.bits.rxtclass)
1428 np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); 1428 np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(opt_skb));
1429 if (ipv6_opt_accepted(sk, opt_skb)) { 1429 if (ipv6_opt_accepted(sk, opt_skb)) {
1430 skb_set_owner_r(opt_skb, sk); 1430 skb_set_owner_r(opt_skb, sk);
1431 opt_skb = xchg(&np->pktoptions, opt_skb); 1431 opt_skb = xchg(&np->pktoptions, opt_skb);
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 8755a3079d0f..6cd625e37706 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -34,8 +34,10 @@ static int xfrm6_local_dontfrag(struct sk_buff *skb)
34 struct sock *sk = skb->sk; 34 struct sock *sk = skb->sk;
35 35
36 if (sk) { 36 if (sk) {
37 proto = sk->sk_protocol; 37 if (sk->sk_family != AF_INET6)
38 return 0;
38 39
40 proto = sk->sk_protocol;
39 if (proto == IPPROTO_UDP || proto == IPPROTO_RAW) 41 if (proto == IPPROTO_UDP || proto == IPPROTO_RAW)
40 return inet6_sk(sk)->dontfrag; 42 return inet6_sk(sk)->dontfrag;
41 } 43 }
@@ -54,13 +56,15 @@ static void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu)
54 ipv6_local_rxpmtu(sk, &fl6, mtu); 56 ipv6_local_rxpmtu(sk, &fl6, mtu);
55} 57}
56 58
57static void xfrm6_local_error(struct sk_buff *skb, u32 mtu) 59void xfrm6_local_error(struct sk_buff *skb, u32 mtu)
58{ 60{
59 struct flowi6 fl6; 61 struct flowi6 fl6;
62 const struct ipv6hdr *hdr;
60 struct sock *sk = skb->sk; 63 struct sock *sk = skb->sk;
61 64
65 hdr = skb->encapsulation ? inner_ipv6_hdr(skb) : ipv6_hdr(skb);
62 fl6.fl6_dport = inet_sk(sk)->inet_dport; 66 fl6.fl6_dport = inet_sk(sk)->inet_dport;
63 fl6.daddr = ipv6_hdr(skb)->daddr; 67 fl6.daddr = hdr->daddr;
64 68
65 ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); 69 ipv6_local_error(sk, EMSGSIZE, &fl6, mtu);
66} 70}
@@ -80,7 +84,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
80 if (xfrm6_local_dontfrag(skb)) 84 if (xfrm6_local_dontfrag(skb))
81 xfrm6_local_rxpmtu(skb, mtu); 85 xfrm6_local_rxpmtu(skb, mtu);
82 else if (skb->sk) 86 else if (skb->sk)
83 xfrm6_local_error(skb, mtu); 87 xfrm_local_error(skb, mtu);
84 else 88 else
85 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 89 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
86 ret = -EMSGSIZE; 90 ret = -EMSGSIZE;
@@ -136,13 +140,18 @@ static int __xfrm6_output(struct sk_buff *skb)
136{ 140{
137 struct dst_entry *dst = skb_dst(skb); 141 struct dst_entry *dst = skb_dst(skb);
138 struct xfrm_state *x = dst->xfrm; 142 struct xfrm_state *x = dst->xfrm;
139 int mtu = ip6_skb_dst_mtu(skb); 143 int mtu;
144
145 if (skb->protocol == htons(ETH_P_IPV6))
146 mtu = ip6_skb_dst_mtu(skb);
147 else
148 mtu = dst_mtu(skb_dst(skb));
140 149
141 if (skb->len > mtu && xfrm6_local_dontfrag(skb)) { 150 if (skb->len > mtu && xfrm6_local_dontfrag(skb)) {
142 xfrm6_local_rxpmtu(skb, mtu); 151 xfrm6_local_rxpmtu(skb, mtu);
143 return -EMSGSIZE; 152 return -EMSGSIZE;
144 } else if (!skb->local_df && skb->len > mtu && skb->sk) { 153 } else if (!skb->local_df && skb->len > mtu && skb->sk) {
145 xfrm6_local_error(skb, mtu); 154 xfrm_local_error(skb, mtu);
146 return -EMSGSIZE; 155 return -EMSGSIZE;
147 } 156 }
148 157
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index d8c70b8efc24..3fc970135fc6 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -183,6 +183,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
183 .extract_input = xfrm6_extract_input, 183 .extract_input = xfrm6_extract_input,
184 .extract_output = xfrm6_extract_output, 184 .extract_output = xfrm6_extract_output,
185 .transport_finish = xfrm6_transport_finish, 185 .transport_finish = xfrm6_transport_finish,
186 .local_error = xfrm6_local_error,
186}; 187};
187 188
188int __init xfrm6_state_init(void) 189int __init xfrm6_state_init(void)