1 // SPDX-License-Identifier: GPL-2.0-only 2 /* xfrm4_tunnel.c: Generic IP tunnel transformer. 3 * 4 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 5 */ 6 7 #define pr_fmt(fmt) "IPsec: " fmt 8 9 #include <linux/skbuff.h> 10 #include <linux/module.h> 11 #include <linux/mutex.h> 12 #include <net/xfrm.h> 13 #include <net/ip.h> 14 #include <net/protocol.h> 15 16 static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) 17 { 18 skb_push(skb, -skb_network_offset(skb)); 19 return 0; 20 } 21 22 static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) 23 { 24 return ip_hdr(skb)->protocol; 25 } 26 27 static int ipip_init_state(struct xfrm_state *x) 28 { 29 if (x->props.mode != XFRM_MODE_TUNNEL) 30 return -EINVAL; 31 32 if (x->encap) 33 return -EINVAL; 34 35 x->props.header_len = sizeof(struct iphdr); 36 37 return 0; 38 } 39 40 static void ipip_destroy(struct xfrm_state *x) 41 { 42 } 43 44 static const struct xfrm_type ipip_type = { 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 = 4, 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 = 3, 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 xfrm_unregister_type(&ipip_type, AF_INET); 111 } 112 113 module_init(ipip_init); 114 module_exit(ipip_fini); 115 MODULE_LICENSE("GPL"); 116 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP); 117