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 15static 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 21static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) 22{ 23 return ip_hdr(skb)->protocol; 24} 25 26static 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 39static void ipip_destroy(struct xfrm_state *x) 40{ 41} 42 43static 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 53static int xfrm_tunnel_rcv(struct sk_buff *skb) 54{ 55 return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr); 56} 57 58static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) 59{ 60 return -ENOENT; 61} 62 63static 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) 70static 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 77static 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 100static 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 114module_init(ipip_init); 115module_exit(ipip_fini); 116MODULE_LICENSE("GPL"); 117MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP); 118