FD.io VPP  v19.04.2-12-g66b1689
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  p.rport.start = ntohs (mp->entry.remote_port_start);
154  p.rport.stop = ntohs (mp->entry.remote_port_stop);
155  p.lport.start = ntohs (mp->entry.local_port_start);
156  p.lport.stop = ntohs (mp->entry.local_port_stop);
157 
158  rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
159 
160  if (rv)
161  goto out;
162 
163  /* policy action resolve unsupported */
164  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
165  {
166  clib_warning ("unsupported action: 'resolve'");
167  rv = VNET_API_ERROR_UNIMPLEMENTED;
168  goto out;
169  }
170  p.sa_id = ntohl (mp->entry.sa_id);
171  rv =
172  ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
173  &p.type);
174  if (rv)
175  goto out;
176 
177  rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
178  if (rv)
179  goto out;
180 
181 #else
182  rv = VNET_API_ERROR_UNIMPLEMENTED;
183  goto out;
184 #endif
185 
186 out:
187  /* *INDENT-OFF* */
188  REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
189  ({
190  rmp->stat_index = ntohl(stat_index);
191  }));
192  /* *INDENT-ON* */
193 }
194 
195 static int
196 ipsec_proto_decode (vl_api_ipsec_proto_t in, ipsec_protocol_t * out)
197 {
198  in = clib_net_to_host_u32 (in);
199 
200  switch (in)
201  {
202  case IPSEC_API_PROTO_ESP:
203  *out = IPSEC_PROTOCOL_ESP;
204  return (0);
205  case IPSEC_API_PROTO_AH:
206  *out = IPSEC_PROTOCOL_AH;
207  return (0);
208  }
209  return (VNET_API_ERROR_INVALID_PROTOCOL);
210 }
211 
212 static vl_api_ipsec_proto_t
214 {
215  switch (p)
216  {
217  case IPSEC_PROTOCOL_ESP:
218  return clib_host_to_net_u32 (IPSEC_API_PROTO_ESP);
219  case IPSEC_PROTOCOL_AH:
220  return clib_host_to_net_u32 (IPSEC_API_PROTO_AH);
221  }
222  return (VNET_API_ERROR_UNIMPLEMENTED);
223 }
224 
225 static int
226 ipsec_crypto_algo_decode (vl_api_ipsec_crypto_alg_t in,
227  ipsec_crypto_alg_t * out)
228 {
229  in = clib_net_to_host_u32 (in);
230 
231  switch (in)
232  {
233 #define _(v,f,s) case IPSEC_API_CRYPTO_ALG_##f: \
234  *out = IPSEC_CRYPTO_ALG_##f; \
235  return (0);
237 #undef _
238  }
239  return (VNET_API_ERROR_INVALID_ALGORITHM);
240 }
241 
242 static vl_api_ipsec_crypto_alg_t
244 {
245  switch (c)
246  {
247 #define _(v,f,s) case IPSEC_CRYPTO_ALG_##f: \
248  return clib_host_to_net_u32(IPSEC_API_CRYPTO_ALG_##f);
250 #undef _
251  case IPSEC_CRYPTO_N_ALG:
252  break;
253  }
254  ASSERT (0);
255  return (VNET_API_ERROR_UNIMPLEMENTED);
256 }
257 
258 
259 static int
260 ipsec_integ_algo_decode (vl_api_ipsec_integ_alg_t in, ipsec_integ_alg_t * out)
261 {
262  in = clib_net_to_host_u32 (in);
263 
264  switch (in)
265  {
266 #define _(v,f,s) case IPSEC_API_INTEG_ALG_##f: \
267  *out = IPSEC_INTEG_ALG_##f; \
268  return (0);
270 #undef _
271  }
272  return (VNET_API_ERROR_INVALID_ALGORITHM);
273 }
274 
275 static vl_api_ipsec_integ_alg_t
277 {
278  switch (i)
279  {
280 #define _(v,f,s) case IPSEC_INTEG_ALG_##f: \
281  return (clib_host_to_net_u32(IPSEC_API_INTEG_ALG_##f));
283 #undef _
284  case IPSEC_INTEG_N_ALG:
285  break;
286  }
287  ASSERT (0);
288  return (VNET_API_ERROR_UNIMPLEMENTED);
289 }
290 
291 static void
292 ipsec_key_decode (const vl_api_key_t * key, ipsec_key_t * out)
293 {
294  ipsec_mk_key (out, key->data, key->length);
295 }
296 
297 static void
298 ipsec_key_encode (const ipsec_key_t * in, vl_api_key_t * out)
299 {
300  out->length = in->len;
301  clib_memcpy (out->data, in->data, out->length);
302 }
303 
304 static ipsec_sa_flags_t
305 ipsec_sa_flags_decode (vl_api_ipsec_sad_flags_t in)
306 {
307  ipsec_sa_flags_t flags = IPSEC_SA_FLAG_NONE;
308  in = clib_net_to_host_u32 (in);
309 
311  flags |= IPSEC_SA_FLAG_USE_ESN;
313  flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
315  flags |= IPSEC_SA_FLAG_IS_TUNNEL;
317  flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
319  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
320 
321  return (flags);
322 }
323 
324 static vl_api_ipsec_sad_flags_t
326 {
327  vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
328 
329  if (ipsec_sa_is_set_USE_ESN (sa))
331  if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
333  if (ipsec_sa_is_set_IS_TUNNEL (sa))
335  if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa))
337  if (ipsec_sa_is_set_UDP_ENCAP (sa))
339 
340  return clib_host_to_net_u32 (flags);
341 }
342 
345 {
346  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
348  ip46_address_t tun_src = { }, tun_dst =
349  {
350  };
351  ipsec_key_t crypto_key, integ_key;
352  ipsec_crypto_alg_t crypto_alg;
353  ipsec_integ_alg_t integ_alg;
354  ipsec_protocol_t proto;
356  u32 id, spi, sa_index = ~0;
357  int rv;
358 
359 #if WITH_LIBSSL > 0
360 
361  id = ntohl (mp->entry.sad_id);
362  spi = ntohl (mp->entry.spi);
363 
364  rv = ipsec_proto_decode (mp->entry.protocol, &proto);
365 
366  if (rv)
367  goto out;
368 
369  rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
370 
371  if (rv)
372  goto out;
373 
374  rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
375 
376  if (rv)
377  goto out;
378 
379  ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
380  ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
381 
382  flags = ipsec_sa_flags_decode (mp->entry.flags);
383 
384  ip_address_decode (&mp->entry.tunnel_src, &tun_src);
385  ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
386 
387 
388  if (mp->is_add)
389  rv = ipsec_sa_add (id, spi, proto,
390  crypto_alg, &crypto_key,
391  integ_alg, &integ_key, flags,
392  0, 0, &tun_src, &tun_dst, &sa_index);
393  else
394  rv = ipsec_sa_del (id);
395 
396 #else
397  rv = VNET_API_ERROR_UNIMPLEMENTED;
398 #endif
399 
400 out:
401  /* *INDENT-OFF* */
402  REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
403  {
404  rmp->stat_index = htonl (sa_index);
405  });
406  /* *INDENT-ON* */
407 }
408 
409 static void
411  u32 context)
412 {
414  u32 n_policies = 0;
415 
416  mp = vl_msg_api_alloc (sizeof (*mp));
417  clib_memset (mp, 0, sizeof (*mp));
418  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPDS_DETAILS);
419  mp->context = context;
420 
421  mp->spd_id = htonl (spd->id);
422 #define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
424 #undef _
425  mp->npolicies = htonl (n_policies);
426 
427  vl_api_send_msg (reg, (u8 *) mp);
428 }
429 
430 static void
432 {
434  ipsec_main_t *im = &ipsec_main;
435  ipsec_spd_t *spd;
436 #if WITH_LIBSSL > 0
438  if (!reg)
439  return;
440 
441  /* *INDENT-OFF* */
442  pool_foreach (spd, im->spds, ({
443  send_ipsec_spds_details (spd, reg, mp->context);
444  }));
445  /* *INDENT-ON* */
446 #else
447  clib_warning ("unimplemented");
448 #endif
449 }
450 
451 vl_api_ipsec_spd_action_t
453 {
454  vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
455 
456  switch (in)
457  {
458 #define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
459  out = IPSEC_API_SPD_ACTION_##f; \
460  break;
462 #undef _
463  }
464  return (clib_host_to_net_u32 (out));
465 }
466 
467 static void
469  u32 context)
470 {
472 
473  mp = vl_msg_api_alloc (sizeof (*mp));
474  clib_memset (mp, 0, sizeof (*mp));
475  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
476  mp->context = context;
477 
478  mp->entry.spd_id = htonl (p->id);
479  mp->entry.priority = htonl (p->priority);
480  mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
481  (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
482 
484  &mp->entry.local_address_start);
486  &mp->entry.local_address_stop);
488  &mp->entry.remote_address_start);
490  &mp->entry.remote_address_stop);
491  mp->entry.local_port_start = htons (p->lport.start);
492  mp->entry.local_port_stop = htons (p->lport.stop);
493  mp->entry.remote_port_start = htons (p->rport.start);
494  mp->entry.remote_port_stop = htons (p->rport.stop);
495  mp->entry.protocol = p->protocol;
496  mp->entry.policy = ipsec_spd_action_encode (p->policy);
497  mp->entry.sa_id = htonl (p->sa_id);
498 
499  vl_api_send_msg (reg, (u8 *) mp);
500 }
501 
502 static void
504 {
506  ipsec_main_t *im = &ipsec_main;
509  ipsec_spd_t *spd;
510  uword *p;
511  u32 spd_index, *ii;
512 #if WITH_LIBSSL > 0
514  if (!reg)
515  return;
516 
517  p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
518  if (!p)
519  return;
520 
521  spd_index = p[0];
522  spd = pool_elt_at_index (im->spds, spd_index);
523 
524  /* *INDENT-OFF* */
526  vec_foreach(ii, spd->policies[ptype])
527  {
528  policy = pool_elt_at_index(im->policies, *ii);
529 
530  if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
531  send_ipsec_spd_details (policy, reg, mp->context);
532  }
533  }
534  /* *INDENT-ON* */
535 #else
536  clib_warning ("unimplemented");
537 #endif
538 }
539 
540 static void
543 {
545 
546  mp = vl_msg_api_alloc (sizeof (*mp));
547  clib_memset (mp, 0, sizeof (*mp));
548  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_INTERFACE_DETAILS);
549  mp->context = context;
550 
551  mp->spd_index = htonl (spd_index);
552  mp->sw_if_index = htonl (sw_if_index);
553 
554  vl_api_send_msg (reg, (u8 *) mp);
555 }
556 
557 static void
559  mp)
560 {
561  ipsec_main_t *im = &ipsec_main;
563  u32 k, v, spd_index;
564 
565 #if WITH_LIBSSL > 0
567  if (!reg)
568  return;
569 
570  if (mp->spd_index_valid)
571  {
572  spd_index = ntohl (mp->spd_index);
573  /* *INDENT-OFF* */
575  if (v == spd_index)
576  send_ipsec_spd_interface_details(reg, v, k, mp->context);
577  }));
578  /* *INDENT-ON* */
579  }
580  else
581  {
582  /* *INDENT-OFF* */
584  send_ipsec_spd_interface_details(reg, v, k, mp->context);
585  }));
586  /* *INDENT-ON* */
587  }
588 
589 #else
590  clib_warning ("unimplemented");
591 #endif
592 }
593 
594 static void
596 {
597  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
598  vl_api_ipsec_sa_set_key_reply_t *rmp;
599  ipsec_key_t ck, ik;
600  u32 id;
601  int rv;
602 #if WITH_LIBSSL > 0
603 
604  id = ntohl (mp->sa_id);
605 
606  ipsec_key_decode (&mp->crypto_key, &ck);
607  ipsec_key_decode (&mp->integrity_key, &ik);
608 
609  rv = ipsec_set_sa_key (id, &ck, &ik);
610 #else
611  rv = VNET_API_ERROR_UNIMPLEMENTED;
612 #endif
613 
614  REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
615 }
616 
617 static void
619  mp)
620 {
622  ipsec_main_t *im = &ipsec_main;
623  vnet_main_t *vnm = im->vnet_main;
624  u32 sw_if_index = ~0;
625  ip46_type_t itype;
626  int rv;
627 
628 #if WITH_LIBSSL > 0
630 
631  clib_memset (&tun, 0, sizeof (ipsec_add_del_tunnel_args_t));
632 
633  tun.is_add = mp->is_add;
634  tun.esn = mp->esn;
635  tun.anti_replay = mp->anti_replay;
636  tun.local_spi = ntohl (mp->local_spi);
637  tun.remote_spi = ntohl (mp->remote_spi);
638  tun.crypto_alg = mp->crypto_alg;
641  tun.integ_alg = mp->integ_alg;
644  tun.udp_encap = mp->udp_encap;
645  tun.tx_table_id = ntohl (mp->tx_table_id);
646  itype = ip_address_decode (&mp->local_ip, &tun.local_ip);
647  itype = ip_address_decode (&mp->remote_ip, &tun.remote_ip);
648  tun.is_ip6 = (IP46_TYPE_IP6 == itype);
649  memcpy (&tun.local_crypto_key, &mp->local_crypto_key,
651  memcpy (&tun.remote_crypto_key, &mp->remote_crypto_key,
653  memcpy (&tun.local_integ_key, &mp->local_integ_key,
654  mp->local_integ_key_len);
655  memcpy (&tun.remote_integ_key, &mp->remote_integ_key,
657  tun.renumber = mp->renumber;
658  tun.show_instance = ntohl (mp->show_instance);
659 
660  rv = ipsec_add_del_tunnel_if_internal (vnm, &tun, &sw_if_index);
661 
662 #else
663  rv = VNET_API_ERROR_UNIMPLEMENTED;
664 #endif
665 
666  /* *INDENT-OFF* */
667  REPLY_MACRO2 (VL_API_IPSEC_TUNNEL_IF_ADD_DEL_REPLY,
668  ({
669  rmp->sw_if_index = htonl (sw_if_index);
670  }));
671  /* *INDENT-ON* */
672 }
673 
674 static void
677 {
679 
680  mp = vl_msg_api_alloc (sizeof (*mp));
681  clib_memset (mp, 0, sizeof (*mp));
682  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
683  mp->context = context;
684 
685  mp->entry.sad_id = htonl (sa->id);
686  mp->entry.spi = htonl (sa->spi);
687  mp->entry.protocol = ipsec_proto_encode (sa->protocol);
688  mp->entry.tx_table_id =
690 
691  mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
692  ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
693 
694  mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
695  ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
696 
697  mp->entry.flags = ipsec_sad_flags_encode (sa);
698 
699  if (ipsec_sa_is_set_IS_TUNNEL (sa))
700  {
702  &mp->entry.tunnel_src);
704  &mp->entry.tunnel_dst);
705  }
706 
707  mp->sw_if_index = htonl (sw_if_index);
708  mp->salt = clib_host_to_net_u32 (sa->salt);
709  mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
710  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
711  if (ipsec_sa_is_set_USE_ESN (sa))
712  {
713  mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
714  mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
715  }
716  if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
717  mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
718 
719  vl_api_send_msg (reg, (u8 *) mp);
720 }
721 
722 
723 static void
725 {
727  ipsec_main_t *im = &ipsec_main;
728  vnet_main_t *vnm = im->vnet_main;
729  ipsec_sa_t *sa;
731  u32 *sa_index_to_tun_if_index = 0;
732 
733 #if WITH_LIBSSL > 0
735  if (!reg || pool_elts (im->sad) == 0)
736  return;
737 
738  vec_validate_init_empty (sa_index_to_tun_if_index, vec_len (im->sad) - 1,
739  ~0);
740 
741  /* *INDENT-OFF* */
743  ({
744  vnet_hw_interface_t *hi;
745  u32 sw_if_index = ~0;
746 
747  hi = vnet_get_hw_interface (vnm, t->hw_if_index);
748  sw_if_index = hi->sw_if_index;
749  sa_index_to_tun_if_index[t->input_sa_index] = sw_if_index;
750  sa_index_to_tun_if_index[t->output_sa_index] = sw_if_index;
751  }));
752 
753  pool_foreach (sa, im->sad,
754  ({
755  if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == sa->id)
756  send_ipsec_sa_details (sa, reg, mp->context,
757  sa_index_to_tun_if_index[sa - im->sad]);
758  }));
759  /* *INDENT-ON* */
760 
761  vec_free (sa_index_to_tun_if_index);
762 #else
763  clib_warning ("unimplemented");
764 #endif
765 }
766 
767 
768 static void
770  mp)
771 {
772  vl_api_ipsec_tunnel_if_set_key_reply_t *rmp;
773  ipsec_main_t *im = &ipsec_main;
774  vnet_main_t *vnm = im->vnet_main;
776  u8 *key = 0;
777  int rv;
778 
779 #if WITH_LIBSSL > 0
780  sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
781 
782  switch (mp->key_type)
783  {
786  if (mp->alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
787  mp->alg >= IPSEC_CRYPTO_N_ALG)
788  {
789  rv = VNET_API_ERROR_INVALID_ALGORITHM;
790  goto out;
791  }
792  break;
795  if (mp->alg >= IPSEC_INTEG_N_ALG)
796  {
797  rv = VNET_API_ERROR_INVALID_ALGORITHM;
798  goto out;
799  }
800  break;
802  default:
803  rv = VNET_API_ERROR_UNIMPLEMENTED;
804  goto out;
805  break;
806  }
807 
808  key = vec_new (u8, mp->key_len);
809  clib_memcpy (key, mp->key, mp->key_len);
810 
811  rv = ipsec_set_interface_key (vnm, sw->hw_if_index, mp->key_type, mp->alg,
812  key);
813  vec_free (key);
814 #else
815  clib_warning ("unimplemented");
816 #endif
817 
818 out:
819  REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_KEY_REPLY);
820 }
821 
822 
823 static void
825 {
826  vl_api_ipsec_tunnel_if_set_sa_reply_t *rmp;
827  ipsec_main_t *im = &ipsec_main;
828  vnet_main_t *vnm = im->vnet_main;
830  int rv;
831 
832 #if WITH_LIBSSL > 0
833  sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
834 
835  rv = ipsec_set_interface_sa (vnm, sw->hw_if_index, ntohl (mp->sa_id),
836  mp->is_outbound);
837 #else
838  clib_warning ("unimplemented");
839 #endif
840 
841  REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_SA_REPLY);
842 }
843 
844 static void
846 {
848  ipsec_main_t *im = &ipsec_main;
849  u32 context = mp->context;
850 
852 
853  if (rp == 0)
854  {
855  clib_warning ("Client %d AWOL", mp->client_index);
856  return;
857  }
858 
859  ipsec_ah_backend_t *ab;
861  /* *INDENT-OFF* */
862  pool_foreach (ab, im->ah_backends, {
863  vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
864  clib_memset (mp, 0, sizeof (*mp));
865  mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
866  mp->context = context;
867  snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
868  ab->name);
869  mp->protocol = ntohl (IPSEC_API_PROTO_AH);
870  mp->index = ab - im->ah_backends;
871  mp->active = mp->index == im->ah_current_backend ? 1 : 0;
872  vl_api_send_msg (rp, (u8 *)mp);
873  });
874  pool_foreach (eb, im->esp_backends, {
875  vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
876  clib_memset (mp, 0, sizeof (*mp));
877  mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
878  mp->context = context;
879  snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
880  eb->name);
881  mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
882  mp->index = eb - im->esp_backends;
883  mp->active = mp->index == im->esp_current_backend ? 1 : 0;
884  vl_api_send_msg (rp, (u8 *)mp);
885  });
886  /* *INDENT-ON* */
887 }
888 
889 static void
891 {
892  ipsec_main_t *im = &ipsec_main;
893  vl_api_ipsec_select_backend_reply_t *rmp;
895  int rv = 0;
896  if (pool_elts (im->sad) > 0)
897  {
898  rv = VNET_API_ERROR_INSTANCE_IN_USE;
899  goto done;
900  }
901 
902  rv = ipsec_proto_decode (mp->protocol, &protocol);
903 
904  if (rv)
905  goto done;
906 
907 #if WITH_LIBSSL > 0
908  switch (protocol)
909  {
910  case IPSEC_PROTOCOL_ESP:
911  rv = ipsec_select_esp_backend (im, mp->index);
912  break;
913  case IPSEC_PROTOCOL_AH:
914  rv = ipsec_select_ah_backend (im, mp->index);
915  break;
916  default:
917  rv = VNET_API_ERROR_INVALID_PROTOCOL;
918  break;
919  }
920 #else
921  clib_warning ("unimplemented"); /* FIXME */
922 #endif
923 done:
924  REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
925 }
926 
927 /*
928  * ipsec_api_hookup
929  * Add vpe's API message handlers to the table.
930  * vlib has already mapped shared memory and
931  * added the client registration handlers.
932  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
933  */
934 #define vl_msg_name_crc_list
935 #include <vnet/vnet_all_api_h.h>
936 #undef vl_msg_name_crc_list
937 
938 static void
940 {
941 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
942  foreach_vl_msg_name_crc_ipsec;
943 #undef _
944 }
945 
946 static clib_error_t *
948 {
949  api_main_t *am = &api_main;
950 
951 #define _(N,n) \
952  vl_msg_api_set_handlers(VL_API_##N, #n, \
953  vl_api_##n##_t_handler, \
954  vl_noop_handler, \
955  vl_api_##n##_t_endian, \
956  vl_api_##n##_t_print, \
957  sizeof(vl_api_##n##_t), 1);
959 #undef _
960 
961  /*
962  * Set up the (msg_name, crc, message-id) table
963  */
965 
966  return 0;
967 }
968 
970 
971 /*
972  * fd.io coding-style-patch-verification: ON
973  *
974  * Local Variables:
975  * eval: (c-set-style "gnu")
976  * End:
977  */
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:595
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:452
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:769
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:243
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:939
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:724
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:305
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:196
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:618
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:845
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:503
static void vl_api_ipsec_spd_interface_dump_t_handler(vl_api_ipsec_spd_interface_dump_t *mp)
Definition: ipsec_api.c:558
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:325
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:675
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:824
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:226
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:431
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:541
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:468
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:410
static vl_api_ipsec_proto_t ipsec_proto_encode(ipsec_protocol_t p)
Definition: ipsec_api.c:213
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:260
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:276
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:292
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:298
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:947
#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:890
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:344
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128