X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv4%2Ftunnel4.c;h=978b3fd61e65533f3cf01f26521fc6f406288fac;hb=5e226e4d9016daee170699f8a4188a5505021756;hp=0d7d386dac2287bbfb9ef42ec6bbf0d83bb5073f;hpb=d62e54abca1146981fc9f98f85ff398a113a22c2;p=linux-2.6 diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index 0d7d386dac..978b3fd61e 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c @@ -8,13 +8,21 @@ #include #include #include +#include +#include #include #include static struct xfrm_tunnel *tunnel4_handlers; +static struct xfrm_tunnel *tunnel64_handlers; static DEFINE_MUTEX(tunnel4_mutex); -int xfrm4_tunnel_register(struct xfrm_tunnel *handler) +static inline struct xfrm_tunnel **fam_handlers(unsigned short family) +{ + return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; +} + +int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) { struct xfrm_tunnel **pprev; int ret = -EEXIST; @@ -22,7 +30,7 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler) mutex_lock(&tunnel4_mutex); - for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { + for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) { if ((*pprev)->priority > priority) break; if ((*pprev)->priority == priority) @@ -42,14 +50,14 @@ err: 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; int ret = -ENOENT; mutex_lock(&tunnel4_mutex); - for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { + for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) { if (*pprev == handler) { *pprev = handler->next; ret = 0; @@ -70,14 +78,40 @@ static int tunnel4_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + for (handler = tunnel4_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; } +#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) { struct xfrm_tunnel *handler; @@ -87,23 +121,53 @@ static void tunnel4_err(struct sk_buff *skb, u32 info) break; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static void tunnel64_err(struct sk_buff *skb, u32 info) +{ + struct xfrm_tunnel *handler; + + for (handler = tunnel64_handlers; handler; handler = handler->next) + if (!handler->err_handler(skb, info)) + break; +} +#endif + static struct net_protocol tunnel4_protocol = { .handler = tunnel4_rcv, .err_handler = tunnel4_err, .no_policy = 1, }; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static struct net_protocol tunnel64_protocol = { + .handler = tunnel64_rcv, + .err_handler = tunnel64_err, + .no_policy = 1, +}; +#endif + static int __init tunnel4_init(void) { if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 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; } 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)) printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); }