.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * IPv6 virtual tunneling interface |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * |
---|
9 | 10 | * Based on: |
---|
10 | 11 | * net/ipv6/ip6_tunnel.c |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or |
---|
13 | | - * modify it under the terms of the GNU General Public License |
---|
14 | | - * as published by the Free Software Foundation; either version |
---|
15 | | - * 2 of the License, or (at your option) any later version. |
---|
16 | 12 | */ |
---|
17 | 13 | |
---|
18 | 14 | #include <linux/module.h> |
---|
.. | .. |
---|
299 | 295 | dev_put(dev); |
---|
300 | 296 | } |
---|
301 | 297 | |
---|
302 | | -static int vti6_rcv(struct sk_buff *skb) |
---|
| 298 | +static int vti6_input_proto(struct sk_buff *skb, int nexthdr, __be32 spi, |
---|
| 299 | + int encap_type) |
---|
303 | 300 | { |
---|
304 | 301 | struct ip6_tnl *t; |
---|
305 | 302 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
---|
.. | .. |
---|
326 | 323 | |
---|
327 | 324 | rcu_read_unlock(); |
---|
328 | 325 | |
---|
329 | | - return xfrm6_rcv_tnl(skb, t); |
---|
| 326 | + XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t; |
---|
| 327 | + XFRM_SPI_SKB_CB(skb)->family = AF_INET6; |
---|
| 328 | + XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); |
---|
| 329 | + return xfrm_input(skb, nexthdr, spi, encap_type); |
---|
330 | 330 | } |
---|
331 | 331 | rcu_read_unlock(); |
---|
332 | 332 | return -EINVAL; |
---|
.. | .. |
---|
335 | 335 | return 0; |
---|
336 | 336 | } |
---|
337 | 337 | |
---|
| 338 | +static int vti6_rcv(struct sk_buff *skb) |
---|
| 339 | +{ |
---|
| 340 | + int nexthdr = skb_network_header(skb)[IP6CB(skb)->nhoff]; |
---|
| 341 | + |
---|
| 342 | + return vti6_input_proto(skb, nexthdr, 0, 0); |
---|
| 343 | +} |
---|
| 344 | + |
---|
338 | 345 | static int vti6_rcv_cb(struct sk_buff *skb, int err) |
---|
339 | 346 | { |
---|
340 | 347 | unsigned short family; |
---|
341 | 348 | struct net_device *dev; |
---|
342 | | - struct pcpu_sw_netstats *tstats; |
---|
343 | 349 | struct xfrm_state *x; |
---|
344 | | - struct xfrm_mode *inner_mode; |
---|
| 350 | + const struct xfrm_mode *inner_mode; |
---|
345 | 351 | struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; |
---|
346 | 352 | u32 orig_mark = skb->mark; |
---|
347 | 353 | int ret; |
---|
.. | .. |
---|
360 | 366 | |
---|
361 | 367 | x = xfrm_input_state(skb); |
---|
362 | 368 | |
---|
363 | | - inner_mode = x->inner_mode; |
---|
| 369 | + inner_mode = &x->inner_mode; |
---|
364 | 370 | |
---|
365 | 371 | if (x->sel.family == AF_UNSPEC) { |
---|
366 | 372 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
---|
.. | .. |
---|
371 | 377 | } |
---|
372 | 378 | } |
---|
373 | 379 | |
---|
374 | | - family = inner_mode->afinfo->family; |
---|
| 380 | + family = inner_mode->family; |
---|
375 | 381 | |
---|
376 | 382 | skb->mark = be32_to_cpu(t->parms.i_key); |
---|
377 | 383 | ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); |
---|
.. | .. |
---|
382 | 388 | |
---|
383 | 389 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev))); |
---|
384 | 390 | skb->dev = dev; |
---|
385 | | - |
---|
386 | | - tstats = this_cpu_ptr(dev->tstats); |
---|
387 | | - u64_stats_update_begin(&tstats->syncp); |
---|
388 | | - tstats->rx_packets++; |
---|
389 | | - tstats->rx_bytes += skb->len; |
---|
390 | | - u64_stats_update_end(&tstats->syncp); |
---|
| 391 | + dev_sw_netstats_rx_add(dev, skb->len); |
---|
391 | 392 | |
---|
392 | 393 | return 0; |
---|
393 | 394 | } |
---|
.. | .. |
---|
483 | 484 | } |
---|
484 | 485 | |
---|
485 | 486 | dst_hold(dst); |
---|
486 | | - dst = xfrm_lookup(t->net, dst, fl, NULL, 0); |
---|
| 487 | + dst = xfrm_lookup_route(t->net, dst, fl, NULL, 0); |
---|
487 | 488 | if (IS_ERR(dst)) { |
---|
488 | 489 | err = PTR_ERR(dst); |
---|
489 | 490 | dst = NULL; |
---|
490 | 491 | goto tx_err_link_failure; |
---|
491 | 492 | } |
---|
| 493 | + |
---|
| 494 | + if (dst->flags & DST_XFRM_QUEUE) |
---|
| 495 | + goto queued; |
---|
492 | 496 | |
---|
493 | 497 | x = dst->xfrm; |
---|
494 | 498 | if (!vti6_state_check(x, &t->parms.raddr, &t->parms.laddr)) |
---|
.. | .. |
---|
515 | 519 | if (mtu < IPV6_MIN_MTU) |
---|
516 | 520 | mtu = IPV6_MIN_MTU; |
---|
517 | 521 | |
---|
518 | | - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
---|
| 522 | + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
---|
519 | 523 | } else { |
---|
520 | | - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
---|
521 | | - htonl(mtu)); |
---|
| 524 | + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
---|
| 525 | + htonl(mtu)); |
---|
522 | 526 | } |
---|
523 | 527 | |
---|
524 | 528 | err = -EMSGSIZE; |
---|
525 | 529 | goto tx_err_dst_release; |
---|
526 | 530 | } |
---|
527 | 531 | |
---|
| 532 | +queued: |
---|
528 | 533 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); |
---|
529 | 534 | skb_dst_set(skb, dst); |
---|
530 | 535 | skb->dev = skb_dst(skb)->dev; |
---|
.. | .. |
---|
562 | 567 | vti6_addr_conflict(t, ipv6_hdr(skb))) |
---|
563 | 568 | goto tx_err; |
---|
564 | 569 | |
---|
565 | | - xfrm_decode_session(skb, &fl, AF_INET6); |
---|
566 | 570 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |
---|
| 571 | + xfrm_decode_session(skb, &fl, AF_INET6); |
---|
567 | 572 | break; |
---|
568 | 573 | case htons(ETH_P_IP): |
---|
569 | | - xfrm_decode_session(skb, &fl, AF_INET); |
---|
570 | 574 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); |
---|
| 575 | + xfrm_decode_session(skb, &fl, AF_INET); |
---|
571 | 576 | break; |
---|
572 | 577 | default: |
---|
573 | 578 | goto tx_err; |
---|
.. | .. |
---|
899 | 904 | static void vti6_dev_setup(struct net_device *dev) |
---|
900 | 905 | { |
---|
901 | 906 | dev->netdev_ops = &vti6_netdev_ops; |
---|
| 907 | + dev->header_ops = &ip_tunnel_header_ops; |
---|
902 | 908 | dev->needs_free_netdev = true; |
---|
903 | 909 | dev->priv_destructor = vti6_dev_free; |
---|
904 | 910 | |
---|
.. | .. |
---|
1190 | 1196 | |
---|
1191 | 1197 | static struct xfrm6_protocol vti_esp6_protocol __read_mostly = { |
---|
1192 | 1198 | .handler = vti6_rcv, |
---|
| 1199 | + .input_handler = vti6_input_proto, |
---|
1193 | 1200 | .cb_handler = vti6_rcv_cb, |
---|
1194 | 1201 | .err_handler = vti6_err, |
---|
1195 | 1202 | .priority = 100, |
---|
.. | .. |
---|
1197 | 1204 | |
---|
1198 | 1205 | static struct xfrm6_protocol vti_ah6_protocol __read_mostly = { |
---|
1199 | 1206 | .handler = vti6_rcv, |
---|
| 1207 | + .input_handler = vti6_input_proto, |
---|
1200 | 1208 | .cb_handler = vti6_rcv_cb, |
---|
1201 | 1209 | .err_handler = vti6_err, |
---|
1202 | 1210 | .priority = 100, |
---|
.. | .. |
---|
1204 | 1212 | |
---|
1205 | 1213 | static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = { |
---|
1206 | 1214 | .handler = vti6_rcv, |
---|
| 1215 | + .input_handler = vti6_input_proto, |
---|
1207 | 1216 | .cb_handler = vti6_rcv_cb, |
---|
1208 | 1217 | .err_handler = vti6_err, |
---|
1209 | 1218 | .priority = 100, |
---|
1210 | 1219 | }; |
---|
| 1220 | + |
---|
| 1221 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
---|
| 1222 | +static int vti6_rcv_tunnel(struct sk_buff *skb) |
---|
| 1223 | +{ |
---|
| 1224 | + const xfrm_address_t *saddr; |
---|
| 1225 | + __be32 spi; |
---|
| 1226 | + |
---|
| 1227 | + saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr; |
---|
| 1228 | + spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr); |
---|
| 1229 | + |
---|
| 1230 | + return vti6_input_proto(skb, IPPROTO_IPV6, spi, 0); |
---|
| 1231 | +} |
---|
| 1232 | + |
---|
| 1233 | +static struct xfrm6_tunnel vti_ipv6_handler __read_mostly = { |
---|
| 1234 | + .handler = vti6_rcv_tunnel, |
---|
| 1235 | + .cb_handler = vti6_rcv_cb, |
---|
| 1236 | + .err_handler = vti6_err, |
---|
| 1237 | + .priority = 0, |
---|
| 1238 | +}; |
---|
| 1239 | + |
---|
| 1240 | +static struct xfrm6_tunnel vti_ip6ip_handler __read_mostly = { |
---|
| 1241 | + .handler = vti6_rcv_tunnel, |
---|
| 1242 | + .cb_handler = vti6_rcv_cb, |
---|
| 1243 | + .err_handler = vti6_err, |
---|
| 1244 | + .priority = 0, |
---|
| 1245 | +}; |
---|
| 1246 | +#endif |
---|
1211 | 1247 | |
---|
1212 | 1248 | /** |
---|
1213 | 1249 | * vti6_tunnel_init - register protocol and reserve needed resources |
---|
.. | .. |
---|
1234 | 1270 | err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP); |
---|
1235 | 1271 | if (err < 0) |
---|
1236 | 1272 | goto xfrm_proto_comp_failed; |
---|
| 1273 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
---|
| 1274 | + msg = "ipv6 tunnel"; |
---|
| 1275 | + err = xfrm6_tunnel_register(&vti_ipv6_handler, AF_INET6); |
---|
| 1276 | + if (err < 0) |
---|
| 1277 | + goto vti_tunnel_ipv6_failed; |
---|
| 1278 | + err = xfrm6_tunnel_register(&vti_ip6ip_handler, AF_INET); |
---|
| 1279 | + if (err < 0) |
---|
| 1280 | + goto vti_tunnel_ip6ip_failed; |
---|
| 1281 | +#endif |
---|
1237 | 1282 | |
---|
1238 | 1283 | msg = "netlink interface"; |
---|
1239 | 1284 | err = rtnl_link_register(&vti6_link_ops); |
---|
.. | .. |
---|
1243 | 1288 | return 0; |
---|
1244 | 1289 | |
---|
1245 | 1290 | rtnl_link_failed: |
---|
| 1291 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
---|
| 1292 | + err = xfrm6_tunnel_deregister(&vti_ip6ip_handler, AF_INET); |
---|
| 1293 | +vti_tunnel_ip6ip_failed: |
---|
| 1294 | + err = xfrm6_tunnel_deregister(&vti_ipv6_handler, AF_INET6); |
---|
| 1295 | +vti_tunnel_ipv6_failed: |
---|
| 1296 | +#endif |
---|
1246 | 1297 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
---|
1247 | 1298 | xfrm_proto_comp_failed: |
---|
1248 | 1299 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
---|
.. | .. |
---|
1261 | 1312 | static void __exit vti6_tunnel_cleanup(void) |
---|
1262 | 1313 | { |
---|
1263 | 1314 | rtnl_link_unregister(&vti6_link_ops); |
---|
| 1315 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
---|
| 1316 | + xfrm6_tunnel_deregister(&vti_ip6ip_handler, AF_INET); |
---|
| 1317 | + xfrm6_tunnel_deregister(&vti_ipv6_handler, AF_INET6); |
---|
| 1318 | +#endif |
---|
1264 | 1319 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
---|
1265 | 1320 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
---|
1266 | 1321 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
---|