Blame view
net/ipv4/xfrm4_mode_beet.c
3.77 KB
0a69452cb [XFRM]: BEET mode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* * xfrm4_mode_beet.c - BEET mode encapsulation for IPv4. * * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com> * Miika Komu <miika@iki.fi> * Herbert Xu <herbert@gondor.apana.org.au> * Abhinav Pathak <abhinav.pathak@hiit.fi> * Jeff Ahrenholz <ahrenholz@gmail.com> */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/skbuff.h> #include <linux/stringify.h> #include <net/dst.h> #include <net/ip.h> #include <net/xfrm.h> |
227620e29 [IPSEC]: Separate... |
19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
static void xfrm4_beet_make_header(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); iph->ihl = 5; iph->version = 4; iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; iph->tos = XFRM_MODE_SKB_CB(skb)->tos; iph->id = XFRM_MODE_SKB_CB(skb)->id; iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off; iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl; } |
0a69452cb [XFRM]: BEET mode |
33 34 35 |
/* Add encapsulation header. * * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. |
0a69452cb [XFRM]: BEET mode |
36 37 38 |
*/ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) { |
37fedd3aa [IPSEC]: Use IPv6... |
39 |
struct ip_beet_phdr *ph; |
732c8bd59 [IPSEC]: Fix BEET... |
40 |
struct iphdr *top_iph; |
0a69452cb [XFRM]: BEET mode |
41 |
int hdrlen, optlen; |
0a69452cb [XFRM]: BEET mode |
42 |
hdrlen = 0; |
732c8bd59 [IPSEC]: Fix BEET... |
43 |
optlen = XFRM_MODE_SKB_CB(skb)->optlen; |
0a69452cb [XFRM]: BEET mode |
44 45 |
if (unlikely(optlen)) hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); |
eb49e6309 ipsec: Interfamil... |
46 47 48 49 |
skb_set_network_header(skb, -x->props.header_len - hdrlen + (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph))); if (x->sel.family != AF_INET6) skb->network_header += IPV4_BEET_PHMAXLEN; |
37fedd3aa [IPSEC]: Use IPv6... |
50 51 |
skb->mac_header = skb->network_header + offsetof(struct iphdr, protocol); |
732c8bd59 [IPSEC]: Fix BEET... |
52 |
skb->transport_header = skb->network_header + sizeof(*top_iph); |
37fedd3aa [IPSEC]: Use IPv6... |
53 |
|
227620e29 [IPSEC]: Separate... |
54 |
xfrm4_beet_make_header(skb); |
732c8bd59 [IPSEC]: Fix BEET... |
55 56 |
ph = (struct ip_beet_phdr *) __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen); |
0a69452cb [XFRM]: BEET mode |
57 |
|
37fedd3aa [IPSEC]: Use IPv6... |
58 |
top_iph = ip_hdr(skb); |
36cf9acf9 [IPSEC]: Separate... |
59 |
|
0a69452cb [XFRM]: BEET mode |
60 |
if (unlikely(optlen)) { |
0a69452cb [XFRM]: BEET mode |
61 |
BUG_ON(optlen < 0); |
0a69452cb [XFRM]: BEET mode |
62 |
ph->padlen = 4 - (optlen & 4); |
05d224468 [XFRM]: beet: fix... |
63 |
ph->hdrlen = optlen / 8; |
0a69452cb [XFRM]: BEET mode |
64 |
ph->nexthdr = top_iph->protocol; |
04fef9893 [XFRM]: beet: use... |
65 66 |
if (ph->padlen) memset(ph + 1, IPOPT_NOP, ph->padlen); |
0a69452cb [XFRM]: BEET mode |
67 68 69 70 71 72 73 74 75 76 77 78 79 |
top_iph->protocol = IPPROTO_BEETPH; top_iph->ihl = sizeof(struct iphdr) / 4; } top_iph->saddr = x->props.saddr.a4; top_iph->daddr = x->id.daddr.a4; return 0; } static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) { |
227620e29 [IPSEC]: Separate... |
80 |
struct iphdr *iph; |
0a69452cb [XFRM]: BEET mode |
81 |
int optlen = 0; |
0a69452cb [XFRM]: BEET mode |
82 |
int err = -EINVAL; |
227620e29 [IPSEC]: Separate... |
83 |
if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) { |
254d0d24e [XFRM]: beet: fix... |
84 |
struct ip_beet_phdr *ph; |
227620e29 [IPSEC]: Separate... |
85 |
int phlen; |
0a69452cb [XFRM]: BEET mode |
86 87 88 |
if (!pskb_may_pull(skb, sizeof(*ph))) goto out; |
227620e29 [IPSEC]: Separate... |
89 90 |
ph = (struct ip_beet_phdr *)skb->data; |
0a69452cb [XFRM]: BEET mode |
91 |
|
d4b1e8406 [XFRM]: beet: fix... |
92 |
phlen = sizeof(*ph) + ph->padlen; |
05d224468 [XFRM]: beet: fix... |
93 |
optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); |
0a69452cb [XFRM]: BEET mode |
94 95 |
if (optlen < 0 || optlen & 3 || optlen > 250) goto out; |
227620e29 [IPSEC]: Separate... |
96 |
XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr; |
0a69452cb [XFRM]: BEET mode |
97 |
|
322c8a3c3 [IPSEC] xfrm4_bee... |
98 |
if (!pskb_may_pull(skb, phlen)) |
227620e29 [IPSEC]: Separate... |
99 100 |
goto out; __skb_pull(skb, phlen); |
0a69452cb [XFRM]: BEET mode |
101 |
} |
227620e29 [IPSEC]: Separate... |
102 103 104 105 106 107 108 109 |
skb_push(skb, sizeof(*iph)); skb_reset_network_header(skb); memmove(skb->data - skb->mac_len, skb_mac_header(skb), skb->mac_len); skb_set_mac_header(skb, -skb->mac_len); xfrm4_beet_make_header(skb); |
0a69452cb [XFRM]: BEET mode |
110 |
|
eddc9ec53 [SK_BUFF]: Introd... |
111 |
iph = ip_hdr(skb); |
227620e29 [IPSEC]: Separate... |
112 113 114 |
iph->ihl += optlen / 4; iph->tot_len = htons(skb->len); |
0a69452cb [XFRM]: BEET mode |
115 116 |
iph->daddr = x->sel.daddr.a4; iph->saddr = x->sel.saddr.a4; |
0a69452cb [XFRM]: BEET mode |
117 |
iph->check = 0; |
d56f90a7c [SK_BUFF]: Introd... |
118 |
iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl); |
0a69452cb [XFRM]: BEET mode |
119 120 121 122 123 124 |
err = 0; out: return err; } static struct xfrm_mode xfrm4_beet_mode = { |
227620e29 [IPSEC]: Separate... |
125 126 |
.input2 = xfrm4_beet_input, .input = xfrm_prepare_input, |
36cf9acf9 [IPSEC]: Separate... |
127 128 |
.output2 = xfrm4_beet_output, .output = xfrm4_prepare_output, |
0a69452cb [XFRM]: BEET mode |
129 130 |
.owner = THIS_MODULE, .encap = XFRM_MODE_BEET, |
1bfcb10f6 [IPSEC]: Add miss... |
131 |
.flags = XFRM_MODE_FLAG_TUNNEL, |
0a69452cb [XFRM]: BEET mode |
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
}; static int __init xfrm4_beet_init(void) { return xfrm_register_mode(&xfrm4_beet_mode, AF_INET); } static void __exit xfrm4_beet_exit(void) { int err; err = xfrm_unregister_mode(&xfrm4_beet_mode, AF_INET); BUG_ON(err); } module_init(xfrm4_beet_init); module_exit(xfrm4_beet_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_BEET); |