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 16static 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 22static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) 23{ 24 return ip_hdr(skb)->protocol; 25} 26 27static 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 40static void ipip_destroy(struct xfrm_state *x) 41{ 42} 43 44static const struct xfrm_type ipip_type = { 45 .description = "IPIP", 46 .owner = THIS_MODULE, 47 .proto = IPPROTO_IPIP, 48 .init_state = ipip_init_state, 49 .destructor = ipip_destroy, 50 .input = ipip_xfrm_rcv, 51 .output = ipip_output 52}; 53 54static int xfrm_tunnel_rcv(struct sk_buff *skb) 55{ 56 return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr); 57} 58 59static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) 60{ 61 return -ENOENT; 62} 63 64static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { 65 .handler = xfrm_tunnel_rcv, 66 .err_handler = xfrm_tunnel_err, 67 .priority = 4, 68}; 69 70#if IS_ENABLED(CONFIG_IPV6) 71static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = { 72 .handler = xfrm_tunnel_rcv, 73 .err_handler = xfrm_tunnel_err, 74 .priority = 3, 75}; 76#endif 77 78static int __init ipip_init(void) 79{ 80 if (xfrm_register_type(&ipip_type, AF_INET) < 0) { 81 pr_info("%s: can't add xfrm type\n", __func__); 82 return -EAGAIN; 83 } 84 85 if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) { 86 pr_info("%s: can't add xfrm handler for AF_INET\n", __func__); 87 xfrm_unregister_type(&ipip_type, AF_INET); 88 return -EAGAIN; 89 } 90#if IS_ENABLED(CONFIG_IPV6) 91 if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) { 92 pr_info("%s: can't add xfrm handler for AF_INET6\n", __func__); 93 xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET); 94 xfrm_unregister_type(&ipip_type, AF_INET); 95 return -EAGAIN; 96 } 97#endif 98 return 0; 99} 100 101static void __exit ipip_fini(void) 102{ 103#if IS_ENABLED(CONFIG_IPV6) 104 if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6)) 105 pr_info("%s: can't remove xfrm handler for AF_INET6\n", 106 __func__); 107#endif 108 if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET)) 109 pr_info("%s: can't remove xfrm handler for AF_INET\n", 110 __func__); 111 xfrm_unregister_type(&ipip_type, AF_INET); 112} 113 114module_init(ipip_init); 115module_exit(ipip_fini); 116MODULE_LICENSE("GPL"); 117MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP); 118