]> Git Repo - linux.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
authorDavid S. Miller <[email protected]>
Thu, 30 Jul 2020 21:39:31 +0000 (14:39 -0700)
committerDavid S. Miller <[email protected]>
Thu, 30 Jul 2020 21:39:31 +0000 (14:39 -0700)
Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2020-07-30

Please note that I did the first time now --no-ff merges
of my testing branch into the master branch to include
the [PATCH 0/n] message of a patchset. Please let me
know if this is desirable, or if I should do it any
different.

1) Introduce a oseq-may-wrap flag to disable anti-replay
   protection for manually distributed ICVs as suggested
   in RFC 4303. From Petr VanÄ›k.

2) Patchset to fully support IPCOMP for vti4, vti6 and
   xfrm interfaces. From Xin Long.

3) Switch from a linear list to a hash list for xfrm interface
   lookups. From Eyal Birger.

4) Fixes to not register one xfrm(6)_tunnel object twice.
   From Xin Long.

5) Fix two compile errors that were introduced with the
   IPCOMP support for vti and xfrm interfaces.
   Also from Xin Long.

6) Make the policy hold queue work with VTI. This was
   forgotten when VTI was implemented.

Please pull or let me know if there are problems.
====================

Signed-off-by: David S. Miller <[email protected]>
1  2 
include/net/xfrm.h
net/ipv4/ip_vti.c
net/ipv6/ip6_vti.c
net/xfrm/xfrm_interface.c

diff --combined include/net/xfrm.h
index 5e81868b574a73442d9a974946b2c86d946fb66f,83a532dda1bd23c905998628a48bf221b57ad98a..5c09ba299cde1b86ba24e30f5d093c5bb20f8d72
@@@ -15,7 -15,6 +15,7 @@@
  #include <linux/audit.h>
  #include <linux/slab.h>
  #include <linux/refcount.h>
 +#include <linux/sockptr.h>
  
  #include <net/sock.h>
  #include <net/dst.h>
@@@ -128,7 -127,7 +128,7 @@@ struct xfrm_state_walk 
  
  struct xfrm_state_offload {
        struct net_device       *dev;
 -      struct net_device       *slave_dev;
 +      struct net_device       *real_dev;
        unsigned long           offload_handle;
        unsigned int            num_exthdrs;
        u8                      flags;
@@@ -374,7 -373,8 +374,8 @@@ struct xfrm_state_afinfo *xfrm_state_ge
  struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family);
  
  struct xfrm_input_afinfo {
-       unsigned int            family;
+       u8                      family;
+       bool                    is_ipip;
        int                     (*callback)(struct sk_buff *skb, u8 protocol,
                                            int err);
  };
@@@ -1010,7 -1010,6 +1011,7 @@@ struct xfrm_offload 
  #define       XFRM_GRO                32
  #define       XFRM_ESP_NO_TRAILER     64
  #define       XFRM_DEV_RESUME         128
 +#define       XFRM_XMIT               256
  
        __u32                   status;
  #define CRYPTO_SUCCESS                                1
@@@ -1417,6 -1416,7 +1418,7 @@@ struct xfrm6_protocol 
  /* XFRM tunnel handlers.  */
  struct xfrm_tunnel {
        int (*handler)(struct sk_buff *skb);
+       int (*cb_handler)(struct sk_buff *skb, int err);
        int (*err_handler)(struct sk_buff *skb, u32 info);
  
        struct xfrm_tunnel __rcu *next;
  
  struct xfrm6_tunnel {
        int (*handler)(struct sk_buff *skb);
+       int (*cb_handler)(struct sk_buff *skb, int err);
        int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
                           u8 type, u8 code, int offset, __be32 info);
        struct xfrm6_tunnel __rcu *next;
@@@ -1610,11 -1611,10 +1613,11 @@@ int xfrm6_find_1stfragopt(struct xfrm_s
  void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu);
  int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
  int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
 -int xfrm_user_policy(struct sock *sk, int optname,
 -                   u8 __user *optval, int optlen);
 +int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval,
 +                   int optlen);
  #else
 -static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
 +static inline int xfrm_user_policy(struct sock *sk, int optname,
 +                                 sockptr_t optval, int optlen)
  {
        return -ENOPROTOOPT;
  }
diff --combined net/ipv4/ip_vti.c
index 460ca1099e8acf82b639d4ec02393a93ec7ccd71,8b962eac9ed89e0eff5238c2b0db992ea20109e4..49daaed897649c1429abd83785ce3d9ebe70e4f7
@@@ -91,32 -91,6 +91,6 @@@ static int vti_rcv_proto(struct sk_buf
        return vti_rcv(skb, 0, false);
  }
  
- static int vti_rcv_tunnel(struct sk_buff *skb)
- {
-       struct ip_tunnel_net *itn = net_generic(dev_net(skb->dev), vti_net_id);
-       const struct iphdr *iph = ip_hdr(skb);
-       struct ip_tunnel *tunnel;
-       tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
-                                 iph->saddr, iph->daddr, 0);
-       if (tunnel) {
-               struct tnl_ptk_info tpi = {
-                       .proto = htons(ETH_P_IP),
-               };
-               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
-                       goto drop;
-               if (iptunnel_pull_header(skb, 0, tpi.proto, false))
-                       goto drop;
-               return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, false);
-       }
-       return -EINVAL;
- drop:
-       kfree_skb(skb);
-       return 0;
- }
  static int vti_rcv_cb(struct sk_buff *skb, int err)
  {
        unsigned short family;
@@@ -244,12 -218,15 +218,15 @@@ static netdev_tx_t vti_xmit(struct sk_b
        }
  
        dst_hold(dst);
-       dst = xfrm_lookup(tunnel->net, dst, fl, NULL, 0);
+       dst = xfrm_lookup_route(tunnel->net, dst, fl, NULL, 0);
        if (IS_ERR(dst)) {
                dev->stats.tx_carrier_errors++;
                goto tx_error_icmp;
        }
  
+       if (dst->flags & DST_XFRM_QUEUE)
+               goto queued;
        if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) {
                dev->stats.tx_carrier_errors++;
                dst_release(dst);
                goto tx_error;
        }
  
+ queued:
        skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
        skb_dst_set(skb, dst);
        skb->dev = skb_dst(skb)->dev;
@@@ -441,7 -419,6 +419,7 @@@ static const struct net_device_ops vti_
  static void vti_tunnel_setup(struct net_device *dev)
  {
        dev->netdev_ops         = &vti_netdev_ops;
 +      dev->header_ops         = &ip_tunnel_header_ops;
        dev->type               = ARPHRD_TUNNEL;
        ip_tunnel_setup(dev, vti_net_id);
  }
@@@ -496,11 -473,29 +474,29 @@@ static struct xfrm4_protocol vti_ipcomp
        .priority       =       100,
  };
  
- static struct xfrm_tunnel ipip_handler __read_mostly = {
+ #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
+ static int vti_rcv_tunnel(struct sk_buff *skb)
+ {
+       XFRM_SPI_SKB_CB(skb)->family = AF_INET;
+       XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+       return vti_input(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr, 0, false);
+ }
+ static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
+       .handler        =       vti_rcv_tunnel,
+       .cb_handler     =       vti_rcv_cb,
+       .err_handler    =       vti4_err,
+       .priority       =       0,
+ };
+ static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
        .handler        =       vti_rcv_tunnel,
+       .cb_handler     =       vti_rcv_cb,
        .err_handler    =       vti4_err,
        .priority       =       0,
  };
+ #endif
  
  static int __net_init vti_init_net(struct net *net)
  {
@@@ -670,10 -665,17 +666,17 @@@ static int __init vti_init(void
        if (err < 0)
                goto xfrm_proto_comp_failed;
  
+ #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
        msg = "ipip tunnel";
-       err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
+       err = xfrm4_tunnel_register(&vti_ipip_handler, AF_INET);
+       if (err < 0)
+               goto xfrm_tunnel_ipip_failed;
+ #if IS_ENABLED(CONFIG_IPV6)
+       err = xfrm4_tunnel_register(&vti_ipip6_handler, AF_INET6);
        if (err < 0)
-               goto xfrm_tunnel_failed;
+               goto xfrm_tunnel_ipip6_failed;
+ #endif
+ #endif
  
        msg = "netlink interface";
        err = rtnl_link_register(&vti_link_ops);
        return err;
  
  rtnl_link_failed:
-       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
- xfrm_tunnel_failed:
+ #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
+ #if IS_ENABLED(CONFIG_IPV6)
+       xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
+ xfrm_tunnel_ipip6_failed:
+ #endif
+       xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
+ xfrm_tunnel_ipip_failed:
+ #endif
        xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
  xfrm_proto_comp_failed:
        xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
@@@ -700,7 -708,12 +709,12 @@@ pernet_dev_failed
  static void __exit vti_fini(void)
  {
        rtnl_link_unregister(&vti_link_ops);
-       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+ #if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
+ #if IS_ENABLED(CONFIG_IPV6)
+       xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
+ #endif
+       xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
+ #endif
        xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
        xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
        xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
diff --combined net/ipv6/ip6_vti.c
index 0d964160a9dd559b6c2624ae129aaf899c9292ea,f5a4c4a6492bbd2751aaa289a0d3ba52fd6d6d73..fac01b80a1040d9e4aebec4aecf1d1c629ebfb1c
@@@ -491,13 -491,16 +491,16 @@@ vti6_xmit(struct sk_buff *skb, struct n
        }
  
        dst_hold(dst);
-       dst = xfrm_lookup(t->net, dst, fl, NULL, 0);
+       dst = xfrm_lookup_route(t->net, dst, fl, NULL, 0);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                dst = NULL;
                goto tx_err_link_failure;
        }
  
+       if (dst->flags & DST_XFRM_QUEUE)
+               goto queued;
        x = dst->xfrm;
        if (!vti6_state_check(x, &t->parms.raddr, &t->parms.laddr))
                goto tx_err_link_failure;
                goto tx_err_dst_release;
        }
  
+ queued:
        skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
        skb_dst_set(skb, dst);
        skb->dev = skb_dst(skb)->dev;
@@@ -905,7 -909,6 +909,7 @@@ static const struct net_device_ops vti6
  static void vti6_dev_setup(struct net_device *dev)
  {
        dev->netdev_ops = &vti6_netdev_ops;
 +      dev->header_ops = &ip_tunnel_header_ops;
        dev->needs_free_netdev = true;
        dev->priv_destructor = vti6_dev_free;
  
@@@ -1219,6 -1222,33 +1223,33 @@@ static struct xfrm6_protocol vti_ipcomp
        .priority       =       100,
  };
  
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ static int vti6_rcv_tunnel(struct sk_buff *skb)
+ {
+       const xfrm_address_t *saddr;
+       __be32 spi;
+       saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr;
+       spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr);
+       return vti6_input_proto(skb, IPPROTO_IPV6, spi, 0);
+ }
+ static struct xfrm6_tunnel vti_ipv6_handler __read_mostly = {
+       .handler        =       vti6_rcv_tunnel,
+       .cb_handler     =       vti6_rcv_cb,
+       .err_handler    =       vti6_err,
+       .priority       =       0,
+ };
+ static struct xfrm6_tunnel vti_ip6ip_handler __read_mostly = {
+       .handler        =       vti6_rcv_tunnel,
+       .cb_handler     =       vti6_rcv_cb,
+       .err_handler    =       vti6_err,
+       .priority       =       0,
+ };
+ #endif
  /**
   * vti6_tunnel_init - register protocol and reserve needed resources
   *
@@@ -1244,6 -1274,15 +1275,15 @@@ static int __init vti6_tunnel_init(void
        err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP);
        if (err < 0)
                goto xfrm_proto_comp_failed;
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+       msg = "ipv6 tunnel";
+       err = xfrm6_tunnel_register(&vti_ipv6_handler, AF_INET6);
+       if (err < 0)
+               goto vti_tunnel_ipv6_failed;
+       err = xfrm6_tunnel_register(&vti_ip6ip_handler, AF_INET);
+       if (err < 0)
+               goto vti_tunnel_ip6ip_failed;
+ #endif
  
        msg = "netlink interface";
        err = rtnl_link_register(&vti6_link_ops);
        return 0;
  
  rtnl_link_failed:
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+       err = xfrm6_tunnel_deregister(&vti_ip6ip_handler, AF_INET);
+ vti_tunnel_ip6ip_failed:
+       err = xfrm6_tunnel_deregister(&vti_ipv6_handler, AF_INET6);
+ vti_tunnel_ipv6_failed:
+ #endif
        xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP);
  xfrm_proto_comp_failed:
        xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
@@@ -1271,6 -1316,10 +1317,10 @@@ pernet_dev_failed
  static void __exit vti6_tunnel_cleanup(void)
  {
        rtnl_link_unregister(&vti6_link_ops);
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+       xfrm6_tunnel_deregister(&vti_ip6ip_handler, AF_INET);
+       xfrm6_tunnel_deregister(&vti_ipv6_handler, AF_INET6);
+ #endif
        xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP);
        xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
        xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
index b615729812e5acd1c1be39f402db5a9a6061e25d,4c904d33200704281c658307d24daa5f83981345..eb8181987620db73ab35d1fa512d0d24caa58fea
@@@ -37,7 -37,6 +37,7 @@@
  #include <net/ip.h>
  #include <net/ipv6.h>
  #include <net/ip6_route.h>
 +#include <net/ip_tunnels.h>
  #include <net/addrconf.h>
  #include <net/xfrm.h>
  #include <net/net_namespace.h>
@@@ -48,21 -47,30 +48,30 @@@ static int xfrmi_dev_init(struct net_de
  static void xfrmi_dev_setup(struct net_device *dev);
  static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
  static unsigned int xfrmi_net_id __read_mostly;
+ static const struct net_device_ops xfrmi_netdev_ops;
+ #define XFRMI_HASH_BITS       8
+ #define XFRMI_HASH_SIZE       BIT(XFRMI_HASH_BITS)
  
  struct xfrmi_net {
        /* lists for storing interfaces in use */
-       struct xfrm_if __rcu *xfrmi[1];
+       struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE];
  };
  
  #define for_each_xfrmi_rcu(start, xi) \
        for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
  
+ static u32 xfrmi_hash(u32 if_id)
+ {
+       return hash_32(if_id, XFRMI_HASH_BITS);
+ }
  static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
  {
        struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
        struct xfrm_if *xi;
  
-       for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
+       for_each_xfrmi_rcu(xfrmn->xfrmi[xfrmi_hash(x->if_id)], xi) {
                if (x->if_id == xi->p.if_id &&
                    (xi->dev->flags & IFF_UP))
                        return xi;
@@@ -74,8 -82,7 +83,7 @@@
  static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
                                            unsigned short family)
  {
-       struct xfrmi_net *xfrmn;
-       struct xfrm_if *xi;
+       struct net_device *dev;
        int ifindex = 0;
  
        if (!secpath_exists(skb) || !skb->dev)
                ifindex = inet_sdif(skb);
                break;
        }
-       if (!ifindex)
-               ifindex = skb->dev->ifindex;
  
-       xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id);
+       if (ifindex) {
+               struct net *net = xs_net(xfrm_input_state(skb));
  
-       for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
-               if (ifindex == xi->dev->ifindex &&
-                       (xi->dev->flags & IFF_UP))
-                               return xi;
+               dev = dev_get_by_index_rcu(net, ifindex);
+       } else {
+               dev = skb->dev;
        }
  
-       return NULL;
+       if (!dev || !(dev->flags & IFF_UP))
+               return NULL;
+       if (dev->netdev_ops != &xfrmi_netdev_ops)
+               return NULL;
+       return netdev_priv(dev);
  }
  
  static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
  {
-       struct xfrm_if __rcu **xip = &xfrmn->xfrmi[0];
+       struct xfrm_if __rcu **xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
  
        rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
        rcu_assign_pointer(*xip, xi);
@@@ -116,7 -126,7 +127,7 @@@ static void xfrmi_unlink(struct xfrmi_n
        struct xfrm_if __rcu **xip;
        struct xfrm_if *iter;
  
-       for (xip = &xfrmn->xfrmi[0];
+       for (xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
             (iter = rtnl_dereference(*xip)) != NULL;
             xip = &iter->next) {
                if (xi == iter) {
@@@ -160,7 -170,7 +171,7 @@@ static struct xfrm_if *xfrmi_locate(str
        struct xfrm_if *xi;
        struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
  
-       for (xip = &xfrmn->xfrmi[0];
+       for (xip = &xfrmn->xfrmi[xfrmi_hash(p->if_id)];
             (xi = rtnl_dereference(*xip)) != NULL;
             xip = &xi->next)
                if (xi->p.if_id == p->if_id)
@@@ -582,7 -592,6 +593,7 @@@ static const struct net_device_ops xfrm
  static void xfrmi_dev_setup(struct net_device *dev)
  {
        dev->netdev_ops         = &xfrmi_netdev_ops;
 +      dev->header_ops         = &ip_tunnel_header_ops;
        dev->type               = ARPHRD_NONE;
        dev->mtu                = ETH_DATA_LEN;
        dev->min_mtu            = ETH_MIN_MTU;
@@@ -760,11 -769,14 +771,14 @@@ static void __net_exit xfrmi_exit_batch
                struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
                struct xfrm_if __rcu **xip;
                struct xfrm_if *xi;
+               int i;
  
-               for (xip = &xfrmn->xfrmi[0];
-                    (xi = rtnl_dereference(*xip)) != NULL;
-                    xip = &xi->next)
-                       unregister_netdevice_queue(xi->dev, &list);
+               for (i = 0; i < XFRMI_HASH_SIZE; i++) {
+                       for (xip = &xfrmn->xfrmi[i];
+                            (xi = rtnl_dereference(*xip)) != NULL;
+                            xip = &xi->next)
+                               unregister_netdevice_queue(xi->dev, &list);
+               }
        }
        unregister_netdevice_many(&list);
        rtnl_unlock();
@@@ -800,6 -812,33 +814,33 @@@ static struct xfrm6_protocol xfrmi_ipco
        .priority       =       10,
  };
  
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ static int xfrmi6_rcv_tunnel(struct sk_buff *skb)
+ {
+       const xfrm_address_t *saddr;
+       __be32 spi;
+       saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr;
+       spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr);
+       return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
+ }
+ static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = {
+       .handler        =       xfrmi6_rcv_tunnel,
+       .cb_handler     =       xfrmi_rcv_cb,
+       .err_handler    =       xfrmi6_err,
+       .priority       =       -1,
+ };
+ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
+       .handler        =       xfrmi6_rcv_tunnel,
+       .cb_handler     =       xfrmi_rcv_cb,
+       .err_handler    =       xfrmi6_err,
+       .priority       =       -1,
+ };
+ #endif
  static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
        .handler        =       xfrm4_rcv,
        .input_handler  =       xfrm_input,
@@@ -824,6 -863,27 +865,27 @@@ static struct xfrm4_protocol xfrmi_ipco
        .priority       =       10,
  };
  
+ #if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+ static int xfrmi4_rcv_tunnel(struct sk_buff *skb)
+ {
+       return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
+ }
+ static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = {
+       .handler        =       xfrmi4_rcv_tunnel,
+       .cb_handler     =       xfrmi_rcv_cb,
+       .err_handler    =       xfrmi4_err,
+       .priority       =       -1,
+ };
+ static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = {
+       .handler        =       xfrmi4_rcv_tunnel,
+       .cb_handler     =       xfrmi_rcv_cb,
+       .err_handler    =       xfrmi4_err,
+       .priority       =       -1,
+ };
+ #endif
  static int __init xfrmi4_init(void)
  {
        int err;
        err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
        if (err < 0)
                goto xfrm_proto_comp_failed;
+ #if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+       err = xfrm4_tunnel_register(&xfrmi_ipip_handler, AF_INET);
+       if (err < 0)
+               goto xfrm_tunnel_ipip_failed;
+       err = xfrm4_tunnel_register(&xfrmi_ipip6_handler, AF_INET6);
+       if (err < 0)
+               goto xfrm_tunnel_ipip6_failed;
+ #endif
  
        return 0;
  
+ #if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+ xfrm_tunnel_ipip6_failed:
+       xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
+ xfrm_tunnel_ipip_failed:
+       xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+ #endif
  xfrm_proto_comp_failed:
        xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
  xfrm_proto_ah_failed:
@@@ -850,6 -924,10 +926,10 @@@ xfrm_proto_esp_failed
  
  static void xfrmi4_fini(void)
  {
+ #if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+       xfrm4_tunnel_deregister(&xfrmi_ipip6_handler, AF_INET6);
+       xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
+ #endif
        xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
        xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
        xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
@@@ -868,9 -946,23 +948,23 @@@ static int __init xfrmi6_init(void
        err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
        if (err < 0)
                goto xfrm_proto_comp_failed;
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+       err = xfrm6_tunnel_register(&xfrmi_ipv6_handler, AF_INET6);
+       if (err < 0)
+               goto xfrm_tunnel_ipv6_failed;
+       err = xfrm6_tunnel_register(&xfrmi_ip6ip_handler, AF_INET);
+       if (err < 0)
+               goto xfrm_tunnel_ip6ip_failed;
+ #endif
  
        return 0;
  
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ xfrm_tunnel_ip6ip_failed:
+       xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
+ xfrm_tunnel_ipv6_failed:
+       xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+ #endif
  xfrm_proto_comp_failed:
        xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
  xfrm_proto_ah_failed:
@@@ -881,6 -973,10 +975,10 @@@ xfrm_proto_esp_failed
  
  static void xfrmi6_fini(void)
  {
+ #if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+       xfrm6_tunnel_deregister(&xfrmi_ip6ip_handler, AF_INET);
+       xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
+ #endif
        xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
        xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
        xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
This page took 0.097896 seconds and 4 git commands to generate.