xref: /openbmc/linux/net/ipv4/xfrm4_tunnel.c (revision 25ec92cd)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /* xfrm4_tunnel.c: Generic IP tunnel transformer.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (C) 2003 David S. Miller (davem@redhat.com)
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds 
7afd46503SJoe Perches #define pr_fmt(fmt) "IPsec: " fmt
8afd46503SJoe Perches 
91da177e4SLinus Torvalds #include <linux/skbuff.h>
101da177e4SLinus Torvalds #include <linux/module.h>
111da177e4SLinus Torvalds #include <net/xfrm.h>
121da177e4SLinus Torvalds #include <net/protocol.h>
131da177e4SLinus Torvalds 
ipip_output(struct xfrm_state * x,struct sk_buff * skb)141da177e4SLinus Torvalds static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
151da177e4SLinus Torvalds {
167b277b1aSHerbert Xu 	skb_push(skb, -skb_network_offset(skb));
171da177e4SLinus Torvalds 	return 0;
181da177e4SLinus Torvalds }
191da177e4SLinus Torvalds 
ipip_xfrm_rcv(struct xfrm_state * x,struct sk_buff * skb)20e695633eSHerbert Xu static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
211da177e4SLinus Torvalds {
2204663d0bSHerbert Xu 	return ip_hdr(skb)->protocol;
231da177e4SLinus Torvalds }
241da177e4SLinus Torvalds 
ipip_init_state(struct xfrm_state * x,struct netlink_ext_ack * extack)25e1e10b44SSabrina Dubroca static int ipip_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
261da177e4SLinus Torvalds {
27*25ec92cdSSabrina Dubroca 	if (x->props.mode != XFRM_MODE_TUNNEL) {
28*25ec92cdSSabrina Dubroca 		NL_SET_ERR_MSG(extack, "IPv4 tunnel can only be used with tunnel mode");
291da177e4SLinus Torvalds 		return -EINVAL;
30*25ec92cdSSabrina Dubroca 	}
311da177e4SLinus Torvalds 
32*25ec92cdSSabrina Dubroca 	if (x->encap) {
33*25ec92cdSSabrina Dubroca 		NL_SET_ERR_MSG(extack, "IPv4 tunnel is not compatible with encapsulation");
341da177e4SLinus Torvalds 		return -EINVAL;
35*25ec92cdSSabrina Dubroca 	}
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 	x->props.header_len = sizeof(struct iphdr);
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds 	return 0;
401da177e4SLinus Torvalds }
411da177e4SLinus Torvalds 
ipip_destroy(struct xfrm_state * x)421da177e4SLinus Torvalds static void ipip_destroy(struct xfrm_state *x)
431da177e4SLinus Torvalds {
441da177e4SLinus Torvalds }
451da177e4SLinus Torvalds 
46533cb5b0SEric Dumazet static const struct xfrm_type ipip_type = {
471da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
481da177e4SLinus Torvalds 	.proto	     	= IPPROTO_IPIP,
491da177e4SLinus Torvalds 	.init_state	= ipip_init_state,
501da177e4SLinus Torvalds 	.destructor	= ipip_destroy,
511da177e4SLinus Torvalds 	.input		= ipip_xfrm_rcv,
521da177e4SLinus Torvalds 	.output		= ipip_output
531da177e4SLinus Torvalds };
541da177e4SLinus Torvalds 
xfrm_tunnel_rcv(struct sk_buff * skb)55c4541b41SHerbert Xu static int xfrm_tunnel_rcv(struct sk_buff *skb)
56c4541b41SHerbert Xu {
57b1641064SHerbert Xu 	return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
58c4541b41SHerbert Xu }
59c4541b41SHerbert Xu 
xfrm_tunnel_err(struct sk_buff * skb,u32 info)60d2acc347SHerbert Xu static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
61d2acc347SHerbert Xu {
62d2acc347SHerbert Xu 	return -ENOENT;
63d2acc347SHerbert Xu }
64d2acc347SHerbert Xu 
656dcd814bSEric Dumazet static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = {
66c4541b41SHerbert Xu 	.handler	=	xfrm_tunnel_rcv,
67d2acc347SHerbert Xu 	.err_handler	=	xfrm_tunnel_err,
687fe94612SXin Long 	.priority	=	4,
691da177e4SLinus Torvalds };
701da177e4SLinus Torvalds 
71dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
726dcd814bSEric Dumazet static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = {
73c4541b41SHerbert Xu 	.handler	=	xfrm_tunnel_rcv,
74c0d56408SKazunori MIYAZAWA 	.err_handler	=	xfrm_tunnel_err,
757fe94612SXin Long 	.priority	=	3,
76c0d56408SKazunori MIYAZAWA };
77c0d56408SKazunori MIYAZAWA #endif
78c0d56408SKazunori MIYAZAWA 
ipip_init(void)791da177e4SLinus Torvalds static int __init ipip_init(void)
801da177e4SLinus Torvalds {
811da177e4SLinus Torvalds 	if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
82058bd4d2SJoe Perches 		pr_info("%s: can't add xfrm type\n", __func__);
831da177e4SLinus Torvalds 		return -EAGAIN;
841da177e4SLinus Torvalds 	}
85c0d56408SKazunori MIYAZAWA 
86c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
87058bd4d2SJoe Perches 		pr_info("%s: can't add xfrm handler for AF_INET\n", __func__);
881da177e4SLinus Torvalds 		xfrm_unregister_type(&ipip_type, AF_INET);
891da177e4SLinus Torvalds 		return -EAGAIN;
901da177e4SLinus Torvalds 	}
91dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
92c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
93058bd4d2SJoe Perches 		pr_info("%s: can't add xfrm handler for AF_INET6\n", __func__);
94c0d56408SKazunori MIYAZAWA 		xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
95c0d56408SKazunori MIYAZAWA 		xfrm_unregister_type(&ipip_type, AF_INET);
96c0d56408SKazunori MIYAZAWA 		return -EAGAIN;
97c0d56408SKazunori MIYAZAWA 	}
98c0d56408SKazunori MIYAZAWA #endif
991da177e4SLinus Torvalds 	return 0;
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds 
ipip_fini(void)1021da177e4SLinus Torvalds static void __exit ipip_fini(void)
1031da177e4SLinus Torvalds {
104dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
105c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
106058bd4d2SJoe Perches 		pr_info("%s: can't remove xfrm handler for AF_INET6\n",
107058bd4d2SJoe Perches 			__func__);
108c0d56408SKazunori MIYAZAWA #endif
109c0d56408SKazunori MIYAZAWA 	if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
110058bd4d2SJoe Perches 		pr_info("%s: can't remove xfrm handler for AF_INET\n",
111058bd4d2SJoe Perches 			__func__);
1124f518e80SFlorian Westphal 	xfrm_unregister_type(&ipip_type, AF_INET);
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds module_init(ipip_init);
1161da177e4SLinus Torvalds module_exit(ipip_fini);
1171da177e4SLinus Torvalds MODULE_LICENSE("GPL");
118d3d6dd3aSMasahide NAKAMURA MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
119