1 /* xfrm4_tunnel.c: Generic IP tunnel transformer. 2 * 3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 4 */ 5 6 #define pr_fmt(fmt) "IPsec: " fmt 7 8 #include <linux/skbuff.h> 9 #include <linux/module.h> 10 #include <linux/mutex.h> 11 #include <net/xfrm.h> 12 #include <net/ip.h> 13 #include <net/protocol.h> 14 15 static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) 16 { 17 skb_push(skb, -skb_network_offset(skb)); 18 return 0; 19 } 20 21 static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) 22 { 23 return ip_hdr(skb)->protocol; 24 } 25 26 static int ipip_init_state(struct xfrm_state *x) 27 { 28 if (x->props.mode != XFRM_MODE_TUNNEL) 29 return -EINVAL; 30 31 if (x->encap) 32 return -EINVAL; 33 34 x->props.header_len = sizeof(struct iphdr); 35 36 return 0; 37 } 38 39 static void ipip_destroy(struct xfrm_state *x) 40 { 41 } 42 43 static const struct xfrm_type ipip_type = { 44 .description = "IPIP", 45 .owner = THIS_MODULE, 46 .proto = IPPROTO_IPIP, 47 .init_state = ipip_init_state, 48 .destructor = ipip_destroy, 49 .input = ipip_xfrm_rcv, 50 .output = ipip_output 51 }; 52 53 static int xfrm_tunnel_rcv(struct sk_buff *skb) 54 { 55 return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr); 56 } 57 58 static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) 59 { 60 return -ENOENT; 61 } 62 63 static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { 64 .handler = xfrm_tunnel_rcv, 65 .err_handler = xfrm_tunnel_err, 66 .priority = 3, 67 }; 68 69 #if IS_ENABLED(CONFIG_IPV6) 70 static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = { 71 .handler = xfrm_tunnel_rcv, 72 .err_handler = xfrm_tunnel_err, 73 .priority = 2, 74 }; 75 #endif 76 77 static int __init ipip_init(void) 78 { 79 if (xfrm_register_type(&ipip_type, AF_INET) < 0) { 80 pr_info("%s: can't add xfrm type\n", __func__); 81 return -EAGAIN; 82 } 83 84 if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) { 85 pr_info("%s: can't add xfrm handler for AF_INET\n", __func__); 86 xfrm_unregister_type(&ipip_type, AF_INET); 87 return -EAGAIN; 88 } 89 #if IS_ENABLED(CONFIG_IPV6) 90 if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) { 91 pr_info("%s: can't add xfrm handler for AF_INET6\n", __func__); 92 xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET); 93 xfrm_unregister_type(&ipip_type, AF_INET); 94 return -EAGAIN; 95 } 96 #endif 97 return 0; 98 } 99 100 static void __exit ipip_fini(void) 101 { 102 #if IS_ENABLED(CONFIG_IPV6) 103 if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6)) 104 pr_info("%s: can't remove xfrm handler for AF_INET6\n", 105 __func__); 106 #endif 107 if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET)) 108 pr_info("%s: can't remove xfrm handler for AF_INET\n", 109 __func__); 110 if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) 111 pr_info("%s: can't remove xfrm type\n", __func__); 112 } 113 114 module_init(ipip_init); 115 module_exit(ipip_fini); 116 MODULE_LICENSE("GPL"); 117 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP); 118