15 #include <linux/kernel.h>
16 #include <linux/netdevice.h>
23 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
37 memset(&fl6, 0,
sizeof(fl6));
38 memcpy(&fl6.daddr, daddr,
sizeof(fl6.daddr));
40 memcpy(&fl6.saddr, saddr,
sizeof(fl6.saddr));
53 static int xfrm6_get_saddr(
struct net *net,
59 dst = xfrm6_dst_lookup(net, 0,
NULL, daddr);
63 dev = ip6_dst_idev(dst)->
dev;
71 static int xfrm6_get_tos(
const struct flowi *
fl)
76 static void xfrm6_init_dst(
struct net *net,
struct xfrm_dst *xdst)
80 rt6_init_peer(rt, net->ipv6.peers);
92 path->
u.
rt6.rt6i_nfheader_len = nfheader_len;
102 xdst->
u.
dst.dev = dev;
105 xdst->
u.
rt6.rt6i_idev = in6_dev_get(dev);
106 if (!xdst->
u.
rt6.rt6i_idev)
109 rt6_transfer_peer(&xdst->
u.
rt6, rt);
113 xdst->
u.
rt6.n = neigh_clone(rt->
n);
121 xdst->
u.
rt6.rt6i_dst = rt->rt6i_dst;
132 u16 offset = skb_network_header_len(skb);
135 const unsigned char *nh = skb_network_header(skb);
139 fl6->flowi6_mark = skb->
mark;
144 while (nh + offset + 1 < skb->
data ||
145 pskb_may_pull(skb, nh + offset + 1 - skb->
data)) {
146 nh = skb_network_header(skb);
165 if (!onlyproto && (nh + offset + 4 < skb->
data ||
166 pskb_may_pull(skb, nh + offset + 4 - skb->
data))) {
169 fl6->fl6_sport = ports[!!reverse];
170 fl6->fl6_dport = ports[!reverse];
176 if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->
data)) {
177 u8 *icmp = (
u8 *)exthdr;
179 fl6->fl6_icmp_type = icmp[0];
180 fl6->fl6_icmp_code = icmp[1];
185 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
187 if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->
data)) {
189 mh = (
struct ip6_mh *)exthdr;
202 fl6->fl6_ipsec_spi = 0;
209 static inline int xfrm6_garbage_collect(
struct dst_ops *ops)
211 struct net *net =
container_of(ops,
struct net, xfrm.xfrm6_dst_ops);
213 xfrm6_policy_afinfo.garbage_collect(net);
214 return dst_entries_get_fast(ops) > ops->
gc_thresh * 2;
223 path->
ops->update_pmtu(path, sk, skb, mtu);
226 static void xfrm6_redirect(
struct dst_entry *dst,
struct sock *sk,
232 path->
ops->redirect(path, sk, skb);
235 static void xfrm6_dst_destroy(
struct dst_entry *dst)
240 in6_dev_put(xdst->
u.
rt6.rt6i_idev);
241 dst_destroy_metrics_generic(dst);
242 if (rt6_has_peer(&xdst->
u.
rt6)) {
246 xfrm_dst_destroy(xdst);
258 if (xdst->
u.
rt6.rt6i_idev->dev == dev) {
264 in6_dev_put(xdst->
u.
rt6.rt6i_idev);
265 xdst->
u.
rt6.rt6i_idev = loopback_idev;
266 in6_dev_hold(loopback_idev);
268 }
while (xdst->
u.
dst.xfrm);
270 __in6_dev_put(loopback_idev);
276 static struct dst_ops xfrm6_dst_ops = {
279 .gc = xfrm6_garbage_collect,
280 .update_pmtu = xfrm6_update_pmtu,
281 .redirect = xfrm6_redirect,
283 .destroy = xfrm6_dst_destroy,
284 .ifdown = xfrm6_dst_ifdown,
291 .dst_ops = &xfrm6_dst_ops,
292 .dst_lookup = xfrm6_dst_lookup,
293 .get_saddr = xfrm6_get_saddr,
294 .decode_session = _decode_session6,
295 .get_tos = xfrm6_get_tos,
296 .init_dst = xfrm6_init_dst,
297 .init_path = xfrm6_init_path,
298 .fill_dst = xfrm6_fill_dst,
302 static int __init xfrm6_policy_init(
void)
307 static void xfrm6_policy_fini(
void)
313 static struct ctl_table xfrm6_policy_table[] = {
316 .data = &
init_net.xfrm.xfrm6_dst_ops.gc_thresh,
317 .maxlen =
sizeof(
int),
330 unsigned int gc_thresh;
344 xfrm6_dst_ops.
gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
345 dst_entries_init(&xfrm6_dst_ops);
347 ret = xfrm6_policy_init();
349 dst_entries_destroy(&xfrm6_dst_ops);
376 dst_entries_destroy(&xfrm6_dst_ops);