diff options
Diffstat (limited to 'net/ipv4/xfrm4_policy.c')
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 47 |
1 files changed, 17 insertions, 30 deletions
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 4464f3bff6a7..b057d40addec 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/inetdevice.h> | 13 | #include <linux/inetdevice.h> |
14 | #include <linux/if_tunnel.h> | ||
14 | #include <net/dst.h> | 15 | #include <net/dst.h> |
15 | #include <net/xfrm.h> | 16 | #include <net/xfrm.h> |
16 | #include <net/ip.h> | 17 | #include <net/ip.h> |
@@ -22,12 +23,8 @@ static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, | |||
22 | xfrm_address_t *daddr) | 23 | xfrm_address_t *daddr) |
23 | { | 24 | { |
24 | struct flowi fl = { | 25 | struct flowi fl = { |
25 | .nl_u = { | 26 | .fl4_dst = daddr->a4, |
26 | .ip4_u = { | 27 | .fl4_tos = tos, |
27 | .tos = tos, | ||
28 | .daddr = daddr->a4, | ||
29 | }, | ||
30 | }, | ||
31 | }; | 28 | }; |
32 | struct dst_entry *dst; | 29 | struct dst_entry *dst; |
33 | struct rtable *rt; | 30 | struct rtable *rt; |
@@ -80,10 +77,6 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
80 | xdst->u.dst.dev = dev; | 77 | xdst->u.dst.dev = dev; |
81 | dev_hold(dev); | 78 | dev_hold(dev); |
82 | 79 | ||
83 | xdst->u.rt.idev = in_dev_get(dev); | ||
84 | if (!xdst->u.rt.idev) | ||
85 | return -ENODEV; | ||
86 | |||
87 | xdst->u.rt.peer = rt->peer; | 80 | xdst->u.rt.peer = rt->peer; |
88 | if (rt->peer) | 81 | if (rt->peer) |
89 | atomic_inc(&rt->peer->refcnt); | 82 | atomic_inc(&rt->peer->refcnt); |
@@ -158,6 +151,20 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
158 | fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); | 151 | fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); |
159 | } | 152 | } |
160 | break; | 153 | break; |
154 | |||
155 | case IPPROTO_GRE: | ||
156 | if (pskb_may_pull(skb, xprth + 12 - skb->data)) { | ||
157 | __be16 *greflags = (__be16 *)xprth; | ||
158 | __be32 *gre_hdr = (__be32 *)xprth; | ||
159 | |||
160 | if (greflags[0] & GRE_KEY) { | ||
161 | if (greflags[0] & GRE_CSUM) | ||
162 | gre_hdr++; | ||
163 | fl->fl_gre_key = gre_hdr[1]; | ||
164 | } | ||
165 | } | ||
166 | break; | ||
167 | |||
161 | default: | 168 | default: |
162 | fl->fl_ipsec_spi = 0; | 169 | fl->fl_ipsec_spi = 0; |
163 | break; | 170 | break; |
@@ -189,8 +196,6 @@ static void xfrm4_dst_destroy(struct dst_entry *dst) | |||
189 | { | 196 | { |
190 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | 197 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
191 | 198 | ||
192 | if (likely(xdst->u.rt.idev)) | ||
193 | in_dev_put(xdst->u.rt.idev); | ||
194 | if (likely(xdst->u.rt.peer)) | 199 | if (likely(xdst->u.rt.peer)) |
195 | inet_putpeer(xdst->u.rt.peer); | 200 | inet_putpeer(xdst->u.rt.peer); |
196 | xfrm_dst_destroy(xdst); | 201 | xfrm_dst_destroy(xdst); |
@@ -199,27 +204,9 @@ static void xfrm4_dst_destroy(struct dst_entry *dst) | |||
199 | static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | 204 | static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, |
200 | int unregister) | 205 | int unregister) |
201 | { | 206 | { |
202 | struct xfrm_dst *xdst; | ||
203 | |||
204 | if (!unregister) | 207 | if (!unregister) |
205 | return; | 208 | return; |
206 | 209 | ||
207 | xdst = (struct xfrm_dst *)dst; | ||
208 | if (xdst->u.rt.idev->dev == dev) { | ||
209 | struct in_device *loopback_idev = | ||
210 | in_dev_get(dev_net(dev)->loopback_dev); | ||
211 | BUG_ON(!loopback_idev); | ||
212 | |||
213 | do { | ||
214 | in_dev_put(xdst->u.rt.idev); | ||
215 | xdst->u.rt.idev = loopback_idev; | ||
216 | in_dev_hold(loopback_idev); | ||
217 | xdst = (struct xfrm_dst *)xdst->u.dst.child; | ||
218 | } while (xdst->u.dst.xfrm); | ||
219 | |||
220 | __in_dev_put(loopback_idev); | ||
221 | } | ||
222 | |||
223 | xfrm_dst_ifdown(dst, dev); | 210 | xfrm_dst_ifdown(dst, dev); |
224 | } | 211 | } |
225 | 212 | ||