| .. | .. |
|---|
| 37 | 37 | #include <net/ip.h> |
|---|
| 38 | 38 | #include <net/ipv6.h> |
|---|
| 39 | 39 | #include <net/ip6_route.h> |
|---|
| 40 | +#include <net/ip_tunnels.h> |
|---|
| 40 | 41 | #include <net/addrconf.h> |
|---|
| 41 | 42 | #include <net/xfrm.h> |
|---|
| 42 | 43 | #include <net/net_namespace.h> |
|---|
| .. | .. |
|---|
| 47 | 48 | static void xfrmi_dev_setup(struct net_device *dev); |
|---|
| 48 | 49 | static struct rtnl_link_ops xfrmi_link_ops __read_mostly; |
|---|
| 49 | 50 | static unsigned int xfrmi_net_id __read_mostly; |
|---|
| 51 | +static const struct net_device_ops xfrmi_netdev_ops; |
|---|
| 52 | + |
|---|
| 53 | +#define XFRMI_HASH_BITS 8 |
|---|
| 54 | +#define XFRMI_HASH_SIZE BIT(XFRMI_HASH_BITS) |
|---|
| 50 | 55 | |
|---|
| 51 | 56 | struct xfrmi_net { |
|---|
| 52 | 57 | /* lists for storing interfaces in use */ |
|---|
| 53 | | - struct xfrm_if __rcu *xfrmi[1]; |
|---|
| 58 | + struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE]; |
|---|
| 54 | 59 | }; |
|---|
| 55 | 60 | |
|---|
| 56 | 61 | #define for_each_xfrmi_rcu(start, xi) \ |
|---|
| 57 | 62 | for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next)) |
|---|
| 63 | + |
|---|
| 64 | +static u32 xfrmi_hash(u32 if_id) |
|---|
| 65 | +{ |
|---|
| 66 | + return hash_32(if_id, XFRMI_HASH_BITS); |
|---|
| 67 | +} |
|---|
| 58 | 68 | |
|---|
| 59 | 69 | static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x) |
|---|
| 60 | 70 | { |
|---|
| 61 | 71 | struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); |
|---|
| 62 | 72 | struct xfrm_if *xi; |
|---|
| 63 | 73 | |
|---|
| 64 | | - for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) { |
|---|
| 74 | + for_each_xfrmi_rcu(xfrmn->xfrmi[xfrmi_hash(x->if_id)], xi) { |
|---|
| 65 | 75 | if (x->if_id == xi->p.if_id && |
|---|
| 66 | 76 | (xi->dev->flags & IFF_UP)) |
|---|
| 67 | 77 | return xi; |
|---|
| .. | .. |
|---|
| 73 | 83 | static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb, |
|---|
| 74 | 84 | unsigned short family) |
|---|
| 75 | 85 | { |
|---|
| 76 | | - struct xfrmi_net *xfrmn; |
|---|
| 77 | | - struct xfrm_if *xi; |
|---|
| 86 | + struct net_device *dev; |
|---|
| 78 | 87 | int ifindex = 0; |
|---|
| 79 | 88 | |
|---|
| 80 | 89 | if (!secpath_exists(skb) || !skb->dev) |
|---|
| .. | .. |
|---|
| 88 | 97 | ifindex = inet_sdif(skb); |
|---|
| 89 | 98 | break; |
|---|
| 90 | 99 | } |
|---|
| 91 | | - if (!ifindex) |
|---|
| 92 | | - ifindex = skb->dev->ifindex; |
|---|
| 93 | 100 | |
|---|
| 94 | | - xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id); |
|---|
| 101 | + if (ifindex) { |
|---|
| 102 | + struct net *net = xs_net(xfrm_input_state(skb)); |
|---|
| 95 | 103 | |
|---|
| 96 | | - for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) { |
|---|
| 97 | | - if (ifindex == xi->dev->ifindex && |
|---|
| 98 | | - (xi->dev->flags & IFF_UP)) |
|---|
| 99 | | - return xi; |
|---|
| 104 | + dev = dev_get_by_index_rcu(net, ifindex); |
|---|
| 105 | + } else { |
|---|
| 106 | + dev = skb->dev; |
|---|
| 100 | 107 | } |
|---|
| 101 | 108 | |
|---|
| 102 | | - return NULL; |
|---|
| 109 | + if (!dev || !(dev->flags & IFF_UP)) |
|---|
| 110 | + return NULL; |
|---|
| 111 | + if (dev->netdev_ops != &xfrmi_netdev_ops) |
|---|
| 112 | + return NULL; |
|---|
| 113 | + |
|---|
| 114 | + return netdev_priv(dev); |
|---|
| 103 | 115 | } |
|---|
| 104 | 116 | |
|---|
| 105 | 117 | static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi) |
|---|
| 106 | 118 | { |
|---|
| 107 | | - struct xfrm_if __rcu **xip = &xfrmn->xfrmi[0]; |
|---|
| 119 | + struct xfrm_if __rcu **xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)]; |
|---|
| 108 | 120 | |
|---|
| 109 | 121 | rcu_assign_pointer(xi->next , rtnl_dereference(*xip)); |
|---|
| 110 | 122 | rcu_assign_pointer(*xip, xi); |
|---|
| .. | .. |
|---|
| 115 | 127 | struct xfrm_if __rcu **xip; |
|---|
| 116 | 128 | struct xfrm_if *iter; |
|---|
| 117 | 129 | |
|---|
| 118 | | - for (xip = &xfrmn->xfrmi[0]; |
|---|
| 130 | + for (xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)]; |
|---|
| 119 | 131 | (iter = rtnl_dereference(*xip)) != NULL; |
|---|
| 120 | 132 | xip = &iter->next) { |
|---|
| 121 | 133 | if (xi == iter) { |
|---|
| .. | .. |
|---|
| 145 | 157 | if (err < 0) |
|---|
| 146 | 158 | goto out; |
|---|
| 147 | 159 | |
|---|
| 148 | | - dev_hold(dev); |
|---|
| 149 | 160 | xfrmi_link(xfrmn, xi); |
|---|
| 150 | 161 | |
|---|
| 151 | 162 | return 0; |
|---|
| .. | .. |
|---|
| 160 | 171 | struct xfrm_if *xi; |
|---|
| 161 | 172 | struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); |
|---|
| 162 | 173 | |
|---|
| 163 | | - for (xip = &xfrmn->xfrmi[0]; |
|---|
| 174 | + for (xip = &xfrmn->xfrmi[xfrmi_hash(p->if_id)]; |
|---|
| 164 | 175 | (xi = rtnl_dereference(*xip)) != NULL; |
|---|
| 165 | 176 | xip = &xi->next) |
|---|
| 166 | 177 | if (xi->p.if_id == p->if_id) |
|---|
| .. | .. |
|---|
| 175 | 186 | struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id); |
|---|
| 176 | 187 | |
|---|
| 177 | 188 | xfrmi_unlink(xfrmn, xi); |
|---|
| 178 | | - dev_put(dev); |
|---|
| 179 | 189 | } |
|---|
| 180 | 190 | |
|---|
| 181 | 191 | static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet) |
|---|
| .. | .. |
|---|
| 185 | 195 | skb->skb_iif = 0; |
|---|
| 186 | 196 | skb->ignore_df = 0; |
|---|
| 187 | 197 | skb_dst_drop(skb); |
|---|
| 188 | | - nf_reset(skb); |
|---|
| 198 | + nf_reset_ct(skb); |
|---|
| 189 | 199 | nf_reset_trace(skb); |
|---|
| 190 | 200 | |
|---|
| 191 | 201 | if (!xnet) |
|---|
| .. | .. |
|---|
| 199 | 209 | |
|---|
| 200 | 210 | static int xfrmi_rcv_cb(struct sk_buff *skb, int err) |
|---|
| 201 | 211 | { |
|---|
| 202 | | - struct pcpu_sw_netstats *tstats; |
|---|
| 203 | | - struct xfrm_mode *inner_mode; |
|---|
| 212 | + const struct xfrm_mode *inner_mode; |
|---|
| 204 | 213 | struct net_device *dev; |
|---|
| 205 | 214 | struct xfrm_state *x; |
|---|
| 206 | 215 | struct xfrm_if *xi; |
|---|
| 207 | 216 | bool xnet; |
|---|
| 208 | 217 | |
|---|
| 209 | | - if (err && !skb->sp) |
|---|
| 218 | + if (err && !secpath_exists(skb)) |
|---|
| 210 | 219 | return 0; |
|---|
| 211 | 220 | |
|---|
| 212 | 221 | x = xfrm_input_state(skb); |
|---|
| .. | .. |
|---|
| 228 | 237 | xnet = !net_eq(xi->net, dev_net(skb->dev)); |
|---|
| 229 | 238 | |
|---|
| 230 | 239 | if (xnet) { |
|---|
| 231 | | - inner_mode = x->inner_mode; |
|---|
| 240 | + inner_mode = &x->inner_mode; |
|---|
| 232 | 241 | |
|---|
| 233 | 242 | if (x->sel.family == AF_UNSPEC) { |
|---|
| 234 | 243 | inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); |
|---|
| .. | .. |
|---|
| 240 | 249 | } |
|---|
| 241 | 250 | |
|---|
| 242 | 251 | if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, |
|---|
| 243 | | - inner_mode->afinfo->family)) |
|---|
| 252 | + inner_mode->family)) |
|---|
| 244 | 253 | return -EPERM; |
|---|
| 245 | 254 | } |
|---|
| 246 | 255 | |
|---|
| 247 | 256 | xfrmi_scrub_packet(skb, xnet); |
|---|
| 248 | | - |
|---|
| 249 | | - tstats = this_cpu_ptr(dev->tstats); |
|---|
| 250 | | - |
|---|
| 251 | | - u64_stats_update_begin(&tstats->syncp); |
|---|
| 252 | | - tstats->rx_packets++; |
|---|
| 253 | | - tstats->rx_bytes += skb->len; |
|---|
| 254 | | - u64_stats_update_end(&tstats->syncp); |
|---|
| 257 | + dev_sw_netstats_rx_add(dev, skb->len); |
|---|
| 255 | 258 | |
|---|
| 256 | 259 | return 0; |
|---|
| 257 | 260 | } |
|---|
| .. | .. |
|---|
| 300 | 303 | if (mtu < IPV6_MIN_MTU) |
|---|
| 301 | 304 | mtu = IPV6_MIN_MTU; |
|---|
| 302 | 305 | |
|---|
| 303 | | - icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
|---|
| 306 | + if (skb->len > 1280) |
|---|
| 307 | + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
|---|
| 308 | + else |
|---|
| 309 | + goto xmit; |
|---|
| 304 | 310 | } else { |
|---|
| 305 | 311 | if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) |
|---|
| 306 | 312 | goto xmit; |
|---|
| .. | .. |
|---|
| 451 | 457 | } |
|---|
| 452 | 458 | |
|---|
| 453 | 459 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
|---|
| 454 | | - ipv4_update_pmtu(skb, net, info, 0, 0, protocol, 0); |
|---|
| 460 | + ipv4_update_pmtu(skb, net, info, 0, protocol); |
|---|
| 455 | 461 | else |
|---|
| 456 | | - ipv4_redirect(skb, net, 0, 0, protocol, 0); |
|---|
| 462 | + ipv4_redirect(skb, net, 0, protocol); |
|---|
| 457 | 463 | xfrm_state_put(x); |
|---|
| 458 | 464 | |
|---|
| 459 | 465 | return 0; |
|---|
| .. | .. |
|---|
| 541 | 547 | static void xfrmi_get_stats64(struct net_device *dev, |
|---|
| 542 | 548 | struct rtnl_link_stats64 *s) |
|---|
| 543 | 549 | { |
|---|
| 544 | | - int cpu; |
|---|
| 545 | | - |
|---|
| 546 | | - if (!dev->tstats) |
|---|
| 547 | | - return; |
|---|
| 548 | | - |
|---|
| 549 | | - for_each_possible_cpu(cpu) { |
|---|
| 550 | | - struct pcpu_sw_netstats *stats; |
|---|
| 551 | | - struct pcpu_sw_netstats tmp; |
|---|
| 552 | | - int start; |
|---|
| 553 | | - |
|---|
| 554 | | - stats = per_cpu_ptr(dev->tstats, cpu); |
|---|
| 555 | | - do { |
|---|
| 556 | | - start = u64_stats_fetch_begin_irq(&stats->syncp); |
|---|
| 557 | | - tmp.rx_packets = stats->rx_packets; |
|---|
| 558 | | - tmp.rx_bytes = stats->rx_bytes; |
|---|
| 559 | | - tmp.tx_packets = stats->tx_packets; |
|---|
| 560 | | - tmp.tx_bytes = stats->tx_bytes; |
|---|
| 561 | | - } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); |
|---|
| 562 | | - |
|---|
| 563 | | - s->rx_packets += tmp.rx_packets; |
|---|
| 564 | | - s->rx_bytes += tmp.rx_bytes; |
|---|
| 565 | | - s->tx_packets += tmp.tx_packets; |
|---|
| 566 | | - s->tx_bytes += tmp.tx_bytes; |
|---|
| 567 | | - } |
|---|
| 550 | + dev_fetch_sw_netstats(s, dev->tstats); |
|---|
| 568 | 551 | |
|---|
| 569 | 552 | s->rx_dropped = dev->stats.rx_dropped; |
|---|
| 570 | 553 | s->tx_dropped = dev->stats.tx_dropped; |
|---|
| .. | .. |
|---|
| 589 | 572 | static void xfrmi_dev_setup(struct net_device *dev) |
|---|
| 590 | 573 | { |
|---|
| 591 | 574 | dev->netdev_ops = &xfrmi_netdev_ops; |
|---|
| 575 | + dev->header_ops = &ip_tunnel_header_ops; |
|---|
| 592 | 576 | dev->type = ARPHRD_NONE; |
|---|
| 593 | 577 | dev->mtu = ETH_DATA_LEN; |
|---|
| 594 | 578 | dev->min_mtu = ETH_MIN_MTU; |
|---|
| .. | .. |
|---|
| 698 | 682 | struct net *net = xi->net; |
|---|
| 699 | 683 | struct xfrm_if_parms p = {}; |
|---|
| 700 | 684 | |
|---|
| 685 | + xfrmi_netlink_parms(data, &p); |
|---|
| 701 | 686 | if (!p.if_id) { |
|---|
| 702 | 687 | NL_SET_ERR_MSG(extack, "if_id must be non zero"); |
|---|
| 703 | 688 | return -EINVAL; |
|---|
| 704 | 689 | } |
|---|
| 705 | 690 | |
|---|
| 706 | | - xfrmi_netlink_parms(data, &p); |
|---|
| 707 | 691 | xi = xfrmi_locate(net, &p); |
|---|
| 708 | 692 | if (!xi) { |
|---|
| 709 | 693 | xi = netdev_priv(dev); |
|---|
| .. | .. |
|---|
| 739 | 723 | return -EMSGSIZE; |
|---|
| 740 | 724 | } |
|---|
| 741 | 725 | |
|---|
| 742 | | -struct net *xfrmi_get_link_net(const struct net_device *dev) |
|---|
| 726 | +static struct net *xfrmi_get_link_net(const struct net_device *dev) |
|---|
| 743 | 727 | { |
|---|
| 744 | 728 | struct xfrm_if *xi = netdev_priv(dev); |
|---|
| 745 | 729 | |
|---|
| .. | .. |
|---|
| 766 | 750 | .get_link_net = xfrmi_get_link_net, |
|---|
| 767 | 751 | }; |
|---|
| 768 | 752 | |
|---|
| 769 | | -static void __net_exit xfrmi_destroy_interfaces(struct xfrmi_net *xfrmn) |
|---|
| 770 | | -{ |
|---|
| 771 | | - struct xfrm_if *xi; |
|---|
| 772 | | - LIST_HEAD(list); |
|---|
| 773 | | - |
|---|
| 774 | | - xi = rtnl_dereference(xfrmn->xfrmi[0]); |
|---|
| 775 | | - if (!xi) |
|---|
| 776 | | - return; |
|---|
| 777 | | - |
|---|
| 778 | | - unregister_netdevice_queue(xi->dev, &list); |
|---|
| 779 | | - unregister_netdevice_many(&list); |
|---|
| 780 | | -} |
|---|
| 781 | | - |
|---|
| 782 | | -static int __net_init xfrmi_init_net(struct net *net) |
|---|
| 783 | | -{ |
|---|
| 784 | | - return 0; |
|---|
| 785 | | -} |
|---|
| 786 | | - |
|---|
| 787 | | -static void __net_exit xfrmi_exit_net(struct net *net) |
|---|
| 788 | | -{ |
|---|
| 789 | | - struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); |
|---|
| 790 | | - |
|---|
| 791 | | - rtnl_lock(); |
|---|
| 792 | | - xfrmi_destroy_interfaces(xfrmn); |
|---|
| 793 | | - rtnl_unlock(); |
|---|
| 794 | | -} |
|---|
| 795 | | - |
|---|
| 796 | 753 | static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list) |
|---|
| 797 | 754 | { |
|---|
| 798 | 755 | struct net *net; |
|---|
| .. | .. |
|---|
| 803 | 760 | struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); |
|---|
| 804 | 761 | struct xfrm_if __rcu **xip; |
|---|
| 805 | 762 | struct xfrm_if *xi; |
|---|
| 763 | + int i; |
|---|
| 806 | 764 | |
|---|
| 807 | | - for (xip = &xfrmn->xfrmi[0]; |
|---|
| 808 | | - (xi = rtnl_dereference(*xip)) != NULL; |
|---|
| 809 | | - xip = &xi->next) |
|---|
| 810 | | - unregister_netdevice_queue(xi->dev, &list); |
|---|
| 765 | + for (i = 0; i < XFRMI_HASH_SIZE; i++) { |
|---|
| 766 | + for (xip = &xfrmn->xfrmi[i]; |
|---|
| 767 | + (xi = rtnl_dereference(*xip)) != NULL; |
|---|
| 768 | + xip = &xi->next) |
|---|
| 769 | + unregister_netdevice_queue(xi->dev, &list); |
|---|
| 770 | + } |
|---|
| 811 | 771 | } |
|---|
| 812 | 772 | unregister_netdevice_many(&list); |
|---|
| 813 | 773 | rtnl_unlock(); |
|---|
| .. | .. |
|---|
| 815 | 775 | |
|---|
| 816 | 776 | static struct pernet_operations xfrmi_net_ops = { |
|---|
| 817 | 777 | .exit_batch = xfrmi_exit_batch_net, |
|---|
| 818 | | - .init = xfrmi_init_net, |
|---|
| 819 | | - .exit = xfrmi_exit_net, |
|---|
| 820 | 778 | .id = &xfrmi_net_id, |
|---|
| 821 | 779 | .size = sizeof(struct xfrmi_net), |
|---|
| 822 | 780 | }; |
|---|
| 823 | 781 | |
|---|
| 824 | 782 | static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = { |
|---|
| 825 | 783 | .handler = xfrm6_rcv, |
|---|
| 784 | + .input_handler = xfrm_input, |
|---|
| 826 | 785 | .cb_handler = xfrmi_rcv_cb, |
|---|
| 827 | 786 | .err_handler = xfrmi6_err, |
|---|
| 828 | 787 | .priority = 10, |
|---|
| .. | .. |
|---|
| 830 | 789 | |
|---|
| 831 | 790 | static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = { |
|---|
| 832 | 791 | .handler = xfrm6_rcv, |
|---|
| 792 | + .input_handler = xfrm_input, |
|---|
| 833 | 793 | .cb_handler = xfrmi_rcv_cb, |
|---|
| 834 | 794 | .err_handler = xfrmi6_err, |
|---|
| 835 | 795 | .priority = 10, |
|---|
| .. | .. |
|---|
| 837 | 797 | |
|---|
| 838 | 798 | static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = { |
|---|
| 839 | 799 | .handler = xfrm6_rcv, |
|---|
| 800 | + .input_handler = xfrm_input, |
|---|
| 840 | 801 | .cb_handler = xfrmi_rcv_cb, |
|---|
| 841 | 802 | .err_handler = xfrmi6_err, |
|---|
| 842 | 803 | .priority = 10, |
|---|
| 843 | 804 | }; |
|---|
| 805 | + |
|---|
| 806 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
|---|
| 807 | +static int xfrmi6_rcv_tunnel(struct sk_buff *skb) |
|---|
| 808 | +{ |
|---|
| 809 | + const xfrm_address_t *saddr; |
|---|
| 810 | + __be32 spi; |
|---|
| 811 | + |
|---|
| 812 | + saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr; |
|---|
| 813 | + spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr); |
|---|
| 814 | + |
|---|
| 815 | + return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL); |
|---|
| 816 | +} |
|---|
| 817 | + |
|---|
| 818 | +static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = { |
|---|
| 819 | + .handler = xfrmi6_rcv_tunnel, |
|---|
| 820 | + .cb_handler = xfrmi_rcv_cb, |
|---|
| 821 | + .err_handler = xfrmi6_err, |
|---|
| 822 | + .priority = 2, |
|---|
| 823 | +}; |
|---|
| 824 | + |
|---|
| 825 | +static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = { |
|---|
| 826 | + .handler = xfrmi6_rcv_tunnel, |
|---|
| 827 | + .cb_handler = xfrmi_rcv_cb, |
|---|
| 828 | + .err_handler = xfrmi6_err, |
|---|
| 829 | + .priority = 2, |
|---|
| 830 | +}; |
|---|
| 831 | +#endif |
|---|
| 844 | 832 | |
|---|
| 845 | 833 | static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = { |
|---|
| 846 | 834 | .handler = xfrm4_rcv, |
|---|
| .. | .. |
|---|
| 866 | 854 | .priority = 10, |
|---|
| 867 | 855 | }; |
|---|
| 868 | 856 | |
|---|
| 857 | +#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL) |
|---|
| 858 | +static int xfrmi4_rcv_tunnel(struct sk_buff *skb) |
|---|
| 859 | +{ |
|---|
| 860 | + return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr); |
|---|
| 861 | +} |
|---|
| 862 | + |
|---|
| 863 | +static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = { |
|---|
| 864 | + .handler = xfrmi4_rcv_tunnel, |
|---|
| 865 | + .cb_handler = xfrmi_rcv_cb, |
|---|
| 866 | + .err_handler = xfrmi4_err, |
|---|
| 867 | + .priority = 3, |
|---|
| 868 | +}; |
|---|
| 869 | + |
|---|
| 870 | +static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = { |
|---|
| 871 | + .handler = xfrmi4_rcv_tunnel, |
|---|
| 872 | + .cb_handler = xfrmi_rcv_cb, |
|---|
| 873 | + .err_handler = xfrmi4_err, |
|---|
| 874 | + .priority = 2, |
|---|
| 875 | +}; |
|---|
| 876 | +#endif |
|---|
| 877 | + |
|---|
| 869 | 878 | static int __init xfrmi4_init(void) |
|---|
| 870 | 879 | { |
|---|
| 871 | 880 | int err; |
|---|
| .. | .. |
|---|
| 879 | 888 | err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP); |
|---|
| 880 | 889 | if (err < 0) |
|---|
| 881 | 890 | goto xfrm_proto_comp_failed; |
|---|
| 891 | +#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL) |
|---|
| 892 | + err = xfrm4_tunnel_register(&xfrmi_ipip_handler, AF_INET); |
|---|
| 893 | + if (err < 0) |
|---|
| 894 | + goto xfrm_tunnel_ipip_failed; |
|---|
| 895 | + err = xfrm4_tunnel_register(&xfrmi_ipip6_handler, AF_INET6); |
|---|
| 896 | + if (err < 0) |
|---|
| 897 | + goto xfrm_tunnel_ipip6_failed; |
|---|
| 898 | +#endif |
|---|
| 882 | 899 | |
|---|
| 883 | 900 | return 0; |
|---|
| 884 | 901 | |
|---|
| 902 | +#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL) |
|---|
| 903 | +xfrm_tunnel_ipip6_failed: |
|---|
| 904 | + xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET); |
|---|
| 905 | +xfrm_tunnel_ipip_failed: |
|---|
| 906 | + xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP); |
|---|
| 907 | +#endif |
|---|
| 885 | 908 | xfrm_proto_comp_failed: |
|---|
| 886 | 909 | xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH); |
|---|
| 887 | 910 | xfrm_proto_ah_failed: |
|---|
| .. | .. |
|---|
| 892 | 915 | |
|---|
| 893 | 916 | static void xfrmi4_fini(void) |
|---|
| 894 | 917 | { |
|---|
| 918 | +#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL) |
|---|
| 919 | + xfrm4_tunnel_deregister(&xfrmi_ipip6_handler, AF_INET6); |
|---|
| 920 | + xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET); |
|---|
| 921 | +#endif |
|---|
| 895 | 922 | xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP); |
|---|
| 896 | 923 | xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH); |
|---|
| 897 | 924 | xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP); |
|---|
| .. | .. |
|---|
| 910 | 937 | err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP); |
|---|
| 911 | 938 | if (err < 0) |
|---|
| 912 | 939 | goto xfrm_proto_comp_failed; |
|---|
| 940 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
|---|
| 941 | + err = xfrm6_tunnel_register(&xfrmi_ipv6_handler, AF_INET6); |
|---|
| 942 | + if (err < 0) |
|---|
| 943 | + goto xfrm_tunnel_ipv6_failed; |
|---|
| 944 | + err = xfrm6_tunnel_register(&xfrmi_ip6ip_handler, AF_INET); |
|---|
| 945 | + if (err < 0) |
|---|
| 946 | + goto xfrm_tunnel_ip6ip_failed; |
|---|
| 947 | +#endif |
|---|
| 913 | 948 | |
|---|
| 914 | 949 | return 0; |
|---|
| 915 | 950 | |
|---|
| 951 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
|---|
| 952 | +xfrm_tunnel_ip6ip_failed: |
|---|
| 953 | + xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6); |
|---|
| 954 | +xfrm_tunnel_ipv6_failed: |
|---|
| 955 | + xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP); |
|---|
| 956 | +#endif |
|---|
| 916 | 957 | xfrm_proto_comp_failed: |
|---|
| 917 | 958 | xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH); |
|---|
| 918 | 959 | xfrm_proto_ah_failed: |
|---|
| .. | .. |
|---|
| 923 | 964 | |
|---|
| 924 | 965 | static void xfrmi6_fini(void) |
|---|
| 925 | 966 | { |
|---|
| 967 | +#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL) |
|---|
| 968 | + xfrm6_tunnel_deregister(&xfrmi_ip6ip_handler, AF_INET); |
|---|
| 969 | + xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6); |
|---|
| 970 | +#endif |
|---|
| 926 | 971 | xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP); |
|---|
| 927 | 972 | xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH); |
|---|
| 928 | 973 | xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP); |
|---|