diff options
-rw-r--r-- | include/net/xfrm.h | 8 | ||||
-rw-r--r-- | net/ipv4/xfrm4_input.c | 36 | ||||
-rw-r--r-- | net/ipv4/xfrm4_tunnel.c | 9 |
3 files changed, 26 insertions, 27 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0e844845f3f4..680739f69003 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -1046,7 +1046,15 @@ extern void xfrm_replay_notify(struct xfrm_state *x, int event); | |||
1046 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); | 1046 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); |
1047 | extern int xfrm_init_state(struct xfrm_state *x); | 1047 | extern int xfrm_init_state(struct xfrm_state *x); |
1048 | extern int xfrm_output(struct sk_buff *skb); | 1048 | extern int xfrm_output(struct sk_buff *skb); |
1049 | extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, | ||
1050 | int encap_type); | ||
1049 | extern int xfrm4_rcv(struct sk_buff *skb); | 1051 | extern int xfrm4_rcv(struct sk_buff *skb); |
1052 | |||
1053 | static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) | ||
1054 | { | ||
1055 | return xfrm4_rcv_encap(skb, nexthdr, spi, 0); | ||
1056 | } | ||
1057 | |||
1050 | extern int xfrm4_output(struct sk_buff *skb); | 1058 | extern int xfrm4_output(struct sk_buff *skb); |
1051 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); | 1059 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); |
1052 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); | 1060 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index e9bbfde19ac3..5cb0b5995bc8 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -16,19 +16,6 @@ | |||
16 | #include <net/ip.h> | 16 | #include <net/ip.h> |
17 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
18 | 18 | ||
19 | static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | ||
20 | { | ||
21 | switch (nexthdr) { | ||
22 | case IPPROTO_IPIP: | ||
23 | case IPPROTO_IPV6: | ||
24 | *spi = ip_hdr(skb)->saddr; | ||
25 | *seq = 0; | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | return xfrm_parse_spi(skb, nexthdr, spi, seq); | ||
30 | } | ||
31 | |||
32 | #ifdef CONFIG_NETFILTER | 19 | #ifdef CONFIG_NETFILTER |
33 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | 20 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) |
34 | { | 21 | { |
@@ -46,28 +33,29 @@ drop: | |||
46 | } | 33 | } |
47 | #endif | 34 | #endif |
48 | 35 | ||
49 | static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | 36 | int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, |
37 | int encap_type) | ||
50 | { | 38 | { |
51 | __be32 spi, seq; | 39 | int err; |
40 | __be32 seq; | ||
52 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; | 41 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; |
53 | struct xfrm_state *x; | 42 | struct xfrm_state *x; |
54 | int xfrm_nr = 0; | 43 | int xfrm_nr = 0; |
55 | int decaps = 0; | 44 | int decaps = 0; |
56 | int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq); | ||
57 | unsigned int nhoff = offsetof(struct iphdr, protocol); | 45 | unsigned int nhoff = offsetof(struct iphdr, protocol); |
58 | 46 | ||
59 | if (err != 0) | 47 | seq = 0; |
48 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) | ||
60 | goto drop; | 49 | goto drop; |
61 | 50 | ||
62 | do { | 51 | do { |
63 | const struct iphdr *iph = ip_hdr(skb); | 52 | const struct iphdr *iph = ip_hdr(skb); |
64 | int nexthdr; | ||
65 | 53 | ||
66 | if (xfrm_nr == XFRM_MAX_DEPTH) | 54 | if (xfrm_nr == XFRM_MAX_DEPTH) |
67 | goto drop; | 55 | goto drop; |
68 | 56 | ||
69 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, | 57 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, |
70 | iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET); | 58 | nexthdr, AF_INET); |
71 | if (x == NULL) | 59 | if (x == NULL) |
72 | goto drop; | 60 | goto drop; |
73 | 61 | ||
@@ -111,7 +99,7 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
111 | break; | 99 | break; |
112 | } | 100 | } |
113 | 101 | ||
114 | err = xfrm_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq); | 102 | err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); |
115 | if (err < 0) | 103 | if (err < 0) |
116 | goto drop; | 104 | goto drop; |
117 | } while (!err); | 105 | } while (!err); |
@@ -165,6 +153,7 @@ drop: | |||
165 | kfree_skb(skb); | 153 | kfree_skb(skb); |
166 | return 0; | 154 | return 0; |
167 | } | 155 | } |
156 | EXPORT_SYMBOL(xfrm4_rcv_encap); | ||
168 | 157 | ||
169 | /* If it's a keepalive packet, then just eat it. | 158 | /* If it's a keepalive packet, then just eat it. |
170 | * If it's an encapsulated packet, then pass it to the | 159 | * If it's an encapsulated packet, then pass it to the |
@@ -252,11 +241,8 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) | |||
252 | __skb_pull(skb, len); | 241 | __skb_pull(skb, len); |
253 | skb_reset_transport_header(skb); | 242 | skb_reset_transport_header(skb); |
254 | 243 | ||
255 | /* modify the protocol (it's ESP!) */ | ||
256 | iph->protocol = IPPROTO_ESP; | ||
257 | |||
258 | /* process ESP */ | 244 | /* process ESP */ |
259 | ret = xfrm4_rcv_encap(skb, encap_type); | 245 | ret = xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, encap_type); |
260 | return ret; | 246 | return ret; |
261 | 247 | ||
262 | drop: | 248 | drop: |
@@ -266,7 +252,7 @@ drop: | |||
266 | 252 | ||
267 | int xfrm4_rcv(struct sk_buff *skb) | 253 | int xfrm4_rcv(struct sk_buff *skb) |
268 | { | 254 | { |
269 | return xfrm4_rcv_encap(skb, 0); | 255 | return xfrm4_rcv_spi(skb, ip_hdr(skb)->protocol, 0); |
270 | } | 256 | } |
271 | 257 | ||
272 | EXPORT_SYMBOL(xfrm4_rcv); | 258 | EXPORT_SYMBOL(xfrm4_rcv); |
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 83e9580feac4..326845195620 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -48,20 +48,25 @@ static struct xfrm_type ipip_type = { | |||
48 | .output = ipip_output | 48 | .output = ipip_output |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static int xfrm_tunnel_rcv(struct sk_buff *skb) | ||
52 | { | ||
53 | return xfrm4_rcv_spi(skb, IPPROTO_IP, ip_hdr(skb)->saddr); | ||
54 | } | ||
55 | |||
51 | static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) | 56 | static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) |
52 | { | 57 | { |
53 | return -ENOENT; | 58 | return -ENOENT; |
54 | } | 59 | } |
55 | 60 | ||
56 | static struct xfrm_tunnel xfrm_tunnel_handler = { | 61 | static struct xfrm_tunnel xfrm_tunnel_handler = { |
57 | .handler = xfrm4_rcv, | 62 | .handler = xfrm_tunnel_rcv, |
58 | .err_handler = xfrm_tunnel_err, | 63 | .err_handler = xfrm_tunnel_err, |
59 | .priority = 2, | 64 | .priority = 2, |
60 | }; | 65 | }; |
61 | 66 | ||
62 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 67 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
63 | static struct xfrm_tunnel xfrm64_tunnel_handler = { | 68 | static struct xfrm_tunnel xfrm64_tunnel_handler = { |
64 | .handler = xfrm4_rcv, | 69 | .handler = xfrm_tunnel_rcv, |
65 | .err_handler = xfrm_tunnel_err, | 70 | .err_handler = xfrm_tunnel_err, |
66 | .priority = 2, | 71 | .priority = 2, |
67 | }; | 72 | }; |