1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/init.h>
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/skbuff.h>
31#include <linux/spinlock.h>
32#include <linux/stringify.h>
33#include <linux/time.h>
34#include <net/ipv6.h>
35#include <net/xfrm.h>
36
37
38
39
40
41
42static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
43{
44 struct ipv6hdr *iph;
45 u8 *prevhdr;
46 int hdr_len;
47
48 iph = ipv6_hdr(skb);
49
50 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
51 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
52 skb_set_network_header(skb, -x->props.header_len);
53 skb->transport_header = skb->network_header + hdr_len;
54 __skb_pull(skb, hdr_len);
55 memmove(ipv6_hdr(skb), iph, hdr_len);
56
57 x->lastused = get_seconds();
58
59 return 0;
60}
61
62static struct xfrm_mode xfrm6_ro_mode = {
63 .output = xfrm6_ro_output,
64 .owner = THIS_MODULE,
65 .encap = XFRM_MODE_ROUTEOPTIMIZATION,
66};
67
68static int __init xfrm6_ro_init(void)
69{
70 return xfrm_register_mode(&xfrm6_ro_mode, AF_INET6);
71}
72
73static void __exit xfrm6_ro_exit(void)
74{
75 int err;
76
77 err = xfrm_unregister_mode(&xfrm6_ro_mode, AF_INET6);
78 BUG_ON(err);
79}
80
81module_init(xfrm6_ro_init);
82module_exit(xfrm6_ro_exit);
83MODULE_LICENSE("GPL");
84MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_ROUTEOPTIMIZATION);
85