aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_input.c
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2014-02-21 02:41:08 -0500
committerSteffen Klassert <steffen.klassert@secunet.com>2014-02-25 01:04:16 -0500
commit3328715e6c1fcb10cd86b0f3212d18290b7e4463 (patch)
tree15ba89891638afb7075b5a5046d357c9263ac265 /net/xfrm/xfrm_input.c
parent51adfcc333e1490d3a22490f5b3504f64c7b28b4 (diff)
xfrm4: Add IPsec protocol multiplexer
This patch add an IPsec protocol multiplexer. With this it is possible to add alternative protocol handlers as needed for IPsec virtual tunnel interfaces. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_input.c')
-rw-r--r--net/xfrm/xfrm_input.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 6c7ac016ce3a..99e3a9e5285e 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -108,7 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
108 int err; 108 int err;
109 __be32 seq; 109 __be32 seq;
110 __be32 seq_hi; 110 __be32 seq_hi;
111 struct xfrm_state *x; 111 struct xfrm_state *x = NULL;
112 xfrm_address_t *daddr; 112 xfrm_address_t *daddr;
113 struct xfrm_mode *inner_mode; 113 struct xfrm_mode *inner_mode;
114 unsigned int family; 114 unsigned int family;
@@ -120,9 +120,14 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
120 async = 1; 120 async = 1;
121 x = xfrm_input_state(skb); 121 x = xfrm_input_state(skb);
122 seq = XFRM_SKB_CB(skb)->seq.input.low; 122 seq = XFRM_SKB_CB(skb)->seq.input.low;
123 family = x->outer_mode->afinfo->family;
123 goto resume; 124 goto resume;
124 } 125 }
125 126
127 daddr = (xfrm_address_t *)(skb_network_header(skb) +
128 XFRM_SPI_SKB_CB(skb)->daddroff);
129 family = XFRM_SPI_SKB_CB(skb)->family;
130
126 /* Allocate new secpath or COW existing one. */ 131 /* Allocate new secpath or COW existing one. */
127 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { 132 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
128 struct sec_path *sp; 133 struct sec_path *sp;
@@ -137,10 +142,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
137 skb->sp = sp; 142 skb->sp = sp;
138 } 143 }
139 144
140 daddr = (xfrm_address_t *)(skb_network_header(skb) +
141 XFRM_SPI_SKB_CB(skb)->daddroff);
142 family = XFRM_SPI_SKB_CB(skb)->family;
143
144 seq = 0; 145 seq = 0;
145 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { 146 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
146 XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); 147 XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
@@ -201,7 +202,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
201 202
202 if (nexthdr == -EINPROGRESS) 203 if (nexthdr == -EINPROGRESS)
203 return 0; 204 return 0;
204
205resume: 205resume:
206 spin_lock(&x->lock); 206 spin_lock(&x->lock);
207 if (nexthdr <= 0) { 207 if (nexthdr <= 0) {
@@ -263,6 +263,10 @@ resume:
263 } 263 }
264 } while (!err); 264 } while (!err);
265 265
266 err = xfrm_rcv_cb(skb, family, x->type->proto, 0);
267 if (err)
268 goto drop;
269
266 nf_reset(skb); 270 nf_reset(skb);
267 271
268 if (decaps) { 272 if (decaps) {
@@ -276,6 +280,7 @@ resume:
276drop_unlock: 280drop_unlock:
277 spin_unlock(&x->lock); 281 spin_unlock(&x->lock);
278drop: 282drop:
283 xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1);
279 kfree_skb(skb); 284 kfree_skb(skb);
280 return 0; 285 return 0;
281} 286}