11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * xfrm4_state.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Changes:
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	YOSHIFUJI Hideaki @USAGI
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 		Split up af-specific portion
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu#include <net/ip.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/xfrm.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pfkeyv2.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ipsec.h>
14862b82c6f960cc61274d370aa78ce1112f92a83eHerbert Xu#include <linux/netfilter_ipv4.h>
15bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xustatic int xfrm4_init_flags(struct xfrm_state *x)
18dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu{
19974eda11c54290a1be8f8b155edae7d791e5ce57Hannes Frederic Sowa	if (xs_net(x)->ipv4.sysctl_ip_no_pmtu_disc)
20dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu		x->props.flags |= XFRM_STATE_NOPMTUDISC;
21dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu	return 0;
22dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu}
23dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2573e5ebb20f2809e2eb0b904448481e010c2599d7David S. Miller__xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
268444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer{
277e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	const struct flowi4 *fl4 = &fl->u.ip4;
287e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller
297e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	sel->daddr.a4 = fl4->daddr;
307e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	sel->saddr.a4 = fl4->saddr;
317e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	sel->dport = xfrm_flowi_dport(fl, &fl4->uli);
328444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer	sel->dport_mask = htons(0xffff);
337e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	sel->sport = xfrm_flowi_sport(fl, &fl4->uli);
348444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer	sel->sport_mask = htons(0xffff);
358444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer	sel->family = AF_INET;
368444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer	sel->prefixlen_d = 32;
378444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer	sel->prefixlen_s = 32;
387e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	sel->proto = fl4->flowi4_proto;
397e1dc7b6f709dfc1a9ab4b320dbe723f45992693David S. Miller	sel->ifindex = fl4->flowi4_oif;
408444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer}
418444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer
428444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egererstatic void
4319bd62441c36279ab33e311faebd357ef04ba344David S. Millerxfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl,
4419bd62441c36279ab33e311faebd357ef04ba344David S. Miller		   const xfrm_address_t *daddr, const xfrm_address_t *saddr)
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x->id = tmpl->id;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (x->id.daddr.a4 == 0)
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x->id.daddr.a4 = daddr->a4;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x->props.saddr = tmpl->saddr;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (x->props.saddr.a4 == 0)
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x->props.saddr.a4 = saddr->a4;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x->props.mode = tmpl->mode;
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x->props.reqid = tmpl->reqid;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x->props.family = AF_INET;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5736cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xuint xfrm4_extract_header(struct sk_buff *skb)
5836cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu{
59b71d1d426d263b0b6cb5760322efebbfc89d4463Eric Dumazet	const struct iphdr *iph = ip_hdr(skb);
6036cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu
61732c8bd590625e8bc0b88313b82930e336b2bec4Herbert Xu	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
6236cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	XFRM_MODE_SKB_CB(skb)->id = iph->id;
6336cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
6436cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
6536cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
66732c8bd590625e8bc0b88313b82930e336b2bec4Herbert Xu	XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph);
6736cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
6836cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	       sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
6936cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu
7036cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	return 0;
7136cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu}
7236cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct xfrm_state_afinfo xfrm4_state_afinfo = {
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.family			= AF_INET,
7536cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	.proto			= IPPROTO_IPIP,
76227620e295090629fcb2c46ad3828222ab65438dHerbert Xu	.eth_proto		= htons(ETH_P_IP),
7717c2a42a24e1e8dd6aa7cea4f84e034ab1bfff31Herbert Xu	.owner			= THIS_MODULE,
78dd87147eed934eaff92869f3d158697c7239d1d2Herbert Xu	.init_flags		= xfrm4_init_flags,
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init_tempsel		= __xfrm4_init_tempsel,
808444cf712c5f71845cba9dc30d8f530ff0d5ff83Thomas Egerer	.init_temprop		= xfrm4_init_temprop,
81cdca72652adf597f7fef821a27595fd0dd5eea19Miika Komu	.output			= xfrm4_output,
8243a4dea4c9d44baae38ddc14b9b6d86fde4c8b88Steffen Klassert	.output_finish		= xfrm4_output_finish,
83227620e295090629fcb2c46ad3828222ab65438dHerbert Xu	.extract_input		= xfrm4_extract_input,
8436cf9acf93e8561d9faec24849e57688a81eb9c5Herbert Xu	.extract_output		= xfrm4_extract_output,
85716062fd4c2f88a33ab409f62a1e7397ad0a7e33Herbert Xu	.transport_finish	= xfrm4_transport_finish,
86628e341f319f1a64a4639088faba952e4ec8f0a8Hannes Frederic Sowa	.local_error		= xfrm4_local_error,
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init xfrm4_state_init(void)
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xfrm_state_register_afinfo(&xfrm4_state_afinfo);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
940742fd53a3774781255bd1e471e7aa2e4a82d5f7Adrian Bunk#if 0
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __exit xfrm4_state_fini(void)
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
990742fd53a3774781255bd1e471e7aa2e4a82d5f7Adrian Bunk#endif  /*  0  */
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101