diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/ip_gre.c | 3 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 16 | ||||
| -rw-r--r-- | net/ipv4/ipip.c | 3 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_output.c | 13 |
4 files changed, 24 insertions, 11 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index abe23923e4e7..9981dcd68f11 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -830,7 +830,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 830 | skb->h.raw = skb->nh.raw; | 830 | skb->h.raw = skb->nh.raw; |
| 831 | skb->nh.raw = skb_push(skb, gre_hlen); | 831 | skb->nh.raw = skb_push(skb, gre_hlen); |
| 832 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 832 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
| 833 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | 833 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
| 834 | IPSKB_REROUTED); | ||
| 834 | dst_release(skb->dst); | 835 | dst_release(skb->dst); |
| 835 | skb->dst = &rt->u.dst; | 836 | skb->dst = &rt->u.dst; |
| 836 | 837 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3324fbfe528a..57d290d89ec2 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -207,8 +207,10 @@ static inline int ip_finish_output(struct sk_buff *skb) | |||
| 207 | { | 207 | { |
| 208 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 208 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
| 209 | /* Policy lookup after SNAT yielded a new policy */ | 209 | /* Policy lookup after SNAT yielded a new policy */ |
| 210 | if (skb->dst->xfrm != NULL) | 210 | if (skb->dst->xfrm != NULL) { |
| 211 | return xfrm4_output_finish(skb); | 211 | IPCB(skb)->flags |= IPSKB_REROUTED; |
| 212 | return dst_output(skb); | ||
| 213 | } | ||
| 212 | #endif | 214 | #endif |
| 213 | if (skb->len > dst_mtu(skb->dst) && | 215 | if (skb->len > dst_mtu(skb->dst) && |
| 214 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | 216 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) |
| @@ -271,8 +273,9 @@ int ip_mc_output(struct sk_buff *skb) | |||
| 271 | newskb->dev, ip_dev_loopback_xmit); | 273 | newskb->dev, ip_dev_loopback_xmit); |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 274 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, | 276 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, |
| 275 | ip_finish_output); | 277 | ip_finish_output, |
| 278 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
| 276 | } | 279 | } |
| 277 | 280 | ||
| 278 | int ip_output(struct sk_buff *skb) | 281 | int ip_output(struct sk_buff *skb) |
| @@ -284,8 +287,9 @@ int ip_output(struct sk_buff *skb) | |||
| 284 | skb->dev = dev; | 287 | skb->dev = dev; |
| 285 | skb->protocol = htons(ETH_P_IP); | 288 | skb->protocol = htons(ETH_P_IP); |
| 286 | 289 | ||
| 287 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, | 290 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, |
| 288 | ip_finish_output); | 291 | ip_finish_output, |
| 292 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
| 289 | } | 293 | } |
| 290 | 294 | ||
| 291 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | 295 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index e5cbe72c6b80..03d13742a4b8 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
| @@ -622,7 +622,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 622 | skb->h.raw = skb->nh.raw; | 622 | skb->h.raw = skb->nh.raw; |
| 623 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 623 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
| 624 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 624 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
| 625 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | 625 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
| 626 | IPSKB_REROUTED); | ||
| 626 | dst_release(skb->dst); | 627 | dst_release(skb->dst); |
| 627 | skb->dst = &rt->u.dst; | 628 | skb->dst = &rt->u.dst; |
| 628 | 629 | ||
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index d4df0ddd424b..32ad229b4fed 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
| @@ -152,10 +152,16 @@ error_nolock: | |||
| 152 | goto out_exit; | 152 | goto out_exit; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | int xfrm4_output_finish(struct sk_buff *skb) | 155 | static int xfrm4_output_finish(struct sk_buff *skb) |
| 156 | { | 156 | { |
| 157 | int err; | 157 | int err; |
| 158 | 158 | ||
| 159 | #ifdef CONFIG_NETFILTER | ||
| 160 | if (!skb->dst->xfrm) { | ||
| 161 | IPCB(skb)->flags |= IPSKB_REROUTED; | ||
| 162 | return dst_output(skb); | ||
| 163 | } | ||
| 164 | #endif | ||
| 159 | while (likely((err = xfrm4_output_one(skb)) == 0)) { | 165 | while (likely((err = xfrm4_output_one(skb)) == 0)) { |
| 160 | nf_reset(skb); | 166 | nf_reset(skb); |
| 161 | 167 | ||
| @@ -178,6 +184,7 @@ int xfrm4_output_finish(struct sk_buff *skb) | |||
| 178 | 184 | ||
| 179 | int xfrm4_output(struct sk_buff *skb) | 185 | int xfrm4_output(struct sk_buff *skb) |
| 180 | { | 186 | { |
| 181 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, | 187 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, |
| 182 | xfrm4_output_finish); | 188 | xfrm4_output_finish, |
| 189 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
| 183 | } | 190 | } |
