Blame view

net/ipv6/xfrm6_state.c 4.46 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>
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
18
  #include <net/dsfield.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <net/ipv6.h>
ee51b1b6c   Patrick McHardy   [XFRM]: IPsec tun...
20
  #include <net/addrconf.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
27
28
29
30
31
32
33
  
  static struct xfrm_state_afinfo xfrm6_state_afinfo;
  
  static void
  __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
  		     struct xfrm_tmpl *tmpl,
  		     xfrm_address_t *daddr, xfrm_address_t *saddr)
  {
  	/* Initialize temporary selector matching only
  	 * to current session. */
  	ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
  	ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
  	x->sel.dport = xfrm_flowi_dport(fl);
8f83f23e6   Al Viro   [XFRM]: ports in ...
34
  	x->sel.dport_mask = htons(0xffff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  	x->sel.sport = xfrm_flowi_sport(fl);
8f83f23e6   Al Viro   [XFRM]: ports in ...
36
  	x->sel.sport_mask = htons(0xffff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  	x->sel.prefixlen_d = 128;
  	x->sel.prefixlen_s = 128;
  	x->sel.proto = fl->proto;
  	x->sel.ifindex = fl->oif;
  	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 ...
51
  /* distribution counting sort function for xfrm_state and xfrm_tmpl */
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
52
  static int
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
53
  __xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass)
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
54
55
  {
  	int i;
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
56
57
  	int class[XFRM_MAX_DEPTH];
  	int count[maxclass];
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
58

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

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

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

58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
70
  	for (i = 0; i < n; i++) {
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
71
72
  		dst[count[class[i] - 1]++] = src[i];
  		src[i] = 0;
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
73
  	}
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
74

58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
75
76
  	return 0;
  }
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
77
78
79
80
81
82
83
84
85
86
  /*
   * 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 ...
87
  {
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
88
89
90
91
92
93
94
95
  	struct xfrm_state *v = p;
  
  	switch (v->props.mode) {
  	case XFRM_MODE_TRANSPORT:
  		if (v->id.proto != IPPROTO_AH)
  			return 1;
  		else
  			return 3;
59fbb3a61   Masahide NAKAMURA   [IPV6] MIP6: Load...
96
  #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
97
98
99
  	case XFRM_MODE_ROUTEOPTIMIZATION:
  	case XFRM_MODE_IN_TRIGGER:
  		return 2;
64d9fdda8   Masahide NAKAMURA   [XFRM] IPV6: Supp...
100
  #endif
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
101
102
103
  	case XFRM_MODE_TUNNEL:
  	case XFRM_MODE_BEET:
  		return 4;
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
104
  	}
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
105
106
  	return 5;
  }
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
107

3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  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;
  #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
  	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 ...
137
  	}
3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
138
139
  	return 4;
  }
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
140

3b6cdf94c   YOSHIFUJI Hideaki   [XFRM] IPV6: Use ...
141
142
143
144
145
  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 ...
146
  }
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
147
148
149
  int xfrm6_extract_header(struct sk_buff *skb)
  {
  	struct ipv6hdr *iph = ipv6_hdr(skb);
732c8bd59   Herbert Xu   [IPSEC]: Fix BEET...
150
  	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
151
152
153
154
  	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...
155
  	XFRM_MODE_SKB_CB(skb)->optlen = 0;
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
156
157
158
159
160
  	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
161
162
  static struct xfrm_state_afinfo xfrm6_state_afinfo = {
  	.family			= AF_INET6,
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
163
  	.proto			= IPPROTO_IPV6,
227620e29   Herbert Xu   [IPSEC]: Separate...
164
  	.eth_proto		= htons(ETH_P_IPV6),
17c2a42a2   Herbert Xu   [IPSEC]: Store af...
165
  	.owner			= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  	.init_tempsel		= __xfrm6_init_tempsel,
58c949d1b   Masahide NAKAMURA   [XFRM] IPV6: Add ...
167
168
  	.tmpl_sort		= __xfrm6_tmpl_sort,
  	.state_sort		= __xfrm6_state_sort,
cdca72652   Miika Komu   [IPSEC]: exportin...
169
  	.output			= xfrm6_output,
227620e29   Herbert Xu   [IPSEC]: Separate...
170
  	.extract_input		= xfrm6_extract_input,
36cf9acf9   Herbert Xu   [IPSEC]: Separate...
171
  	.extract_output		= xfrm6_extract_output,
716062fd4   Herbert Xu   [IPSEC]: Merge mo...
172
  	.transport_finish	= xfrm6_transport_finish,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  };
0013cabab   Daniel Lezcano   [IPV6]: Make xfrm...
174
  int __init xfrm6_state_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  {
0013cabab   Daniel Lezcano   [IPV6]: Make xfrm...
176
  	return xfrm_state_register_afinfo(&xfrm6_state_afinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
181
182
  }
  
  void xfrm6_state_fini(void)
  {
  	xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
  }