Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * ipsec_api.c - ipsec api
4 : *
5 : * Copyright (c) 2016 Cisco and/or its affiliates.
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at:
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : *------------------------------------------------------------------
18 : */
19 :
20 : #include <vnet/vnet.h>
21 : #include <vlibmemory/api.h>
22 :
23 : #include <vnet/interface.h>
24 : #include <vnet/api_errno.h>
25 : #include <vnet/ip/ip.h>
26 : #include <vnet/ip/ip_types_api.h>
27 : #include <vnet/ipsec/ipsec_types_api.h>
28 : #include <vnet/tunnel/tunnel_types_api.h>
29 : #include <vnet/fib/fib.h>
30 : #include <vnet/ipip/ipip.h>
31 : #include <vnet/tunnel/tunnel_types_api.h>
32 : #include <vnet/ipsec/ipsec.h>
33 : #include <vnet/ipsec/ipsec_tun.h>
34 : #include <vnet/ipsec/ipsec_itf.h>
35 :
36 : #include <vnet/format_fns.h>
37 : #include <vnet/ipsec/ipsec.api_enum.h>
38 : #include <vnet/ipsec/ipsec.api_types.h>
39 :
40 : #define REPLY_MSG_ID_BASE ipsec_main.msg_id_base
41 : #include <vlibapi/api_helper_macros.h>
42 :
43 : static void
44 3386 : vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
45 : {
46 3386 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
47 : vl_api_ipsec_spd_add_del_reply_t *rmp;
48 : int rv;
49 :
50 3386 : rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
51 :
52 3386 : REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
53 : }
54 :
55 3448 : static void vl_api_ipsec_interface_add_del_spd_t_handler
56 : (vl_api_ipsec_interface_add_del_spd_t * mp)
57 : {
58 3448 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
59 : vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
60 : int rv;
61 : u32 sw_if_index __attribute__ ((unused));
62 : u32 spd_id __attribute__ ((unused));
63 :
64 3448 : sw_if_index = ntohl (mp->sw_if_index);
65 3448 : spd_id = ntohl (mp->spd_id);
66 :
67 3448 : VALIDATE_SW_IF_INDEX (mp);
68 :
69 3448 : rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
70 :
71 3448 : BAD_SW_IF_INDEX_LABEL;
72 :
73 3448 : REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
74 : }
75 :
76 186 : static void vl_api_ipsec_tunnel_protect_update_t_handler
77 : (vl_api_ipsec_tunnel_protect_update_t * mp)
78 : {
79 186 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
80 : vl_api_ipsec_tunnel_protect_update_reply_t *rmp;
81 186 : u32 sw_if_index, ii, *sa_ins = NULL;
82 : ip_address_t nh;
83 : int rv;
84 :
85 186 : sw_if_index = ntohl (mp->tunnel.sw_if_index);
86 :
87 186 : VALIDATE_SW_IF_INDEX (&(mp->tunnel));
88 :
89 374 : for (ii = 0; ii < mp->tunnel.n_sa_in; ii++)
90 188 : vec_add1 (sa_ins, ntohl (mp->tunnel.sa_in[ii]));
91 :
92 186 : ip_address_decode2 (&mp->tunnel.nh, &nh);
93 :
94 186 : rv = ipsec_tun_protect_update (sw_if_index, &nh,
95 : ntohl (mp->tunnel.sa_out), sa_ins);
96 :
97 186 : BAD_SW_IF_INDEX_LABEL;
98 :
99 186 : REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_UPDATE_REPLY);
100 : }
101 :
102 156 : static void vl_api_ipsec_tunnel_protect_del_t_handler
103 : (vl_api_ipsec_tunnel_protect_del_t * mp)
104 : {
105 156 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
106 : vl_api_ipsec_tunnel_protect_del_reply_t *rmp;
107 : ip_address_t nh;
108 : u32 sw_if_index;
109 : int rv;
110 :
111 156 : sw_if_index = ntohl (mp->sw_if_index);
112 :
113 156 : VALIDATE_SW_IF_INDEX (mp);
114 :
115 156 : ip_address_decode2 (&mp->nh, &nh);
116 156 : rv = ipsec_tun_protect_del (sw_if_index, &nh);
117 :
118 156 : BAD_SW_IF_INDEX_LABEL;
119 :
120 156 : REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_DEL_REPLY);
121 : }
122 :
123 : typedef struct ipsec_dump_walk_ctx_t_
124 : {
125 : vl_api_registration_t *reg;
126 : u32 context;
127 : u32 sw_if_index;
128 : } ipsec_dump_walk_ctx_t;
129 :
130 : static walk_rc_t
131 854 : send_ipsec_tunnel_protect_details (index_t itpi, void *arg)
132 : {
133 854 : ipsec_dump_walk_ctx_t *ctx = arg;
134 : vl_api_ipsec_tunnel_protect_details_t *mp;
135 : ipsec_tun_protect_t *itp;
136 854 : u32 ii = 0;
137 : ipsec_sa_t *sa;
138 :
139 854 : itp = ipsec_tun_protect_get (itpi);
140 :
141 854 : mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (u32) * itp->itp_n_sa_in));
142 854 : clib_memset (mp, 0, sizeof (*mp));
143 854 : mp->_vl_msg_id =
144 854 : ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_TUNNEL_PROTECT_DETAILS);
145 854 : mp->context = ctx->context;
146 :
147 854 : mp->tun.sw_if_index = htonl (itp->itp_sw_if_index);
148 854 : ip_address_encode2 (itp->itp_key, &mp->tun.nh);
149 :
150 854 : sa = ipsec_sa_get (itp->itp_out_sa);
151 854 : mp->tun.sa_out = htonl (sa->id);
152 854 : mp->tun.n_sa_in = itp->itp_n_sa_in;
153 : /* *INDENT-OFF* */
154 1708 : FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa,
155 : ({
156 : mp->tun.sa_in[ii++] = htonl (sa->id);
157 : }));
158 : /* *INDENT-ON* */
159 :
160 854 : vl_api_send_msg (ctx->reg, (u8 *) mp);
161 :
162 854 : return (WALK_CONTINUE);
163 : }
164 :
165 : static void
166 288 : vl_api_ipsec_tunnel_protect_dump_t_handler (vl_api_ipsec_tunnel_protect_dump_t
167 : * mp)
168 : {
169 : vl_api_registration_t *reg;
170 : u32 sw_if_index;
171 :
172 288 : reg = vl_api_client_index_to_registration (mp->client_index);
173 288 : if (!reg)
174 0 : return;
175 :
176 288 : ipsec_dump_walk_ctx_t ctx = {
177 : .reg = reg,
178 288 : .context = mp->context,
179 : };
180 :
181 288 : sw_if_index = ntohl (mp->sw_if_index);
182 :
183 288 : if (~0 == sw_if_index)
184 : {
185 0 : ipsec_tun_protect_walk (send_ipsec_tunnel_protect_details, &ctx);
186 : }
187 : else
188 : {
189 288 : ipsec_tun_protect_walk_itf (sw_if_index,
190 : send_ipsec_tunnel_protect_details, &ctx);
191 : }
192 : }
193 :
194 : static int
195 33260 : ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
196 : ipsec_policy_action_t * out)
197 : {
198 33260 : in = clib_net_to_host_u32 (in);
199 :
200 33260 : switch (in)
201 : {
202 : #define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
203 : *out = IPSEC_POLICY_ACTION_##f; \
204 : return (0);
205 33260 : foreach_ipsec_policy_action
206 : #undef _
207 : }
208 0 : return (VNET_API_ERROR_UNIMPLEMENTED);
209 : }
210 :
211 0 : static void vl_api_ipsec_spd_entry_add_del_t_handler
212 : (vl_api_ipsec_spd_entry_add_del_t * mp)
213 : {
214 0 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
215 : vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
216 : ip46_type_t itype;
217 : u32 stat_index;
218 : int rv;
219 :
220 0 : stat_index = ~0;
221 :
222 : ipsec_policy_t p;
223 :
224 0 : clib_memset (&p, 0, sizeof (p));
225 :
226 0 : p.id = ntohl (mp->entry.spd_id);
227 0 : p.priority = ntohl (mp->entry.priority);
228 :
229 0 : itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
230 0 : ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
231 0 : ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
232 0 : ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
233 :
234 0 : p.is_ipv6 = (itype == IP46_TYPE_IP6);
235 :
236 0 : p.protocol =
237 0 : mp->entry.protocol ? mp->entry.protocol : IPSEC_POLICY_PROTOCOL_ANY;
238 0 : p.rport.start = ntohs (mp->entry.remote_port_start);
239 0 : p.rport.stop = ntohs (mp->entry.remote_port_stop);
240 0 : p.lport.start = ntohs (mp->entry.local_port_start);
241 0 : p.lport.stop = ntohs (mp->entry.local_port_stop);
242 :
243 0 : rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
244 :
245 0 : if (rv)
246 0 : goto out;
247 :
248 : /* policy action resolve unsupported */
249 0 : if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
250 : {
251 0 : clib_warning ("unsupported action: 'resolve'");
252 0 : rv = VNET_API_ERROR_UNIMPLEMENTED;
253 0 : goto out;
254 : }
255 0 : p.sa_id = ntohl (mp->entry.sa_id);
256 : rv =
257 0 : ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
258 : &p.type);
259 0 : if (rv)
260 0 : goto out;
261 :
262 0 : rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
263 0 : if (rv)
264 0 : goto out;
265 :
266 0 : out:
267 : /* *INDENT-OFF* */
268 0 : REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
269 : ({
270 : rmp->stat_index = ntohl(stat_index);
271 : }));
272 : /* *INDENT-ON* */
273 : }
274 :
275 : static void
276 33260 : vl_api_ipsec_spd_entry_add_del_v2_t_handler (
277 : vl_api_ipsec_spd_entry_add_del_v2_t *mp)
278 : {
279 33260 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
280 : vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
281 : ip46_type_t itype;
282 : u32 stat_index;
283 : int rv;
284 :
285 33260 : stat_index = ~0;
286 :
287 : ipsec_policy_t p;
288 :
289 33260 : clib_memset (&p, 0, sizeof (p));
290 :
291 33260 : p.id = ntohl (mp->entry.spd_id);
292 33260 : p.priority = ntohl (mp->entry.priority);
293 :
294 33260 : itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
295 33260 : ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
296 33260 : ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
297 33260 : ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
298 :
299 33260 : p.is_ipv6 = (itype == IP46_TYPE_IP6);
300 :
301 33260 : p.protocol = mp->entry.protocol;
302 33260 : p.rport.start = ntohs (mp->entry.remote_port_start);
303 33260 : p.rport.stop = ntohs (mp->entry.remote_port_stop);
304 33260 : p.lport.start = ntohs (mp->entry.local_port_start);
305 33260 : p.lport.stop = ntohs (mp->entry.local_port_stop);
306 :
307 33260 : rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
308 :
309 33260 : if (rv)
310 0 : goto out;
311 :
312 : /* policy action resolve unsupported */
313 33260 : if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
314 : {
315 0 : clib_warning ("unsupported action: 'resolve'");
316 0 : rv = VNET_API_ERROR_UNIMPLEMENTED;
317 0 : goto out;
318 : }
319 33260 : p.sa_id = ntohl (mp->entry.sa_id);
320 : rv =
321 33260 : ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy, &p.type);
322 33260 : if (rv)
323 0 : goto out;
324 :
325 33260 : rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
326 33260 : if (rv)
327 0 : goto out;
328 :
329 33260 : out:
330 33260 : REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_V2_REPLY,
331 : ({ rmp->stat_index = ntohl (stat_index); }));
332 : }
333 :
334 2 : static void vl_api_ipsec_sad_entry_add_del_t_handler
335 : (vl_api_ipsec_sad_entry_add_del_t * mp)
336 : {
337 : vl_api_ipsec_sad_entry_add_del_reply_t *rmp;
338 : ipsec_key_t crypto_key, integ_key;
339 : ipsec_crypto_alg_t crypto_alg;
340 : ipsec_integ_alg_t integ_alg;
341 : ipsec_protocol_t proto;
342 : ipsec_sa_flags_t flags;
343 2 : u32 id, spi, sa_index = ~0;
344 2 : tunnel_t tun = {
345 : .t_flags = TUNNEL_FLAG_NONE,
346 : .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
347 : .t_dscp = 0,
348 : .t_mode = TUNNEL_MODE_P2P,
349 : .t_table_id = 0,
350 : .t_hop_limit = 255,
351 : };
352 : int rv;
353 :
354 2 : id = ntohl (mp->entry.sad_id);
355 2 : if (!mp->is_add)
356 : {
357 1 : rv = ipsec_sa_unlock_id (id);
358 1 : goto out;
359 : }
360 1 : spi = ntohl (mp->entry.spi);
361 :
362 1 : rv = ipsec_proto_decode (mp->entry.protocol, &proto);
363 :
364 1 : if (rv)
365 0 : goto out;
366 :
367 1 : rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
368 :
369 1 : if (rv)
370 0 : goto out;
371 :
372 1 : rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
373 :
374 1 : if (rv)
375 0 : goto out;
376 :
377 1 : ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
378 1 : ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
379 :
380 1 : flags = ipsec_sa_flags_decode (mp->entry.flags);
381 :
382 1 : ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
383 1 : ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
384 :
385 1 : rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key,
386 : integ_alg, &integ_key, flags, mp->entry.salt,
387 1 : htons (mp->entry.udp_src_port),
388 1 : htons (mp->entry.udp_dst_port), &tun, &sa_index);
389 :
390 2 : out:
391 : /* *INDENT-OFF* */
392 2 : REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
393 : {
394 : rmp->stat_index = htonl (sa_index);
395 : });
396 : /* *INDENT-ON* */
397 : }
398 :
399 0 : static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
400 : (vl_api_ipsec_sad_entry_add_del_v2_t * mp)
401 : {
402 0 : vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
403 : vl_api_ipsec_sad_entry_add_del_v2_reply_t *rmp;
404 : ipsec_key_t crypto_key, integ_key;
405 : ipsec_crypto_alg_t crypto_alg;
406 : ipsec_integ_alg_t integ_alg;
407 : ipsec_protocol_t proto;
408 : ipsec_sa_flags_t flags;
409 0 : u32 id, spi, sa_index = ~0;
410 : int rv;
411 0 : tunnel_t tun = {
412 : .t_flags = TUNNEL_FLAG_NONE,
413 : .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
414 : .t_dscp = 0,
415 : .t_mode = TUNNEL_MODE_P2P,
416 0 : .t_table_id = htonl (mp->entry.tx_table_id),
417 : .t_hop_limit = 255,
418 : };
419 :
420 0 : id = ntohl (mp->entry.sad_id);
421 0 : if (!mp->is_add)
422 : {
423 0 : rv = ipsec_sa_unlock_id (id);
424 0 : goto out;
425 : }
426 :
427 0 : spi = ntohl (mp->entry.spi);
428 :
429 0 : rv = ipsec_proto_decode (mp->entry.protocol, &proto);
430 :
431 0 : if (rv)
432 0 : goto out;
433 :
434 0 : rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
435 :
436 0 : if (rv)
437 0 : goto out;
438 :
439 0 : rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
440 :
441 0 : if (rv)
442 0 : goto out;
443 :
444 0 : rv = tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags,
445 : &tun.t_encap_decap_flags);
446 :
447 0 : if (rv)
448 0 : goto out;
449 :
450 0 : ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
451 0 : ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
452 :
453 0 : flags = ipsec_sa_flags_decode (mp->entry.flags);
454 0 : tun.t_dscp = ip_dscp_decode (mp->entry.dscp);
455 :
456 0 : ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
457 0 : ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
458 :
459 0 : rv = ipsec_sa_add_and_lock (
460 : id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
461 0 : mp->entry.salt, htons (mp->entry.udp_src_port),
462 0 : htons (mp->entry.udp_dst_port), &tun, &sa_index);
463 :
464 0 : out:
465 : /* *INDENT-OFF* */
466 0 : REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V2_REPLY,
467 : {
468 : rmp->stat_index = htonl (sa_index);
469 : });
470 : /* *INDENT-ON* */
471 : }
472 :
473 : static int
474 6975 : ipsec_sad_entry_add_v3 (const vl_api_ipsec_sad_entry_v3_t *entry,
475 : u32 *sa_index)
476 : {
477 : ipsec_key_t crypto_key, integ_key;
478 : ipsec_crypto_alg_t crypto_alg;
479 : ipsec_integ_alg_t integ_alg;
480 : ipsec_protocol_t proto;
481 : ipsec_sa_flags_t flags;
482 : u32 id, spi;
483 6975 : tunnel_t tun = { 0 };
484 : int rv;
485 :
486 6975 : id = ntohl (entry->sad_id);
487 6975 : spi = ntohl (entry->spi);
488 :
489 6975 : rv = ipsec_proto_decode (entry->protocol, &proto);
490 :
491 6975 : if (rv)
492 0 : return (rv);
493 :
494 6975 : rv = ipsec_crypto_algo_decode (entry->crypto_algorithm, &crypto_alg);
495 :
496 6975 : if (rv)
497 0 : return (rv);
498 :
499 6975 : rv = ipsec_integ_algo_decode (entry->integrity_algorithm, &integ_alg);
500 :
501 6975 : if (rv)
502 0 : return (rv);
503 :
504 6975 : flags = ipsec_sa_flags_decode (entry->flags);
505 :
506 6975 : if (flags & IPSEC_SA_FLAG_IS_TUNNEL)
507 : {
508 3392 : rv = tunnel_decode (&entry->tunnel, &tun);
509 :
510 3392 : if (rv)
511 0 : return (rv);
512 : }
513 :
514 6975 : ipsec_key_decode (&entry->crypto_key, &crypto_key);
515 6975 : ipsec_key_decode (&entry->integrity_key, &integ_key);
516 :
517 6975 : return ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key,
518 : integ_alg, &integ_key, flags, entry->salt,
519 6975 : htons (entry->udp_src_port),
520 6975 : htons (entry->udp_dst_port), &tun, sa_index);
521 : }
522 :
523 : static void
524 0 : vl_api_ipsec_sad_entry_add_del_v3_t_handler (
525 : vl_api_ipsec_sad_entry_add_del_v3_t *mp)
526 : {
527 : vl_api_ipsec_sad_entry_add_del_v3_reply_t *rmp;
528 0 : u32 id, sa_index = ~0;
529 : int rv;
530 :
531 0 : id = ntohl (mp->entry.sad_id);
532 :
533 0 : if (!mp->is_add)
534 : {
535 0 : rv = ipsec_sa_unlock_id (id);
536 : }
537 : else
538 : {
539 0 : rv = ipsec_sad_entry_add_v3 (&mp->entry, &sa_index);
540 : }
541 :
542 0 : REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V3_REPLY,
543 : { rmp->stat_index = htonl (sa_index); });
544 : }
545 :
546 : static void
547 6977 : vl_api_ipsec_sad_entry_del_t_handler (vl_api_ipsec_sad_entry_del_t *mp)
548 : {
549 : vl_api_ipsec_sad_entry_del_reply_t *rmp;
550 : int rv;
551 :
552 6977 : rv = ipsec_sa_unlock_id (ntohl (mp->id));
553 :
554 6977 : REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_DEL_REPLY);
555 : }
556 :
557 : static void
558 6975 : vl_api_ipsec_sad_entry_add_t_handler (vl_api_ipsec_sad_entry_add_t *mp)
559 : {
560 : vl_api_ipsec_sad_entry_add_reply_t *rmp;
561 6975 : u32 sa_index = ~0;
562 : int rv;
563 :
564 6975 : rv = ipsec_sad_entry_add_v3 (&mp->entry, &sa_index);
565 :
566 6975 : REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_REPLY,
567 : { rmp->stat_index = htonl (sa_index); });
568 : }
569 :
570 : static void
571 8 : vl_api_ipsec_sad_entry_update_t_handler (vl_api_ipsec_sad_entry_update_t *mp)
572 : {
573 : vl_api_ipsec_sad_entry_update_reply_t *rmp;
574 : u32 id;
575 8 : tunnel_t tun = { 0 };
576 : int rv;
577 :
578 8 : id = ntohl (mp->sad_id);
579 :
580 8 : if (mp->is_tun)
581 : {
582 2 : rv = tunnel_decode (&mp->tunnel, &tun);
583 :
584 2 : if (rv)
585 0 : goto out;
586 : }
587 :
588 8 : rv = ipsec_sa_update (id, htons (mp->udp_src_port), htons (mp->udp_dst_port),
589 8 : &tun, mp->is_tun);
590 :
591 8 : out:
592 8 : REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_UPDATE_REPLY);
593 : }
594 :
595 : static void
596 1 : vl_api_ipsec_sad_bind_t_handler (vl_api_ipsec_sad_bind_t *mp)
597 : {
598 : vl_api_ipsec_sad_bind_reply_t *rmp;
599 : u32 sa_id;
600 : u32 worker;
601 : int rv;
602 :
603 1 : sa_id = ntohl (mp->sa_id);
604 1 : worker = ntohl (mp->worker);
605 :
606 1 : rv = ipsec_sa_bind (sa_id, worker, true /* bind */);
607 :
608 1 : REPLY_MACRO (VL_API_IPSEC_SAD_BIND_REPLY);
609 : }
610 :
611 : static void
612 0 : vl_api_ipsec_sad_unbind_t_handler (vl_api_ipsec_sad_unbind_t *mp)
613 : {
614 : vl_api_ipsec_sad_unbind_reply_t *rmp;
615 : u32 sa_id;
616 : int rv;
617 :
618 0 : sa_id = ntohl (mp->sa_id);
619 :
620 0 : rv = ipsec_sa_bind (sa_id, ~0, false /* bind */);
621 :
622 0 : REPLY_MACRO (VL_API_IPSEC_SAD_UNBIND_REPLY);
623 : }
624 :
625 : static void
626 17 : send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
627 : u32 context)
628 : {
629 : vl_api_ipsec_spds_details_t *mp;
630 17 : u32 n_policies = 0;
631 :
632 17 : mp = vl_msg_api_alloc (sizeof (*mp));
633 17 : clib_memset (mp, 0, sizeof (*mp));
634 17 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SPDS_DETAILS);
635 17 : mp->context = context;
636 :
637 17 : mp->spd_id = htonl (spd->id);
638 : #define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
639 17 : foreach_ipsec_spd_policy_type
640 : #undef _
641 17 : mp->npolicies = htonl (n_policies);
642 :
643 17 : vl_api_send_msg (reg, (u8 *) mp);
644 17 : }
645 :
646 : static void
647 508 : vl_api_ipsec_spds_dump_t_handler (vl_api_ipsec_spds_dump_t * mp)
648 : {
649 : vl_api_registration_t *reg;
650 508 : ipsec_main_t *im = &ipsec_main;
651 : ipsec_spd_t *spd;
652 :
653 508 : reg = vl_api_client_index_to_registration (mp->client_index);
654 508 : if (!reg)
655 0 : return;
656 :
657 525 : pool_foreach (spd, im->spds) {
658 17 : send_ipsec_spds_details (spd, reg, mp->context);
659 : }
660 : }
661 :
662 : vl_api_ipsec_spd_action_t
663 244 : ipsec_spd_action_encode (ipsec_policy_action_t in)
664 : {
665 244 : vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
666 :
667 244 : switch (in)
668 : {
669 : #define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
670 : out = IPSEC_API_SPD_ACTION_##f; \
671 : break;
672 244 : foreach_ipsec_policy_action
673 : #undef _
674 : }
675 244 : return (clib_host_to_net_u32 (out));
676 : }
677 :
678 : static void
679 244 : send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
680 : u32 context)
681 : {
682 : vl_api_ipsec_spd_details_t *mp;
683 :
684 244 : mp = vl_msg_api_alloc (sizeof (*mp));
685 244 : clib_memset (mp, 0, sizeof (*mp));
686 244 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SPD_DETAILS);
687 244 : mp->context = context;
688 :
689 244 : mp->entry.spd_id = htonl (p->id);
690 244 : mp->entry.priority = htonl (p->priority);
691 488 : mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
692 244 : (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
693 :
694 244 : ip_address_encode (&p->laddr.start, IP46_TYPE_ANY,
695 : &mp->entry.local_address_start);
696 244 : ip_address_encode (&p->laddr.stop, IP46_TYPE_ANY,
697 : &mp->entry.local_address_stop);
698 244 : ip_address_encode (&p->raddr.start, IP46_TYPE_ANY,
699 : &mp->entry.remote_address_start);
700 244 : ip_address_encode (&p->raddr.stop, IP46_TYPE_ANY,
701 : &mp->entry.remote_address_stop);
702 244 : mp->entry.local_port_start = htons (p->lport.start);
703 244 : mp->entry.local_port_stop = htons (p->lport.stop);
704 244 : mp->entry.remote_port_start = htons (p->rport.start);
705 244 : mp->entry.remote_port_stop = htons (p->rport.stop);
706 244 : mp->entry.protocol = p->protocol;
707 244 : mp->entry.policy = ipsec_spd_action_encode (p->policy);
708 244 : mp->entry.sa_id = htonl (p->sa_id);
709 :
710 244 : vl_api_send_msg (reg, (u8 *) mp);
711 244 : }
712 :
713 : static void
714 4714 : vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
715 : {
716 : vl_api_registration_t *reg;
717 4714 : ipsec_main_t *im = &ipsec_main;
718 : ipsec_spd_policy_type_t ptype;
719 : ipsec_policy_t *policy;
720 : ipsec_spd_t *spd;
721 : uword *p;
722 : u32 spd_index, *ii;
723 :
724 4714 : reg = vl_api_client_index_to_registration (mp->client_index);
725 4714 : if (!reg)
726 0 : return;
727 :
728 4714 : p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
729 4714 : if (!p)
730 4622 : return;
731 :
732 92 : spd_index = p[0];
733 92 : spd = pool_elt_at_index (im->spds, spd_index);
734 :
735 828 : FOR_EACH_IPSEC_SPD_POLICY_TYPE(ptype) {
736 980 : vec_foreach(ii, spd->policies[ptype])
737 : {
738 244 : policy = pool_elt_at_index(im->policies, *ii);
739 :
740 244 : if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
741 244 : send_ipsec_spd_details (policy, reg, mp->context);
742 : }
743 : }
744 : }
745 :
746 : static void
747 17 : send_ipsec_spd_interface_details (vl_api_registration_t * reg, u32 spd_index,
748 : u32 sw_if_index, u32 context)
749 : {
750 : vl_api_ipsec_spd_interface_details_t *mp;
751 :
752 17 : mp = vl_msg_api_alloc (sizeof (*mp));
753 17 : clib_memset (mp, 0, sizeof (*mp));
754 17 : mp->_vl_msg_id =
755 17 : ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SPD_INTERFACE_DETAILS);
756 17 : mp->context = context;
757 :
758 17 : mp->spd_index = htonl (spd_index);
759 17 : mp->sw_if_index = htonl (sw_if_index);
760 :
761 17 : vl_api_send_msg (reg, (u8 *) mp);
762 17 : }
763 :
764 : static void
765 539 : vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t *
766 : mp)
767 : {
768 539 : ipsec_main_t *im = &ipsec_main;
769 : vl_api_registration_t *reg;
770 : u32 k, v, spd_index;
771 :
772 539 : reg = vl_api_client_index_to_registration (mp->client_index);
773 539 : if (!reg)
774 0 : return;
775 :
776 539 : if (mp->spd_index_valid)
777 : {
778 0 : spd_index = ntohl (mp->spd_index);
779 : /* *INDENT-OFF* */
780 0 : hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
781 : if (v == spd_index)
782 : send_ipsec_spd_interface_details(reg, v, k, mp->context);
783 : }));
784 : /* *INDENT-ON* */
785 : }
786 : else
787 : {
788 35052 : hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
789 : send_ipsec_spd_interface_details(reg, v, k, mp->context);
790 : }));
791 : }
792 : }
793 :
794 : static void
795 11 : vl_api_ipsec_itf_create_t_handler (vl_api_ipsec_itf_create_t * mp)
796 : {
797 : vl_api_ipsec_itf_create_reply_t *rmp;
798 : tunnel_mode_t mode;
799 11 : u32 sw_if_index = ~0;
800 : int rv;
801 :
802 11 : rv = tunnel_mode_decode (mp->itf.mode, &mode);
803 :
804 11 : if (!rv)
805 11 : rv = ipsec_itf_create (ntohl (mp->itf.user_instance), mode, &sw_if_index);
806 :
807 : /* *INDENT-OFF* */
808 11 : REPLY_MACRO2 (VL_API_IPSEC_ITF_CREATE_REPLY,
809 : ({
810 : rmp->sw_if_index = htonl (sw_if_index);
811 : }));
812 : /* *INDENT-ON* */
813 : }
814 :
815 : static void
816 11 : vl_api_ipsec_itf_delete_t_handler (vl_api_ipsec_itf_delete_t * mp)
817 : {
818 : vl_api_ipsec_itf_delete_reply_t *rmp;
819 : int rv;
820 :
821 11 : rv = ipsec_itf_delete (ntohl (mp->sw_if_index));
822 :
823 11 : REPLY_MACRO (VL_API_IPSEC_ITF_DELETE_REPLY);
824 : }
825 :
826 : static walk_rc_t
827 13 : send_ipsec_itf_details (ipsec_itf_t *itf, void *arg)
828 : {
829 13 : ipsec_dump_walk_ctx_t *ctx = arg;
830 : vl_api_ipsec_itf_details_t *mp;
831 :
832 13 : if (~0 != ctx->sw_if_index && ctx->sw_if_index != itf->ii_sw_if_index)
833 0 : return (WALK_CONTINUE);
834 :
835 13 : mp = vl_msg_api_alloc (sizeof (*mp));
836 13 : clib_memset (mp, 0, sizeof (*mp));
837 13 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_ITF_DETAILS);
838 13 : mp->context = ctx->context;
839 :
840 13 : mp->itf.mode = tunnel_mode_encode (itf->ii_mode);
841 13 : mp->itf.user_instance = htonl (itf->ii_user_instance);
842 13 : mp->itf.sw_if_index = htonl (itf->ii_sw_if_index);
843 13 : vl_api_send_msg (ctx->reg, (u8 *) mp);
844 :
845 13 : return (WALK_CONTINUE);
846 : }
847 :
848 : static void
849 24 : vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp)
850 : {
851 : vl_api_registration_t *reg;
852 :
853 24 : reg = vl_api_client_index_to_registration (mp->client_index);
854 24 : if (!reg)
855 0 : return;
856 :
857 24 : ipsec_dump_walk_ctx_t ctx = {
858 : .reg = reg,
859 24 : .context = mp->context,
860 24 : .sw_if_index = ntohl (mp->sw_if_index),
861 : };
862 :
863 24 : ipsec_itf_walk (send_ipsec_itf_details, &ctx);
864 : }
865 :
866 : typedef struct ipsec_sa_dump_match_ctx_t_
867 : {
868 : index_t sai;
869 : u32 sw_if_index;
870 : } ipsec_sa_dump_match_ctx_t;
871 :
872 : static walk_rc_t
873 1 : ipsec_sa_dump_match_sa (index_t itpi, void *arg)
874 : {
875 1 : ipsec_sa_dump_match_ctx_t *ctx = arg;
876 : ipsec_tun_protect_t *itp;
877 : index_t sai;
878 :
879 1 : itp = ipsec_tun_protect_get (itpi);
880 :
881 1 : if (itp->itp_out_sa == ctx->sai)
882 : {
883 0 : ctx->sw_if_index = itp->itp_sw_if_index;
884 0 : return (WALK_STOP);
885 : }
886 :
887 1 : FOR_EACH_IPSEC_PROTECT_INPUT_SAI (itp, sai,
888 : ({
889 : if (sai == ctx->sai)
890 : {
891 : ctx->sw_if_index = itp->itp_sw_if_index;
892 : return (WALK_STOP);
893 : }
894 : }));
895 :
896 0 : return (WALK_CONTINUE);
897 : }
898 :
899 : static walk_rc_t
900 348 : send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
901 : {
902 348 : ipsec_dump_walk_ctx_t *ctx = arg;
903 : vl_api_ipsec_sa_details_t *mp;
904 :
905 348 : mp = vl_msg_api_alloc (sizeof (*mp));
906 348 : clib_memset (mp, 0, sizeof (*mp));
907 348 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_DETAILS);
908 348 : mp->context = ctx->context;
909 :
910 348 : mp->entry.sad_id = htonl (sa->id);
911 348 : mp->entry.spi = htonl (sa->spi);
912 348 : mp->entry.protocol = ipsec_proto_encode (sa->protocol);
913 348 : mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
914 :
915 348 : mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
916 348 : ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
917 :
918 348 : mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
919 348 : ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
920 :
921 348 : mp->entry.flags = ipsec_sad_flags_encode (sa);
922 348 : mp->entry.salt = clib_host_to_net_u32 (sa->salt);
923 :
924 348 : if (ipsec_sa_is_set_IS_PROTECT (sa))
925 : {
926 1 : ipsec_sa_dump_match_ctx_t ctx = {
927 1 : .sai = sa - ipsec_sa_pool,
928 : .sw_if_index = ~0,
929 : };
930 1 : ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
931 :
932 1 : mp->sw_if_index = htonl (ctx.sw_if_index);
933 : }
934 : else
935 347 : mp->sw_if_index = ~0;
936 :
937 348 : if (ipsec_sa_is_set_IS_TUNNEL (sa))
938 : {
939 2 : ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
940 2 : ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
941 : }
942 348 : if (ipsec_sa_is_set_UDP_ENCAP (sa))
943 : {
944 6 : mp->entry.udp_src_port = sa->udp_hdr.src_port;
945 6 : mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
946 : }
947 :
948 348 : mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
949 348 : mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
950 348 : if (ipsec_sa_is_set_USE_ESN (sa))
951 : {
952 4 : mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
953 4 : mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
954 : }
955 348 : if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
956 348 : mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
957 :
958 348 : mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
959 :
960 348 : vl_api_send_msg (ctx->reg, (u8 *) mp);
961 :
962 348 : return (WALK_CONTINUE);
963 : }
964 :
965 : static void
966 140 : vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
967 : {
968 : vl_api_registration_t *reg;
969 :
970 140 : reg = vl_api_client_index_to_registration (mp->client_index);
971 140 : if (!reg)
972 0 : return;
973 :
974 140 : ipsec_dump_walk_ctx_t ctx = {
975 : .reg = reg,
976 140 : .context = mp->context,
977 : };
978 :
979 140 : ipsec_sa_walk (send_ipsec_sa_details, &ctx);
980 : }
981 :
982 : static walk_rc_t
983 0 : send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
984 : {
985 0 : ipsec_dump_walk_ctx_t *ctx = arg;
986 : vl_api_ipsec_sa_v2_details_t *mp;
987 :
988 0 : mp = vl_msg_api_alloc (sizeof (*mp));
989 0 : clib_memset (mp, 0, sizeof (*mp));
990 0 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V2_DETAILS);
991 0 : mp->context = ctx->context;
992 :
993 0 : mp->entry.sad_id = htonl (sa->id);
994 0 : mp->entry.spi = htonl (sa->spi);
995 0 : mp->entry.protocol = ipsec_proto_encode (sa->protocol);
996 0 : mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
997 :
998 0 : mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
999 0 : ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1000 :
1001 0 : mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1002 0 : ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1003 :
1004 0 : mp->entry.flags = ipsec_sad_flags_encode (sa);
1005 0 : mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1006 :
1007 0 : if (ipsec_sa_is_set_IS_PROTECT (sa))
1008 : {
1009 0 : ipsec_sa_dump_match_ctx_t ctx = {
1010 0 : .sai = sa - ipsec_sa_pool,
1011 : .sw_if_index = ~0,
1012 : };
1013 0 : ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1014 :
1015 0 : mp->sw_if_index = htonl (ctx.sw_if_index);
1016 : }
1017 : else
1018 0 : mp->sw_if_index = ~0;
1019 :
1020 0 : if (ipsec_sa_is_set_IS_TUNNEL (sa))
1021 : {
1022 0 : ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
1023 0 : ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
1024 : }
1025 0 : if (ipsec_sa_is_set_UDP_ENCAP (sa))
1026 : {
1027 0 : mp->entry.udp_src_port = sa->udp_hdr.src_port;
1028 0 : mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1029 : }
1030 :
1031 0 : mp->entry.tunnel_flags =
1032 0 : tunnel_encap_decap_flags_encode (sa->tunnel.t_encap_decap_flags);
1033 0 : mp->entry.dscp = ip_dscp_encode (sa->tunnel.t_dscp);
1034 :
1035 0 : mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1036 0 : mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
1037 0 : if (ipsec_sa_is_set_USE_ESN (sa))
1038 : {
1039 0 : mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1040 0 : mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1041 : }
1042 0 : if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1043 0 : mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1044 :
1045 0 : mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1046 :
1047 0 : vl_api_send_msg (ctx->reg, (u8 *) mp);
1048 :
1049 0 : return (WALK_CONTINUE);
1050 : }
1051 :
1052 : static void
1053 0 : vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_v2_dump_t *mp)
1054 : {
1055 : vl_api_registration_t *reg;
1056 :
1057 0 : reg = vl_api_client_index_to_registration (mp->client_index);
1058 0 : if (!reg)
1059 0 : return;
1060 :
1061 0 : ipsec_dump_walk_ctx_t ctx = {
1062 : .reg = reg,
1063 0 : .context = mp->context,
1064 : };
1065 :
1066 0 : ipsec_sa_walk (send_ipsec_sa_v2_details, &ctx);
1067 : }
1068 :
1069 : static walk_rc_t
1070 4568 : send_ipsec_sa_v3_details (ipsec_sa_t *sa, void *arg)
1071 : {
1072 4568 : ipsec_dump_walk_ctx_t *ctx = arg;
1073 : vl_api_ipsec_sa_v3_details_t *mp;
1074 :
1075 4568 : mp = vl_msg_api_alloc (sizeof (*mp));
1076 4568 : clib_memset (mp, 0, sizeof (*mp));
1077 4568 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V3_DETAILS);
1078 4568 : mp->context = ctx->context;
1079 :
1080 4568 : mp->entry.sad_id = htonl (sa->id);
1081 4568 : mp->entry.spi = htonl (sa->spi);
1082 4568 : mp->entry.protocol = ipsec_proto_encode (sa->protocol);
1083 :
1084 4568 : mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
1085 4568 : ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1086 :
1087 4568 : mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1088 4568 : ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1089 :
1090 4568 : mp->entry.flags = ipsec_sad_flags_encode (sa);
1091 4568 : mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1092 :
1093 4568 : if (ipsec_sa_is_set_IS_PROTECT (sa))
1094 : {
1095 0 : ipsec_sa_dump_match_ctx_t ctx = {
1096 0 : .sai = sa - ipsec_sa_pool,
1097 : .sw_if_index = ~0,
1098 : };
1099 0 : ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1100 :
1101 0 : mp->sw_if_index = htonl (ctx.sw_if_index);
1102 : }
1103 : else
1104 4568 : mp->sw_if_index = ~0;
1105 :
1106 4568 : if (ipsec_sa_is_set_IS_TUNNEL (sa))
1107 1088 : tunnel_encode (&sa->tunnel, &mp->entry.tunnel);
1108 :
1109 4568 : if (ipsec_sa_is_set_UDP_ENCAP (sa))
1110 : {
1111 148 : mp->entry.udp_src_port = sa->udp_hdr.src_port;
1112 148 : mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1113 : }
1114 :
1115 4568 : mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1116 4568 : mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
1117 4568 : if (ipsec_sa_is_set_USE_ESN (sa))
1118 : {
1119 0 : mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1120 0 : mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1121 : }
1122 4568 : if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1123 68 : mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1124 :
1125 4568 : mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1126 :
1127 4568 : vl_api_send_msg (ctx->reg, (u8 *) mp);
1128 :
1129 4568 : return (WALK_CONTINUE);
1130 : }
1131 :
1132 : static void
1133 2487 : vl_api_ipsec_sa_v3_dump_t_handler (vl_api_ipsec_sa_v3_dump_t *mp)
1134 : {
1135 : vl_api_registration_t *reg;
1136 :
1137 2487 : reg = vl_api_client_index_to_registration (mp->client_index);
1138 2487 : if (!reg)
1139 0 : return;
1140 :
1141 2487 : ipsec_dump_walk_ctx_t ctx = {
1142 : .reg = reg,
1143 2487 : .context = mp->context,
1144 : };
1145 :
1146 2487 : ipsec_sa_walk (send_ipsec_sa_v3_details, &ctx);
1147 : }
1148 :
1149 : static walk_rc_t
1150 2 : send_ipsec_sa_v4_details (ipsec_sa_t *sa, void *arg)
1151 : {
1152 2 : ipsec_dump_walk_ctx_t *ctx = arg;
1153 : vl_api_ipsec_sa_v4_details_t *mp;
1154 :
1155 2 : mp = vl_msg_api_alloc (sizeof (*mp));
1156 2 : clib_memset (mp, 0, sizeof (*mp));
1157 2 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V4_DETAILS);
1158 2 : mp->context = ctx->context;
1159 :
1160 2 : mp->entry.sad_id = htonl (sa->id);
1161 2 : mp->entry.spi = htonl (sa->spi);
1162 2 : mp->entry.protocol = ipsec_proto_encode (sa->protocol);
1163 :
1164 2 : mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
1165 2 : ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1166 :
1167 2 : mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1168 2 : ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1169 :
1170 2 : mp->entry.flags = ipsec_sad_flags_encode (sa);
1171 2 : mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1172 :
1173 2 : if (ipsec_sa_is_set_IS_PROTECT (sa))
1174 : {
1175 0 : ipsec_sa_dump_match_ctx_t ctx = {
1176 0 : .sai = sa - ipsec_sa_pool,
1177 : .sw_if_index = ~0,
1178 : };
1179 0 : ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1180 :
1181 0 : mp->sw_if_index = htonl (ctx.sw_if_index);
1182 : }
1183 : else
1184 2 : mp->sw_if_index = ~0;
1185 :
1186 2 : if (ipsec_sa_is_set_IS_TUNNEL (sa))
1187 0 : tunnel_encode (&sa->tunnel, &mp->entry.tunnel);
1188 :
1189 2 : if (ipsec_sa_is_set_UDP_ENCAP (sa))
1190 : {
1191 0 : mp->entry.udp_src_port = sa->udp_hdr.src_port;
1192 0 : mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1193 : }
1194 :
1195 2 : mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1196 2 : mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
1197 2 : if (ipsec_sa_is_set_USE_ESN (sa))
1198 : {
1199 0 : mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1200 0 : mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1201 : }
1202 2 : if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1203 0 : mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1204 :
1205 2 : mp->thread_index = clib_host_to_net_u32 (sa->thread_index);
1206 2 : mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1207 :
1208 2 : vl_api_send_msg (ctx->reg, (u8 *) mp);
1209 :
1210 2 : return (WALK_CONTINUE);
1211 : }
1212 :
1213 : static void
1214 2 : vl_api_ipsec_sa_v4_dump_t_handler (vl_api_ipsec_sa_v4_dump_t *mp)
1215 : {
1216 : vl_api_registration_t *reg;
1217 :
1218 2 : reg = vl_api_client_index_to_registration (mp->client_index);
1219 2 : if (!reg)
1220 0 : return;
1221 :
1222 2 : ipsec_dump_walk_ctx_t ctx = {
1223 : .reg = reg,
1224 2 : .context = mp->context,
1225 : };
1226 :
1227 2 : ipsec_sa_walk (send_ipsec_sa_v4_details, &ctx);
1228 : }
1229 :
1230 : static void
1231 1 : vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
1232 : {
1233 : vl_api_registration_t *rp;
1234 1 : ipsec_main_t *im = &ipsec_main;
1235 1 : u32 context = mp->context;
1236 :
1237 1 : rp = vl_api_client_index_to_registration (mp->client_index);
1238 :
1239 1 : if (rp == 0)
1240 : {
1241 0 : clib_warning ("Client %d AWOL", mp->client_index);
1242 0 : return;
1243 : }
1244 :
1245 : ipsec_ah_backend_t *ab;
1246 : ipsec_esp_backend_t *eb;
1247 : /* *INDENT-OFF* */
1248 2 : pool_foreach (ab, im->ah_backends) {
1249 1 : vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1250 1 : clib_memset (mp, 0, sizeof (*mp));
1251 1 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_BACKEND_DETAILS);
1252 1 : mp->context = context;
1253 1 : snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
1254 : ab->name);
1255 1 : mp->protocol = ntohl (IPSEC_API_PROTO_AH);
1256 1 : mp->index = ab - im->ah_backends;
1257 1 : mp->active = mp->index == im->ah_current_backend ? 1 : 0;
1258 1 : vl_api_send_msg (rp, (u8 *)mp);
1259 : }
1260 2 : pool_foreach (eb, im->esp_backends) {
1261 1 : vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1262 1 : clib_memset (mp, 0, sizeof (*mp));
1263 1 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_BACKEND_DETAILS);
1264 1 : mp->context = context;
1265 1 : snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
1266 : eb->name);
1267 1 : mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
1268 1 : mp->index = eb - im->esp_backends;
1269 1 : mp->active = mp->index == im->esp_current_backend ? 1 : 0;
1270 1 : vl_api_send_msg (rp, (u8 *)mp);
1271 : }
1272 : /* *INDENT-ON* */
1273 : }
1274 :
1275 : static void
1276 6 : vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
1277 : {
1278 6 : ipsec_main_t *im = &ipsec_main;
1279 : vl_api_ipsec_select_backend_reply_t *rmp;
1280 : ipsec_protocol_t protocol;
1281 6 : int rv = 0;
1282 6 : if (pool_elts (ipsec_sa_pool) > 0)
1283 : {
1284 1 : rv = VNET_API_ERROR_INSTANCE_IN_USE;
1285 1 : goto done;
1286 : }
1287 :
1288 5 : rv = ipsec_proto_decode (mp->protocol, &protocol);
1289 :
1290 5 : if (rv)
1291 0 : goto done;
1292 :
1293 5 : switch (protocol)
1294 : {
1295 2 : case IPSEC_PROTOCOL_ESP:
1296 2 : rv = ipsec_select_esp_backend (im, mp->index);
1297 2 : break;
1298 3 : case IPSEC_PROTOCOL_AH:
1299 3 : rv = ipsec_select_ah_backend (im, mp->index);
1300 3 : break;
1301 0 : default:
1302 0 : rv = VNET_API_ERROR_INVALID_PROTOCOL;
1303 0 : break;
1304 : }
1305 6 : done:
1306 6 : REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1307 : }
1308 :
1309 : static void
1310 2 : vl_api_ipsec_set_async_mode_t_handler (vl_api_ipsec_set_async_mode_t * mp)
1311 : {
1312 : vl_api_ipsec_set_async_mode_reply_t *rmp;
1313 2 : int rv = 0;
1314 :
1315 2 : ipsec_set_async_mode (mp->async_enable);
1316 :
1317 2 : REPLY_MACRO (VL_API_IPSEC_SET_ASYNC_MODE_REPLY);
1318 : }
1319 :
1320 : #include <vnet/ipsec/ipsec.api.c>
1321 : static clib_error_t *
1322 575 : ipsec_api_hookup (vlib_main_t * vm)
1323 : {
1324 : /*
1325 : * Set up the (msg_name, crc, message-id) table
1326 : */
1327 575 : REPLY_MSG_ID_BASE = setup_message_id_table ();
1328 :
1329 575 : return 0;
1330 : }
1331 :
1332 8063 : VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1333 :
1334 : /*
1335 : * fd.io coding-style-patch-verification: ON
1336 : *
1337 : * Local Variables:
1338 : * eval: (c-set-style "gnu")
1339 : * End:
1340 : */
|