diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
| -rw-r--r-- | net/ipv6/ip6_output.c | 64 |
1 files changed, 31 insertions, 33 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e7a5f17d5e95..5173acaeb501 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -67,8 +67,8 @@ int __ip6_local_out(struct sk_buff *skb) | |||
| 67 | len = 0; | 67 | len = 0; |
| 68 | ipv6_hdr(skb)->payload_len = htons(len); | 68 | ipv6_hdr(skb)->payload_len = htons(len); |
| 69 | 69 | ||
| 70 | return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, | 70 | return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
| 71 | dst_output); | 71 | skb_dst(skb)->dev, dst_output); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | int ip6_local_out(struct sk_buff *skb) | 74 | int ip6_local_out(struct sk_buff *skb) |
| @@ -83,22 +83,6 @@ int ip6_local_out(struct sk_buff *skb) | |||
| 83 | } | 83 | } |
| 84 | EXPORT_SYMBOL_GPL(ip6_local_out); | 84 | EXPORT_SYMBOL_GPL(ip6_local_out); |
| 85 | 85 | ||
| 86 | static int ip6_output_finish(struct sk_buff *skb) | ||
| 87 | { | ||
| 88 | struct dst_entry *dst = skb_dst(skb); | ||
| 89 | |||
| 90 | if (dst->hh) | ||
| 91 | return neigh_hh_output(dst->hh, skb); | ||
| 92 | else if (dst->neighbour) | ||
| 93 | return dst->neighbour->output(skb); | ||
| 94 | |||
| 95 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
| 96 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
| 97 | kfree_skb(skb); | ||
| 98 | return -EINVAL; | ||
| 99 | |||
| 100 | } | ||
| 101 | |||
| 102 | /* dev_loopback_xmit for use with netfilter. */ | 86 | /* dev_loopback_xmit for use with netfilter. */ |
| 103 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | 87 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) |
| 104 | { | 88 | { |
| @@ -112,8 +96,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
| 112 | return 0; | 96 | return 0; |
| 113 | } | 97 | } |
| 114 | 98 | ||
| 115 | 99 | static int ip6_finish_output2(struct sk_buff *skb) | |
| 116 | static int ip6_output2(struct sk_buff *skb) | ||
| 117 | { | 100 | { |
| 118 | struct dst_entry *dst = skb_dst(skb); | 101 | struct dst_entry *dst = skb_dst(skb); |
| 119 | struct net_device *dev = dst->dev; | 102 | struct net_device *dev = dst->dev; |
| @@ -135,8 +118,8 @@ static int ip6_output2(struct sk_buff *skb) | |||
| 135 | is not supported in any case. | 118 | is not supported in any case. |
| 136 | */ | 119 | */ |
| 137 | if (newskb) | 120 | if (newskb) |
| 138 | NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, newskb, | 121 | NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, |
| 139 | NULL, newskb->dev, | 122 | newskb, NULL, newskb->dev, |
| 140 | ip6_dev_loopback_xmit); | 123 | ip6_dev_loopback_xmit); |
| 141 | 124 | ||
| 142 | if (ipv6_hdr(skb)->hop_limit == 0) { | 125 | if (ipv6_hdr(skb)->hop_limit == 0) { |
| @@ -151,8 +134,15 @@ static int ip6_output2(struct sk_buff *skb) | |||
| 151 | skb->len); | 134 | skb->len); |
| 152 | } | 135 | } |
| 153 | 136 | ||
| 154 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | 137 | if (dst->hh) |
| 155 | ip6_output_finish); | 138 | return neigh_hh_output(dst->hh, skb); |
| 139 | else if (dst->neighbour) | ||
| 140 | return dst->neighbour->output(skb); | ||
| 141 | |||
| 142 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
| 143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
| 144 | kfree_skb(skb); | ||
| 145 | return -EINVAL; | ||
| 156 | } | 146 | } |
| 157 | 147 | ||
| 158 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | 148 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) |
| @@ -163,21 +153,29 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | |||
| 163 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | 153 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); |
| 164 | } | 154 | } |
| 165 | 155 | ||
| 156 | static int ip6_finish_output(struct sk_buff *skb) | ||
| 157 | { | ||
| 158 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | ||
| 159 | dst_allfrag(skb_dst(skb))) | ||
| 160 | return ip6_fragment(skb, ip6_finish_output2); | ||
| 161 | else | ||
| 162 | return ip6_finish_output2(skb); | ||
| 163 | } | ||
| 164 | |||
| 166 | int ip6_output(struct sk_buff *skb) | 165 | int ip6_output(struct sk_buff *skb) |
| 167 | { | 166 | { |
| 167 | struct net_device *dev = skb_dst(skb)->dev; | ||
| 168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
| 169 | if (unlikely(idev->cnf.disable_ipv6)) { | 169 | if (unlikely(idev->cnf.disable_ipv6)) { |
| 170 | IP6_INC_STATS(dev_net(skb_dst(skb)->dev), idev, | 170 | IP6_INC_STATS(dev_net(dev), idev, |
| 171 | IPSTATS_MIB_OUTDISCARDS); | 171 | IPSTATS_MIB_OUTDISCARDS); |
| 172 | kfree_skb(skb); | 172 | kfree_skb(skb); |
| 173 | return 0; | 173 | return 0; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 176 | return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, dev, |
| 177 | dst_allfrag(skb_dst(skb))) | 177 | ip6_finish_output, |
| 178 | return ip6_fragment(skb, ip6_output2); | 178 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); |
| 179 | else | ||
| 180 | return ip6_output2(skb); | ||
| 181 | } | 179 | } |
| 182 | 180 | ||
| 183 | /* | 181 | /* |
| @@ -256,8 +254,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
| 256 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { | 254 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { |
| 257 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), | 255 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), |
| 258 | IPSTATS_MIB_OUT, skb->len); | 256 | IPSTATS_MIB_OUT, skb->len); |
| 259 | return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 257 | return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
| 260 | dst_output); | 258 | dst->dev, dst_output); |
| 261 | } | 259 | } |
| 262 | 260 | ||
| 263 | if (net_ratelimit()) | 261 | if (net_ratelimit()) |
| @@ -533,7 +531,7 @@ int ip6_forward(struct sk_buff *skb) | |||
| 533 | hdr->hop_limit--; | 531 | hdr->hop_limit--; |
| 534 | 532 | ||
| 535 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); | 533 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); |
| 536 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev, | 534 | return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, |
| 537 | ip6_forward_finish); | 535 | ip6_forward_finish); |
| 538 | 536 | ||
| 539 | error: | 537 | error: |
