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.c40
1 files changed, 17 insertions, 23 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index decc21d19c53..5b2d63ed793e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -83,24 +83,12 @@ int ip6_local_out(struct sk_buff *skb)
83} 83}
84EXPORT_SYMBOL_GPL(ip6_local_out); 84EXPORT_SYMBOL_GPL(ip6_local_out);
85 85
86/* dev_loopback_xmit for use with netfilter. */
87static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
88{
89 skb_reset_mac_header(newskb);
90 __skb_pull(newskb, skb_network_offset(newskb));
91 newskb->pkt_type = PACKET_LOOPBACK;
92 newskb->ip_summed = CHECKSUM_UNNECESSARY;
93 WARN_ON(!skb_dst(newskb));
94
95 netif_rx_ni(newskb);
96 return 0;
97}
98
99static int ip6_finish_output2(struct sk_buff *skb) 86static int ip6_finish_output2(struct sk_buff *skb)
100{ 87{
101 struct dst_entry *dst = skb_dst(skb); 88 struct dst_entry *dst = skb_dst(skb);
102 struct net_device *dev = dst->dev; 89 struct net_device *dev = dst->dev;
103 struct neighbour *neigh; 90 struct neighbour *neigh;
91 struct rt6_info *rt;
104 92
105 skb->protocol = htons(ETH_P_IPV6); 93 skb->protocol = htons(ETH_P_IPV6);
106 skb->dev = dev; 94 skb->dev = dev;
@@ -121,7 +109,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
121 if (newskb) 109 if (newskb)
122 NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, 110 NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING,
123 newskb, NULL, newskb->dev, 111 newskb, NULL, newskb->dev,
124 ip6_dev_loopback_xmit); 112 dev_loopback_xmit);
125 113
126 if (ipv6_hdr(skb)->hop_limit == 0) { 114 if (ipv6_hdr(skb)->hop_limit == 0) {
127 IP6_INC_STATS(dev_net(dev), idev, 115 IP6_INC_STATS(dev_net(dev), idev,
@@ -136,9 +124,10 @@ static int ip6_finish_output2(struct sk_buff *skb)
136 } 124 }
137 125
138 rcu_read_lock(); 126 rcu_read_lock();
139 neigh = dst_get_neighbour_noref(dst); 127 rt = (struct rt6_info *) dst;
128 neigh = rt->n;
140 if (neigh) { 129 if (neigh) {
141 int res = neigh_output(neigh, skb); 130 int res = dst_neigh_output(dst, neigh, skb);
142 131
143 rcu_read_unlock(); 132 rcu_read_unlock();
144 return res; 133 return res;
@@ -463,6 +452,7 @@ int ip6_forward(struct sk_buff *skb)
463 */ 452 */
464 if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) { 453 if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) {
465 struct in6_addr *target = NULL; 454 struct in6_addr *target = NULL;
455 struct inet_peer *peer;
466 struct rt6_info *rt; 456 struct rt6_info *rt;
467 457
468 /* 458 /*
@@ -476,14 +466,15 @@ int ip6_forward(struct sk_buff *skb)
476 else 466 else
477 target = &hdr->daddr; 467 target = &hdr->daddr;
478 468
479 if (!rt->rt6i_peer) 469 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
480 rt6_bind_peer(rt, 1);
481 470
482 /* Limit redirects both by destination (here) 471 /* Limit redirects both by destination (here)
483 and by source (inside ndisc_send_redirect) 472 and by source (inside ndisc_send_redirect)
484 */ 473 */
485 if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) 474 if (inet_peer_xrlim_allow(peer, 1*HZ))
486 ndisc_send_redirect(skb, target); 475 ndisc_send_redirect(skb, target);
476 if (peer)
477 inet_putpeer(peer);
487 } else { 478 } else {
488 int addrtype = ipv6_addr_type(&hdr->saddr); 479 int addrtype = ipv6_addr_type(&hdr->saddr);
489 480
@@ -604,12 +595,13 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
604 595
605 if (rt && !(rt->dst.flags & DST_NOPEER)) { 596 if (rt && !(rt->dst.flags & DST_NOPEER)) {
606 struct inet_peer *peer; 597 struct inet_peer *peer;
598 struct net *net;
607 599
608 if (!rt->rt6i_peer) 600 net = dev_net(rt->dst.dev);
609 rt6_bind_peer(rt, 1); 601 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
610 peer = rt->rt6i_peer;
611 if (peer) { 602 if (peer) {
612 fhdr->identification = htonl(inet_getid(peer, 0)); 603 fhdr->identification = htonl(inet_getid(peer, 0));
604 inet_putpeer(peer);
613 return; 605 return;
614 } 606 }
615 } 607 }
@@ -960,6 +952,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
960 struct net *net = sock_net(sk); 952 struct net *net = sock_net(sk);
961#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 953#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
962 struct neighbour *n; 954 struct neighbour *n;
955 struct rt6_info *rt;
963#endif 956#endif
964 int err; 957 int err;
965 958
@@ -988,7 +981,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
988 * dst entry of the nexthop router 981 * dst entry of the nexthop router
989 */ 982 */
990 rcu_read_lock(); 983 rcu_read_lock();
991 n = dst_get_neighbour_noref(*dst); 984 rt = (struct rt6_info *) *dst;
985 n = rt->n;
992 if (n && !(n->nud_state & NUD_VALID)) { 986 if (n && !(n->nud_state & NUD_VALID)) {
993 struct inet6_ifaddr *ifp; 987 struct inet6_ifaddr *ifp;
994 struct flowi6 fl_gw6; 988 struct flowi6 fl_gw6;