diff options
Diffstat (limited to 'net/ipv6/xfrm6_policy.c')
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index c9844135c9c..d879f7efbd1 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/ip.h> | 20 | #include <net/ip.h> |
21 | #include <net/ipv6.h> | 21 | #include <net/ipv6.h> |
22 | #include <net/ip6_route.h> | 22 | #include <net/ip6_route.h> |
23 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | 23 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
24 | #include <net/mip6.h> | 24 | #include <net/mip6.h> |
25 | #endif | 25 | #endif |
26 | 26 | ||
@@ -73,13 +73,6 @@ static int xfrm6_get_tos(const struct flowi *fl) | |||
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | static void xfrm6_init_dst(struct net *net, struct xfrm_dst *xdst) | ||
77 | { | ||
78 | struct rt6_info *rt = (struct rt6_info *)xdst; | ||
79 | |||
80 | rt6_init_peer(rt, net->ipv6.peers); | ||
81 | } | ||
82 | |||
83 | static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, | 76 | static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, |
84 | int nfheader_len) | 77 | int nfheader_len) |
85 | { | 78 | { |
@@ -106,11 +99,12 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
106 | if (!xdst->u.rt6.rt6i_idev) | 99 | if (!xdst->u.rt6.rt6i_idev) |
107 | return -ENODEV; | 100 | return -ENODEV; |
108 | 101 | ||
109 | rt6_transfer_peer(&xdst->u.rt6, rt); | 102 | xdst->u.rt6.rt6i_peer = rt->rt6i_peer; |
103 | if (rt->rt6i_peer) | ||
104 | atomic_inc(&rt->rt6i_peer->refcnt); | ||
110 | 105 | ||
111 | /* Sheit... I remember I did this right. Apparently, | 106 | /* Sheit... I remember I did this right. Apparently, |
112 | * it was magically lost, so this code needs audit */ | 107 | * it was magically lost, so this code needs audit */ |
113 | xdst->u.rt6.n = neigh_clone(rt->n); | ||
114 | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | | 108 | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | |
115 | RTF_LOCAL); | 109 | RTF_LOCAL); |
116 | xdst->u.rt6.rt6i_metric = rt->rt6i_metric; | 110 | xdst->u.rt6.rt6i_metric = rt->rt6i_metric; |
@@ -138,8 +132,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
138 | memset(fl6, 0, sizeof(struct flowi6)); | 132 | memset(fl6, 0, sizeof(struct flowi6)); |
139 | fl6->flowi6_mark = skb->mark; | 133 | fl6->flowi6_mark = skb->mark; |
140 | 134 | ||
141 | fl6->daddr = reverse ? hdr->saddr : hdr->daddr; | 135 | ipv6_addr_copy(&fl6->daddr, reverse ? &hdr->saddr : &hdr->daddr); |
142 | fl6->saddr = reverse ? hdr->daddr : hdr->saddr; | 136 | ipv6_addr_copy(&fl6->saddr, reverse ? &hdr->daddr : &hdr->saddr); |
143 | 137 | ||
144 | while (nh + offset + 1 < skb->data || | 138 | while (nh + offset + 1 < skb->data || |
145 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { | 139 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { |
@@ -182,7 +176,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
182 | fl6->flowi6_proto = nexthdr; | 176 | fl6->flowi6_proto = nexthdr; |
183 | return; | 177 | return; |
184 | 178 | ||
185 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | 179 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
186 | case IPPROTO_MH: | 180 | case IPPROTO_MH: |
187 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 181 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
188 | struct ip6_mh *mh; | 182 | struct ip6_mh *mh; |
@@ -214,22 +208,12 @@ static inline int xfrm6_garbage_collect(struct dst_ops *ops) | |||
214 | return dst_entries_get_fast(ops) > ops->gc_thresh * 2; | 208 | return dst_entries_get_fast(ops) > ops->gc_thresh * 2; |
215 | } | 209 | } |
216 | 210 | ||
217 | static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk, | 211 | static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu) |
218 | struct sk_buff *skb, u32 mtu) | ||
219 | { | ||
220 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | ||
221 | struct dst_entry *path = xdst->route; | ||
222 | |||
223 | path->ops->update_pmtu(path, sk, skb, mtu); | ||
224 | } | ||
225 | |||
226 | static void xfrm6_redirect(struct dst_entry *dst, struct sock *sk, | ||
227 | struct sk_buff *skb) | ||
228 | { | 212 | { |
229 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | 213 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
230 | struct dst_entry *path = xdst->route; | 214 | struct dst_entry *path = xdst->route; |
231 | 215 | ||
232 | path->ops->redirect(path, sk, skb); | 216 | path->ops->update_pmtu(path, mtu); |
233 | } | 217 | } |
234 | 218 | ||
235 | static void xfrm6_dst_destroy(struct dst_entry *dst) | 219 | static void xfrm6_dst_destroy(struct dst_entry *dst) |
@@ -239,10 +223,8 @@ static void xfrm6_dst_destroy(struct dst_entry *dst) | |||
239 | if (likely(xdst->u.rt6.rt6i_idev)) | 223 | if (likely(xdst->u.rt6.rt6i_idev)) |
240 | in6_dev_put(xdst->u.rt6.rt6i_idev); | 224 | in6_dev_put(xdst->u.rt6.rt6i_idev); |
241 | dst_destroy_metrics_generic(dst); | 225 | dst_destroy_metrics_generic(dst); |
242 | if (rt6_has_peer(&xdst->u.rt6)) { | 226 | if (likely(xdst->u.rt6.rt6i_peer)) |
243 | struct inet_peer *peer = rt6_peer_ptr(&xdst->u.rt6); | 227 | inet_putpeer(xdst->u.rt6.rt6i_peer); |
244 | inet_putpeer(peer); | ||
245 | } | ||
246 | xfrm_dst_destroy(xdst); | 228 | xfrm_dst_destroy(xdst); |
247 | } | 229 | } |
248 | 230 | ||
@@ -278,7 +260,6 @@ static struct dst_ops xfrm6_dst_ops = { | |||
278 | .protocol = cpu_to_be16(ETH_P_IPV6), | 260 | .protocol = cpu_to_be16(ETH_P_IPV6), |
279 | .gc = xfrm6_garbage_collect, | 261 | .gc = xfrm6_garbage_collect, |
280 | .update_pmtu = xfrm6_update_pmtu, | 262 | .update_pmtu = xfrm6_update_pmtu, |
281 | .redirect = xfrm6_redirect, | ||
282 | .cow_metrics = dst_cow_metrics_generic, | 263 | .cow_metrics = dst_cow_metrics_generic, |
283 | .destroy = xfrm6_dst_destroy, | 264 | .destroy = xfrm6_dst_destroy, |
284 | .ifdown = xfrm6_dst_ifdown, | 265 | .ifdown = xfrm6_dst_ifdown, |
@@ -293,7 +274,6 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | |||
293 | .get_saddr = xfrm6_get_saddr, | 274 | .get_saddr = xfrm6_get_saddr, |
294 | .decode_session = _decode_session6, | 275 | .decode_session = _decode_session6, |
295 | .get_tos = xfrm6_get_tos, | 276 | .get_tos = xfrm6_get_tos, |
296 | .init_dst = xfrm6_init_dst, | ||
297 | .init_path = xfrm6_init_path, | 277 | .init_path = xfrm6_init_path, |
298 | .fill_dst = xfrm6_fill_dst, | 278 | .fill_dst = xfrm6_fill_dst, |
299 | .blackhole_route = ip6_blackhole_route, | 279 | .blackhole_route = ip6_blackhole_route, |
@@ -327,7 +307,21 @@ static struct ctl_table_header *sysctl_hdr; | |||
327 | int __init xfrm6_init(void) | 307 | int __init xfrm6_init(void) |
328 | { | 308 | { |
329 | int ret; | 309 | int ret; |
330 | 310 | unsigned int gc_thresh; | |
311 | |||
312 | /* | ||
313 | * We need a good default value for the xfrm6 gc threshold. | ||
314 | * In ipv4 we set it to the route hash table size * 8, which | ||
315 | * is half the size of the maximaum route cache for ipv4. It | ||
316 | * would be good to do the same thing for v6, except the table is | ||
317 | * constructed differently here. Here each table for a net namespace | ||
318 | * can have FIB_TABLE_HASHSZ entries, so lets go with the same | ||
319 | * computation that we used for ipv4 here. Also, lets keep the initial | ||
320 | * gc_thresh to a minimum of 1024, since, the ipv6 route cache defaults | ||
321 | * to that as a minimum as well | ||
322 | */ | ||
323 | gc_thresh = FIB6_TABLE_HASHSZ * 8; | ||
324 | xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh; | ||
331 | dst_entries_init(&xfrm6_dst_ops); | 325 | dst_entries_init(&xfrm6_dst_ops); |
332 | 326 | ||
333 | ret = xfrm6_policy_init(); | 327 | ret = xfrm6_policy_init(); |
@@ -340,8 +334,8 @@ int __init xfrm6_init(void) | |||
340 | goto out_policy; | 334 | goto out_policy; |
341 | 335 | ||
342 | #ifdef CONFIG_SYSCTL | 336 | #ifdef CONFIG_SYSCTL |
343 | sysctl_hdr = register_net_sysctl(&init_net, "net/ipv6", | 337 | sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv6_ctl_path, |
344 | xfrm6_policy_table); | 338 | xfrm6_policy_table); |
345 | #endif | 339 | #endif |
346 | out: | 340 | out: |
347 | return ret; | 341 | return ret; |
@@ -356,6 +350,7 @@ void xfrm6_fini(void) | |||
356 | if (sysctl_hdr) | 350 | if (sysctl_hdr) |
357 | unregister_net_sysctl_table(sysctl_hdr); | 351 | unregister_net_sysctl_table(sysctl_hdr); |
358 | #endif | 352 | #endif |
353 | //xfrm6_input_fini(); | ||
359 | xfrm6_policy_fini(); | 354 | xfrm6_policy_fini(); |
360 | xfrm6_state_fini(); | 355 | xfrm6_state_fini(); |
361 | dst_entries_destroy(&xfrm6_dst_ops); | 356 | dst_entries_destroy(&xfrm6_dst_ops); |