aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/xfrm6_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/xfrm6_policy.c')
-rw-r--r--net/ipv6/xfrm6_policy.c63
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
76static 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
83static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, 76static 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
217static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk, 211static 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
226static 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
235static void xfrm6_dst_destroy(struct dst_entry *dst) 219static 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;
327int __init xfrm6_init(void) 307int __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
346out: 340out:
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);