1 /* tunnel4.c: Generic IP tunnel transformer. 2 * 3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 4 */ 5 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> 11 #include <net/icmp.h> 12 #include <net/ip.h> 13 #include <net/protocol.h> 14 #include <net/xfrm.h> 15 16 static struct xfrm_tunnel *tunnel4_handlers; 17 static DEFINE_MUTEX(tunnel4_mutex); 18 19 int xfrm4_tunnel_register(struct xfrm_tunnel *handler) 20 { 21 struct xfrm_tunnel **pprev; 22 int ret = -EEXIST; 23 int priority = handler->priority; 24 25 mutex_lock(&tunnel4_mutex); 26 27 for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { 28 if ((*pprev)->priority > priority) 29 break; 30 if ((*pprev)->priority == priority) 31 goto err; 32 } 33 34 handler->next = *pprev; 35 *pprev = handler; 36 37 ret = 0; 38 39 err: 40 mutex_unlock(&tunnel4_mutex); 41 42 return ret; 43 } 44 45 EXPORT_SYMBOL(xfrm4_tunnel_register); 46 47 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) 48 { 49 struct xfrm_tunnel **pprev; 50 int ret = -ENOENT; 51 52 mutex_lock(&tunnel4_mutex); 53 54 for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { 55 if (*pprev == handler) { 56 *pprev = handler->next; 57 ret = 0; 58 break; 59 } 60 } 61 62 mutex_unlock(&tunnel4_mutex); 63 64 synchronize_net(); 65 66 return ret; 67 } 68 69 EXPORT_SYMBOL(xfrm4_tunnel_deregister); 70 71 static int tunnel4_rcv(struct sk_buff *skb) 72 { 73 struct xfrm_tunnel *handler; 74 75 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 76 goto drop; 77 78 for (handler = tunnel4_handlers; handler; handler = handler->next) 79 if (!handler->handler(skb)) 80 return 0; 81 82 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 83 84 drop: 85 kfree_skb(skb); 86 return 0; 87 } 88 89 static void tunnel4_err(struct sk_buff *skb, u32 info) 90 { 91 struct xfrm_tunnel *handler; 92 93 for (handler = tunnel4_handlers; handler; handler = handler->next) 94 if (!handler->err_handler(skb, info)) 95 break; 96 } 97 98 static struct net_protocol tunnel4_protocol = { 99 .handler = tunnel4_rcv, 100 .err_handler = tunnel4_err, 101 .no_policy = 1, 102 }; 103 104 static int __init tunnel4_init(void) 105 { 106 if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { 107 printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 108 return -EAGAIN; 109 } 110 return 0; 111 } 112 113 static void __exit tunnel4_fini(void) 114 { 115 if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 116 printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); 117 } 118 119 module_init(tunnel4_init); 120 module_exit(tunnel4_fini); 121 MODULE_LICENSE("GPL"); 122