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 12 static 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 23 static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 24 { 25 return 0; 26 } 27 28 static struct xfrm_tunnel *ipip_handler; 29 static DECLARE_MUTEX(xfrm4_tunnel_sem); 30 31 int 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 46 EXPORT_SYMBOL(xfrm4_tunnel_register); 47 48 int 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 65 EXPORT_SYMBOL(xfrm4_tunnel_deregister); 66 67 static 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 78 static 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 86 static 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 99 static void ipip_destroy(struct xfrm_state *x) 100 { 101 } 102 103 static 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 113 static struct net_protocol ipip_protocol = { 114 .handler = ipip_rcv, 115 .err_handler = ipip_err, 116 .no_policy = 1, 117 }; 118 119 static 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 133 static 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 141 module_init(ipip_init); 142 module_exit(ipip_fini); 143 MODULE_LICENSE("GPL"); 144