FD.io VPP  v19.04.1-1-ge4a0f9f
Vector Packet Processing
ipsec_api.c
Go to the documentation of this file.
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/fib/fib.h>
28 
29 #include <vnet/vnet_msg_enum.h>
30 
31 #if WITH_LIBSSL > 0
32 #include <vnet/ipsec/ipsec.h>
33 #endif /* IPSEC */
34 
35 #define vl_typedefs /* define message structures */
36 #include <vnet/vnet_all_api_h.h>
37 #undef vl_typedefs
38 
39 #define vl_endianfun /* define message structures */
40 #include <vnet/vnet_all_api_h.h>
41 #undef vl_endianfun
42 
43 /* instantiate all the print functions we know about */
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45 #define vl_printfun
46 #include <vnet/vnet_all_api_h.h>
47 #undef vl_printfun
48 
50 
51 #define foreach_vpe_api_msg \
52 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del) \
53 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \
54 _(IPSEC_SPD_ENTRY_ADD_DEL, ipsec_spd_entry_add_del) \
55 _(IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del) \
56 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key) \
57 _(IPSEC_SA_DUMP, ipsec_sa_dump) \
58 _(IPSEC_SPDS_DUMP, ipsec_spds_dump) \
59 _(IPSEC_SPD_DUMP, ipsec_spd_dump) \
60 _(IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump) \
61 _(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del) \
62 _(IPSEC_TUNNEL_IF_SET_KEY, ipsec_tunnel_if_set_key) \
63 _(IPSEC_TUNNEL_IF_SET_SA, ipsec_tunnel_if_set_sa) \
64 _(IPSEC_SELECT_BACKEND, ipsec_select_backend) \
65 _(IPSEC_BACKEND_DUMP, ipsec_backend_dump)
66 
67 static void
69 {
70 #if WITH_LIBSSL == 0
71  clib_warning ("unimplemented");
72 #else
73 
74  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
75  vl_api_ipsec_spd_add_del_reply_t *rmp;
76  int rv;
77 
78  rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
79 
80  REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
81 #endif
82 }
83 
86 {
87  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
88  vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
89  int rv;
90  u32 sw_if_index __attribute__ ((unused));
91  u32 spd_id __attribute__ ((unused));
92 
93  sw_if_index = ntohl (mp->sw_if_index);
94  spd_id = ntohl (mp->spd_id);
95 
97 
98 #if WITH_LIBSSL > 0
99  rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
100 #else
101  rv = VNET_API_ERROR_UNIMPLEMENTED;
102 #endif
103 
105 
106  REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
107 }
108 
109 static int
110 ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
111  ipsec_policy_action_t * out)
112 {
113  in = clib_net_to_host_u32 (in);
114 
115  switch (in)
116  {
117 #define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
118  *out = IPSEC_POLICY_ACTION_##f; \
119  return (0);
121 #undef _
122  }
123  return (VNET_API_ERROR_UNIMPLEMENTED);
124 }
125 
128 {
129  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
131  ip46_type_t itype;
132  u32 stat_index;
133  int rv;
134 
135  stat_index = ~0;
136 
137 #if WITH_LIBSSL > 0
138  ipsec_policy_t p;
139 
140  clib_memset (&p, 0, sizeof (p));
141 
142  p.id = ntohl (mp->entry.spd_id);
143  p.priority = ntohl (mp->entry.priority);
144 
145  itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
146  ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
147  ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
148  ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
149 
150  p.is_ipv6 = (itype == IP46_TYPE_IP6);
151 
152  p.protocol = mp->entry.protocol;
153  /* leave the ports in network order */
154  p.rport.start = mp->entry.remote_port_start;
155  p.rport.stop = mp->entry.remote_port_stop;
156  p.lport.start = mp->entry.local_port_start;
157  p.lport.stop = mp->entry.local_port_stop;
158 
159  rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
160 
161  if (rv)
162  goto out;
163 
164  /* policy action resolve unsupported */
165  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
166  {
167  clib_warning ("unsupported action: 'resolve'");
168  rv = VNET_API_ERROR_UNIMPLEMENTED;
169  goto out;
170  }
171  p.sa_id = ntohl (mp->entry.sa_id);
172  rv =
173  ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
174  &p.type);
175  if (rv)
176  goto out;
177 
178  rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
179  if (rv)
180  goto out;
181 
182 #else
183  rv = VNET_API_ERROR_UNIMPLEMENTED;
184  goto out;
185 #endif
186 
187 out:
188  /* *INDENT-OFF* */
189  REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
190  ({
191  rmp->stat_index = ntohl(stat_index);
192  }));
193  /* *INDENT-ON* */
194 }
195 
196 static int
197 ipsec_proto_decode (vl_api_ipsec_proto_t in, ipsec_protocol_t * out)
198 {
199  in = clib_net_to_host_u32 (in);
200 
201  switch (in)
202  {
203  case IPSEC_API_PROTO_ESP:
204  *out = IPSEC_PROTOCOL_ESP;
205  return (0);
206  case IPSEC_API_PROTO_AH:
207  *out = IPSEC_PROTOCOL_AH;
208  return (0);
209  }
210  return (VNET_API_ERROR_INVALID_PROTOCOL);
211 }
212 
213 static vl_api_ipsec_proto_t
215 {
216  switch (p)
217  {
218  case IPSEC_PROTOCOL_ESP:
219  return clib_host_to_net_u32 (IPSEC_API_PROTO_ESP);
220  case IPSEC_PROTOCOL_AH:
221  return clib_host_to_net_u32 (IPSEC_API_PROTO_AH);
222  }
223  return (VNET_API_ERROR_UNIMPLEMENTED);
224 }
225 
226 static int
227 ipsec_crypto_algo_decode (vl_api_ipsec_crypto_alg_t in,
228  ipsec_crypto_alg_t * out)
229 {
230  in = clib_net_to_host_u32 (in);
231 
232  switch (in)
233  {
234 #define _(v,f,s) case IPSEC_API_CRYPTO_ALG_##f: \
235  *out = IPSEC_CRYPTO_ALG_##f; \
236  return (0);
238 #undef _
239  }
240  return (VNET_API_ERROR_INVALID_ALGORITHM);
241 }
242 
243 static vl_api_ipsec_crypto_alg_t
245 {
246  switch (c)
247  {
248 #define _(v,f,s) case IPSEC_CRYPTO_ALG_##f: \
249  return clib_host_to_net_u32(IPSEC_API_CRYPTO_ALG_##f);
251 #undef _
252  case IPSEC_CRYPTO_N_ALG:
253  break;
254  }
255  ASSERT (0);
256  return (VNET_API_ERROR_UNIMPLEMENTED);
257 }
258 
259 
260 static int
261 ipsec_integ_algo_decode (vl_api_ipsec_integ_alg_t in, ipsec_integ_alg_t * out)
262 {
263  in = clib_net_to_host_u32 (in);
264 
265  switch (in)
266  {
267 #define _(v,f,s) case IPSEC_API_INTEG_ALG_##f: \
268  *out = IPSEC_INTEG_ALG_##f; \
269  return (0);
271 #undef _
272  }
273  return (VNET_API_ERROR_INVALID_ALGORITHM);
274 }
275 
276 static vl_api_ipsec_integ_alg_t
278 {
279  switch (i)
280  {
281 #define _(v,f,s) case IPSEC_INTEG_ALG_##f: \
282  return (clib_host_to_net_u32(IPSEC_API_INTEG_ALG_##f));
284 #undef _
285  case IPSEC_INTEG_N_ALG:
286  break;
287  }
288  ASSERT (0);
289  return (VNET_API_ERROR_UNIMPLEMENTED);
290 }
291 
292 static void
293 ipsec_key_decode (const vl_api_key_t * key, ipsec_key_t * out)
294 {
295  ipsec_mk_key (out, key->data, key->length);
296 }
297 
298 static void
299 ipsec_key_encode (const ipsec_key_t * in, vl_api_key_t * out)
300 {
301  out->length = in->len;
302  clib_memcpy (out->data, in->data, out->length);
303 }
304 
305 static ipsec_sa_flags_t
306 ipsec_sa_flags_decode (vl_api_ipsec_sad_flags_t in)
307 {
308  ipsec_sa_flags_t flags = IPSEC_SA_FLAG_NONE;
309  in = clib_net_to_host_u32 (in);
310 
312  flags |= IPSEC_SA_FLAG_USE_ESN;
314  flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
316  flags |= IPSEC_SA_FLAG_IS_TUNNEL;
318  flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
320  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
321 
322  return (flags);
323 }
324 
325 static vl_api_ipsec_sad_flags_t
327 {
328  vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
329 
330  if (ipsec_sa_is_set_USE_ESN (sa))
332  if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
334  if (ipsec_sa_is_set_IS_TUNNEL (sa))
336  if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa))
338  if (ipsec_sa_is_set_UDP_ENCAP (sa))
340 
341  return clib_host_to_net_u32 (flags);
342 }
343 
346 {
347  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
349  ip46_address_t tun_src = { }, tun_dst =
350  {
351  };
352  ipsec_key_t crypto_key, integ_key;
353  ipsec_crypto_alg_t crypto_alg;
354  ipsec_integ_alg_t integ_alg;
355  ipsec_protocol_t proto;
357  u32 id, spi, sa_index = ~0;
358  int rv;
359 
360 #if WITH_LIBSSL > 0
361 
362  id = ntohl (mp->entry.sad_id);
363  spi = ntohl (mp->entry.spi);
364 
365  rv = ipsec_proto_decode (mp->entry.protocol, &proto);
366 
367  if (rv)
368  goto out;
369 
370  rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
371 
372  if (rv)
373  goto out;
374 
375  rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
376 
377  if (rv)
378  goto out;
379 
380  ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
381  ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
382 
383  flags = ipsec_sa_flags_decode (mp->entry.flags);
384 
385  ip_address_decode (&mp->entry.tunnel_src, &tun_src);
386  ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
387 
388 
389  if (mp->is_add)
390  rv = ipsec_sa_add (id, spi, proto,
391  crypto_alg, &crypto_key,
392  integ_alg, &integ_key, flags,
393  0, 0, &tun_src, &tun_dst, &sa_index);
394  else
395  rv = ipsec_sa_del (id);
396 
397 #else
398  rv = VNET_API_ERROR_UNIMPLEMENTED;
399 #endif
400 
401 out:
402  /* *INDENT-OFF* */
403  REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
404  {
405  rmp->stat_index = htonl (sa_index);
406  });
407  /* *INDENT-ON* */
408 }
409 
410 static void
412  u32 context)
413 {
415  u32 n_policies = 0;
416 
417  mp = vl_msg_api_alloc (sizeof (*mp));
418  clib_memset (mp, 0, sizeof (*mp));
419  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPDS_DETAILS);
420  mp->context = context;
421 
422  mp->spd_id = htonl (spd->id);
423 #define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
425 #undef _
426  mp->npolicies = htonl (n_policies);
427 
428  vl_api_send_msg (reg, (u8 *) mp);
429 }
430 
431 static void
433 {
435  ipsec_main_t *im = &ipsec_main;
436  ipsec_spd_t *spd;
437 #if WITH_LIBSSL > 0
439  if (!reg)
440  return;
441 
442  /* *INDENT-OFF* */
443  pool_foreach (spd, im->spds, ({
444  send_ipsec_spds_details (spd, reg, mp->context);
445  }));
446  /* *INDENT-ON* */
447 #else
448  clib_warning ("unimplemented");
449 #endif
450 }
451 
452 vl_api_ipsec_spd_action_t
454 {
455  vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
456 
457  switch (in)
458  {
459 #define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
460  out = IPSEC_API_SPD_ACTION_##f; \
461  break;
463 #undef _
464  }
465  return (clib_host_to_net_u32 (out));
466 }
467 
468 static void
470  u32 context)
471 {
473 
474  mp = vl_msg_api_alloc (sizeof (*mp));
475  clib_memset (mp, 0, sizeof (*mp));
476  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
477  mp->context = context;
478 
479  mp->entry.spd_id = htonl (p->id);
480  mp->entry.priority = htonl (p->priority);
481  mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
482  (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
483 
485  &mp->entry.local_address_start);
487  &mp->entry.local_address_stop);
489  &mp->entry.remote_address_start);
491  &mp->entry.remote_address_stop);
492  mp->entry.local_port_start = p->lport.start;
493  mp->entry.local_port_stop = p->lport.stop;
494  mp->entry.remote_port_start = p->rport.start;
495  mp->entry.remote_port_stop = p->rport.stop;
496  mp->entry.protocol = p->protocol;
497  mp->entry.policy = ipsec_spd_action_encode (p->policy);
498  mp->entry.sa_id = htonl (p->sa_id);
499 
500  vl_api_send_msg (reg, (u8 *) mp);
501 }
502 
503 static void
505 {
507  ipsec_main_t *im = &ipsec_main;
510  ipsec_spd_t *spd;
511  uword *p;
512  u32 spd_index, *ii;
513 #if WITH_LIBSSL > 0
515  if (!reg)
516  return;
517 
518  p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
519  if (!p)
520  return;
521 
522  spd_index = p[0];
523  spd = pool_elt_at_index (im->spds, spd_index);
524 
525  /* *INDENT-OFF* */
527  vec_foreach(ii, spd->policies[ptype])
528  {
529  policy = pool_elt_at_index(im->policies, *ii);
530 
531  if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
532  send_ipsec_spd_details (policy, reg, mp->context);
533  }
534  }
535  /* *INDENT-ON* */
536 #else
537  clib_warning ("unimplemented");
538 #endif
539 }
540 
541 static void
544 {
546 
547  mp = vl_msg_api_alloc (sizeof (*mp));
548  clib_memset (mp, 0, sizeof (*mp));
549  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_INTERFACE_DETAILS);
550  mp->context = context;
551 
552  mp->spd_index = htonl (spd_index);
553  mp->sw_if_index = htonl (sw_if_index);
554 
555  vl_api_send_msg (reg, (u8 *) mp);
556 }
557 
558 static void
560  mp)
561 {
562  ipsec_main_t *im = &ipsec_main;
564  u32 k, v, spd_index;
565 
566 #if WITH_LIBSSL > 0
568  if (!reg)
569  return;
570 
571  if (mp->spd_index_valid)
572  {
573  spd_index = ntohl (mp->spd_index);
574  /* *INDENT-OFF* */
576  if (v == spd_index)
577  send_ipsec_spd_interface_details(reg, v, k, mp->context);
578  }));
579  /* *INDENT-ON* */
580  }
581  else
582  {
583  /* *INDENT-OFF* */
585  send_ipsec_spd_interface_details(reg, v, k, mp->context);
586  }));
587  /* *INDENT-ON* */
588  }
589 
590 #else
591  clib_warning ("unimplemented");
592 #endif
593 }
594 
595 static void
597 {
598  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
599  vl_api_ipsec_sa_set_key_reply_t *rmp;
600  ipsec_key_t ck, ik;
601  u32 id;
602  int rv;
603 #if WITH_LIBSSL > 0
604 
605  id = ntohl (mp->sa_id);
606 
607  ipsec_key_decode (&mp->crypto_key, &ck);
608  ipsec_key_decode (&mp->integrity_key, &ik);
609 
610  rv = ipsec_set_sa_key (id, &ck, &ik);
611 #else
612  rv = VNET_API_ERROR_UNIMPLEMENTED;
613 #endif
614 
615  REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
616 }
617 
618 static void
620  mp)
621 {
623  ipsec_main_t *im = &ipsec_main;
624  vnet_main_t *vnm = im->vnet_main;
625  u32 sw_if_index = ~0;
626  ip46_type_t itype;
627  int rv;
628 
629 #if WITH_LIBSSL > 0
631 
632  clib_memset (&tun, 0, sizeof (ipsec_add_del_tunnel_args_t));
633 
634  tun.is_add = mp->is_add;
635  tun.esn = mp->esn;
636  tun.anti_replay = mp->anti_replay;
637  tun.local_spi = ntohl (mp->local_spi);
638  tun.remote_spi = ntohl (mp->remote_spi);
639  tun.crypto_alg = mp->crypto_alg;
642  tun.integ_alg = mp->integ_alg;
645  tun.udp_encap = mp->udp_encap;
646  tun.tx_table_id = ntohl (mp->tx_table_id);
647  itype = ip_address_decode (&mp->local_ip, &tun.local_ip);
648  itype = ip_address_decode (&mp->remote_ip, &tun.remote_ip);
649  tun.is_ip6 = (IP46_TYPE_IP6 == itype);
650  memcpy (&tun.local_crypto_key, &mp->local_crypto_key,
652  memcpy (&tun.remote_crypto_key, &mp->remote_crypto_key,
654  memcpy (&tun.local_integ_key, &mp->local_integ_key,
655  mp->local_integ_key_len);
656  memcpy (&tun.remote_integ_key, &mp->remote_integ_key,
658  tun.renumber = mp->renumber;
659  tun.show_instance = ntohl (mp->show_instance);
660 
661  rv = ipsec_add_del_tunnel_if_internal (vnm, &tun, &sw_if_index);
662 
663 #else
664  rv = VNET_API_ERROR_UNIMPLEMENTED;
665 #endif
666 
667  /* *INDENT-OFF* */
668  REPLY_MACRO2 (VL_API_IPSEC_TUNNEL_IF_ADD_DEL_REPLY,
669  ({
670  rmp->sw_if_index = htonl (sw_if_index);
671  }));
672  /* *INDENT-ON* */
673 }
674 
675 static void
678 {
680 
681  mp = vl_msg_api_alloc (sizeof (*mp));
682  clib_memset (mp, 0, sizeof (*mp));
683  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
684  mp->context = context;
685 
686  mp->entry.sad_id = htonl (sa->id);
687  mp->entry.spi = htonl (sa->spi);
688  mp->entry.protocol = ipsec_proto_encode (sa->protocol);
689  mp->entry.tx_table_id =
691 
692  mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
693  ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
694 
695  mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
696  ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
697 
698  mp->entry.flags = ipsec_sad_flags_encode (sa);
699 
700  if (ipsec_sa_is_set_IS_TUNNEL (sa))
701  {
703  &mp->entry.tunnel_src);
705  &mp->entry.tunnel_dst);
706  }
707 
708  mp->sw_if_index = htonl (sw_if_index);
709  mp->salt = clib_host_to_net_u32 (sa->salt);
710  mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
711  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
712  if (ipsec_sa_is_set_USE_ESN (sa))
713  {
714  mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
715  mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
716  }
717  if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
718  mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
719 
720  vl_api_send_msg (reg, (u8 *) mp);
721 }
722 
723 
724 static void
726 {
728  ipsec_main_t *im = &ipsec_main;
729  vnet_main_t *vnm = im->vnet_main;
730  ipsec_sa_t *sa;
732  u32 *sa_index_to_tun_if_index = 0;
733 
734 #if WITH_LIBSSL > 0
736  if (!reg || pool_elts (im->sad) == 0)
737  return;
738 
739  vec_validate_init_empty (sa_index_to_tun_if_index, vec_len (im->sad) - 1,
740  ~0);
741 
742  /* *INDENT-OFF* */
744  ({
745  vnet_hw_interface_t *hi;
746  u32 sw_if_index = ~0;
747 
748  hi = vnet_get_hw_interface (vnm, t->hw_if_index);
749  sw_if_index = hi->sw_if_index;
750  sa_index_to_tun_if_index[t->input_sa_index] = sw_if_index;
751  sa_index_to_tun_if_index[t->output_sa_index] = sw_if_index;
752  }));
753 
754  pool_foreach (sa, im->sad,
755  ({
756  if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == sa->id)
757  send_ipsec_sa_details (sa, reg, mp->context,
758  sa_index_to_tun_if_index[sa - im->sad]);
759  }));
760  /* *INDENT-ON* */
761 
762  vec_free (sa_index_to_tun_if_index);
763 #else
764  clib_warning ("unimplemented");
765 #endif
766 }
767 
768 
769 static void
771  mp)
772 {
773  vl_api_ipsec_tunnel_if_set_key_reply_t *rmp;
774  ipsec_main_t *im = &ipsec_main;
775  vnet_main_t *vnm = im->vnet_main;
777  u8 *key = 0;
778  int rv;
779 
780 #if WITH_LIBSSL > 0
781  sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
782 
783  switch (mp->key_type)
784  {
787  if (mp->alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
788  mp->alg >= IPSEC_CRYPTO_N_ALG)
789  {
790  rv = VNET_API_ERROR_INVALID_ALGORITHM;
791  goto out;
792  }
793  break;
796  if (mp->alg >= IPSEC_INTEG_N_ALG)
797  {
798  rv = VNET_API_ERROR_INVALID_ALGORITHM;
799  goto out;
800  }
801  break;
803  default:
804  rv = VNET_API_ERROR_UNIMPLEMENTED;
805  goto out;
806  break;
807  }
808 
809  key = vec_new (u8, mp->key_len);
810  clib_memcpy (key, mp->key, mp->key_len);
811 
812  rv = ipsec_set_interface_key (vnm, sw->hw_if_index, mp->key_type, mp->alg,
813  key);
814  vec_free (key);
815 #else
816  clib_warning ("unimplemented");
817 #endif
818 
819 out:
820  REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_KEY_REPLY);
821 }
822 
823 
824 static void
826 {
827  vl_api_ipsec_tunnel_if_set_sa_reply_t *rmp;
828  ipsec_main_t *im = &ipsec_main;
829  vnet_main_t *vnm = im->vnet_main;
831  int rv;
832 
833 #if WITH_LIBSSL > 0
834  sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
835 
836  rv = ipsec_set_interface_sa (vnm, sw->hw_if_index, ntohl (mp->sa_id),
837  mp->is_outbound);
838 #else
839  clib_warning ("unimplemented");
840 #endif
841 
842  REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_SA_REPLY);
843 }
844 
845 static void
847 {
849  ipsec_main_t *im = &ipsec_main;
850  u32 context = mp->context;
851 
853 
854  if (rp == 0)
855  {
856  clib_warning ("Client %d AWOL", mp->client_index);
857  return;
858  }
859 
860  ipsec_ah_backend_t *ab;
862  /* *INDENT-OFF* */
863  pool_foreach (ab, im->ah_backends, {
864  vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
865  clib_memset (mp, 0, sizeof (*mp));
866  mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
867  mp->context = context;
868  snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
869  ab->name);
870  mp->protocol = ntohl (IPSEC_API_PROTO_AH);
871  mp->index = ab - im->ah_backends;
872  mp->active = mp->index == im->ah_current_backend ? 1 : 0;
873  vl_api_send_msg (rp, (u8 *)mp);
874  });
875  pool_foreach (eb, im->esp_backends, {
876  vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
877  clib_memset (mp, 0, sizeof (*mp));
878  mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
879  mp->context = context;
880  snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
881  eb->name);
882  mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
883  mp->index = eb - im->esp_backends;
884  mp->active = mp->index == im->esp_current_backend ? 1 : 0;
885  vl_api_send_msg (rp, (u8 *)mp);
886  });
887  /* *INDENT-ON* */
888 }
889 
890 static void
892 {
893  ipsec_main_t *im = &ipsec_main;
894  vl_api_ipsec_select_backend_reply_t *rmp;
896  int rv = 0;
897  if (pool_elts (im->sad) > 0)
898  {
899  rv = VNET_API_ERROR_INSTANCE_IN_USE;
900  goto done;
901  }
902 
903  rv = ipsec_proto_decode (mp->protocol, &protocol);
904 
905  if (rv)
906  goto done;
907 
908 #if WITH_LIBSSL > 0
909  switch (protocol)
910  {
911  case IPSEC_PROTOCOL_ESP:
912  rv = ipsec_select_esp_backend (im, mp->index);
913  break;
914  case IPSEC_PROTOCOL_AH:
915  rv = ipsec_select_ah_backend (im, mp->index);
916  break;
917  default:
918  rv = VNET_API_ERROR_INVALID_PROTOCOL;
919  break;
920  }
921 #else
922  clib_warning ("unimplemented"); /* FIXME */
923 #endif
924 done:
925  REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
926 }
927 
928 /*
929  * ipsec_api_hookup
930  * Add vpe's API message handlers to the table.
931  * vlib has already mapped shared memory and
932  * added the client registration handlers.
933  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
934  */
935 #define vl_msg_name_crc_list
936 #include <vnet/vnet_all_api_h.h>
937 #undef vl_msg_name_crc_list
938 
939 static void
941 {
942 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
943  foreach_vl_msg_name_crc_ipsec;
944 #undef _
945 }
946 
947 static clib_error_t *
949 {
950  api_main_t *am = &api_main;
951 
952 #define _(N,n) \
953  vl_msg_api_set_handlers(VL_API_##N, #n, \
954  vl_api_##n##_t_handler, \
955  vl_noop_handler, \
956  vl_api_##n##_t_endian, \
957  vl_api_##n##_t_print, \
958  sizeof(vl_api_##n##_t), 1);
960 #undef _
961 
962  /*
963  * Set up the (msg_name, crc, message-id) table
964  */
966 
967  return 0;
968 }
969 
971 
972 /*
973  * fd.io coding-style-patch-verification: ON
974  *
975  * Local Variables:
976  * eval: (c-set-style "gnu")
977  * End:
978  */
u32 sw_if_index
Definition: ipsec_gre.api:37
static void vl_api_ipsec_sa_set_key_t_handler(vl_api_ipsec_sa_set_key_t *mp)
Definition: ipsec_api.c:596
vl_api_key_t crypto_key
Definition: ipsec.api:323
ipsec_spd_t * spds
Definition: ipsec.h:93
IPsec: Add/delete Security Policy Database entry.
Definition: ipsec.api:117
u32 flags
Definition: vhost_user.h:115
vl_api_ipsec_spd_action_t ipsec_spd_action_encode(ipsec_policy_action_t in)
Definition: ipsec_api.c:453
ipsec_tunnel_if_t * tunnel_interfaces
Definition: ipsec.h:100
ip46_address_t tunnel_src_addr
Definition: ipsec_sa.h:156
u32 ipsec_sa_del(u32 id)
Definition: ipsec_sa.c:254
enum ipsec_spd_policy_t_ ipsec_spd_policy_type_t
IPsec: SPD interface response.
Definition: ipsec.api:346
static void vl_api_ipsec_tunnel_if_set_key_t_handler(vl_api_ipsec_tunnel_if_set_key_t *mp)
Definition: ipsec_api.c:770
ip46_address_t local_ip
Definition: ipsec_if.h:47
Dump IPsec backends.
Definition: ipsec.api:504
ipsec_integ_alg_t
Definition: ipsec_sa.h:60
VLIB_API_INIT_FUNCTION(ipsec_api_hookup)
static vl_api_ipsec_crypto_alg_t ipsec_crypto_algo_encode(ipsec_crypto_alg_t c)
Definition: ipsec_api.c:244
IPsec: Update Security Association keys.
Definition: ipsec.api:316
unsigned long u64
Definition: types.h:89
ip46_address_range_t laddr
#define REPLY_MACRO2(t, body)
#define foreach_ipsec_crypto_alg
Definition: ipsec_sa.h:24
#define FOR_EACH_IPSEC_SPD_POLICY_TYPE(_t)
Definition: ipsec_spd.h:36
int ipsec_set_interface_sa(vnet_main_t *vnm, u32 hw_if_index, u32 sa_id, u8 is_outbound)
Definition: ipsec_if.c:563
int ipsec_policy_mk_type(bool is_outbound, bool is_ipv6, ipsec_policy_action_t action, ipsec_spd_policy_type_t *type)
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:34
ipsec_key_t crypto_key
Definition: ipsec_sa.h:151
int ipsec_set_sa_key(u32 id, const ipsec_key_t *ck, const ipsec_key_t *ik)
Definition: ipsec_sa.c:321
ipsec_integ_alg_t integ_alg
Definition: ipsec_sa.h:153
ipsec_protocol_t
Definition: ipsec_sa.h:68
static void setup_message_id_table(api_main_t *am)
Definition: ipsec_api.c:940
int i
#define foreach_ipsec_integ_alg
Definition: ipsec_sa.h:51
vl_api_ipsec_spd_action_t policy
Definition: ipsec.api:95
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static void vl_api_ipsec_sa_dump_t_handler(vl_api_ipsec_sa_dump_t *mp)
Definition: ipsec_api.c:725
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
int ipsec_select_ah_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:195
A Secruity Policy Database.
Definition: ipsec_spd.h:44
static ipsec_sa_flags_t ipsec_sa_flags_decode(vl_api_ipsec_sad_flags_t in)
Definition: ipsec_api.c:306
void * vl_msg_api_alloc(int nbytes)
void ipsec_mk_key(ipsec_key_t *key, const u8 *data, u8 len)
Definition: ipsec_sa.c:54
u8 is_add
Definition: ipsec.api:121
unsigned char u8
Definition: types.h:56
#define foreach_vpe_api_msg
Definition: ipsec_api.c:51
vl_api_address_t remote_ip
Definition: ipsec.api:385
u32 seq_hi
Definition: ipsec_sa.h:123
uword * spd_index_by_sw_if_index
Definition: ipsec.h:110
static void vl_api_ipsec_interface_add_del_spd_t_handler(vl_api_ipsec_interface_add_del_spd_t *mp)
Definition: ipsec_api.c:85
#define clib_memcpy(d, s, n)
Definition: string.h:180
u64 replay_window
Definition: ipsec_sa.h:126
vl_api_key_t crypto_key
Definition: ipsec.api:275
Select IPsec backend.
Definition: ipsec.api:529
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
static int ipsec_proto_decode(vl_api_ipsec_proto_t in, ipsec_protocol_t *out)
Definition: ipsec_api.c:197
ipsec_main_t ipsec_main
Definition: ipsec.c:28
Definition: ipsec.api:299
#define vec_new(T, N)
Create new vector of given type and length (unspecified alignment, no header).
Definition: vec.h:311
static void vl_api_ipsec_tunnel_if_add_del_t_handler(vl_api_ipsec_tunnel_if_add_del_t *mp)
Definition: ipsec_api.c:619
Set key on IPsec interface.
Definition: ipsec.api:475
static void vl_api_ipsec_backend_dump_t_handler(vl_api_ipsec_backend_dump_t *mp)
Definition: ipsec_api.c:846
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:218
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
static void vl_api_ipsec_spd_dump_t_handler(vl_api_ipsec_spd_dump_t *mp)
Definition: ipsec_api.c:504
static void vl_api_ipsec_spd_interface_dump_t_handler(vl_api_ipsec_spd_interface_dump_t *mp)
Definition: ipsec_api.c:559
vl_api_address_t local_ip
Definition: ipsec.api:384
port_range_t rport
int ipsec_set_interface_key(vnet_main_t *vnm, u32 hw_if_index, ipsec_if_set_key_type_t type, u8 alg, u8 *key)
Definition: ipsec_if.c:517
unsigned int u32
Definition: types.h:88
IPsec: Reply Add/delete Security Policy Database entry.
Definition: ipsec.api:131
ip46_type_t ip_address_decode(const vl_api_address_t *in, ip46_address_t *out)
Definition: ip_types_api.c:83
static void vl_api_ipsec_spd_add_del_t_handler(vl_api_ipsec_spd_add_del_t *mp)
Definition: ipsec_api.c:68
u32 last_seq
Definition: ipsec_sa.h:124
#define hash_get(h, key)
Definition: hash.h:249
IPsec: Add/delete Security Association Database entry.
Definition: ipsec.api:292
u32 tx_fib_index
Definition: ipsec_sa.h:162
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
Dump IPsec all SPD IDs response.
Definition: ipsec.api:152
Add/delete IPsec tunnel interface response.
Definition: ipsec.api:409
IPsec: Add/delete Security Policy Database.
Definition: ipsec.api:28
u32 salt
Definition: ipsec_sa.h:163
vnet_main_t * vnet_main
Definition: ipsec.h:106
int ipsec_add_del_policy(vlib_main_t *vm, ipsec_policy_t *policy, int is_add, u32 *stat_index)
Add/Delete a SPD.
u32 last_seq_hi
Definition: ipsec_sa.h:125
static int ipsec_spd_action_decode(vl_api_ipsec_spd_action_t in, ipsec_policy_action_t *out)
Definition: ipsec_api.c:110
ip46_address_t remote_ip
Definition: ipsec_if.h:47
#define REPLY_MACRO(t)
ipsec_spd_policy_type_t type
static vl_api_ipsec_sad_flags_t ipsec_sad_flags_encode(const ipsec_sa_t *sa)
Definition: ipsec_api.c:326
static void send_ipsec_sa_details(ipsec_sa_t *sa, vl_api_registration_t *reg, u32 context, u32 sw_if_index)
Definition: ipsec_api.c:676
ipsec_policy_action_t
uword * spd_index_by_spd_id
Definition: ipsec.h:109
static void vl_api_ipsec_tunnel_if_set_sa_t_handler(vl_api_ipsec_tunnel_if_set_sa_t *mp)
Definition: ipsec_api.c:825
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:202
ip46_address_t tunnel_dst_addr
Definition: ipsec_sa.h:157
An API client registration, only in vpp/vlib.
Definition: api_common.h:45
#define BAD_SW_IF_INDEX_LABEL
IPsec: Add/delete SPD from interface.
Definition: ipsec.api:46
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_if.h:50
svmdb_client_t * c
vlib_main_t * vm
Definition: buffer.c:312
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:142
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
Dump IPsec all SPD IDs.
Definition: ipsec.api:142
vl_api_ipsec_sad_entry_t entry
Definition: ipsec.api:297
ipsec_policy_action_t policy
ip46_address_t start
u32 context
Definition: ipsec_gre.api:33
#define clib_warning(format, args...)
Definition: error.h:59
static int ipsec_crypto_algo_decode(vl_api_ipsec_crypto_alg_t in, ipsec_crypto_alg_t *out)
Definition: ipsec_api.c:227
enum ipsec_sad_flags_t_ ipsec_sa_flags_t
vl_api_ipsec_proto_t protocol
Definition: ipsec.api:532
Set new SA on IPsec interface.
Definition: ipsec.api:492
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:56
A Secruity Policy.
static void vl_api_ipsec_spds_dump_t_handler(vl_api_ipsec_spds_dump_t *mp)
Definition: ipsec_api.c:432
static void send_ipsec_spd_interface_details(vl_api_registration_t *reg, u32 spd_index, u32 sw_if_index, u32 context)
Definition: ipsec_api.c:542
vl_api_ipsec_sad_entry_t entry
Definition: ipsec.api:455
static void send_ipsec_spd_details(ipsec_policy_t *p, vl_api_registration_t *reg, u32 context)
Definition: ipsec_api.c:469
u8 data[IPSEC_KEY_MAX_LEN]
Definition: ipsec_sa.h:80
#define ASSERT(truth)
u32 spi
Definition: ipsec.api:270
static void vl_api_ipsec_spd_entry_add_del_t_handler(vl_api_ipsec_spd_entry_add_del_t *mp)
Definition: ipsec_api.c:127
ipsec_policy_t * policies
Definition: ipsec.h:97
Dump IPsec security association.
Definition: ipsec.api:420
ipsec_integ_alg_t integ_alg
Definition: ipsec_if.h:55
ip46_type_t
Definition: ip6_packet.h:70
ipsec_sa_t * sad
Definition: ipsec.h:95
u32 fib_table_get_table_id(u32 fib_index, fib_protocol_t proto)
Get the Table-ID of the FIB from protocol and index.
Definition: fib_table.c:1053
u32 * policies[IPSEC_SPD_POLICY_N_TYPES]
vectors for each of the policy types
Definition: ipsec_spd.h:49
Dump ipsec policy database data.
Definition: ipsec.api:164
u32 stat_index
Definition: ipsec.api:135
int ipsec_add_del_tunnel_if_internal(vnet_main_t *vnm, ipsec_add_del_tunnel_args_t *args, u32 *sw_if_index)
Definition: ipsec_if.c:256
ipsec_protocol_t protocol
Definition: ipsec_sa.h:148
static void send_ipsec_spds_details(ipsec_spd_t *spd, vl_api_registration_t *reg, u32 context)
Definition: ipsec_api.c:411
static vl_api_ipsec_proto_t ipsec_proto_encode(ipsec_protocol_t p)
Definition: ipsec_api.c:214
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
IPsec policy database response.
Definition: ipsec.api:177
IPsec: Get SPD interfaces.
Definition: ipsec.api:334
vl_api_ipsec_spd_entry_t entry
Definition: ipsec.api:179
vl_api_ipsec_spd_entry_t entry
Definition: ipsec.api:122
int ipsec_sa_add(u32 id, u32 spi, ipsec_protocol_t proto, ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck, ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik, ipsec_sa_flags_t flags, u32 tx_table_id, u32 salt, const ip46_address_t *tun_src, const ip46_address_t *tun_dst, u32 *sa_out_index)
Definition: ipsec_sa.c:123
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip46_address_range_t raddr
u64 uword
Definition: types.h:112
ipsec_crypto_alg_t
Definition: ipsec_sa.h:38
typedef key
Definition: ipsec.api:244
static int ipsec_integ_algo_decode(vl_api_ipsec_integ_alg_t in, ipsec_integ_alg_t *out)
Definition: ipsec_api.c:261
u8 is_add
Definition: ipsec.api:296
int ipsec_set_interface_spd(vlib_main_t *vm, u32 sw_if_index, u32 spd_id, int is_add)
Bind/attach a SPD to an interface.
Definition: ipsec_spd.c:63
static vl_api_ipsec_integ_alg_t ipsec_integ_algo_encode(ipsec_integ_alg_t i)
Definition: ipsec_api.c:277
vl_api_gbp_endpoint_tun_t tun
Definition: gbp.api:121
void ip_address_encode(const ip46_address_t *in, ip46_type_t type, vl_api_address_t *out)
Definition: ip_types_api.c:100
static void ipsec_key_decode(const vl_api_key_t *key, ipsec_key_t *out)
Definition: ipsec_api.c:293
u32 id
the User&#39;s ID for this policy
Definition: ipsec_spd.h:47
static void ipsec_key_encode(const ipsec_key_t *in, vl_api_key_t *out)
Definition: ipsec_api.c:299
vl_api_key_t integrity_key
Definition: ipsec.api:324
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_sa.h:150
port_range_t lport
int ipsec_add_del_spd(vlib_main_t *vm, u32 spd_id, int is_add)
Add/Delete a SPD.
Definition: ipsec_spd.c:20
static clib_error_t * ipsec_api_hookup(vlib_main_t *vm)
Definition: ipsec_api.c:948
#define foreach_ipsec_spd_policy_type
Definition: ipsec_spd.h:20
#define vec_foreach(var, vec)
Vector iterator.
u32 id
Definition: udp.api:45
static void vl_api_ipsec_select_backend_t_handler(vl_api_ipsec_select_backend_t *mp)
Definition: ipsec_api.c:891
IPsec security association database response.
Definition: ipsec.api:453
ipsec_esp_backend_t * esp_backends
Definition: ipsec.h:144
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
ipsec_key_t integ_key
Definition: ipsec_sa.h:154
api_main_t api_main
Definition: api_shared.c:35
Add or delete IPsec tunnel interface.
Definition: ipsec.api:378
u8 protocol
Definition: ipsec.api:96
#define VALIDATE_SW_IF_INDEX(mp)
u32 stat_index
Definition: ipsec.api:303
static void vl_api_ipsec_sad_entry_add_del_t_handler(vl_api_ipsec_sad_entry_add_del_t *mp)
Definition: ipsec_api.c:345
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128