xref: /linux/net/ipv4/xfrm4_state.c (revision 7e1dc7b6f709dfc1a9ab4b320dbe723f45992693)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * xfrm4_state.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Changes:
51da177e4SLinus Torvalds  * 	YOSHIFUJI Hideaki @USAGI
61da177e4SLinus Torvalds  * 		Split up af-specific portion
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
10dd87147eSHerbert Xu #include <net/ip.h>
111da177e4SLinus Torvalds #include <net/xfrm.h>
121da177e4SLinus Torvalds #include <linux/pfkeyv2.h>
131da177e4SLinus Torvalds #include <linux/ipsec.h>
14862b82c6SHerbert Xu #include <linux/netfilter_ipv4.h>
151da177e4SLinus Torvalds 
16dd87147eSHerbert Xu static int xfrm4_init_flags(struct xfrm_state *x)
17dd87147eSHerbert Xu {
18dd87147eSHerbert Xu 	if (ipv4_config.no_pmtu_disc)
19dd87147eSHerbert Xu 		x->props.flags |= XFRM_STATE_NOPMTUDISC;
20dd87147eSHerbert Xu 	return 0;
21dd87147eSHerbert Xu }
22dd87147eSHerbert Xu 
231da177e4SLinus Torvalds static void
2473e5ebb2SDavid S. Miller __xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
258444cf71SThomas Egerer {
26*7e1dc7b6SDavid S. Miller 	const struct flowi4 *fl4 = &fl->u.ip4;
27*7e1dc7b6SDavid S. Miller 
28*7e1dc7b6SDavid S. Miller 	sel->daddr.a4 = fl4->daddr;
29*7e1dc7b6SDavid S. Miller 	sel->saddr.a4 = fl4->saddr;
30*7e1dc7b6SDavid S. Miller 	sel->dport = xfrm_flowi_dport(fl, &fl4->uli);
318444cf71SThomas Egerer 	sel->dport_mask = htons(0xffff);
32*7e1dc7b6SDavid S. Miller 	sel->sport = xfrm_flowi_sport(fl, &fl4->uli);
338444cf71SThomas Egerer 	sel->sport_mask = htons(0xffff);
348444cf71SThomas Egerer 	sel->family = AF_INET;
358444cf71SThomas Egerer 	sel->prefixlen_d = 32;
368444cf71SThomas Egerer 	sel->prefixlen_s = 32;
37*7e1dc7b6SDavid S. Miller 	sel->proto = fl4->flowi4_proto;
38*7e1dc7b6SDavid S. Miller 	sel->ifindex = fl4->flowi4_oif;
398444cf71SThomas Egerer }
408444cf71SThomas Egerer 
418444cf71SThomas Egerer static void
4219bd6244SDavid S. Miller xfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl,
4319bd6244SDavid S. Miller 		   const xfrm_address_t *daddr, const xfrm_address_t *saddr)
441da177e4SLinus Torvalds {
451da177e4SLinus Torvalds 	x->id = tmpl->id;
461da177e4SLinus Torvalds 	if (x->id.daddr.a4 == 0)
471da177e4SLinus Torvalds 		x->id.daddr.a4 = daddr->a4;
481da177e4SLinus Torvalds 	x->props.saddr = tmpl->saddr;
491da177e4SLinus Torvalds 	if (x->props.saddr.a4 == 0)
501da177e4SLinus Torvalds 		x->props.saddr.a4 = saddr->a4;
511da177e4SLinus Torvalds 	x->props.mode = tmpl->mode;
521da177e4SLinus Torvalds 	x->props.reqid = tmpl->reqid;
531da177e4SLinus Torvalds 	x->props.family = AF_INET;
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds 
5636cf9acfSHerbert Xu int xfrm4_extract_header(struct sk_buff *skb)
5736cf9acfSHerbert Xu {
5836cf9acfSHerbert Xu 	struct iphdr *iph = ip_hdr(skb);
5936cf9acfSHerbert Xu 
60732c8bd5SHerbert Xu 	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
6136cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->id = iph->id;
6236cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
6336cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
6436cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
65732c8bd5SHerbert Xu 	XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph);
6636cf9acfSHerbert Xu 	memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
6736cf9acfSHerbert Xu 	       sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
6836cf9acfSHerbert Xu 
6936cf9acfSHerbert Xu 	return 0;
7036cf9acfSHerbert Xu }
7136cf9acfSHerbert Xu 
721da177e4SLinus Torvalds static struct xfrm_state_afinfo xfrm4_state_afinfo = {
731da177e4SLinus Torvalds 	.family			= AF_INET,
7436cf9acfSHerbert Xu 	.proto			= IPPROTO_IPIP,
75227620e2SHerbert Xu 	.eth_proto		= htons(ETH_P_IP),
7617c2a42aSHerbert Xu 	.owner			= THIS_MODULE,
77dd87147eSHerbert Xu 	.init_flags		= xfrm4_init_flags,
781da177e4SLinus Torvalds 	.init_tempsel		= __xfrm4_init_tempsel,
798444cf71SThomas Egerer 	.init_temprop		= xfrm4_init_temprop,
80cdca7265SMiika Komu 	.output			= xfrm4_output,
81227620e2SHerbert Xu 	.extract_input		= xfrm4_extract_input,
8236cf9acfSHerbert Xu 	.extract_output		= xfrm4_extract_output,
83716062fdSHerbert Xu 	.transport_finish	= xfrm4_transport_finish,
841da177e4SLinus Torvalds };
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds void __init xfrm4_state_init(void)
871da177e4SLinus Torvalds {
881da177e4SLinus Torvalds 	xfrm_state_register_afinfo(&xfrm4_state_afinfo);
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds 
910742fd53SAdrian Bunk #if 0
921da177e4SLinus Torvalds void __exit xfrm4_state_fini(void)
931da177e4SLinus Torvalds {
941da177e4SLinus Torvalds 	xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
951da177e4SLinus Torvalds }
960742fd53SAdrian Bunk #endif  /*  0  */
971da177e4SLinus Torvalds 
98