Commit c0d56408 authored by Kazunori MIYAZAWA's avatar Kazunori MIYAZAWA Committed by David S. Miller

[IPSEC]: Changing API of xfrm4_tunnel_register.

This patch changes xfrm4_tunnel register and deregister
interface to prepare for solving the conflict of device
tunnels with inter address family IPsec tunnel.
Signed-off-by: default avatarKazunori MIYAZAWA <miyazawa@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 600ff0c2
...@@ -946,8 +946,8 @@ extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); ...@@ -946,8 +946,8 @@ extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x); extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm4_rcv(struct sk_buff *skb); extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb); extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi); extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb); extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
......
...@@ -871,7 +871,7 @@ static int __init ipip_init(void) ...@@ -871,7 +871,7 @@ static int __init ipip_init(void)
printk(banner); printk(banner);
if (xfrm4_tunnel_register(&ipip_handler)) { if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
printk(KERN_INFO "ipip init: can't register tunnel\n"); printk(KERN_INFO "ipip init: can't register tunnel\n");
return -EAGAIN; return -EAGAIN;
} }
...@@ -893,7 +893,7 @@ static int __init ipip_init(void) ...@@ -893,7 +893,7 @@ static int __init ipip_init(void)
err2: err2:
free_netdev(ipip_fb_tunnel_dev); free_netdev(ipip_fb_tunnel_dev);
err1: err1:
xfrm4_tunnel_deregister(&ipip_handler); xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
goto out; goto out;
} }
...@@ -913,7 +913,7 @@ static void __exit ipip_destroy_tunnels(void) ...@@ -913,7 +913,7 @@ static void __exit ipip_destroy_tunnels(void)
static void __exit ipip_fini(void) static void __exit ipip_fini(void)
{ {
if (xfrm4_tunnel_deregister(&ipip_handler)) if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
printk(KERN_INFO "ipip close: can't deregister tunnel\n"); printk(KERN_INFO "ipip close: can't deregister tunnel\n");
rtnl_lock(); rtnl_lock();
......
...@@ -14,9 +14,10 @@ ...@@ -14,9 +14,10 @@
#include <net/xfrm.h> #include <net/xfrm.h>
static struct xfrm_tunnel *tunnel4_handlers; static struct xfrm_tunnel *tunnel4_handlers;
static struct xfrm_tunnel *tunnel64_handlers;
static DEFINE_MUTEX(tunnel4_mutex); static DEFINE_MUTEX(tunnel4_mutex);
int xfrm4_tunnel_register(struct xfrm_tunnel *handler) int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
{ {
struct xfrm_tunnel **pprev; struct xfrm_tunnel **pprev;
int ret = -EEXIST; int ret = -EEXIST;
...@@ -24,7 +25,8 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler) ...@@ -24,7 +25,8 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
mutex_lock(&tunnel4_mutex); mutex_lock(&tunnel4_mutex);
for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
*pprev; pprev = &(*pprev)->next) {
if ((*pprev)->priority > priority) if ((*pprev)->priority > priority)
break; break;
if ((*pprev)->priority == priority) if ((*pprev)->priority == priority)
...@@ -44,14 +46,15 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler) ...@@ -44,14 +46,15 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
EXPORT_SYMBOL(xfrm4_tunnel_register); EXPORT_SYMBOL(xfrm4_tunnel_register);
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
{ {
struct xfrm_tunnel **pprev; struct xfrm_tunnel **pprev;
int ret = -ENOENT; int ret = -ENOENT;
mutex_lock(&tunnel4_mutex); mutex_lock(&tunnel4_mutex);
for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
*pprev; pprev = &(*pprev)->next) {
if (*pprev == handler) { if (*pprev == handler) {
*pprev = handler->next; *pprev = handler->next;
ret = 0; ret = 0;
...@@ -86,6 +89,26 @@ static int tunnel4_rcv(struct sk_buff *skb) ...@@ -86,6 +89,26 @@ static int tunnel4_rcv(struct sk_buff *skb)
return 0; return 0;
} }
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static int tunnel64_rcv(struct sk_buff *skb)
{
struct xfrm_tunnel *handler;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto drop;
for (handler = tunnel64_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
kfree_skb(skb);
return 0;
}
#endif
static void tunnel4_err(struct sk_buff *skb, u32 info) static void tunnel4_err(struct sk_buff *skb, u32 info)
{ {
struct xfrm_tunnel *handler; struct xfrm_tunnel *handler;
...@@ -101,17 +124,36 @@ static struct net_protocol tunnel4_protocol = { ...@@ -101,17 +124,36 @@ static struct net_protocol tunnel4_protocol = {
.no_policy = 1, .no_policy = 1,
}; };
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct net_protocol tunnel64_protocol = {
.handler = tunnel64_rcv,
.err_handler = tunnel4_err,
.no_policy = 1,
};
#endif
static int __init tunnel4_init(void) static int __init tunnel4_init(void)
{ {
if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
printk(KERN_ERR "tunnel4 init: can't add protocol\n"); printk(KERN_ERR "tunnel4 init: can't add protocol\n");
return -EAGAIN; return -EAGAIN;
} }
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
printk(KERN_ERR "tunnel64 init: can't add protocol\n");
inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
return -EAGAIN;
}
#endif
return 0; return 0;
} }
static void __exit tunnel4_fini(void) static void __exit tunnel4_fini(void)
{ {
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
#endif
if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
} }
......
...@@ -27,6 +27,7 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 ...@@ -27,6 +27,7 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32
{ {
switch (nexthdr) { switch (nexthdr) {
case IPPROTO_IPIP: case IPPROTO_IPIP:
case IPPROTO_IPV6:
*spi = skb->nh.iph->saddr; *spi = skb->nh.iph->saddr;
*seq = 0; *seq = 0;
return 0; return 0;
...@@ -70,7 +71,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) ...@@ -70,7 +71,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (xfrm_nr == XFRM_MAX_DEPTH) if (xfrm_nr == XFRM_MAX_DEPTH)
goto drop; goto drop;
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, iph->protocol, AF_INET); x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);
if (x == NULL) if (x == NULL)
goto drop; goto drop;
......
...@@ -64,24 +64,45 @@ static struct xfrm_tunnel xfrm_tunnel_handler = { ...@@ -64,24 +64,45 @@ static struct xfrm_tunnel xfrm_tunnel_handler = {
.priority = 2, .priority = 2,
}; };
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct xfrm_tunnel xfrm64_tunnel_handler = {
.handler = xfrm4_rcv,
.err_handler = xfrm_tunnel_err,
.priority = 2,
};
#endif
static int __init ipip_init(void) static int __init ipip_init(void)
{ {
if (xfrm_register_type(&ipip_type, AF_INET) < 0) { if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
printk(KERN_INFO "ipip init: can't add xfrm type\n"); printk(KERN_INFO "ipip init: can't add xfrm type\n");
return -EAGAIN; return -EAGAIN;
} }
if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
printk(KERN_INFO "ipip init: can't add xfrm handler\n"); if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n");
xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n");
xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
xfrm_unregister_type(&ipip_type, AF_INET); xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN; return -EAGAIN;
} }
#endif
return 0; return 0;
} }
static void __exit ipip_fini(void) static void __exit ipip_fini(void)
{ {
if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler)) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
printk(KERN_INFO "ipip close: can't remove xfrm handler\n"); if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n");
#endif
if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n");
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
printk(KERN_INFO "ipip close: can't remove xfrm type\n"); printk(KERN_INFO "ipip close: can't remove xfrm type\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment