1 /* tunnel4.c: Generic IP tunnel transformer.
 
   3  * Copyright (C) 2003 David S. Miller (davem@redhat.com)
 
   6 #include <linux/init.h>
 
   7 #include <linux/module.h>
 
   8 #include <linux/mutex.h>
 
   9 #include <linux/netdevice.h>
 
  10 #include <linux/skbuff.h>
 
  13 #include <net/protocol.h>
 
  16 static struct xfrm_tunnel *tunnel4_handlers;
 
  17 static struct xfrm_tunnel *tunnel64_handlers;
 
  18 static DEFINE_MUTEX(tunnel4_mutex);
 
  20 static inline struct xfrm_tunnel **fam_handlers(unsigned short family)
 
  22         return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
 
  25 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
 
  27         struct xfrm_tunnel **pprev;
 
  29         int priority = handler->priority;
 
  31         mutex_lock(&tunnel4_mutex);
 
  33         for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) {
 
  34                 if ((*pprev)->priority > priority)
 
  36                 if ((*pprev)->priority == priority)
 
  40         handler->next = *pprev;
 
  46         mutex_unlock(&tunnel4_mutex);
 
  51 EXPORT_SYMBOL(xfrm4_tunnel_register);
 
  53 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
 
  55         struct xfrm_tunnel **pprev;
 
  58         mutex_lock(&tunnel4_mutex);
 
  60         for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) {
 
  61                 if (*pprev == handler) {
 
  62                         *pprev = handler->next;
 
  68         mutex_unlock(&tunnel4_mutex);
 
  75 EXPORT_SYMBOL(xfrm4_tunnel_deregister);
 
  77 static int tunnel4_rcv(struct sk_buff *skb)
 
  79         struct xfrm_tunnel *handler;
 
  81         if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 
  84         for (handler = tunnel4_handlers; handler; handler = handler->next)
 
  85                 if (!handler->handler(skb))
 
  88         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
  95 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
  96 static int tunnel64_rcv(struct sk_buff *skb)
 
  98         struct xfrm_tunnel *handler;
 
 100         if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 
 103         for (handler = tunnel64_handlers; handler; handler = handler->next)
 
 104                 if (!handler->handler(skb))
 
 107         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
 115 static void tunnel4_err(struct sk_buff *skb, u32 info)
 
 117         struct xfrm_tunnel *handler;
 
 119         for (handler = tunnel4_handlers; handler; handler = handler->next)
 
 120                 if (!handler->err_handler(skb, info))
 
 124 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 125 static void tunnel64_err(struct sk_buff *skb, u32 info)
 
 127         struct xfrm_tunnel *handler;
 
 129         for (handler = tunnel64_handlers; handler; handler = handler->next)
 
 130                 if (!handler->err_handler(skb, info))
 
 135 static struct net_protocol tunnel4_protocol = {
 
 136         .handler        =       tunnel4_rcv,
 
 137         .err_handler    =       tunnel4_err,
 
 142 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 143 static struct net_protocol tunnel64_protocol = {
 
 144         .handler        =       tunnel64_rcv,
 
 145         .err_handler    =       tunnel64_err,
 
 151 static int __init tunnel4_init(void)
 
 153         if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
 
 154                 printk(KERN_ERR "tunnel4 init: can't add protocol\n");
 
 157 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 158         if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
 
 159                 printk(KERN_ERR "tunnel64 init: can't add protocol\n");
 
 160                 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
 
 167 static void __exit tunnel4_fini(void)
 
 169 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 170         if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
 
 171                 printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
 
 173         if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
 
 174                 printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
 
 177 module_init(tunnel4_init);
 
 178 module_exit(tunnel4_fini);
 
 179 MODULE_LICENSE("GPL");