Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc3 121 lines 2.4 kB view raw
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 16static struct xfrm_tunnel *tunnel4_handlers; 17static DEFINE_MUTEX(tunnel4_mutex); 18 19int 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 39err: 40 mutex_unlock(&tunnel4_mutex); 41 42 return ret; 43} 44 45EXPORT_SYMBOL(xfrm4_tunnel_register); 46 47int 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 69EXPORT_SYMBOL(xfrm4_tunnel_deregister); 70 71static 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 84drop: 85 kfree_skb(skb); 86 return 0; 87} 88 89static 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 98static struct net_protocol tunnel4_protocol = { 99 .handler = tunnel4_rcv, 100 .err_handler = tunnel4_err, 101 .no_policy = 1, 102}; 103 104static 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 113static 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 119module_init(tunnel4_init); 120module_exit(tunnel4_fini); 121MODULE_LICENSE("GPL");