Commit 716062fd4c2f88a33ab409f62a1e7397ad0a7e33

Authored by Herbert Xu
Committed by David S. Miller
1 parent c6581a457e

[IPSEC]: Merge most of the input path

As part of the work on asynchronous cryptographic operations, we need
to be able to resume from the spot where they occur.  As such, it
helps if we isolate them to one spot.

This patch moves most of the remaining family-specific processing into
the common input code.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 6 changed files with 164 additions and 217 deletions Side-by-side Diff

... ... @@ -274,6 +274,8 @@
274 274 struct sk_buff *skb);
275 275 int (*extract_output)(struct xfrm_state *x,
276 276 struct sk_buff *skb);
  277 + int (*transport_finish)(struct sk_buff *skb,
  278 + int async);
277 279 };
278 280  
279 281 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
... ... @@ -522,6 +524,22 @@
522 524  
523 525 #define XFRM_MODE_SKB_CB(__skb) ((struct xfrm_mode_skb_cb *)&((__skb)->cb[0]))
524 526  
  527 +/*
  528 + * This structure is used by the input processing to locate the SPI and
  529 + * related information.
  530 + */
  531 +struct xfrm_spi_skb_cb {
  532 + union {
  533 + struct inet_skb_parm h4;
  534 + struct inet6_skb_parm h6;
  535 + } header;
  536 +
  537 + unsigned int nhoff;
  538 + unsigned int daddroff;
  539 +};
  540 +
  541 +#define XFRM_SPI_SKB_CB(__skb) ((struct xfrm_spi_skb_cb *)&((__skb)->cb[0]))
  542 +
525 543 /* Audit Information */
526 544 struct xfrm_audit
527 545 {
528 546  
... ... @@ -1119,12 +1137,15 @@
1119 1137 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
1120 1138 extern int xfrm_init_state(struct xfrm_state *x);
1121 1139 extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
  1140 +extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
  1141 + int encap_type);
1122 1142 extern int xfrm_output_resume(struct sk_buff *skb, int err);
1123 1143 extern int xfrm_output(struct sk_buff *skb);
1124 1144 extern int xfrm4_extract_header(struct sk_buff *skb);
1125 1145 extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
1126 1146 extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
1127 1147 int encap_type);
  1148 +extern int xfrm4_transport_finish(struct sk_buff *skb, int async);
1128 1149 extern int xfrm4_rcv(struct sk_buff *skb);
1129 1150  
1130 1151 static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
... ... @@ -1140,6 +1161,7 @@
1140 1161 extern int xfrm6_extract_header(struct sk_buff *skb);
1141 1162 extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
1142 1163 extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
  1164 +extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
1143 1165 extern int xfrm6_rcv(struct sk_buff *skb);
1144 1166 extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
1145 1167 xfrm_address_t *saddr, u8 proto);
net/ipv4/xfrm4_input.c
... ... @@ -41,124 +41,26 @@
41 41 int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
42 42 int encap_type)
43 43 {
44   - int err;
45   - __be32 seq;
46   - struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
47   - struct xfrm_state *x;
48   - int xfrm_nr = 0;
49   - int decaps = 0;
50   - unsigned int nhoff = offsetof(struct iphdr, protocol);
  44 + XFRM_SPI_SKB_CB(skb)->nhoff = offsetof(struct iphdr, protocol);
  45 + XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
  46 + return xfrm_input(skb, nexthdr, spi, encap_type);
  47 +}
  48 +EXPORT_SYMBOL(xfrm4_rcv_encap);
51 49  
52   - seq = 0;
53   - if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
54   - goto drop;
55   -
56   - do {
57   - const struct iphdr *iph = ip_hdr(skb);
58   -
59   - if (xfrm_nr == XFRM_MAX_DEPTH)
60   - goto drop;
61   -
62   - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
63   - nexthdr, AF_INET);
64   - if (x == NULL)
65   - goto drop;
66   -
67   - spin_lock(&x->lock);
68   - if (unlikely(x->km.state != XFRM_STATE_VALID))
69   - goto drop_unlock;
70   -
71   - if ((x->encap ? x->encap->encap_type : 0) != encap_type)
72   - goto drop_unlock;
73   -
74   - if (x->props.replay_window && xfrm_replay_check(x, seq))
75   - goto drop_unlock;
76   -
77   - if (xfrm_state_check_expire(x))
78   - goto drop_unlock;
79   -
80   - nexthdr = x->type->input(x, skb);
81   - if (nexthdr <= 0)
82   - goto drop_unlock;
83   -
84   - skb_network_header(skb)[nhoff] = nexthdr;
85   -
86   - /* only the first xfrm gets the encap type */
87   - encap_type = 0;
88   -
89   - if (x->props.replay_window)
90   - xfrm_replay_advance(x, seq);
91   -
92   - x->curlft.bytes += skb->len;
93   - x->curlft.packets++;
94   -
95   - spin_unlock(&x->lock);
96   -
97   - xfrm_vec[xfrm_nr++] = x;
98   -
99   - if (x->inner_mode->input(x, skb))
100   - goto drop;
101   -
102   - if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
103   - decaps = 1;
104   - break;
105   - }
106   -
107   - err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
108   - if (err < 0)
109   - goto drop;
110   - } while (!err);
111   -
112   - /* Allocate new secpath or COW existing one. */
113   -
114   - if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
115   - struct sec_path *sp;
116   - sp = secpath_dup(skb->sp);
117   - if (!sp)
118   - goto drop;
119   - if (skb->sp)
120   - secpath_put(skb->sp);
121   - skb->sp = sp;
122   - }
123   - if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
124   - goto drop;
125   -
126   - memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
127   - xfrm_nr * sizeof(xfrm_vec[0]));
128   - skb->sp->len += xfrm_nr;
129   -
130   - nf_reset(skb);
131   -
132   - if (decaps) {
133   - dst_release(skb->dst);
134   - skb->dst = NULL;
135   - netif_rx(skb);
136   - return 0;
137   - } else {
  50 +int xfrm4_transport_finish(struct sk_buff *skb, int async)
  51 +{
138 52 #ifdef CONFIG_NETFILTER
139   - __skb_push(skb, skb->data - skb_network_header(skb));
140   - ip_hdr(skb)->tot_len = htons(skb->len);
141   - ip_send_check(ip_hdr(skb));
  53 + __skb_push(skb, skb->data - skb_network_header(skb));
  54 + ip_hdr(skb)->tot_len = htons(skb->len);
  55 + ip_send_check(ip_hdr(skb));
142 56  
143   - NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
144   - xfrm4_rcv_encap_finish);
145   - return 0;
  57 + NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
  58 + xfrm4_rcv_encap_finish);
  59 + return 0;
146 60 #else
147   - return -ip_hdr(skb)->protocol;
  61 + return -ip_hdr(skb)->protocol;
148 62 #endif
149   - }
150   -
151   -drop_unlock:
152   - spin_unlock(&x->lock);
153   - xfrm_state_put(x);
154   -drop:
155   - while (--xfrm_nr >= 0)
156   - xfrm_state_put(xfrm_vec[xfrm_nr]);
157   -
158   - kfree_skb(skb);
159   - return 0;
160 63 }
161   -EXPORT_SYMBOL(xfrm4_rcv_encap);
162 64  
163 65 /* If it's a keepalive packet, then just eat it.
164 66 * If it's an encapsulated packet, then pass it to the
net/ipv4/xfrm4_state.c
... ... @@ -74,6 +74,7 @@
74 74 .output = xfrm4_output,
75 75 .extract_input = xfrm4_extract_input,
76 76 .extract_output = xfrm4_extract_output,
  77 + .transport_finish = xfrm4_transport_finish,
77 78 };
78 79  
79 80 void __init xfrm4_state_init(void)
net/ipv6/xfrm6_input.c
... ... @@ -23,117 +23,25 @@
23 23  
24 24 int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
25 25 {
26   - int err;
27   - __be32 seq;
28   - struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
29   - struct xfrm_state *x;
30   - int xfrm_nr = 0;
31   - int decaps = 0;
32   - unsigned int nhoff;
  26 + XFRM_SPI_SKB_CB(skb)->nhoff = IP6CB(skb)->nhoff;
  27 + XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
  28 + return xfrm_input(skb, nexthdr, spi, 0);
  29 +}
  30 +EXPORT_SYMBOL(xfrm6_rcv_spi);
33 31  
34   - nhoff = IP6CB(skb)->nhoff;
35   -
36   - seq = 0;
37   - if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
38   - goto drop;
39   -
40   - do {
41   - struct ipv6hdr *iph = ipv6_hdr(skb);
42   -
43   - if (xfrm_nr == XFRM_MAX_DEPTH)
44   - goto drop;
45   -
46   - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
47   - nexthdr, AF_INET6);
48   - if (x == NULL)
49   - goto drop;
50   - spin_lock(&x->lock);
51   - if (unlikely(x->km.state != XFRM_STATE_VALID))
52   - goto drop_unlock;
53   -
54   - if (x->props.replay_window && xfrm_replay_check(x, seq))
55   - goto drop_unlock;
56   -
57   - if (xfrm_state_check_expire(x))
58   - goto drop_unlock;
59   -
60   - nexthdr = x->type->input(x, skb);
61   - if (nexthdr <= 0)
62   - goto drop_unlock;
63   -
64   - skb_network_header(skb)[nhoff] = nexthdr;
65   -
66   - if (x->props.replay_window)
67   - xfrm_replay_advance(x, seq);
68   -
69   - x->curlft.bytes += skb->len;
70   - x->curlft.packets++;
71   -
72   - spin_unlock(&x->lock);
73   -
74   - xfrm_vec[xfrm_nr++] = x;
75   -
76   - if (x->inner_mode->input(x, skb))
77   - goto drop;
78   -
79   - if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
80   - decaps = 1;
81   - break;
82   - }
83   -
84   - if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
85   - goto drop;
86   - } while (!err);
87   -
88   - /* Allocate new secpath or COW existing one. */
89   - if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
90   - struct sec_path *sp;
91   - sp = secpath_dup(skb->sp);
92   - if (!sp)
93   - goto drop;
94   - if (skb->sp)
95   - secpath_put(skb->sp);
96   - skb->sp = sp;
97   - }
98   -
99   - if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
100   - goto drop;
101   -
102   - memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
103   - xfrm_nr * sizeof(xfrm_vec[0]));
104   - skb->sp->len += xfrm_nr;
105   -
106   - nf_reset(skb);
107   -
108   - if (decaps) {
109   - dst_release(skb->dst);
110   - skb->dst = NULL;
111   - netif_rx(skb);
112   - return -1;
113   - } else {
  32 +int xfrm6_transport_finish(struct sk_buff *skb, int async)
  33 +{
114 34 #ifdef CONFIG_NETFILTER
115   - ipv6_hdr(skb)->payload_len = htons(skb->len);
116   - __skb_push(skb, skb->data - skb_network_header(skb));
  35 + ipv6_hdr(skb)->payload_len = htons(skb->len);
  36 + __skb_push(skb, skb->data - skb_network_header(skb));
117 37  
118   - NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
119   - ip6_rcv_finish);
120   - return -1;
  38 + NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
  39 + ip6_rcv_finish);
  40 + return -1;
121 41 #else
122   - return 1;
  42 + return 1;
123 43 #endif
124   - }
125   -
126   -drop_unlock:
127   - spin_unlock(&x->lock);
128   - xfrm_state_put(x);
129   -drop:
130   - while (--xfrm_nr >= 0)
131   - xfrm_state_put(xfrm_vec[xfrm_nr]);
132   - kfree_skb(skb);
133   - return -1;
134 44 }
135   -
136   -EXPORT_SYMBOL(xfrm6_rcv_spi);
137 45  
138 46 int xfrm6_rcv(struct sk_buff *skb)
139 47 {
net/ipv6/xfrm6_state.c
... ... @@ -198,6 +198,7 @@
198 198 .output = xfrm6_output,
199 199 .extract_input = xfrm6_extract_input,
200 200 .extract_output = xfrm6_extract_output,
  201 + .transport_finish = xfrm6_transport_finish,
201 202 };
202 203  
203 204 void __init xfrm6_state_init(void)
net/xfrm/xfrm_input.c
... ... @@ -9,6 +9,8 @@
9 9  
10 10 #include <linux/slab.h>
11 11 #include <linux/module.h>
  12 +#include <linux/netdevice.h>
  13 +#include <net/dst.h>
12 14 #include <net/ip.h>
13 15 #include <net/xfrm.h>
14 16  
... ... @@ -93,6 +95,117 @@
93 95 return x->inner_mode->input2(x, skb);
94 96 }
95 97 EXPORT_SYMBOL(xfrm_prepare_input);
  98 +
  99 +int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
  100 +{
  101 + int err;
  102 + __be32 seq;
  103 + struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
  104 + struct xfrm_state *x;
  105 + int xfrm_nr = 0;
  106 + int decaps = 0;
  107 + unsigned int nhoff = XFRM_SPI_SKB_CB(skb)->nhoff;
  108 + unsigned int daddroff = XFRM_SPI_SKB_CB(skb)->daddroff;
  109 +
  110 + seq = 0;
  111 + if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
  112 + goto drop;
  113 +
  114 + do {
  115 + if (xfrm_nr == XFRM_MAX_DEPTH)
  116 + goto drop;
  117 +
  118 + x = xfrm_state_lookup((xfrm_address_t *)
  119 + (skb_network_header(skb) + daddroff),
  120 + spi, nexthdr, AF_INET);
  121 + if (x == NULL)
  122 + goto drop;
  123 +
  124 + spin_lock(&x->lock);
  125 + if (unlikely(x->km.state != XFRM_STATE_VALID))
  126 + goto drop_unlock;
  127 +
  128 + if ((x->encap ? x->encap->encap_type : 0) != encap_type)
  129 + goto drop_unlock;
  130 +
  131 + if (x->props.replay_window && xfrm_replay_check(x, seq))
  132 + goto drop_unlock;
  133 +
  134 + if (xfrm_state_check_expire(x))
  135 + goto drop_unlock;
  136 +
  137 + nexthdr = x->type->input(x, skb);
  138 + if (nexthdr <= 0)
  139 + goto drop_unlock;
  140 +
  141 + skb_network_header(skb)[nhoff] = nexthdr;
  142 +
  143 + /* only the first xfrm gets the encap type */
  144 + encap_type = 0;
  145 +
  146 + if (x->props.replay_window)
  147 + xfrm_replay_advance(x, seq);
  148 +
  149 + x->curlft.bytes += skb->len;
  150 + x->curlft.packets++;
  151 +
  152 + spin_unlock(&x->lock);
  153 +
  154 + xfrm_vec[xfrm_nr++] = x;
  155 +
  156 + if (x->inner_mode->input(x, skb))
  157 + goto drop;
  158 +
  159 + if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
  160 + decaps = 1;
  161 + break;
  162 + }
  163 +
  164 + err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
  165 + if (err < 0)
  166 + goto drop;
  167 + } while (!err);
  168 +
  169 + /* Allocate new secpath or COW existing one. */
  170 +
  171 + if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
  172 + struct sec_path *sp;
  173 + sp = secpath_dup(skb->sp);
  174 + if (!sp)
  175 + goto drop;
  176 + if (skb->sp)
  177 + secpath_put(skb->sp);
  178 + skb->sp = sp;
  179 + }
  180 + if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
  181 + goto drop;
  182 +
  183 + memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
  184 + xfrm_nr * sizeof(xfrm_vec[0]));
  185 + skb->sp->len += xfrm_nr;
  186 +
  187 + nf_reset(skb);
  188 +
  189 + if (decaps) {
  190 + dst_release(skb->dst);
  191 + skb->dst = NULL;
  192 + netif_rx(skb);
  193 + return 0;
  194 + } else {
  195 + return x->inner_mode->afinfo->transport_finish(skb, 0);
  196 + }
  197 +
  198 +drop_unlock:
  199 + spin_unlock(&x->lock);
  200 + xfrm_state_put(x);
  201 +drop:
  202 + while (--xfrm_nr >= 0)
  203 + xfrm_state_put(xfrm_vec[xfrm_nr]);
  204 +
  205 + kfree_skb(skb);
  206 + return 0;
  207 +}
  208 +EXPORT_SYMBOL(xfrm_input);
96 209  
97 210 void __init xfrm_input_init(void)
98 211 {