blob: ee85c402e868e7056472256c30f192b2d25b7e8e [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * decap.c : IPSec tunnel support
3 *
4 * Copyright (c) 2015 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <vnet/vnet.h>
19#include <vnet/api_errno.h>
20#include <vnet/ip/ip.h>
21#include <vnet/interface.h>
22
23#include <vnet/ipsec/ipsec.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070024#include <vnet/ipsec/ikev2.h>
25
Sergio Gonzalez Monroya10f62b2016-11-25 13:36:12 +000026#if DPDK_CRYPTO==1
27#include <vnet/devices/dpdk/ipsec/esp.h>
28#define ESP_NODE "dpdk-esp-encrypt"
29#else
30#include <vnet/ipsec/esp.h>
31#define ESP_NODE "esp-encrypt"
32#endif
33
34#if DPDK_CRYPTO==0
35/* dummy function */
36static int
37add_del_sa_sess (u32 sa_index, u8 is_add)
38{
39 return 0;
40}
41#endif
42
Matus Fabian694265d2016-08-10 01:55:36 -070043u32
44ipsec_get_sa_index_by_sa_id (u32 sa_id)
45{
46 ipsec_main_t *im = &ipsec_main;
47 uword *p = hash_get (im->sa_index_by_sa_id, sa_id);
48 if (!p)
49 return ~0;
50
51 return p[0];
52}
53
Ed Warnickecb9cada2015-12-08 15:45:58 -070054int
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070055ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id,
56 int is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -070057{
58 ipsec_main_t *im = &ipsec_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -070059 ip4_ipsec_config_t config;
60
Damjan Marion8b3191e2016-11-09 19:54:20 +010061 u32 spd_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -070062 uword *p;
63
64 p = hash_get (im->spd_index_by_spd_id, spd_id);
65 if (!p)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070066 return VNET_API_ERROR_SYSCALL_ERROR_1; /* no such spd-id */
Ed Warnickecb9cada2015-12-08 15:45:58 -070067
68 spd_index = p[0];
69
70 p = hash_get (im->spd_index_by_sw_if_index, sw_if_index);
71 if (p && is_add)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070072 return VNET_API_ERROR_SYSCALL_ERROR_1; /* spd already assigned */
Ed Warnickecb9cada2015-12-08 15:45:58 -070073
74 if (is_add)
75 {
76 hash_set (im->spd_index_by_sw_if_index, sw_if_index, spd_index);
77 }
78 else
79 {
80 hash_unset (im->spd_index_by_sw_if_index, sw_if_index);
81 }
82
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070083 clib_warning ("sw_if_index %u spd_id %u spd_index %u",
84 sw_if_index, spd_id, spd_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -070085
86 /* enable IPsec on TX */
Matus Fabian08a6f012016-11-15 06:08:51 -080087 vnet_feature_enable_disable ("ip4-output", "ipsec-output-ip4", sw_if_index,
88 is_add, 0, 0);
89 vnet_feature_enable_disable ("ip6-output", "ipsec-output-ip6", sw_if_index,
90 is_add, 0, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
92 /* enable IPsec on RX */
Damjan Marion8b3191e2016-11-09 19:54:20 +010093 vnet_feature_enable_disable ("ip4-unicast", "ipsec-input-ip4", sw_if_index,
94 is_add, &config, sizeof (config));
95 vnet_feature_enable_disable ("ip6-unicast", "ipsec-input-ip6", sw_if_index,
96 is_add, &config, sizeof (config));
Ed Warnickecb9cada2015-12-08 15:45:58 -070097
98 return 0;
99}
100
101int
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700102ipsec_add_del_spd (vlib_main_t * vm, u32 spd_id, int is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103{
104 ipsec_main_t *im = &ipsec_main;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700105 ipsec_spd_t *spd = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106 uword *p;
107 u32 spd_index, k, v;
108
109 p = hash_get (im->spd_index_by_spd_id, spd_id);
110 if (p && is_add)
111 return VNET_API_ERROR_INVALID_VALUE;
112 if (!p && !is_add)
113 return VNET_API_ERROR_INVALID_VALUE;
114
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700115 if (!is_add) /* delete */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116 {
117 spd_index = p[0];
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700118 spd = pool_elt_at_index (im->spds, spd_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700119 if (!spd)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700120 return VNET_API_ERROR_INVALID_VALUE;
121 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122 hash_foreach (k, v, im->spd_index_by_sw_if_index, ({
123 if (v == spd_index)
124 ipsec_set_interface_spd(vm, k, spd_id, 0);
125 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700126 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127 hash_unset (im->spd_index_by_spd_id, spd_id);
128 pool_free (spd->policies);
129 vec_free (spd->ipv4_outbound_policies);
130 vec_free (spd->ipv6_outbound_policies);
131 vec_free (spd->ipv4_inbound_protect_policy_indices);
132 vec_free (spd->ipv4_inbound_policy_discard_and_bypass_indices);
133 pool_put (im->spds, spd);
134 }
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700135 else /* create new SPD */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700136 {
137 pool_get (im->spds, spd);
138 memset (spd, 0, sizeof (*spd));
139 spd_index = spd - im->spds;
140 spd->id = spd_id;
141 hash_set (im->spd_index_by_spd_id, spd_id, spd_index);
142 }
143 return 0;
144}
145
146static int
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700147ipsec_spd_entry_sort (void *a1, void *a2)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148{
149 ipsec_main_t *im = &ipsec_main;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700150 u32 *id1 = a1;
151 u32 *id2 = a2;
152 ipsec_spd_t *spd;
153 ipsec_policy_t *p1, *p2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700155 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700156 pool_foreach (spd, im->spds, ({
157 p1 = pool_elt_at_index(spd->policies, *id1);
158 p2 = pool_elt_at_index(spd->policies, *id2);
159 if (p1 && p2)
160 return p2->priority - p1->priority;
161 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700162 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163
164 return 0;
165}
166
167int
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700168ipsec_add_del_policy (vlib_main_t * vm, ipsec_policy_t * policy, int is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169{
170 ipsec_main_t *im = &ipsec_main;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700171 ipsec_spd_t *spd = 0;
172 ipsec_policy_t *vp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700173 uword *p;
174 u32 spd_index;
175
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700176 clib_warning ("policy-id %u priority %d is_outbound %u", policy->id,
177 policy->priority, policy->is_outbound);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700178
179 if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
180 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700181 p = hash_get (im->sa_index_by_sa_id, policy->sa_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182 if (!p)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700183 return VNET_API_ERROR_SYSCALL_ERROR_1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184 policy->sa_index = p[0];
185 }
186
187 p = hash_get (im->spd_index_by_spd_id, policy->id);
188
189 if (!p)
190 return VNET_API_ERROR_SYSCALL_ERROR_1;
191
192 spd_index = p[0];
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700193 spd = pool_elt_at_index (im->spds, spd_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700194 if (!spd)
195 return VNET_API_ERROR_SYSCALL_ERROR_1;
196
197 if (is_add)
198 {
199 u32 policy_index;
200
201 pool_get (spd->policies, vp);
Damjan Marionf1213b82016-03-13 02:22:06 +0100202 clib_memcpy (vp, policy, sizeof (*vp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700203 policy_index = vp - spd->policies;
204
205 if (policy->is_outbound)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700206 {
207 if (policy->is_ipv6)
208 {
209 vec_add1 (spd->ipv6_outbound_policies, policy_index);
210 clib_memcpy (vp, policy, sizeof (ipsec_policy_t));
211 vec_sort_with_function (spd->ipv6_outbound_policies,
212 ipsec_spd_entry_sort);
213 }
214 else
215 {
216 vec_add1 (spd->ipv4_outbound_policies, policy_index);
217 clib_memcpy (vp, policy, sizeof (ipsec_policy_t));
218 vec_sort_with_function (spd->ipv4_outbound_policies,
219 ipsec_spd_entry_sort);
220 }
221 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222 else
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700223 {
224 if (policy->is_ipv6)
225 {
226 if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
227 {
228 vec_add1 (spd->ipv6_inbound_protect_policy_indices,
229 policy_index);
230 clib_memcpy (vp, policy, sizeof (ipsec_policy_t));
Ed Warnicke853e7202016-08-12 11:42:26 -0700231 vec_sort_with_function
232 (spd->ipv6_inbound_protect_policy_indices,
233 ipsec_spd_entry_sort);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700234 }
235 else
236 {
Ed Warnicke853e7202016-08-12 11:42:26 -0700237 vec_add1
238 (spd->ipv6_inbound_policy_discard_and_bypass_indices,
239 policy_index);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700240 clib_memcpy (vp, policy, sizeof (ipsec_policy_t));
Ed Warnicke853e7202016-08-12 11:42:26 -0700241 vec_sort_with_function
242 (spd->ipv6_inbound_policy_discard_and_bypass_indices,
243 ipsec_spd_entry_sort);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700244 }
245 }
246 else
247 {
248 if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
249 {
250 vec_add1 (spd->ipv4_inbound_protect_policy_indices,
251 policy_index);
252 clib_memcpy (vp, policy, sizeof (ipsec_policy_t));
Ed Warnicke853e7202016-08-12 11:42:26 -0700253 vec_sort_with_function
254 (spd->ipv4_inbound_protect_policy_indices,
255 ipsec_spd_entry_sort);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700256 }
257 else
258 {
Ed Warnicke853e7202016-08-12 11:42:26 -0700259 vec_add1
260 (spd->ipv4_inbound_policy_discard_and_bypass_indices,
261 policy_index);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700262 clib_memcpy (vp, policy, sizeof (ipsec_policy_t));
Ed Warnicke853e7202016-08-12 11:42:26 -0700263 vec_sort_with_function
264 (spd->ipv4_inbound_policy_discard_and_bypass_indices,
265 ipsec_spd_entry_sort);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700266 }
267 }
268 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700269
270 }
271 else
272 {
273 u32 i, j;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700274 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275 pool_foreach_index(i, spd->policies, ({
Damjan Marion607de1a2016-08-16 22:53:54 +0200276 vp = pool_elt_at_index(spd->policies, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277 if (vp->priority != policy->priority)
278 continue;
279 if (vp->is_outbound != policy->is_outbound)
280 continue;
281 if (vp->policy != policy->policy)
282 continue;
283 if (vp->sa_id != policy->sa_id)
284 continue;
285 if (vp->protocol != policy->protocol)
286 continue;
287 if (vp->lport.start != policy->lport.start)
288 continue;
289 if (vp->lport.stop != policy->lport.stop)
290 continue;
291 if (vp->rport.start != policy->rport.start)
292 continue;
293 if (vp->rport.stop != policy->rport.stop)
294 continue;
295 if (vp->is_ipv6 != policy->is_ipv6)
296 continue;
297 if (policy->is_ipv6)
298 {
299 if (vp->laddr.start.ip6.as_u64[0] != policy->laddr.start.ip6.as_u64[0])
300 continue;
301 if (vp->laddr.start.ip6.as_u64[1] != policy->laddr.start.ip6.as_u64[1])
302 continue;
303 if (vp->laddr.stop.ip6.as_u64[0] != policy->laddr.stop.ip6.as_u64[0])
304 continue;
305 if (vp->laddr.stop.ip6.as_u64[1] != policy->laddr.stop.ip6.as_u64[1])
306 continue;
307 if (vp->raddr.start.ip6.as_u64[0] != policy->raddr.start.ip6.as_u64[0])
308 continue;
309 if (vp->raddr.start.ip6.as_u64[1] != policy->raddr.start.ip6.as_u64[1])
310 continue;
311 if (vp->raddr.stop.ip6.as_u64[0] != policy->raddr.stop.ip6.as_u64[0])
312 continue;
313 if (vp->laddr.stop.ip6.as_u64[1] != policy->laddr.stop.ip6.as_u64[1])
314 continue;
315 if (policy->is_outbound)
316 {
317 vec_foreach_index(j, spd->ipv6_outbound_policies) {
318 if (vec_elt(spd->ipv6_outbound_policies, j) == i) {
319 vec_del1 (spd->ipv6_outbound_policies, j);
320 break;
321 }
322 }
323 }
324 else
325 {
326 if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
327 {
328 vec_foreach_index(j, spd->ipv6_inbound_protect_policy_indices) {
329 if (vec_elt(spd->ipv6_inbound_protect_policy_indices, j) == i) {
330 vec_del1 (spd->ipv6_inbound_protect_policy_indices, j);
331 break;
332 }
333 }
334 }
335 else
336 {
337 vec_foreach_index(j, spd->ipv6_inbound_policy_discard_and_bypass_indices) {
338 if (vec_elt(spd->ipv6_inbound_policy_discard_and_bypass_indices, j) == i) {
339 vec_del1 (spd->ipv6_inbound_policy_discard_and_bypass_indices, j);
340 break;
341 }
342 }
343 }
344 }
345 }
346 else
347 {
348 if (vp->laddr.start.ip4.as_u32 != policy->laddr.start.ip4.as_u32)
349 continue;
350 if (vp->laddr.stop.ip4.as_u32 != policy->laddr.stop.ip4.as_u32)
351 continue;
352 if (vp->raddr.start.ip4.as_u32 != policy->raddr.start.ip4.as_u32)
353 continue;
354 if (vp->raddr.stop.ip4.as_u32 != policy->raddr.stop.ip4.as_u32)
355 continue;
356 if (policy->is_outbound)
357 {
358 vec_foreach_index(j, spd->ipv4_outbound_policies) {
359 if (vec_elt(spd->ipv4_outbound_policies, j) == i) {
360 vec_del1 (spd->ipv4_outbound_policies, j);
361 break;
362 }
Damjan Marion607de1a2016-08-16 22:53:54 +0200363 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700364 }
365 else
366 {
367 if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
368 {
369 vec_foreach_index(j, spd->ipv4_inbound_protect_policy_indices) {
370 if (vec_elt(spd->ipv4_inbound_protect_policy_indices, j) == i) {
371 vec_del1 (spd->ipv4_inbound_protect_policy_indices, j);
372 break;
373 }
374 }
375 }
376 else
377 {
378 vec_foreach_index(j, spd->ipv4_inbound_policy_discard_and_bypass_indices) {
379 if (vec_elt(spd->ipv4_inbound_policy_discard_and_bypass_indices, j) == i) {
380 vec_del1 (spd->ipv4_inbound_policy_discard_and_bypass_indices, j);
381 break;
382 }
383 }
384 }
385 }
386 pool_put (spd->policies, vp);
387 break;
388 }
389 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700390 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700391 }
392
393 return 0;
394}
395
396static u8
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700397ipsec_is_sa_used (u32 sa_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700399 ipsec_main_t *im = &ipsec_main;
400 ipsec_spd_t *spd;
401 ipsec_policy_t *p;
Matus Fabian694265d2016-08-10 01:55:36 -0700402 ipsec_tunnel_if_t *t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700404 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 pool_foreach(spd, im->spds, ({
406 pool_foreach(p, spd->policies, ({
407 if (p->policy == IPSEC_POLICY_ACTION_PROTECT)
408 {
409 if (p->sa_index == sa_index)
410 return 1;
411 }
412 }));
413 }));
Matus Fabian694265d2016-08-10 01:55:36 -0700414
415 pool_foreach(t, im->tunnel_interfaces, ({
416 if (t->input_sa_index == sa_index)
417 return 1;
418 if (t->output_sa_index == sa_index)
419 return 1;
420 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700421 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422
423 return 0;
424}
425
426int
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700427ipsec_add_del_sa (vlib_main_t * vm, ipsec_sa_t * new_sa, int is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700428{
429 ipsec_main_t *im = &ipsec_main;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700430 ipsec_sa_t *sa = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700431 uword *p;
432 u32 sa_index;
433
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700434 clib_warning ("id %u spi %u", new_sa->id, new_sa->spi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435
436 p = hash_get (im->sa_index_by_sa_id, new_sa->id);
437 if (p && is_add)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700438 return VNET_API_ERROR_SYSCALL_ERROR_1; /* already exists */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700439 if (!p && !is_add)
440 return VNET_API_ERROR_SYSCALL_ERROR_1;
441
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700442 if (!is_add) /* delete */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700443 {
444 sa_index = p[0];
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700445 sa = pool_elt_at_index (im->sad, sa_index);
446 if (ipsec_is_sa_used (sa_index))
447 {
448 clib_warning ("sa_id %u used in policy", sa->id);
449 return VNET_API_ERROR_SYSCALL_ERROR_1; /* sa used in policy */
450 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700451 hash_unset (im->sa_index_by_sa_id, sa->id);
Sergio Gonzalez Monroya10f62b2016-11-25 13:36:12 +0000452 add_del_sa_sess (sa_index, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700453 pool_put (im->sad, sa);
454 }
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700455 else /* create new SA */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700456 {
457 pool_get (im->sad, sa);
Damjan Marionf1213b82016-03-13 02:22:06 +0100458 clib_memcpy (sa, new_sa, sizeof (*sa));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459 sa_index = sa - im->sad;
460 hash_set (im->sa_index_by_sa_id, sa->id, sa_index);
Sergio Gonzalez Monroya10f62b2016-11-25 13:36:12 +0000461 if (add_del_sa_sess (sa_index, is_add) < 0)
462 return VNET_API_ERROR_SYSCALL_ERROR_1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463 }
464 return 0;
465}
466
467int
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700468ipsec_set_sa_key (vlib_main_t * vm, ipsec_sa_t * sa_update)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700469{
470 ipsec_main_t *im = &ipsec_main;
471 uword *p;
472 u32 sa_index;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700473 ipsec_sa_t *sa = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474
475 p = hash_get (im->sa_index_by_sa_id, sa_update->id);
476 if (!p)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700477 return VNET_API_ERROR_SYSCALL_ERROR_1; /* no such sa-id */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700478
479 sa_index = p[0];
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700480 sa = pool_elt_at_index (im->sad, sa_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700481
482 /* new crypto key */
483 if (0 < sa_update->crypto_key_len)
484 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700485 clib_memcpy (sa->crypto_key, sa_update->crypto_key,
486 sa_update->crypto_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487 sa->crypto_key_len = sa_update->crypto_key_len;
488 }
489
490 /* new integ key */
491 if (0 < sa_update->integ_key_len)
492 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700493 clib_memcpy (sa->integ_key, sa_update->integ_key,
494 sa_update->integ_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700495 sa->integ_key_len = sa_update->integ_key_len;
496 }
497
Sergio Gonzalez Monroya10f62b2016-11-25 13:36:12 +0000498 if (sa->crypto_key_len + sa->integ_key_len > 0)
499 {
500 if (add_del_sa_sess (sa_index, 0) < 0)
501 return VNET_API_ERROR_SYSCALL_ERROR_1;
502 }
503
Ed Warnickecb9cada2015-12-08 15:45:58 -0700504 return 0;
505}
506
507static void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700508ipsec_rand_seed (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700509{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700510 struct
511 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512 time_t time;
513 pid_t pid;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700514 void *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700515 } seed_data;
516
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700517 seed_data.time = time (NULL);
518 seed_data.pid = getpid ();
519 seed_data.p = (void *) &seed_data;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700520
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700521 RAND_seed ((const void *) &seed_data, sizeof (seed_data));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700522}
523
524static clib_error_t *
525ipsec_init (vlib_main_t * vm)
526{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700527 clib_error_t *error;
528 ipsec_main_t *im = &ipsec_main;
529 vlib_thread_main_t *tm = vlib_get_thread_main ();
530 vlib_node_t *node;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700532 ipsec_rand_seed ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700533
534 memset (im, 0, sizeof (im[0]));
535
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700536 im->vnet_main = vnet_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700537 im->vlib_main = vm;
538
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700539 im->spd_index_by_spd_id = hash_create (0, sizeof (uword));
540 im->sa_index_by_sa_id = hash_create (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700541 im->spd_index_by_sw_if_index = hash_create (0, sizeof (uword));
542
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700543 vec_validate_aligned (im->empty_buffers, tm->n_vlib_mains - 1,
544 CLIB_CACHE_LINE_BYTES);
Matthew Smith29d85102016-05-01 14:52:08 -0500545
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700547 ASSERT (node);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700548 im->error_drop_node_index = node->index;
549
Sergio Gonzalez Monroya10f62b2016-11-25 13:36:12 +0000550 node = vlib_get_node_by_name (vm, (u8 *) ESP_NODE);
551
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700552 ASSERT (node);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700553 im->esp_encrypt_node_index = node->index;
554
555 node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup");
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700556 ASSERT (node);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700557 im->ip4_lookup_node_index = node->index;
558
Ed Warnickecb9cada2015-12-08 15:45:58 -0700559 if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
560 return error;
561
562 if ((error = vlib_call_init_function (vm, ipsec_tunnel_if_init)))
563 return error;
564
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700565 esp_init ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700566
567 if ((error = ikev2_init (vm)))
568 return error;
569
570 return 0;
571}
572
573VLIB_INIT_FUNCTION (ipsec_init);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700574
575/*
576 * fd.io coding-style-patch-verification: ON
577 *
578 * Local Variables:
579 * eval: (c-set-style "gnu")
580 * End:
581 */