mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
Merge remote-tracking branch 'origin/testing'
Xin Long says:
==================
Now ipip and ipv6 tunnels processing is supported by xfrm4/6_tunnel,
but not in vti and xfrmi. This feature is needed by processing those
uncompressed small fragments and packets when using comp protocol.
It means vti and xfrmi won't be able to accept small fragments or
packets when using comp protocol, which is not expected.
xfrm4/6_tunnel eventually calls xfrm_input() to process ipip and ipv6
tunnels with an ipip/ipv6-proto state (a child state of comp-proto
state), and vti and xfrmi should do the same.
The extra things for vti to do is:
- vti_input() should be called before xfrm_input() to set
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4/6 = tunnel. [A]
- vti_rcv_cb() should be called after xfrm_input() to update
the skb->dev. [B]
And the extra things for xfrmi to do is:
- The ipip/ipv6-proto state should be assigned if_id from its
parent's state. [C]
- xfrmi_rcv_cb() should be called after xfrm_input() to update
the skb->dev. [D]
Patch 4-7 does the things in [A].
To implement [B] and [D], patch 1-3 is to build a callback function
for xfrm4/6_tunnel, which can be called after xfrm_input(), similar
to xfrm4/6_protocol's .cb_handler. vti and xfrmi only needs to give
their own callback function in patch 4-7 and 9-10, which already
exists: vti_rcv_cb() and xfrmi_rcv_cb().
Patch 8 is to do the thing in [C] by assigning child tunnel's if_id
from its parent tunnel.
With the whole patch series, the segments or packets with any size
can work with ipsec comp proto on vti and xfrmi.
v1->v2:
- See Patch 2-3.
v2->v3:
- See Patch 2-3, 4, 6, 9-10.
==================
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
commit
2d4c7986db
|
|
@ -373,7 +373,8 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
|
|||
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);
|
||||
};
|
||||
|
|
@ -1415,6 +1416,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;
|
||||
|
|
@ -1423,6 +1425,7 @@ struct xfrm_tunnel {
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -91,32 +91,6 @@ static int vti_rcv_proto(struct sk_buff *skb)
|
|||
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;
|
||||
|
|
@ -495,11 +469,22 @@ static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
|
|||
.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,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __net_init vti_init_net(struct net *net)
|
||||
{
|
||||
|
|
@ -669,10 +654,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_failed;
|
||||
goto xfrm_tunnel_ipip_failed;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
err = xfrm4_tunnel_register(&vti_ipip_handler, AF_INET6);
|
||||
if (err < 0)
|
||||
goto xfrm_tunnel_ipip6_failed;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
msg = "netlink interface";
|
||||
err = rtnl_link_register(&vti_link_ops);
|
||||
|
|
@ -682,8 +674,14 @@ static int __init vti_init(void)
|
|||
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_ipip_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);
|
||||
|
|
@ -699,7 +697,12 @@ static int __init vti_init(void)
|
|||
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_ipip_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);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
|
|||
t->props.flags = x->props.flags;
|
||||
t->props.extra_flags = x->props.extra_flags;
|
||||
memcpy(&t->mark, &x->mark, sizeof(t->mark));
|
||||
t->if_id = x->if_id;
|
||||
|
||||
if (xfrm_init_state(t))
|
||||
goto error;
|
||||
|
|
|
|||
|
|
@ -110,6 +110,33 @@ static int tunnel4_rcv(struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
|
||||
static int tunnel4_rcv_cb(struct sk_buff *skb, u8 proto, int err)
|
||||
{
|
||||
struct xfrm_tunnel __rcu *head;
|
||||
struct xfrm_tunnel *handler;
|
||||
int ret;
|
||||
|
||||
head = (proto == IPPROTO_IPIP) ? tunnel4_handlers : tunnel64_handlers;
|
||||
|
||||
for_each_tunnel_rcu(head, handler) {
|
||||
if (handler->cb_handler) {
|
||||
ret = handler->cb_handler(skb, err);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xfrm_input_afinfo tunnel4_input_afinfo = {
|
||||
.family = AF_INET,
|
||||
.is_ipip = true,
|
||||
.callback = tunnel4_rcv_cb,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static int tunnel64_rcv(struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -230,6 +257,18 @@ static int __init tunnel4_init(void)
|
|||
#endif
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
|
||||
if (xfrm_input_register_afinfo(&tunnel4_input_afinfo)) {
|
||||
inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MPLS)
|
||||
inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS);
|
||||
#endif
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
|
|
@ -240,6 +279,10 @@ static int __init tunnel4_init(void)
|
|||
|
||||
static void __exit tunnel4_fini(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
|
||||
if (xfrm_input_unregister_afinfo(&tunnel4_input_afinfo))
|
||||
pr_err("tunnel4 close: can't remove input afinfo\n");
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MPLS)
|
||||
if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
|
||||
pr_err("tunnelmpls4 close: can't remove protocol\n");
|
||||
|
|
|
|||
|
|
@ -1218,6 +1218,26 @@ static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = {
|
|||
.priority = 100,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(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,
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vti6_tunnel_init - register protocol and reserve needed resources
|
||||
*
|
||||
|
|
@ -1243,6 +1263,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_ENABLED(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_ipv6_handler, AF_INET);
|
||||
if (err < 0)
|
||||
goto vti_tunnel_ip6ip_failed;
|
||||
#endif
|
||||
|
||||
msg = "netlink interface";
|
||||
err = rtnl_link_register(&vti6_link_ops);
|
||||
|
|
@ -1252,6 +1281,12 @@ static int __init vti6_tunnel_init(void)
|
|||
return 0;
|
||||
|
||||
rtnl_link_failed:
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL)
|
||||
err = xfrm6_tunnel_deregister(&vti_ipv6_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);
|
||||
|
|
@ -1270,6 +1305,10 @@ static int __init vti6_tunnel_init(void)
|
|||
static void __exit vti6_tunnel_cleanup(void)
|
||||
{
|
||||
rtnl_link_unregister(&vti6_link_ops);
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL)
|
||||
xfrm6_tunnel_deregister(&vti_ipv6_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);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
|
|||
t->props.mode = x->props.mode;
|
||||
memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
|
||||
memcpy(&t->mark, &x->mark, sizeof(t->mark));
|
||||
t->if_id = x->if_id;
|
||||
|
||||
if (xfrm_init_state(t))
|
||||
goto error;
|
||||
|
|
|
|||
|
|
@ -155,6 +155,33 @@ static int tunnel6_rcv(struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL)
|
||||
static int tunnel6_rcv_cb(struct sk_buff *skb, u8 proto, int err)
|
||||
{
|
||||
struct xfrm6_tunnel __rcu *head;
|
||||
struct xfrm6_tunnel *handler;
|
||||
int ret;
|
||||
|
||||
head = (proto == IPPROTO_IPV6) ? tunnel6_handlers : tunnel46_handlers;
|
||||
|
||||
for_each_tunnel_rcu(head, handler) {
|
||||
if (handler->cb_handler) {
|
||||
ret = handler->cb_handler(skb, err);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xfrm_input_afinfo tunnel6_input_afinfo = {
|
||||
.family = AF_INET6,
|
||||
.is_ipip = true,
|
||||
.callback = tunnel6_rcv_cb,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int tunnel46_rcv(struct sk_buff *skb)
|
||||
{
|
||||
struct xfrm6_tunnel *handler;
|
||||
|
|
@ -245,11 +272,25 @@ static int __init tunnel6_init(void)
|
|||
inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP);
|
||||
return -EAGAIN;
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL)
|
||||
if (xfrm_input_register_afinfo(&tunnel6_input_afinfo)) {
|
||||
pr_err("%s: can't add input afinfo\n", __func__);
|
||||
inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
|
||||
inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP);
|
||||
if (xfrm6_tunnel_mpls_supported())
|
||||
inet6_del_protocol(&tunnelmpls6_protocol, IPPROTO_MPLS);
|
||||
return -EAGAIN;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit tunnel6_fini(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL)
|
||||
if (xfrm_input_unregister_afinfo(&tunnel6_input_afinfo))
|
||||
pr_err("%s: can't remove input afinfo\n", __func__);
|
||||
#endif
|
||||
if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
|
||||
pr_err("%s: can't remove protocol\n", __func__);
|
||||
if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct xfrm_trans_cb {
|
|||
#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0]))
|
||||
|
||||
static DEFINE_SPINLOCK(xfrm_input_afinfo_lock);
|
||||
static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[AF_INET6 + 1];
|
||||
static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[2][AF_INET6 + 1];
|
||||
|
||||
static struct gro_cells gro_cells;
|
||||
static struct net_device xfrm_napi_dev;
|
||||
|
|
@ -53,14 +53,14 @@ int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo)
|
|||
{
|
||||
int err = 0;
|
||||
|
||||
if (WARN_ON(afinfo->family >= ARRAY_SIZE(xfrm_input_afinfo)))
|
||||
if (WARN_ON(afinfo->family > AF_INET6))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
spin_lock_bh(&xfrm_input_afinfo_lock);
|
||||
if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL))
|
||||
if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family]))
|
||||
err = -EEXIST;
|
||||
else
|
||||
rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo);
|
||||
rcu_assign_pointer(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], afinfo);
|
||||
spin_unlock_bh(&xfrm_input_afinfo_lock);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -71,11 +71,11 @@ int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo)
|
|||
int err = 0;
|
||||
|
||||
spin_lock_bh(&xfrm_input_afinfo_lock);
|
||||
if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) {
|
||||
if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo))
|
||||
if (likely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family])) {
|
||||
if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family] != afinfo))
|
||||
err = -EINVAL;
|
||||
else
|
||||
RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL);
|
||||
RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], NULL);
|
||||
}
|
||||
spin_unlock_bh(&xfrm_input_afinfo_lock);
|
||||
synchronize_rcu();
|
||||
|
|
@ -83,15 +83,15 @@ int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo)
|
|||
}
|
||||
EXPORT_SYMBOL(xfrm_input_unregister_afinfo);
|
||||
|
||||
static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family)
|
||||
static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(u8 family, bool is_ipip)
|
||||
{
|
||||
const struct xfrm_input_afinfo *afinfo;
|
||||
|
||||
if (WARN_ON_ONCE(family >= ARRAY_SIZE(xfrm_input_afinfo)))
|
||||
if (WARN_ON_ONCE(family > AF_INET6))
|
||||
return NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
afinfo = rcu_dereference(xfrm_input_afinfo[family]);
|
||||
afinfo = rcu_dereference(xfrm_input_afinfo[is_ipip][family]);
|
||||
if (unlikely(!afinfo))
|
||||
rcu_read_unlock();
|
||||
return afinfo;
|
||||
|
|
@ -100,9 +100,11 @@ static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family
|
|||
static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol,
|
||||
int err)
|
||||
{
|
||||
bool is_ipip = (protocol == IPPROTO_IPIP || protocol == IPPROTO_IPV6);
|
||||
const struct xfrm_input_afinfo *afinfo;
|
||||
int ret;
|
||||
const struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family);
|
||||
|
||||
afinfo = xfrm_input_get_afinfo(family, is_ipip);
|
||||
if (!afinfo)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
|
|
|
|||
|
|
@ -798,6 +798,26 @@ static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
|
|||
.priority = 10,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(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,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
|
||||
.handler = xfrm4_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
|
|
@ -822,6 +842,20 @@ static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
|
|||
.priority = 10,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(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,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init xfrmi4_init(void)
|
||||
{
|
||||
int err;
|
||||
|
|
@ -835,9 +869,23 @@ static int __init xfrmi4_init(void)
|
|||
err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
|
||||
if (err < 0)
|
||||
goto xfrm_proto_comp_failed;
|
||||
#if IS_ENABLED(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_ipip_handler, AF_INET6);
|
||||
if (err < 0)
|
||||
goto xfrm_tunnel_ipip6_failed;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
#if IS_ENABLED(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:
|
||||
|
|
@ -848,6 +896,10 @@ static int __init xfrmi4_init(void)
|
|||
|
||||
static void xfrmi4_fini(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
|
||||
xfrm4_tunnel_deregister(&xfrmi_ipip_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);
|
||||
|
|
@ -866,9 +918,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_ENABLED(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_ipv6_handler, AF_INET);
|
||||
if (err < 0)
|
||||
goto xfrm_tunnel_ip6ip_failed;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
#if IS_ENABLED(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:
|
||||
|
|
@ -879,6 +945,10 @@ static int __init xfrmi6_init(void)
|
|||
|
||||
static void xfrmi6_fini(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL)
|
||||
xfrm6_tunnel_deregister(&xfrmi_ipv6_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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user