aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c67
1 files changed, 53 insertions, 14 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9d4b165837d..55a35c1dede 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -100,6 +100,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
100{ 100{
101 struct dst_entry *dst = skb_dst(skb); 101 struct dst_entry *dst = skb_dst(skb);
102 struct net_device *dev = dst->dev; 102 struct net_device *dev = dst->dev;
103 struct neighbour *neigh;
103 104
104 skb->protocol = htons(ETH_P_IPV6); 105 skb->protocol = htons(ETH_P_IPV6);
105 skb->dev = dev; 106 skb->dev = dev;
@@ -134,11 +135,15 @@ static int ip6_finish_output2(struct sk_buff *skb)
134 skb->len); 135 skb->len);
135 } 136 }
136 137
137 if (dst->hh) 138 rcu_read_lock();
138 return neigh_hh_output(dst->hh, skb); 139 neigh = dst_get_neighbour(dst);
139 else if (dst->neighbour) 140 if (neigh) {
140 return dst->neighbour->output(skb); 141 int res = neigh_output(neigh, skb);
141 142
143 rcu_read_unlock();
144 return res;
145 }
146 rcu_read_unlock();
142 IP6_INC_STATS_BH(dev_net(dst->dev), 147 IP6_INC_STATS_BH(dev_net(dst->dev),
143 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 148 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
144 kfree_skb(skb); 149 kfree_skb(skb);
@@ -385,6 +390,7 @@ int ip6_forward(struct sk_buff *skb)
385 struct ipv6hdr *hdr = ipv6_hdr(skb); 390 struct ipv6hdr *hdr = ipv6_hdr(skb);
386 struct inet6_skb_parm *opt = IP6CB(skb); 391 struct inet6_skb_parm *opt = IP6CB(skb);
387 struct net *net = dev_net(dst->dev); 392 struct net *net = dev_net(dst->dev);
393 struct neighbour *n;
388 u32 mtu; 394 u32 mtu;
389 395
390 if (net->ipv6.devconf_all->forwarding == 0) 396 if (net->ipv6.devconf_all->forwarding == 0)
@@ -459,11 +465,10 @@ int ip6_forward(struct sk_buff *skb)
459 send redirects to source routed frames. 465 send redirects to source routed frames.
460 We don't send redirects to frames decapsulated from IPsec. 466 We don't send redirects to frames decapsulated from IPsec.
461 */ 467 */
462 if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 && 468 n = dst_get_neighbour(dst);
463 !skb_sec_path(skb)) { 469 if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) {
464 struct in6_addr *target = NULL; 470 struct in6_addr *target = NULL;
465 struct rt6_info *rt; 471 struct rt6_info *rt;
466 struct neighbour *n = dst->neighbour;
467 472
468 /* 473 /*
469 * incoming and outgoing devices are the same 474 * incoming and outgoing devices are the same
@@ -596,6 +601,31 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
596 return offset; 601 return offset;
597} 602}
598 603
604void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
605{
606 static atomic_t ipv6_fragmentation_id;
607 int old, new;
608
609 if (rt && !(rt->dst.flags & DST_NOPEER)) {
610 struct inet_peer *peer;
611
612 if (!rt->rt6i_peer)
613 rt6_bind_peer(rt, 1);
614 peer = rt->rt6i_peer;
615 if (peer) {
616 fhdr->identification = htonl(inet_getid(peer, 0));
617 return;
618 }
619 }
620 do {
621 old = atomic_read(&ipv6_fragmentation_id);
622 new = old + 1;
623 if (!new)
624 new = 1;
625 } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
626 fhdr->identification = htonl(new);
627}
628
599int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) 629int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
600{ 630{
601 struct sk_buff *frag; 631 struct sk_buff *frag;
@@ -680,7 +710,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
680 skb_reset_network_header(skb); 710 skb_reset_network_header(skb);
681 memcpy(skb_network_header(skb), tmp_hdr, hlen); 711 memcpy(skb_network_header(skb), tmp_hdr, hlen);
682 712
683 ipv6_select_ident(fh); 713 ipv6_select_ident(fh, rt);
684 fh->nexthdr = nexthdr; 714 fh->nexthdr = nexthdr;
685 fh->reserved = 0; 715 fh->reserved = 0;
686 fh->frag_off = htons(IP6_MF); 716 fh->frag_off = htons(IP6_MF);
@@ -826,7 +856,7 @@ slow_path:
826 fh->nexthdr = nexthdr; 856 fh->nexthdr = nexthdr;
827 fh->reserved = 0; 857 fh->reserved = 0;
828 if (!frag_id) { 858 if (!frag_id) {
829 ipv6_select_ident(fh); 859 ipv6_select_ident(fh, rt);
830 frag_id = fh->identification; 860 frag_id = fh->identification;
831 } else 861 } else
832 fh->identification = frag_id; 862 fh->identification = frag_id;
@@ -920,8 +950,11 @@ out:
920static int ip6_dst_lookup_tail(struct sock *sk, 950static int ip6_dst_lookup_tail(struct sock *sk,
921 struct dst_entry **dst, struct flowi6 *fl6) 951 struct dst_entry **dst, struct flowi6 *fl6)
922{ 952{
923 int err;
924 struct net *net = sock_net(sk); 953 struct net *net = sock_net(sk);
954#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
955 struct neighbour *n;
956#endif
957 int err;
925 958
926 if (*dst == NULL) 959 if (*dst == NULL)
927 *dst = ip6_route_output(net, sk, fl6); 960 *dst = ip6_route_output(net, sk, fl6);
@@ -947,11 +980,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
947 * dst entry and replace it instead with the 980 * dst entry and replace it instead with the
948 * dst entry of the nexthop router 981 * dst entry of the nexthop router
949 */ 982 */
950 if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { 983 rcu_read_lock();
984 n = dst_get_neighbour(*dst);
985 if (n && !(n->nud_state & NUD_VALID)) {
951 struct inet6_ifaddr *ifp; 986 struct inet6_ifaddr *ifp;
952 struct flowi6 fl_gw6; 987 struct flowi6 fl_gw6;
953 int redirect; 988 int redirect;
954 989
990 rcu_read_unlock();
955 ifp = ipv6_get_ifaddr(net, &fl6->saddr, 991 ifp = ipv6_get_ifaddr(net, &fl6->saddr,
956 (*dst)->dev, 1); 992 (*dst)->dev, 1);
957 993
@@ -971,6 +1007,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
971 if ((err = (*dst)->error)) 1007 if ((err = (*dst)->error))
972 goto out_err_release; 1008 goto out_err_release;
973 } 1009 }
1010 } else {
1011 rcu_read_unlock();
974 } 1012 }
975#endif 1013#endif
976 1014
@@ -1072,7 +1110,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1072 int getfrag(void *from, char *to, int offset, int len, 1110 int getfrag(void *from, char *to, int offset, int len,
1073 int odd, struct sk_buff *skb), 1111 int odd, struct sk_buff *skb),
1074 void *from, int length, int hh_len, int fragheaderlen, 1112 void *from, int length, int hh_len, int fragheaderlen,
1075 int transhdrlen, int mtu,unsigned int flags) 1113 int transhdrlen, int mtu,unsigned int flags,
1114 struct rt6_info *rt)
1076 1115
1077{ 1116{
1078 struct sk_buff *skb; 1117 struct sk_buff *skb;
@@ -1116,7 +1155,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1116 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - 1155 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1117 sizeof(struct frag_hdr)) & ~7; 1156 sizeof(struct frag_hdr)) & ~7;
1118 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 1157 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1119 ipv6_select_ident(&fhdr); 1158 ipv6_select_ident(&fhdr, rt);
1120 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1159 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1121 __skb_queue_tail(&sk->sk_write_queue, skb); 1160 __skb_queue_tail(&sk->sk_write_queue, skb);
1122 1161
@@ -1282,7 +1321,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1282 1321
1283 err = ip6_ufo_append_data(sk, getfrag, from, length, 1322 err = ip6_ufo_append_data(sk, getfrag, from, length,
1284 hh_len, fragheaderlen, 1323 hh_len, fragheaderlen,
1285 transhdrlen, mtu, flags); 1324 transhdrlen, mtu, flags, rt);
1286 if (err) 1325 if (err)
1287 goto error; 1326 goto error;
1288 return 0; 1327 return 0;