[IPV6] address: Convert address dumping to new netlink api
[deliverable/linux.git] / net / ipv6 / xfrm6_state.c
CommitLineData
1da177e4
LT
1/*
2 * xfrm6_state.c: based on xfrm4_state.c
3 *
4 * Authors:
5 * Mitsuru KANDA @USAGI
6 * Kazunori MIYAZAWA @USAGI
7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
8 * IPv6 support
9 * YOSHIFUJI Hideaki @USAGI
10 * Split up af-specific portion
11 *
12 */
13
14#include <net/xfrm.h>
15#include <linux/pfkeyv2.h>
16#include <linux/ipsec.h>
17#include <net/ipv6.h>
ee51b1b6 18#include <net/addrconf.h>
1da177e4
LT
19
20static struct xfrm_state_afinfo xfrm6_state_afinfo;
21
22static void
23__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
24 struct xfrm_tmpl *tmpl,
25 xfrm_address_t *daddr, xfrm_address_t *saddr)
26{
27 /* Initialize temporary selector matching only
28 * to current session. */
29 ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
30 ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
31 x->sel.dport = xfrm_flowi_dport(fl);
32 x->sel.dport_mask = ~0;
33 x->sel.sport = xfrm_flowi_sport(fl);
34 x->sel.sport_mask = ~0;
35 x->sel.prefixlen_d = 128;
36 x->sel.prefixlen_s = 128;
37 x->sel.proto = fl->proto;
38 x->sel.ifindex = fl->oif;
39 x->id = tmpl->id;
40 if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
41 memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
42 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
43 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
44 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
7e49e6de 45 if (tmpl->mode == XFRM_MODE_TUNNEL && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) {
ee51b1b6
PM
46 struct rt6_info *rt;
47 struct flowi fl_tunnel = {
48 .nl_u = {
49 .ip6_u = {
50 .daddr = *(struct in6_addr *)daddr,
51 }
52 }
53 };
54 if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
55 &fl_tunnel, AF_INET6)) {
56 ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr,
57 (struct in6_addr *)&x->props.saddr);
58 dst_release(&rt->u.dst);
59 }
60 }
1da177e4
LT
61 x->props.mode = tmpl->mode;
62 x->props.reqid = tmpl->reqid;
63 x->props.family = AF_INET6;
64}
65
58c949d1
MN
66static int
67__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
68{
69 int i;
70 int j = 0;
71
72 /* Rule 1: select IPsec transport except AH */
73 for (i = 0; i < n; i++) {
74 if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
75 src[i]->id.proto != IPPROTO_AH) {
76 dst[j++] = src[i];
77 src[i] = NULL;
78 }
79 }
80 if (j == n)
81 goto end;
82
64d9fdda
MN
83 /* Rule 2: select MIPv6 RO or inbound trigger */
84#ifdef CONFIG_IPV6_MIP6
85 for (i = 0; i < n; i++) {
86 if (src[i] &&
87 (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
88 src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) {
89 dst[j++] = src[i];
90 src[i] = NULL;
91 }
92 }
93 if (j == n)
94 goto end;
95#endif
58c949d1
MN
96
97 /* Rule 3: select IPsec transport AH */
98 for (i = 0; i < n; i++) {
99 if (src[i] &&
100 src[i]->props.mode == XFRM_MODE_TRANSPORT &&
101 src[i]->id.proto == IPPROTO_AH) {
102 dst[j++] = src[i];
103 src[i] = NULL;
104 }
105 }
106 if (j == n)
107 goto end;
108
109 /* Rule 4: select IPsec tunnel */
110 for (i = 0; i < n; i++) {
111 if (src[i] &&
112 src[i]->props.mode == XFRM_MODE_TUNNEL) {
113 dst[j++] = src[i];
114 src[i] = NULL;
115 }
116 }
117 if (likely(j == n))
118 goto end;
119
120 /* Final rule */
121 for (i = 0; i < n; i++) {
122 if (src[i]) {
123 dst[j++] = src[i];
124 src[i] = NULL;
125 }
126 }
127
128 end:
129 return 0;
130}
131
132static int
133__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
134{
135 int i;
136 int j = 0;
137
138 /* Rule 1: select IPsec transport */
139 for (i = 0; i < n; i++) {
140 if (src[i]->mode == XFRM_MODE_TRANSPORT) {
141 dst[j++] = src[i];
142 src[i] = NULL;
143 }
144 }
145 if (j == n)
146 goto end;
147
64d9fdda
MN
148 /* Rule 2: select MIPv6 RO or inbound trigger */
149#ifdef CONFIG_IPV6_MIP6
150 for (i = 0; i < n; i++) {
151 if (src[i] &&
152 (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
153 src[i]->mode == XFRM_MODE_IN_TRIGGER)) {
154 dst[j++] = src[i];
155 src[i] = NULL;
156 }
157 }
158 if (j == n)
159 goto end;
160#endif
58c949d1
MN
161
162 /* Rule 3: select IPsec tunnel */
163 for (i = 0; i < n; i++) {
164 if (src[i] &&
165 src[i]->mode == XFRM_MODE_TUNNEL) {
166 dst[j++] = src[i];
167 src[i] = NULL;
168 }
169 }
170 if (likely(j == n))
171 goto end;
172
173 /* Final rule */
174 for (i = 0; i < n; i++) {
175 if (src[i]) {
176 dst[j++] = src[i];
177 src[i] = NULL;
178 }
179 }
180
181 end:
182 return 0;
183}
184
1da177e4
LT
185static struct xfrm_state_afinfo xfrm6_state_afinfo = {
186 .family = AF_INET6,
1da177e4 187 .init_tempsel = __xfrm6_init_tempsel,
58c949d1
MN
188 .tmpl_sort = __xfrm6_tmpl_sort,
189 .state_sort = __xfrm6_state_sort,
1da177e4
LT
190};
191
192void __init xfrm6_state_init(void)
193{
194 xfrm_state_register_afinfo(&xfrm6_state_afinfo);
195}
196
197void xfrm6_state_fini(void)
198{
199 xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
200}
201
This page took 0.164059 seconds and 5 git commands to generate.