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 71e1f55ad4bc4c8bcfe696400a950a34263a750e 143 lines 2.8 kB view raw
1/* xfrm4_tunnel.c: Generic IP tunnel transformer. 2 * 3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 4 */ 5 6#include <linux/skbuff.h> 7#include <linux/module.h> 8#include <net/xfrm.h> 9#include <net/ip.h> 10#include <net/protocol.h> 11 12static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) 13{ 14 struct iphdr *iph; 15 16 iph = skb->nh.iph; 17 iph->tot_len = htons(skb->len); 18 ip_send_check(iph); 19 20 return 0; 21} 22 23static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 24{ 25 return 0; 26} 27 28static struct xfrm_tunnel *ipip_handler; 29static DECLARE_MUTEX(xfrm4_tunnel_sem); 30 31int xfrm4_tunnel_register(struct xfrm_tunnel *handler) 32{ 33 int ret; 34 35 down(&xfrm4_tunnel_sem); 36 ret = 0; 37 if (ipip_handler != NULL) 38 ret = -EINVAL; 39 if (!ret) 40 ipip_handler = handler; 41 up(&xfrm4_tunnel_sem); 42 43 return ret; 44} 45 46EXPORT_SYMBOL(xfrm4_tunnel_register); 47 48int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) 49{ 50 int ret; 51 52 down(&xfrm4_tunnel_sem); 53 ret = 0; 54 if (ipip_handler != handler) 55 ret = -EINVAL; 56 if (!ret) 57 ipip_handler = NULL; 58 up(&xfrm4_tunnel_sem); 59 60 synchronize_net(); 61 62 return ret; 63} 64 65EXPORT_SYMBOL(xfrm4_tunnel_deregister); 66 67static int ipip_rcv(struct sk_buff *skb) 68{ 69 struct xfrm_tunnel *handler = ipip_handler; 70 71 /* Tunnel devices take precedence. */ 72 if (handler && handler->handler(skb) == 0) 73 return 0; 74 75 return xfrm4_rcv(skb); 76} 77 78static void ipip_err(struct sk_buff *skb, u32 info) 79{ 80 struct xfrm_tunnel *handler = ipip_handler; 81 82 if (handler) 83 handler->err_handler(skb, info); 84} 85 86static int ipip_init_state(struct xfrm_state *x) 87{ 88 if (!x->props.mode) 89 return -EINVAL; 90 91 if (x->encap) 92 return -EINVAL; 93 94 x->props.header_len = sizeof(struct iphdr); 95 96 return 0; 97} 98 99static void ipip_destroy(struct xfrm_state *x) 100{ 101} 102 103static struct xfrm_type ipip_type = { 104 .description = "IPIP", 105 .owner = THIS_MODULE, 106 .proto = IPPROTO_IPIP, 107 .init_state = ipip_init_state, 108 .destructor = ipip_destroy, 109 .input = ipip_xfrm_rcv, 110 .output = ipip_output 111}; 112 113static struct net_protocol ipip_protocol = { 114 .handler = ipip_rcv, 115 .err_handler = ipip_err, 116 .no_policy = 1, 117}; 118 119static int __init ipip_init(void) 120{ 121 if (xfrm_register_type(&ipip_type, AF_INET) < 0) { 122 printk(KERN_INFO "ipip init: can't add xfrm type\n"); 123 return -EAGAIN; 124 } 125 if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) { 126 printk(KERN_INFO "ipip init: can't add protocol\n"); 127 xfrm_unregister_type(&ipip_type, AF_INET); 128 return -EAGAIN; 129 } 130 return 0; 131} 132 133static void __exit ipip_fini(void) 134{ 135 if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) 136 printk(KERN_INFO "ipip close: can't remove protocol\n"); 137 if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) 138 printk(KERN_INFO "ipip close: can't remove xfrm type\n"); 139} 140 141module_init(ipip_init); 142module_exit(ipip_fini); 143MODULE_LICENSE("GPL");