diff options
Diffstat (limited to 'net/ipv6/xfrm6_policy.c')
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 08e4cbbe3f04..97ab068e8ccc 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -27,7 +27,8 @@ | |||
27 | static struct dst_ops xfrm6_dst_ops; | 27 | static struct dst_ops xfrm6_dst_ops; |
28 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; | 28 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; |
29 | 29 | ||
30 | static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr, | 30 | static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, |
31 | xfrm_address_t *saddr, | ||
31 | xfrm_address_t *daddr) | 32 | xfrm_address_t *daddr) |
32 | { | 33 | { |
33 | struct flowi fl = {}; | 34 | struct flowi fl = {}; |
@@ -38,7 +39,7 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr, | |||
38 | if (saddr) | 39 | if (saddr) |
39 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); | 40 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); |
40 | 41 | ||
41 | dst = ip6_route_output(&init_net, NULL, &fl); | 42 | dst = ip6_route_output(net, NULL, &fl); |
42 | 43 | ||
43 | err = dst->error; | 44 | err = dst->error; |
44 | if (dst->error) { | 45 | if (dst->error) { |
@@ -49,12 +50,13 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr, | |||
49 | return dst; | 50 | return dst; |
50 | } | 51 | } |
51 | 52 | ||
52 | static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) | 53 | static int xfrm6_get_saddr(struct net *net, |
54 | xfrm_address_t *saddr, xfrm_address_t *daddr) | ||
53 | { | 55 | { |
54 | struct dst_entry *dst; | 56 | struct dst_entry *dst; |
55 | struct net_device *dev; | 57 | struct net_device *dev; |
56 | 58 | ||
57 | dst = xfrm6_dst_lookup(0, NULL, daddr); | 59 | dst = xfrm6_dst_lookup(net, 0, NULL, daddr); |
58 | if (IS_ERR(dst)) | 60 | if (IS_ERR(dst)) |
59 | return -EHOSTUNREACH; | 61 | return -EHOSTUNREACH; |
60 | 62 | ||
@@ -144,6 +146,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | |||
144 | static inline void | 146 | static inline void |
145 | _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | 147 | _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) |
146 | { | 148 | { |
149 | int onlyproto = 0; | ||
147 | u16 offset = skb_network_header_len(skb); | 150 | u16 offset = skb_network_header_len(skb); |
148 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 151 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
149 | struct ipv6_opt_hdr *exthdr; | 152 | struct ipv6_opt_hdr *exthdr; |
@@ -159,6 +162,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
159 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); | 162 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
160 | 163 | ||
161 | switch (nexthdr) { | 164 | switch (nexthdr) { |
165 | case NEXTHDR_FRAGMENT: | ||
166 | onlyproto = 1; | ||
162 | case NEXTHDR_ROUTING: | 167 | case NEXTHDR_ROUTING: |
163 | case NEXTHDR_HOP: | 168 | case NEXTHDR_HOP: |
164 | case NEXTHDR_DEST: | 169 | case NEXTHDR_DEST: |
@@ -172,7 +177,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
172 | case IPPROTO_TCP: | 177 | case IPPROTO_TCP: |
173 | case IPPROTO_SCTP: | 178 | case IPPROTO_SCTP: |
174 | case IPPROTO_DCCP: | 179 | case IPPROTO_DCCP: |
175 | if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) { | 180 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { |
176 | __be16 *ports = (__be16 *)exthdr; | 181 | __be16 *ports = (__be16 *)exthdr; |
177 | 182 | ||
178 | fl->fl_ip_sport = ports[!!reverse]; | 183 | fl->fl_ip_sport = ports[!!reverse]; |
@@ -182,7 +187,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
182 | return; | 187 | return; |
183 | 188 | ||
184 | case IPPROTO_ICMPV6: | 189 | case IPPROTO_ICMPV6: |
185 | if (pskb_may_pull(skb, nh + offset + 2 - skb->data)) { | 190 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { |
186 | u8 *icmp = (u8 *)exthdr; | 191 | u8 *icmp = (u8 *)exthdr; |
187 | 192 | ||
188 | fl->fl_icmp_type = icmp[0]; | 193 | fl->fl_icmp_type = icmp[0]; |
@@ -193,7 +198,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
193 | 198 | ||
194 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 199 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
195 | case IPPROTO_MH: | 200 | case IPPROTO_MH: |
196 | if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 201 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
197 | struct ip6_mh *mh; | 202 | struct ip6_mh *mh; |
198 | mh = (struct ip6_mh *)exthdr; | 203 | mh = (struct ip6_mh *)exthdr; |
199 | 204 | ||
@@ -217,7 +222,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
217 | 222 | ||
218 | static inline int xfrm6_garbage_collect(struct dst_ops *ops) | 223 | static inline int xfrm6_garbage_collect(struct dst_ops *ops) |
219 | { | 224 | { |
220 | xfrm6_policy_afinfo.garbage_collect(); | 225 | xfrm6_policy_afinfo.garbage_collect(&init_net); |
221 | return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2); | 226 | return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2); |
222 | } | 227 | } |
223 | 228 | ||
@@ -274,7 +279,6 @@ static struct dst_ops xfrm6_dst_ops = { | |||
274 | .ifdown = xfrm6_dst_ifdown, | 279 | .ifdown = xfrm6_dst_ifdown, |
275 | .local_out = __ip6_local_out, | 280 | .local_out = __ip6_local_out, |
276 | .gc_thresh = 1024, | 281 | .gc_thresh = 1024, |
277 | .entry_size = sizeof(struct xfrm_dst), | ||
278 | .entries = ATOMIC_INIT(0), | 282 | .entries = ATOMIC_INIT(0), |
279 | }; | 283 | }; |
280 | 284 | ||