Skip to content

Commit

Permalink
[IPSEC]: changing API of xfrm6_tunnel_register
Browse files Browse the repository at this point in the history
This patch changes xfrm6_tunnel register and deregister
interface to prepare for solving the conflict of device
tunnels with inter address family IPsec tunnel.
There is no device which conflicts with IPv4 over IPv6
IPsec tunnel.

Signed-off-by: Kazunori MIYAZAWA <miyazawa@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Kazunori MIYAZAWA authored and David S. Miller committed Feb 13, 2007
1 parent c73cb5a commit 73d605d
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 13 deletions.
4 changes: 2 additions & 2 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,8 @@ extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
Expand Down
6 changes: 3 additions & 3 deletions net/ipv6/ip6_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ static int __init ip6_tunnel_init(void)
{
int err;

if (xfrm6_tunnel_register(&ip6ip6_handler)) {
if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
return -EAGAIN;
}
Expand All @@ -1147,7 +1147,7 @@ static int __init ip6_tunnel_init(void)
}
return 0;
fail:
xfrm6_tunnel_deregister(&ip6ip6_handler);
xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
return err;
}

Expand All @@ -1171,7 +1171,7 @@ static void __exit ip6ip6_destroy_tunnels(void)

static void __exit ip6_tunnel_cleanup(void)
{
if (xfrm6_tunnel_deregister(&ip6ip6_handler))
if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");

rtnl_lock();
Expand Down
43 changes: 39 additions & 4 deletions net/ipv6/tunnel6.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,19 @@
#include <net/xfrm.h>

static struct xfrm6_tunnel *tunnel6_handlers;
static struct xfrm6_tunnel *tunnel46_handlers;
static DEFINE_MUTEX(tunnel6_mutex);

int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
{
struct xfrm6_tunnel **pprev;
int ret = -EEXIST;
int priority = handler->priority;

mutex_lock(&tunnel6_mutex);

for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
*pprev; pprev = &(*pprev)->next) {
if ((*pprev)->priority > priority)
break;
if ((*pprev)->priority == priority)
Expand All @@ -60,14 +62,15 @@ int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)

EXPORT_SYMBOL(xfrm6_tunnel_register);

int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
{
struct xfrm6_tunnel **pprev;
int ret = -ENOENT;

mutex_lock(&tunnel6_mutex);

for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
*pprev; pprev = &(*pprev)->next) {
if (*pprev == handler) {
*pprev = handler->next;
ret = 0;
Expand Down Expand Up @@ -103,6 +106,25 @@ static int tunnel6_rcv(struct sk_buff **pskb)
return 0;
}

static int tunnel46_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler;

if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
goto drop;

for (handler = tunnel46_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;

icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);

drop:
kfree_skb(skb);
return 0;
}

static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __be32 info)
{
Expand All @@ -119,17 +141,30 @@ static struct inet6_protocol tunnel6_protocol = {
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};

static struct inet6_protocol tunnel46_protocol = {
.handler = tunnel46_rcv,
.err_handler = tunnel6_err,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};

static int __init tunnel6_init(void)
{
if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
return -EAGAIN;
}
if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) {
printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
return -EAGAIN;
}
return 0;
}

static void __exit tunnel6_fini(void)
{
if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
}
Expand Down
3 changes: 2 additions & 1 deletion net/ipv6/xfrm6_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
if (xfrm_nr == XFRM_MAX_DEPTH)
goto drop;

x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, nexthdr, AF_INET6);
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6);
if (x == NULL)
goto drop;
spin_lock(&x->lock);
Expand Down
19 changes: 16 additions & 3 deletions net/ipv6/xfrm6_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,17 +339,29 @@ static struct xfrm6_tunnel xfrm6_tunnel_handler = {
.priority = 2,
};

static struct xfrm6_tunnel xfrm46_tunnel_handler = {
.handler = xfrm6_tunnel_rcv,
.err_handler = xfrm6_tunnel_err,
.priority = 2,
};

static int __init xfrm6_tunnel_init(void)
{
if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
return -EAGAIN;

if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
if (xfrm6_tunnel_spi_init() < 0) {
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
Expand All @@ -359,7 +371,8 @@ static int __init xfrm6_tunnel_init(void)
static void __exit xfrm6_tunnel_fini(void)
{
xfrm6_tunnel_spi_fini();
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
}

Expand Down

0 comments on commit 73d605d

Please sign in to comment.