.. | .. |
---|
21 | 21 | #include <net/ip_tunnels.h> |
---|
22 | 22 | #include <net/ip6_tunnel.h> |
---|
23 | 23 | |
---|
| 24 | +#include "xfrm_inout.h" |
---|
| 25 | + |
---|
24 | 26 | struct xfrm_trans_tasklet { |
---|
25 | 27 | struct tasklet_struct tasklet; |
---|
26 | 28 | struct sk_buff_head queue; |
---|
.. | .. |
---|
34 | 36 | #endif |
---|
35 | 37 | } header; |
---|
36 | 38 | int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
| 39 | + struct net *net; |
---|
37 | 40 | }; |
---|
38 | 41 | |
---|
39 | 42 | #define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0])) |
---|
40 | 43 | |
---|
41 | | -static struct kmem_cache *secpath_cachep __ro_after_init; |
---|
42 | | - |
---|
43 | 44 | static DEFINE_SPINLOCK(xfrm_input_afinfo_lock); |
---|
44 | | -static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[AF_INET6 + 1]; |
---|
| 45 | +static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[2][AF_INET6 + 1]; |
---|
45 | 46 | |
---|
46 | 47 | static struct gro_cells gro_cells; |
---|
47 | 48 | static struct net_device xfrm_napi_dev; |
---|
.. | .. |
---|
52 | 53 | { |
---|
53 | 54 | int err = 0; |
---|
54 | 55 | |
---|
55 | | - if (WARN_ON(afinfo->family >= ARRAY_SIZE(xfrm_input_afinfo))) |
---|
| 56 | + if (WARN_ON(afinfo->family > AF_INET6)) |
---|
56 | 57 | return -EAFNOSUPPORT; |
---|
57 | 58 | |
---|
58 | 59 | spin_lock_bh(&xfrm_input_afinfo_lock); |
---|
59 | | - if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL)) |
---|
| 60 | + if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family])) |
---|
60 | 61 | err = -EEXIST; |
---|
61 | 62 | else |
---|
62 | | - rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo); |
---|
| 63 | + rcu_assign_pointer(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], afinfo); |
---|
63 | 64 | spin_unlock_bh(&xfrm_input_afinfo_lock); |
---|
64 | 65 | return err; |
---|
65 | 66 | } |
---|
.. | .. |
---|
70 | 71 | int err = 0; |
---|
71 | 72 | |
---|
72 | 73 | spin_lock_bh(&xfrm_input_afinfo_lock); |
---|
73 | | - if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) { |
---|
74 | | - if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo)) |
---|
| 74 | + if (likely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family])) { |
---|
| 75 | + if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family] != afinfo)) |
---|
75 | 76 | err = -EINVAL; |
---|
76 | 77 | else |
---|
77 | | - RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL); |
---|
| 78 | + RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], NULL); |
---|
78 | 79 | } |
---|
79 | 80 | spin_unlock_bh(&xfrm_input_afinfo_lock); |
---|
80 | 81 | synchronize_rcu(); |
---|
.. | .. |
---|
82 | 83 | } |
---|
83 | 84 | EXPORT_SYMBOL(xfrm_input_unregister_afinfo); |
---|
84 | 85 | |
---|
85 | | -static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family) |
---|
| 86 | +static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(u8 family, bool is_ipip) |
---|
86 | 87 | { |
---|
87 | 88 | const struct xfrm_input_afinfo *afinfo; |
---|
88 | 89 | |
---|
89 | | - if (WARN_ON_ONCE(family >= ARRAY_SIZE(xfrm_input_afinfo))) |
---|
| 90 | + if (WARN_ON_ONCE(family > AF_INET6)) |
---|
90 | 91 | return NULL; |
---|
91 | 92 | |
---|
92 | 93 | rcu_read_lock(); |
---|
93 | | - afinfo = rcu_dereference(xfrm_input_afinfo[family]); |
---|
| 94 | + afinfo = rcu_dereference(xfrm_input_afinfo[is_ipip][family]); |
---|
94 | 95 | if (unlikely(!afinfo)) |
---|
95 | 96 | rcu_read_unlock(); |
---|
96 | 97 | return afinfo; |
---|
.. | .. |
---|
99 | 100 | static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol, |
---|
100 | 101 | int err) |
---|
101 | 102 | { |
---|
| 103 | + bool is_ipip = (protocol == IPPROTO_IPIP || protocol == IPPROTO_IPV6); |
---|
| 104 | + const struct xfrm_input_afinfo *afinfo; |
---|
102 | 105 | int ret; |
---|
103 | | - const struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family); |
---|
104 | 106 | |
---|
| 107 | + afinfo = xfrm_input_get_afinfo(family, is_ipip); |
---|
105 | 108 | if (!afinfo) |
---|
106 | 109 | return -EAFNOSUPPORT; |
---|
107 | 110 | |
---|
.. | .. |
---|
111 | 114 | return ret; |
---|
112 | 115 | } |
---|
113 | 116 | |
---|
114 | | -void __secpath_destroy(struct sec_path *sp) |
---|
| 117 | +struct sec_path *secpath_set(struct sk_buff *skb) |
---|
115 | 118 | { |
---|
116 | | - int i; |
---|
117 | | - for (i = 0; i < sp->len; i++) |
---|
118 | | - xfrm_state_put(sp->xvec[i]); |
---|
119 | | - kmem_cache_free(secpath_cachep, sp); |
---|
120 | | -} |
---|
121 | | -EXPORT_SYMBOL(__secpath_destroy); |
---|
| 119 | + struct sec_path *sp, *tmp = skb_ext_find(skb, SKB_EXT_SEC_PATH); |
---|
122 | 120 | |
---|
123 | | -struct sec_path *secpath_dup(struct sec_path *src) |
---|
124 | | -{ |
---|
125 | | - struct sec_path *sp; |
---|
126 | | - |
---|
127 | | - sp = kmem_cache_alloc(secpath_cachep, GFP_ATOMIC); |
---|
| 121 | + sp = skb_ext_add(skb, SKB_EXT_SEC_PATH); |
---|
128 | 122 | if (!sp) |
---|
129 | 123 | return NULL; |
---|
130 | 124 | |
---|
131 | | - sp->len = 0; |
---|
132 | | - sp->olen = 0; |
---|
| 125 | + if (tmp) /* reused existing one (was COW'd if needed) */ |
---|
| 126 | + return sp; |
---|
133 | 127 | |
---|
| 128 | + /* allocated new secpath */ |
---|
134 | 129 | memset(sp->ovec, 0, sizeof(sp->ovec)); |
---|
| 130 | + sp->olen = 0; |
---|
| 131 | + sp->len = 0; |
---|
| 132 | + sp->verified_cnt = 0; |
---|
135 | 133 | |
---|
136 | | - if (src) { |
---|
137 | | - int i; |
---|
138 | | - |
---|
139 | | - memcpy(sp, src, sizeof(*sp)); |
---|
140 | | - for (i = 0; i < sp->len; i++) |
---|
141 | | - xfrm_state_hold(sp->xvec[i]); |
---|
142 | | - } |
---|
143 | | - refcount_set(&sp->refcnt, 1); |
---|
144 | 134 | return sp; |
---|
145 | | -} |
---|
146 | | -EXPORT_SYMBOL(secpath_dup); |
---|
147 | | - |
---|
148 | | -int secpath_set(struct sk_buff *skb) |
---|
149 | | -{ |
---|
150 | | - struct sec_path *sp; |
---|
151 | | - |
---|
152 | | - /* Allocate new secpath or COW existing one. */ |
---|
153 | | - if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) { |
---|
154 | | - sp = secpath_dup(skb->sp); |
---|
155 | | - if (!sp) |
---|
156 | | - return -ENOMEM; |
---|
157 | | - |
---|
158 | | - if (skb->sp) |
---|
159 | | - secpath_put(skb->sp); |
---|
160 | | - skb->sp = sp; |
---|
161 | | - } |
---|
162 | | - return 0; |
---|
163 | 135 | } |
---|
164 | 136 | EXPORT_SYMBOL(secpath_set); |
---|
165 | 137 | |
---|
.. | .. |
---|
200 | 172 | } |
---|
201 | 173 | EXPORT_SYMBOL(xfrm_parse_spi); |
---|
202 | 174 | |
---|
203 | | -int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 175 | +static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb) |
---|
204 | 176 | { |
---|
205 | | - struct xfrm_mode *inner_mode = x->inner_mode; |
---|
| 177 | + struct iphdr *iph; |
---|
| 178 | + int optlen = 0; |
---|
| 179 | + int err = -EINVAL; |
---|
| 180 | + |
---|
| 181 | + if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) { |
---|
| 182 | + struct ip_beet_phdr *ph; |
---|
| 183 | + int phlen; |
---|
| 184 | + |
---|
| 185 | + if (!pskb_may_pull(skb, sizeof(*ph))) |
---|
| 186 | + goto out; |
---|
| 187 | + |
---|
| 188 | + ph = (struct ip_beet_phdr *)skb->data; |
---|
| 189 | + |
---|
| 190 | + phlen = sizeof(*ph) + ph->padlen; |
---|
| 191 | + optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); |
---|
| 192 | + if (optlen < 0 || optlen & 3 || optlen > 250) |
---|
| 193 | + goto out; |
---|
| 194 | + |
---|
| 195 | + XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr; |
---|
| 196 | + |
---|
| 197 | + if (!pskb_may_pull(skb, phlen)) |
---|
| 198 | + goto out; |
---|
| 199 | + __skb_pull(skb, phlen); |
---|
| 200 | + } |
---|
| 201 | + |
---|
| 202 | + skb_push(skb, sizeof(*iph)); |
---|
| 203 | + skb_reset_network_header(skb); |
---|
| 204 | + skb_mac_header_rebuild(skb); |
---|
| 205 | + |
---|
| 206 | + xfrm4_beet_make_header(skb); |
---|
| 207 | + |
---|
| 208 | + iph = ip_hdr(skb); |
---|
| 209 | + |
---|
| 210 | + iph->ihl += optlen / 4; |
---|
| 211 | + iph->tot_len = htons(skb->len); |
---|
| 212 | + iph->daddr = x->sel.daddr.a4; |
---|
| 213 | + iph->saddr = x->sel.saddr.a4; |
---|
| 214 | + iph->check = 0; |
---|
| 215 | + iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl); |
---|
| 216 | + err = 0; |
---|
| 217 | +out: |
---|
| 218 | + return err; |
---|
| 219 | +} |
---|
| 220 | + |
---|
| 221 | +static void ipip_ecn_decapsulate(struct sk_buff *skb) |
---|
| 222 | +{ |
---|
| 223 | + struct iphdr *inner_iph = ipip_hdr(skb); |
---|
| 224 | + |
---|
| 225 | + if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos)) |
---|
| 226 | + IP_ECN_set_ce(inner_iph); |
---|
| 227 | +} |
---|
| 228 | + |
---|
| 229 | +static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 230 | +{ |
---|
| 231 | + int err = -EINVAL; |
---|
| 232 | + |
---|
| 233 | + if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) |
---|
| 234 | + goto out; |
---|
| 235 | + |
---|
| 236 | + if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
---|
| 237 | + goto out; |
---|
| 238 | + |
---|
| 239 | + err = skb_unclone(skb, GFP_ATOMIC); |
---|
| 240 | + if (err) |
---|
| 241 | + goto out; |
---|
| 242 | + |
---|
| 243 | + if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
---|
| 244 | + ipv4_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipip_hdr(skb)); |
---|
| 245 | + if (!(x->props.flags & XFRM_STATE_NOECN)) |
---|
| 246 | + ipip_ecn_decapsulate(skb); |
---|
| 247 | + |
---|
| 248 | + skb_reset_network_header(skb); |
---|
| 249 | + skb_mac_header_rebuild(skb); |
---|
| 250 | + if (skb->mac_len) |
---|
| 251 | + eth_hdr(skb)->h_proto = skb->protocol; |
---|
| 252 | + |
---|
| 253 | + err = 0; |
---|
| 254 | + |
---|
| 255 | +out: |
---|
| 256 | + return err; |
---|
| 257 | +} |
---|
| 258 | + |
---|
| 259 | +static void ipip6_ecn_decapsulate(struct sk_buff *skb) |
---|
| 260 | +{ |
---|
| 261 | + struct ipv6hdr *inner_iph = ipipv6_hdr(skb); |
---|
| 262 | + |
---|
| 263 | + if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos)) |
---|
| 264 | + IP6_ECN_set_ce(skb, inner_iph); |
---|
| 265 | +} |
---|
| 266 | + |
---|
| 267 | +static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 268 | +{ |
---|
| 269 | + int err = -EINVAL; |
---|
| 270 | + |
---|
| 271 | + if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) |
---|
| 272 | + goto out; |
---|
| 273 | + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
---|
| 274 | + goto out; |
---|
| 275 | + |
---|
| 276 | + err = skb_unclone(skb, GFP_ATOMIC); |
---|
| 277 | + if (err) |
---|
| 278 | + goto out; |
---|
| 279 | + |
---|
| 280 | + if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
---|
| 281 | + ipv6_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipipv6_hdr(skb)); |
---|
| 282 | + if (!(x->props.flags & XFRM_STATE_NOECN)) |
---|
| 283 | + ipip6_ecn_decapsulate(skb); |
---|
| 284 | + |
---|
| 285 | + skb_reset_network_header(skb); |
---|
| 286 | + skb_mac_header_rebuild(skb); |
---|
| 287 | + if (skb->mac_len) |
---|
| 288 | + eth_hdr(skb)->h_proto = skb->protocol; |
---|
| 289 | + |
---|
| 290 | + err = 0; |
---|
| 291 | + |
---|
| 292 | +out: |
---|
| 293 | + return err; |
---|
| 294 | +} |
---|
| 295 | + |
---|
| 296 | +static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 297 | +{ |
---|
| 298 | + struct ipv6hdr *ip6h; |
---|
| 299 | + int size = sizeof(struct ipv6hdr); |
---|
206 | 300 | int err; |
---|
207 | 301 | |
---|
208 | | - err = x->outer_mode->afinfo->extract_input(x, skb); |
---|
| 302 | + err = skb_cow_head(skb, size + skb->mac_len); |
---|
209 | 303 | if (err) |
---|
210 | | - return err; |
---|
| 304 | + goto out; |
---|
| 305 | + |
---|
| 306 | + __skb_push(skb, size); |
---|
| 307 | + skb_reset_network_header(skb); |
---|
| 308 | + skb_mac_header_rebuild(skb); |
---|
| 309 | + |
---|
| 310 | + xfrm6_beet_make_header(skb); |
---|
| 311 | + |
---|
| 312 | + ip6h = ipv6_hdr(skb); |
---|
| 313 | + ip6h->payload_len = htons(skb->len - size); |
---|
| 314 | + ip6h->daddr = x->sel.daddr.in6; |
---|
| 315 | + ip6h->saddr = x->sel.saddr.in6; |
---|
| 316 | + err = 0; |
---|
| 317 | +out: |
---|
| 318 | + return err; |
---|
| 319 | +} |
---|
| 320 | + |
---|
| 321 | +/* Remove encapsulation header. |
---|
| 322 | + * |
---|
| 323 | + * The IP header will be moved over the top of the encapsulation |
---|
| 324 | + * header. |
---|
| 325 | + * |
---|
| 326 | + * On entry, the transport header shall point to where the IP header |
---|
| 327 | + * should be and the network header shall be set to where the IP |
---|
| 328 | + * header currently is. skb->data shall point to the start of the |
---|
| 329 | + * payload. |
---|
| 330 | + */ |
---|
| 331 | +static int |
---|
| 332 | +xfrm_inner_mode_encap_remove(struct xfrm_state *x, |
---|
| 333 | + const struct xfrm_mode *inner_mode, |
---|
| 334 | + struct sk_buff *skb) |
---|
| 335 | +{ |
---|
| 336 | + switch (inner_mode->encap) { |
---|
| 337 | + case XFRM_MODE_BEET: |
---|
| 338 | + if (inner_mode->family == AF_INET) |
---|
| 339 | + return xfrm4_remove_beet_encap(x, skb); |
---|
| 340 | + if (inner_mode->family == AF_INET6) |
---|
| 341 | + return xfrm6_remove_beet_encap(x, skb); |
---|
| 342 | + break; |
---|
| 343 | + case XFRM_MODE_TUNNEL: |
---|
| 344 | + if (inner_mode->family == AF_INET) |
---|
| 345 | + return xfrm4_remove_tunnel_encap(x, skb); |
---|
| 346 | + if (inner_mode->family == AF_INET6) |
---|
| 347 | + return xfrm6_remove_tunnel_encap(x, skb); |
---|
| 348 | + break; |
---|
| 349 | + } |
---|
| 350 | + |
---|
| 351 | + WARN_ON_ONCE(1); |
---|
| 352 | + return -EOPNOTSUPP; |
---|
| 353 | +} |
---|
| 354 | + |
---|
| 355 | +static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 356 | +{ |
---|
| 357 | + const struct xfrm_mode *inner_mode = &x->inner_mode; |
---|
| 358 | + |
---|
| 359 | + switch (x->outer_mode.family) { |
---|
| 360 | + case AF_INET: |
---|
| 361 | + xfrm4_extract_header(skb); |
---|
| 362 | + break; |
---|
| 363 | + case AF_INET6: |
---|
| 364 | + xfrm6_extract_header(skb); |
---|
| 365 | + break; |
---|
| 366 | + default: |
---|
| 367 | + WARN_ON_ONCE(1); |
---|
| 368 | + return -EAFNOSUPPORT; |
---|
| 369 | + } |
---|
211 | 370 | |
---|
212 | 371 | if (x->sel.family == AF_UNSPEC) { |
---|
213 | 372 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
---|
214 | | - if (inner_mode == NULL) |
---|
| 373 | + if (!inner_mode) |
---|
215 | 374 | return -EAFNOSUPPORT; |
---|
216 | 375 | } |
---|
217 | 376 | |
---|
218 | | - skb->protocol = inner_mode->afinfo->eth_proto; |
---|
219 | | - return inner_mode->input2(x, skb); |
---|
| 377 | + switch (inner_mode->family) { |
---|
| 378 | + case AF_INET: |
---|
| 379 | + skb->protocol = htons(ETH_P_IP); |
---|
| 380 | + break; |
---|
| 381 | + case AF_INET6: |
---|
| 382 | + skb->protocol = htons(ETH_P_IPV6); |
---|
| 383 | + break; |
---|
| 384 | + default: |
---|
| 385 | + WARN_ON_ONCE(1); |
---|
| 386 | + break; |
---|
| 387 | + } |
---|
| 388 | + |
---|
| 389 | + return xfrm_inner_mode_encap_remove(x, inner_mode, skb); |
---|
220 | 390 | } |
---|
221 | | -EXPORT_SYMBOL(xfrm_prepare_input); |
---|
| 391 | + |
---|
| 392 | +/* Remove encapsulation header. |
---|
| 393 | + * |
---|
| 394 | + * The IP header will be moved over the top of the encapsulation header. |
---|
| 395 | + * |
---|
| 396 | + * On entry, skb_transport_header() shall point to where the IP header |
---|
| 397 | + * should be and skb_network_header() shall be set to where the IP header |
---|
| 398 | + * currently is. skb->data shall point to the start of the payload. |
---|
| 399 | + */ |
---|
| 400 | +static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 401 | +{ |
---|
| 402 | + int ihl = skb->data - skb_transport_header(skb); |
---|
| 403 | + |
---|
| 404 | + if (skb->transport_header != skb->network_header) { |
---|
| 405 | + memmove(skb_transport_header(skb), |
---|
| 406 | + skb_network_header(skb), ihl); |
---|
| 407 | + skb->network_header = skb->transport_header; |
---|
| 408 | + } |
---|
| 409 | + ip_hdr(skb)->tot_len = htons(skb->len + ihl); |
---|
| 410 | + skb_reset_transport_header(skb); |
---|
| 411 | + return 0; |
---|
| 412 | +} |
---|
| 413 | + |
---|
| 414 | +static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) |
---|
| 415 | +{ |
---|
| 416 | +#if IS_ENABLED(CONFIG_IPV6) |
---|
| 417 | + int ihl = skb->data - skb_transport_header(skb); |
---|
| 418 | + |
---|
| 419 | + if (skb->transport_header != skb->network_header) { |
---|
| 420 | + memmove(skb_transport_header(skb), |
---|
| 421 | + skb_network_header(skb), ihl); |
---|
| 422 | + skb->network_header = skb->transport_header; |
---|
| 423 | + } |
---|
| 424 | + ipv6_hdr(skb)->payload_len = htons(skb->len + ihl - |
---|
| 425 | + sizeof(struct ipv6hdr)); |
---|
| 426 | + skb_reset_transport_header(skb); |
---|
| 427 | + return 0; |
---|
| 428 | +#else |
---|
| 429 | + WARN_ON_ONCE(1); |
---|
| 430 | + return -EAFNOSUPPORT; |
---|
| 431 | +#endif |
---|
| 432 | +} |
---|
| 433 | + |
---|
| 434 | +static int xfrm_inner_mode_input(struct xfrm_state *x, |
---|
| 435 | + const struct xfrm_mode *inner_mode, |
---|
| 436 | + struct sk_buff *skb) |
---|
| 437 | +{ |
---|
| 438 | + switch (inner_mode->encap) { |
---|
| 439 | + case XFRM_MODE_BEET: |
---|
| 440 | + case XFRM_MODE_TUNNEL: |
---|
| 441 | + return xfrm_prepare_input(x, skb); |
---|
| 442 | + case XFRM_MODE_TRANSPORT: |
---|
| 443 | + if (inner_mode->family == AF_INET) |
---|
| 444 | + return xfrm4_transport_input(x, skb); |
---|
| 445 | + if (inner_mode->family == AF_INET6) |
---|
| 446 | + return xfrm6_transport_input(x, skb); |
---|
| 447 | + break; |
---|
| 448 | + case XFRM_MODE_ROUTEOPTIMIZATION: |
---|
| 449 | + WARN_ON_ONCE(1); |
---|
| 450 | + break; |
---|
| 451 | + default: |
---|
| 452 | + WARN_ON_ONCE(1); |
---|
| 453 | + break; |
---|
| 454 | + } |
---|
| 455 | + |
---|
| 456 | + return -EOPNOTSUPP; |
---|
| 457 | +} |
---|
222 | 458 | |
---|
223 | 459 | int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) |
---|
224 | 460 | { |
---|
| 461 | + const struct xfrm_state_afinfo *afinfo; |
---|
225 | 462 | struct net *net = dev_net(skb->dev); |
---|
| 463 | + const struct xfrm_mode *inner_mode; |
---|
226 | 464 | int err; |
---|
227 | 465 | __be32 seq; |
---|
228 | 466 | __be32 seq_hi; |
---|
229 | 467 | struct xfrm_state *x = NULL; |
---|
230 | 468 | xfrm_address_t *daddr; |
---|
231 | | - struct xfrm_mode *inner_mode; |
---|
232 | 469 | u32 mark = skb->mark; |
---|
233 | 470 | unsigned int family = AF_UNSPEC; |
---|
234 | 471 | int decaps = 0; |
---|
.. | .. |
---|
236 | 473 | bool xfrm_gro = false; |
---|
237 | 474 | bool crypto_done = false; |
---|
238 | 475 | struct xfrm_offload *xo = xfrm_offload(skb); |
---|
| 476 | + struct sec_path *sp; |
---|
239 | 477 | |
---|
240 | 478 | if (encap_type < 0) { |
---|
241 | 479 | x = xfrm_input_state(skb); |
---|
.. | .. |
---|
252 | 490 | goto drop; |
---|
253 | 491 | } |
---|
254 | 492 | |
---|
255 | | - family = x->outer_mode->afinfo->family; |
---|
| 493 | + family = x->outer_mode.family; |
---|
256 | 494 | |
---|
257 | 495 | /* An encap_type of -1 indicates async resumption. */ |
---|
258 | 496 | if (encap_type == -1) { |
---|
.. | .. |
---|
315 | 553 | break; |
---|
316 | 554 | } |
---|
317 | 555 | |
---|
318 | | - err = secpath_set(skb); |
---|
319 | | - if (err) { |
---|
| 556 | + sp = secpath_set(skb); |
---|
| 557 | + if (!sp) { |
---|
320 | 558 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR); |
---|
321 | 559 | goto drop; |
---|
322 | 560 | } |
---|
.. | .. |
---|
331 | 569 | daddr = (xfrm_address_t *)(skb_network_header(skb) + |
---|
332 | 570 | XFRM_SPI_SKB_CB(skb)->daddroff); |
---|
333 | 571 | do { |
---|
334 | | - if (skb->sp->len == XFRM_MAX_DEPTH) { |
---|
| 572 | + sp = skb_sec_path(skb); |
---|
| 573 | + |
---|
| 574 | + if (sp->len == XFRM_MAX_DEPTH) { |
---|
335 | 575 | secpath_reset(skb); |
---|
336 | 576 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
---|
337 | 577 | goto drop; |
---|
.. | .. |
---|
347 | 587 | |
---|
348 | 588 | skb->mark = xfrm_smark_get(skb->mark, x); |
---|
349 | 589 | |
---|
350 | | - skb->sp->xvec[skb->sp->len++] = x; |
---|
| 590 | + sp->xvec[sp->len++] = x; |
---|
351 | 591 | |
---|
352 | 592 | skb_dst_force(skb); |
---|
353 | 593 | if (!skb_dst(skb)) { |
---|
.. | .. |
---|
434 | 674 | |
---|
435 | 675 | XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; |
---|
436 | 676 | |
---|
437 | | - inner_mode = x->inner_mode; |
---|
| 677 | + inner_mode = &x->inner_mode; |
---|
438 | 678 | |
---|
439 | 679 | if (x->sel.family == AF_UNSPEC) { |
---|
440 | 680 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
---|
.. | .. |
---|
444 | 684 | } |
---|
445 | 685 | } |
---|
446 | 686 | |
---|
447 | | - if (inner_mode->input(x, skb)) { |
---|
| 687 | + if (xfrm_inner_mode_input(x, inner_mode, skb)) { |
---|
448 | 688 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); |
---|
449 | 689 | goto drop; |
---|
450 | 690 | } |
---|
451 | 691 | |
---|
452 | | - if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { |
---|
| 692 | + if (x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL) { |
---|
453 | 693 | decaps = 1; |
---|
454 | 694 | break; |
---|
455 | 695 | } |
---|
.. | .. |
---|
459 | 699 | * transport mode so the outer address is identical. |
---|
460 | 700 | */ |
---|
461 | 701 | daddr = &x->id.daddr; |
---|
462 | | - family = x->outer_mode->afinfo->family; |
---|
| 702 | + family = x->outer_mode.family; |
---|
463 | 703 | |
---|
464 | 704 | err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); |
---|
465 | 705 | if (err < 0) { |
---|
.. | .. |
---|
473 | 713 | if (err) |
---|
474 | 714 | goto drop; |
---|
475 | 715 | |
---|
476 | | - nf_reset(skb); |
---|
| 716 | + nf_reset_ct(skb); |
---|
477 | 717 | |
---|
478 | 718 | if (decaps) { |
---|
479 | | - if (skb->sp) |
---|
480 | | - skb->sp->olen = 0; |
---|
| 719 | + sp = skb_sec_path(skb); |
---|
| 720 | + if (sp) |
---|
| 721 | + sp->olen = 0; |
---|
481 | 722 | skb_dst_drop(skb); |
---|
482 | 723 | gro_cells_receive(&gro_cells, skb); |
---|
483 | 724 | return 0; |
---|
.. | .. |
---|
486 | 727 | if (xo) |
---|
487 | 728 | xfrm_gro = xo->flags & XFRM_GRO; |
---|
488 | 729 | |
---|
489 | | - err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async); |
---|
| 730 | + err = -EAFNOSUPPORT; |
---|
| 731 | + rcu_read_lock(); |
---|
| 732 | + afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode.family); |
---|
| 733 | + if (likely(afinfo)) |
---|
| 734 | + err = afinfo->transport_finish(skb, xfrm_gro || async); |
---|
| 735 | + rcu_read_unlock(); |
---|
490 | 736 | if (xfrm_gro) { |
---|
491 | | - if (skb->sp) |
---|
492 | | - skb->sp->olen = 0; |
---|
| 737 | + sp = skb_sec_path(skb); |
---|
| 738 | + if (sp) |
---|
| 739 | + sp->olen = 0; |
---|
493 | 740 | skb_dst_drop(skb); |
---|
494 | 741 | gro_cells_receive(&gro_cells, skb); |
---|
495 | 742 | return err; |
---|
.. | .. |
---|
523 | 770 | skb_queue_splice_init(&trans->queue, &queue); |
---|
524 | 771 | |
---|
525 | 772 | while ((skb = __skb_dequeue(&queue))) |
---|
526 | | - XFRM_TRANS_SKB_CB(skb)->finish(dev_net(skb->dev), NULL, skb); |
---|
| 773 | + XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net, |
---|
| 774 | + NULL, skb); |
---|
527 | 775 | } |
---|
528 | 776 | |
---|
529 | | -int xfrm_trans_queue(struct sk_buff *skb, |
---|
530 | | - int (*finish)(struct net *, struct sock *, |
---|
531 | | - struct sk_buff *)) |
---|
| 777 | +int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, |
---|
| 778 | + int (*finish)(struct net *, struct sock *, |
---|
| 779 | + struct sk_buff *)) |
---|
532 | 780 | { |
---|
533 | 781 | struct xfrm_trans_tasklet *trans; |
---|
534 | 782 | |
---|
535 | 783 | trans = this_cpu_ptr(&xfrm_trans_tasklet); |
---|
536 | 784 | |
---|
537 | | - if (skb_queue_len(&trans->queue) >= netdev_max_backlog) |
---|
| 785 | + if (skb_queue_len(&trans->queue) >= READ_ONCE(netdev_max_backlog)) |
---|
538 | 786 | return -ENOBUFS; |
---|
539 | 787 | |
---|
| 788 | + BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb)); |
---|
| 789 | + |
---|
540 | 790 | XFRM_TRANS_SKB_CB(skb)->finish = finish; |
---|
| 791 | + XFRM_TRANS_SKB_CB(skb)->net = net; |
---|
541 | 792 | __skb_queue_tail(&trans->queue, skb); |
---|
542 | 793 | tasklet_schedule(&trans->tasklet); |
---|
543 | 794 | return 0; |
---|
| 795 | +} |
---|
| 796 | +EXPORT_SYMBOL(xfrm_trans_queue_net); |
---|
| 797 | + |
---|
| 798 | +int xfrm_trans_queue(struct sk_buff *skb, |
---|
| 799 | + int (*finish)(struct net *, struct sock *, |
---|
| 800 | + struct sk_buff *)) |
---|
| 801 | +{ |
---|
| 802 | + return xfrm_trans_queue_net(dev_net(skb->dev), skb, finish); |
---|
544 | 803 | } |
---|
545 | 804 | EXPORT_SYMBOL(xfrm_trans_queue); |
---|
546 | 805 | |
---|
.. | .. |
---|
553 | 812 | err = gro_cells_init(&gro_cells, &xfrm_napi_dev); |
---|
554 | 813 | if (err) |
---|
555 | 814 | gro_cells.cells = NULL; |
---|
556 | | - |
---|
557 | | - secpath_cachep = kmem_cache_create("secpath_cache", |
---|
558 | | - sizeof(struct sec_path), |
---|
559 | | - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, |
---|
560 | | - NULL); |
---|
561 | 815 | |
---|
562 | 816 | for_each_possible_cpu(i) { |
---|
563 | 817 | struct xfrm_trans_tasklet *trans; |
---|