Blame view

net/ipv6/xfrm6_state.c 4.58 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   * xfrm6_state.c: based on xfrm4_state.c
   *
   * Authors:
   *	Mitsuru KANDA @USAGI
   * 	Kazunori MIYAZAWA @USAGI
   * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
   * 		IPv6 support
   * 	YOSHIFUJI Hideaki @USAGI
   * 		Split up af-specific portion
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
11
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
   */
  
  #include <net/xfrm.h>
  #include <linux/pfkeyv2.h>
  #include <linux/ipsec.h>
862b82c6f   Herbert Xu   [IPSEC]: Merge mo...
17
  #include <linux/netfilter_ipv6.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
18
  #include <linux/export.h>
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
19
  #include <net/dsfield.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <net/ipv6.h>
ee51b1b6c   Patrick McHardy   [XFRM]: IPsec tun...
21
  #include <net/addrconf.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  static void
73e5ebb20   David S. Miller   xfrm: Mark flowi ...
24
  __xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  {
7e1dc7b6f   David S. Miller   net: Use flowi4 a...
26
  	const struct flowi6 *fl6 = &fl->u.ip6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  	/* Initialize temporary selector matching only
  	 * to current session. */
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
29
30
  	*(struct in6_addr *)&sel->daddr = fl6->daddr;
  	*(struct in6_addr *)&sel->saddr = fl6->saddr;
7e1dc7b6f   David S. Miller   net: Use flowi4 a...
31
  	sel->dport = xfrm_flowi_dport(fl, &fl6->uli);
8444cf712   Thomas Egerer   xfrm: Allow diffe...
32
  	sel->dport_mask = htons(0xffff);
7e1dc7b6f   David S. Miller   net: Use flowi4 a...
33
  	sel->sport = xfrm_flowi_sport(fl, &fl6->uli);
8444cf712   Thomas Egerer   xfrm: Allow diffe...
34
35
36
37
  	sel->sport_mask = htons(0xffff);
  	sel->family = AF_INET6;
  	sel->prefixlen_d = 128;
  	sel->prefixlen_s = 128;
7e1dc7b6f   David S. Miller   net: Use flowi4 a...
38
39
  	sel->proto = fl6->flowi6_proto;
  	sel->ifindex = fl6->flowi6_oif;
8444cf712   Thomas Egerer   xfrm: Allow diffe...
40
41
42
  }
  
  static void
19bd62441   David S. Miller   xfrm: Const'ify t...
43
44
  xfrm6_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl,
  		   const xfrm_address_t *daddr, const xfrm_address_t *saddr)
8444cf712   Thomas Egerer   xfrm: Allow diffe...
45
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
55
  	x->id = tmpl->id;
  	if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
  		memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
  	memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
  	if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
  		memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
  	x->props.mode = tmpl->mode;
  	x->props.reqid = tmpl->reqid;
  	x->props.family = AF_INET6;
  }
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
56
  /* distribution counting sort function for xfrm_state and xfrm_tmpl */
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
57
  static int
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
58
  __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass)
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
59
60
  {
  	int i;
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
61
62
  	int class[XFRM_MAX_DEPTH];
  	int count[maxclass];
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
63

3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
64
  	memset(count, 0, sizeof(count));
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
65

64d9fdda8   Masahide NAKAMURA   [XFRM] IPV6: Supp...
66
  	for (i = 0; i < n; i++) {
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
67
68
69
  		int c;
  		class[i] = c = cmp(src[i]);
  		count[c]++;
64d9fdda8   Masahide NAKAMURA   [XFRM] IPV6: Supp...
70
  	}
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
71

3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
72
73
  	for (i = 2; i < maxclass; i++)
  		count[i] += count[i - 1];
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
74

58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
75
  	for (i = 0; i < n; i++) {
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
76
  		dst[count[class[i] - 1]++] = src[i];
66da8c529   Hannes Eder   ipv6: fix sparse ...
77
  		src[i] = NULL;
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
78
  	}
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
79

58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
80
81
  	return 0;
  }
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
82
83
84
85
86
87
88
89
90
91
  /*
   * Rule for xfrm_state:
   *
   * rule 1: select IPsec transport except AH
   * rule 2: select MIPv6 RO or inbound trigger
   * rule 3: select IPsec transport AH
   * rule 4: select IPsec tunnel
   * rule 5: others
   */
  static int __xfrm6_state_sort_cmp(void *p)
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
92
  {
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
93
94
95
96
97
98
99
100
  	struct xfrm_state *v = p;
  
  	switch (v->props.mode) {
  	case XFRM_MODE_TRANSPORT:
  		if (v->id.proto != IPPROTO_AH)
  			return 1;
  		else
  			return 3;
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
101
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
102
103
104
  	case XFRM_MODE_ROUTEOPTIMIZATION:
  	case XFRM_MODE_IN_TRIGGER:
  		return 2;
64d9fdda8   Masahide NAKAMURA   [XFRM] IPV6: Supp...
105
  #endif
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
106
107
108
  	case XFRM_MODE_TUNNEL:
  	case XFRM_MODE_BEET:
  		return 4;
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
109
  	}
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
110
111
  	return 5;
  }
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
112

3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  static int
  __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
  {
  	return __xfrm6_sort((void **)dst, (void **)src, n,
  			    __xfrm6_state_sort_cmp, 6);
  }
  
  /*
   * Rule for xfrm_tmpl:
   *
   * rule 1: select IPsec transport
   * rule 2: select MIPv6 RO or inbound trigger
   * rule 3: select IPsec tunnel
   * rule 4: others
   */
  static int __xfrm6_tmpl_sort_cmp(void *p)
  {
  	struct xfrm_tmpl *v = p;
  	switch (v->mode) {
  	case XFRM_MODE_TRANSPORT:
  		return 1;
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
134
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
135
136
137
138
139
140
141
  	case XFRM_MODE_ROUTEOPTIMIZATION:
  	case XFRM_MODE_IN_TRIGGER:
  		return 2;
  #endif
  	case XFRM_MODE_TUNNEL:
  	case XFRM_MODE_BEET:
  		return 3;
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
142
  	}
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
143
144
  	return 4;
  }
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
145

3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
146
147
148
149
150
  static int
  __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
  {
  	return __xfrm6_sort((void **)dst, (void **)src, n,
  			    __xfrm6_tmpl_sort_cmp, 5);
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
151
  }
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
152
153
154
  int xfrm6_extract_header(struct sk_buff *skb)
  {
  	struct ipv6hdr *iph = ipv6_hdr(skb);
732c8bd59   Herbert Xu   [IPSEC]: Fix BEET...
155
  	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
156
157
158
159
  	XFRM_MODE_SKB_CB(skb)->id = 0;
  	XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF);
  	XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph);
  	XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit;
732c8bd59   Herbert Xu   [IPSEC]: Fix BEET...
160
  	XFRM_MODE_SKB_CB(skb)->optlen = 0;
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
161
162
163
164
165
  	memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl,
  	       sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
  static struct xfrm_state_afinfo xfrm6_state_afinfo = {
  	.family			= AF_INET6,
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
168
  	.proto			= IPPROTO_IPV6,
227620e29   Herbert Xu   [IPSEC]: Separate...
169
  	.eth_proto		= htons(ETH_P_IPV6),
17c2a42a2   Herbert Xu   [IPSEC]: Store af...
170
  	.owner			= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  	.init_tempsel		= __xfrm6_init_tempsel,
8444cf712   Thomas Egerer   xfrm: Allow diffe...
172
  	.init_temprop		= xfrm6_init_temprop,
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
173
174
  	.tmpl_sort		= __xfrm6_tmpl_sort,
  	.state_sort		= __xfrm6_state_sort,
cdca72652   Miika Komu   [IPSEC]: exportin...
175
  	.output			= xfrm6_output,
43a4dea4c   Steffen Klassert   xfrm: Assign the ...
176
  	.output_finish		= xfrm6_output_finish,
227620e29   Herbert Xu   [IPSEC]: Separate...
177
  	.extract_input		= xfrm6_extract_input,
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
178
  	.extract_output		= xfrm6_extract_output,
716062fd4   Herbert Xu   [IPSEC]: Merge mo...
179
  	.transport_finish	= xfrm6_transport_finish,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  };
0013cabab   Daniel Lezcano   [IPV6]: Make xfrm...
181
  int __init xfrm6_state_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  {
0013cabab   Daniel Lezcano   [IPV6]: Make xfrm...
183
  	return xfrm_state_register_afinfo(&xfrm6_state_afinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
  }
  
  void xfrm6_state_fini(void)
  {
  	xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
  }