xref: /linux/net/ipv4/xfrm4_state.c (revision 628e341f319f1a64a4639088faba952e4ec8f0a8)
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>
15bc3b2d7fSPaul Gortmaker #include <linux/export.h>
161da177e4SLinus Torvalds 
17dd87147eSHerbert Xu static int xfrm4_init_flags(struct xfrm_state *x)
18dd87147eSHerbert Xu {
19dd87147eSHerbert Xu 	if (ipv4_config.no_pmtu_disc)
20dd87147eSHerbert Xu 		x->props.flags |= XFRM_STATE_NOPMTUDISC;
21dd87147eSHerbert Xu 	return 0;
22dd87147eSHerbert Xu }
23dd87147eSHerbert Xu 
241da177e4SLinus Torvalds static void
2573e5ebb2SDavid S. Miller __xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
268444cf71SThomas Egerer {
277e1dc7b6SDavid S. Miller 	const struct flowi4 *fl4 = &fl->u.ip4;
287e1dc7b6SDavid S. Miller 
297e1dc7b6SDavid S. Miller 	sel->daddr.a4 = fl4->daddr;
307e1dc7b6SDavid S. Miller 	sel->saddr.a4 = fl4->saddr;
317e1dc7b6SDavid S. Miller 	sel->dport = xfrm_flowi_dport(fl, &fl4->uli);
328444cf71SThomas Egerer 	sel->dport_mask = htons(0xffff);
337e1dc7b6SDavid S. Miller 	sel->sport = xfrm_flowi_sport(fl, &fl4->uli);
348444cf71SThomas Egerer 	sel->sport_mask = htons(0xffff);
358444cf71SThomas Egerer 	sel->family = AF_INET;
368444cf71SThomas Egerer 	sel->prefixlen_d = 32;
378444cf71SThomas Egerer 	sel->prefixlen_s = 32;
387e1dc7b6SDavid S. Miller 	sel->proto = fl4->flowi4_proto;
397e1dc7b6SDavid S. Miller 	sel->ifindex = fl4->flowi4_oif;
408444cf71SThomas Egerer }
418444cf71SThomas Egerer 
428444cf71SThomas Egerer static void
4319bd6244SDavid S. Miller xfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl,
4419bd6244SDavid S. Miller 		   const xfrm_address_t *daddr, const xfrm_address_t *saddr)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds 	x->id = tmpl->id;
471da177e4SLinus Torvalds 	if (x->id.daddr.a4 == 0)
481da177e4SLinus Torvalds 		x->id.daddr.a4 = daddr->a4;
491da177e4SLinus Torvalds 	x->props.saddr = tmpl->saddr;
501da177e4SLinus Torvalds 	if (x->props.saddr.a4 == 0)
511da177e4SLinus Torvalds 		x->props.saddr.a4 = saddr->a4;
521da177e4SLinus Torvalds 	x->props.mode = tmpl->mode;
531da177e4SLinus Torvalds 	x->props.reqid = tmpl->reqid;
541da177e4SLinus Torvalds 	x->props.family = AF_INET;
551da177e4SLinus Torvalds }
561da177e4SLinus Torvalds 
5736cf9acfSHerbert Xu int xfrm4_extract_header(struct sk_buff *skb)
5836cf9acfSHerbert Xu {
59b71d1d42SEric Dumazet 	const struct iphdr *iph = ip_hdr(skb);
6036cf9acfSHerbert Xu 
61732c8bd5SHerbert Xu 	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
6236cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->id = iph->id;
6336cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
6436cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
6536cf9acfSHerbert Xu 	XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
66732c8bd5SHerbert Xu 	XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph);
6736cf9acfSHerbert Xu 	memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
6836cf9acfSHerbert Xu 	       sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
6936cf9acfSHerbert Xu 
7036cf9acfSHerbert Xu 	return 0;
7136cf9acfSHerbert Xu }
7236cf9acfSHerbert Xu 
731da177e4SLinus Torvalds static struct xfrm_state_afinfo xfrm4_state_afinfo = {
741da177e4SLinus Torvalds 	.family			= AF_INET,
7536cf9acfSHerbert Xu 	.proto			= IPPROTO_IPIP,
76227620e2SHerbert Xu 	.eth_proto		= htons(ETH_P_IP),
7717c2a42aSHerbert Xu 	.owner			= THIS_MODULE,
78dd87147eSHerbert Xu 	.init_flags		= xfrm4_init_flags,
791da177e4SLinus Torvalds 	.init_tempsel		= __xfrm4_init_tempsel,
808444cf71SThomas Egerer 	.init_temprop		= xfrm4_init_temprop,
81cdca7265SMiika Komu 	.output			= xfrm4_output,
8243a4dea4SSteffen Klassert 	.output_finish		= xfrm4_output_finish,
83227620e2SHerbert Xu 	.extract_input		= xfrm4_extract_input,
8436cf9acfSHerbert Xu 	.extract_output		= xfrm4_extract_output,
85716062fdSHerbert Xu 	.transport_finish	= xfrm4_transport_finish,
86*628e341fSHannes Frederic Sowa 	.local_error		= xfrm4_local_error,
871da177e4SLinus Torvalds };
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds void __init xfrm4_state_init(void)
901da177e4SLinus Torvalds {
911da177e4SLinus Torvalds 	xfrm_state_register_afinfo(&xfrm4_state_afinfo);
921da177e4SLinus Torvalds }
931da177e4SLinus Torvalds 
940742fd53SAdrian Bunk #if 0
951da177e4SLinus Torvalds void __exit xfrm4_state_fini(void)
961da177e4SLinus Torvalds {
971da177e4SLinus Torvalds 	xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
981da177e4SLinus Torvalds }
990742fd53SAdrian Bunk #endif  /*  0  */
1001da177e4SLinus Torvalds 
101