blob: 7003791c8c89289bb55ff1044a79bc122792898d [file] [log] [blame]
Pavel Kotucek9c7ef032016-12-21 07:46:45 +01001/*
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>
Neale Ranns17dcec02019-01-09 21:22:20 -080026#include <vnet/ip/ip_types_api.h>
Prashant Maheshwaridbf68c92019-11-14 12:42:59 +053027#include <vnet/ipsec/ipsec_types_api.h>
Neale Rannsdd4ccf22020-06-30 07:47:14 +000028#include <vnet/tunnel/tunnel_types_api.h>
Pierre Pfister4c422f92018-12-10 11:19:08 +010029#include <vnet/fib/fib.h>
Neale Ranns12989b52019-09-26 16:20:19 +000030#include <vnet/ipip/ipip.h>
Neale Ranns041add72020-01-02 04:06:10 +000031#include <vnet/tunnel/tunnel_types_api.h>
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010032
33#include <vnet/vnet_msg_enum.h>
34
Damjan Mariona9a951f2017-01-16 22:06:10 +010035#if WITH_LIBSSL > 0
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010036#include <vnet/ipsec/ipsec.h>
Neale Rannsc87b66c2019-02-07 07:26:12 -080037#include <vnet/ipsec/ipsec_tun.h>
Neale Rannsdd4ccf22020-06-30 07:47:14 +000038#include <vnet/ipsec/ipsec_itf.h>
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010039#endif /* IPSEC */
40
41#define vl_typedefs /* define message structures */
42#include <vnet/vnet_all_api_h.h>
43#undef vl_typedefs
44
45#define vl_endianfun /* define message structures */
46#include <vnet/vnet_all_api_h.h>
47#undef vl_endianfun
48
49/* instantiate all the print functions we know about */
50#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
51#define vl_printfun
52#include <vnet/vnet_all_api_h.h>
53#undef vl_printfun
54
55#include <vlibapi/api_helper_macros.h>
56
Klement Sekerab4d30532018-11-08 13:00:02 +010057#define foreach_vpe_api_msg \
58_(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del) \
59_(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \
Neale Ranns17dcec02019-01-09 21:22:20 -080060_(IPSEC_SPD_ENTRY_ADD_DEL, ipsec_spd_entry_add_del) \
61_(IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del) \
Neale Ranns041add72020-01-02 04:06:10 +000062_(IPSEC_SAD_ENTRY_ADD_DEL_V2, ipsec_sad_entry_add_del_v2) \
Klement Sekerab4d30532018-11-08 13:00:02 +010063_(IPSEC_SA_DUMP, ipsec_sa_dump) \
Neale Ranns041add72020-01-02 04:06:10 +000064_(IPSEC_SA_V2_DUMP, ipsec_sa_v2_dump) \
Klement Sekerab4d30532018-11-08 13:00:02 +010065_(IPSEC_SPDS_DUMP, ipsec_spds_dump) \
66_(IPSEC_SPD_DUMP, ipsec_spd_dump) \
67_(IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump) \
Neale Rannsdd4ccf22020-06-30 07:47:14 +000068_(IPSEC_ITF_CREATE, ipsec_itf_create) \
69_(IPSEC_ITF_DELETE, ipsec_itf_delete) \
70_(IPSEC_ITF_DUMP, ipsec_itf_dump) \
Klement Sekerab4d30532018-11-08 13:00:02 +010071_(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del) \
Klement Sekerab4d30532018-11-08 13:00:02 +010072_(IPSEC_TUNNEL_IF_SET_SA, ipsec_tunnel_if_set_sa) \
Klement Sekerab4d30532018-11-08 13:00:02 +010073_(IPSEC_SELECT_BACKEND, ipsec_select_backend) \
Neale Rannsc87b66c2019-02-07 07:26:12 -080074_(IPSEC_BACKEND_DUMP, ipsec_backend_dump) \
75_(IPSEC_TUNNEL_PROTECT_UPDATE, ipsec_tunnel_protect_update) \
76_(IPSEC_TUNNEL_PROTECT_DEL, ipsec_tunnel_protect_del) \
Yulong Pei2e84d662020-08-14 18:21:08 +080077_(IPSEC_TUNNEL_PROTECT_DUMP, ipsec_tunnel_protect_dump) \
78_(IPSEC_SET_ASYNC_MODE, ipsec_set_async_mode)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010079
Klement Sekerab4d30532018-11-08 13:00:02 +010080static void
81vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010082{
Damjan Mariona9a951f2017-01-16 22:06:10 +010083#if WITH_LIBSSL == 0
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010084 clib_warning ("unimplemented");
85#else
86
87 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
88 vl_api_ipsec_spd_add_del_reply_t *rmp;
89 int rv;
90
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010091 rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
Pavel Kotucek9c7ef032016-12-21 07:46:45 +010092
93 REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
94#endif
95}
96
97static void vl_api_ipsec_interface_add_del_spd_t_handler
98 (vl_api_ipsec_interface_add_del_spd_t * mp)
99{
100 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
101 vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
102 int rv;
103 u32 sw_if_index __attribute__ ((unused));
104 u32 spd_id __attribute__ ((unused));
105
106 sw_if_index = ntohl (mp->sw_if_index);
107 spd_id = ntohl (mp->spd_id);
108
109 VALIDATE_SW_IF_INDEX (mp);
110
Damjan Mariona9a951f2017-01-16 22:06:10 +0100111#if WITH_LIBSSL > 0
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100112 rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
113#else
114 rv = VNET_API_ERROR_UNIMPLEMENTED;
115#endif
116
117 BAD_SW_IF_INDEX_LABEL;
118
119 REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
120}
121
Neale Rannsc87b66c2019-02-07 07:26:12 -0800122static void vl_api_ipsec_tunnel_protect_update_t_handler
123 (vl_api_ipsec_tunnel_protect_update_t * mp)
124{
125 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
126 vl_api_ipsec_tunnel_protect_update_reply_t *rmp;
127 u32 sw_if_index, ii, *sa_ins = NULL;
Neale Ranns28287212019-12-16 00:53:11 +0000128 ip_address_t nh;
Neale Rannsc87b66c2019-02-07 07:26:12 -0800129 int rv;
130
131 sw_if_index = ntohl (mp->tunnel.sw_if_index);
132
133 VALIDATE_SW_IF_INDEX (&(mp->tunnel));
134
135#if WITH_LIBSSL > 0
136
137 for (ii = 0; ii < mp->tunnel.n_sa_in; ii++)
138 vec_add1 (sa_ins, ntohl (mp->tunnel.sa_in[ii]));
139
Neale Ranns28287212019-12-16 00:53:11 +0000140 ip_address_decode2 (&mp->tunnel.nh, &nh);
141
142 rv = ipsec_tun_protect_update (sw_if_index, &nh,
Neale Rannsc87b66c2019-02-07 07:26:12 -0800143 ntohl (mp->tunnel.sa_out), sa_ins);
144#else
145 rv = VNET_API_ERROR_UNIMPLEMENTED;
146#endif
147
148 BAD_SW_IF_INDEX_LABEL;
149
150 REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_UPDATE_REPLY);
151}
152
153static void vl_api_ipsec_tunnel_protect_del_t_handler
154 (vl_api_ipsec_tunnel_protect_del_t * mp)
155{
156 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
157 vl_api_ipsec_tunnel_protect_del_reply_t *rmp;
Neale Ranns28287212019-12-16 00:53:11 +0000158 ip_address_t nh;
Neale Rannsc87b66c2019-02-07 07:26:12 -0800159 u32 sw_if_index;
Neale Ranns28287212019-12-16 00:53:11 +0000160 int rv;
Neale Rannsc87b66c2019-02-07 07:26:12 -0800161
162 sw_if_index = ntohl (mp->sw_if_index);
163
164 VALIDATE_SW_IF_INDEX (mp);
165
166#if WITH_LIBSSL > 0
Neale Ranns28287212019-12-16 00:53:11 +0000167 ip_address_decode2 (&mp->nh, &nh);
168 rv = ipsec_tun_protect_del (sw_if_index, &nh);
Neale Rannsc87b66c2019-02-07 07:26:12 -0800169#else
170 rv = VNET_API_ERROR_UNIMPLEMENTED;
171#endif
172
173 BAD_SW_IF_INDEX_LABEL;
174
175 REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_DEL_REPLY);
176}
177
Neale Ranns12989b52019-09-26 16:20:19 +0000178typedef struct ipsec_dump_walk_ctx_t_
Neale Rannsc87b66c2019-02-07 07:26:12 -0800179{
180 vl_api_registration_t *reg;
181 u32 context;
Neale Ranns12989b52019-09-26 16:20:19 +0000182} ipsec_dump_walk_ctx_t;
Neale Rannsc87b66c2019-02-07 07:26:12 -0800183
184static walk_rc_t
185send_ipsec_tunnel_protect_details (index_t itpi, void *arg)
186{
Neale Ranns12989b52019-09-26 16:20:19 +0000187 ipsec_dump_walk_ctx_t *ctx = arg;
Neale Rannsc87b66c2019-02-07 07:26:12 -0800188 vl_api_ipsec_tunnel_protect_details_t *mp;
189 ipsec_tun_protect_t *itp;
Matthew Smith5cee0bc2020-03-31 09:52:17 -0500190 u32 ii = 0;
191 ipsec_sa_t *sa;
Neale Rannsc87b66c2019-02-07 07:26:12 -0800192
193 itp = ipsec_tun_protect_get (itpi);
194
Neale Rannsc87b66c2019-02-07 07:26:12 -0800195 mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (u32) * itp->itp_n_sa_in));
196 clib_memset (mp, 0, sizeof (*mp));
197 mp->_vl_msg_id = ntohs (VL_API_IPSEC_TUNNEL_PROTECT_DETAILS);
198 mp->context = ctx->context;
199
200 mp->tun.sw_if_index = htonl (itp->itp_sw_if_index);
Neale Ranns28287212019-12-16 00:53:11 +0000201 ip_address_encode2 (itp->itp_key, &mp->tun.nh);
Neale Rannsc87b66c2019-02-07 07:26:12 -0800202
Matthew Smith5cee0bc2020-03-31 09:52:17 -0500203 sa = ipsec_sa_get (itp->itp_out_sa);
204 mp->tun.sa_out = htonl (sa->id);
Neale Rannsc87b66c2019-02-07 07:26:12 -0800205 mp->tun.n_sa_in = itp->itp_n_sa_in;
206 /* *INDENT-OFF* */
Matthew Smith5cee0bc2020-03-31 09:52:17 -0500207 FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa,
Neale Rannsc87b66c2019-02-07 07:26:12 -0800208 ({
Matthew Smith5cee0bc2020-03-31 09:52:17 -0500209 mp->tun.sa_in[ii++] = htonl (sa->id);
Neale Rannsc87b66c2019-02-07 07:26:12 -0800210 }));
211 /* *INDENT-ON* */
212
213 vl_api_send_msg (ctx->reg, (u8 *) mp);
214
215 return (WALK_CONTINUE);
216}
217
218static void
219vl_api_ipsec_tunnel_protect_dump_t_handler (vl_api_ipsec_tunnel_protect_dump_t
220 * mp)
221{
222 vl_api_registration_t *reg;
223 u32 sw_if_index;
224
225#if WITH_LIBSSL > 0
226 reg = vl_api_client_index_to_registration (mp->client_index);
227 if (!reg)
228 return;
229
Neale Ranns12989b52019-09-26 16:20:19 +0000230 ipsec_dump_walk_ctx_t ctx = {
Neale Rannsc87b66c2019-02-07 07:26:12 -0800231 .reg = reg,
232 .context = mp->context,
233 };
234
235 sw_if_index = ntohl (mp->sw_if_index);
236
237 if (~0 == sw_if_index)
238 {
239 ipsec_tun_protect_walk (send_ipsec_tunnel_protect_details, &ctx);
240 }
241 else
242 {
Neale Ranns28287212019-12-16 00:53:11 +0000243 ipsec_tun_protect_walk_itf (sw_if_index,
244 send_ipsec_tunnel_protect_details, &ctx);
Neale Rannsc87b66c2019-02-07 07:26:12 -0800245 }
246#else
247 clib_warning ("unimplemented");
248#endif
249}
250
Neale Ranns17dcec02019-01-09 21:22:20 -0800251static int
252ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
253 ipsec_policy_action_t * out)
254{
255 in = clib_net_to_host_u32 (in);
256
257 switch (in)
258 {
259#define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
260 *out = IPSEC_POLICY_ACTION_##f; \
261 return (0);
262 foreach_ipsec_policy_action
263#undef _
264 }
265 return (VNET_API_ERROR_UNIMPLEMENTED);
266}
267
268static void vl_api_ipsec_spd_entry_add_del_t_handler
269 (vl_api_ipsec_spd_entry_add_del_t * mp)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100270{
271 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
Neale Ranns17dcec02019-01-09 21:22:20 -0800272 vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
273 ip46_type_t itype;
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800274 u32 stat_index;
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100275 int rv;
276
Neale Ranns8c2dd1b2019-02-19 08:27:34 -0800277 stat_index = ~0;
278
Damjan Mariona9a951f2017-01-16 22:06:10 +0100279#if WITH_LIBSSL > 0
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100280 ipsec_policy_t p;
281
Dave Barachb7b92992018-10-17 10:38:51 -0400282 clib_memset (&p, 0, sizeof (p));
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100283
Neale Ranns17dcec02019-01-09 21:22:20 -0800284 p.id = ntohl (mp->entry.spd_id);
285 p.priority = ntohl (mp->entry.priority);
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100286
Neale Ranns17dcec02019-01-09 21:22:20 -0800287 itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
288 ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
289 ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
290 ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
291
292 p.is_ipv6 = (itype == IP46_TYPE_IP6);
293
294 p.protocol = mp->entry.protocol;
Neale Rannsa4d24312019-07-10 13:46:21 +0000295 p.rport.start = ntohs (mp->entry.remote_port_start);
296 p.rport.stop = ntohs (mp->entry.remote_port_stop);
297 p.lport.start = ntohs (mp->entry.local_port_start);
298 p.lport.stop = ntohs (mp->entry.local_port_stop);
Neale Ranns17dcec02019-01-09 21:22:20 -0800299
300 rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
301
302 if (rv)
303 goto out;
304
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100305 /* policy action resolve unsupported */
Neale Ranns17dcec02019-01-09 21:22:20 -0800306 if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100307 {
308 clib_warning ("unsupported action: 'resolve'");
309 rv = VNET_API_ERROR_UNIMPLEMENTED;
310 goto out;
311 }
Neale Ranns17dcec02019-01-09 21:22:20 -0800312 p.sa_id = ntohl (mp->entry.sa_id);
Neale Ranns9f231d42019-03-19 10:06:00 +0000313 rv =
314 ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
315 &p.type);
316 if (rv)
317 goto out;
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100318
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800319 rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100320 if (rv)
321 goto out;
322
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100323#else
324 rv = VNET_API_ERROR_UNIMPLEMENTED;
325 goto out;
326#endif
327
328out:
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800329 /* *INDENT-OFF* */
330 REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
331 ({
332 rmp->stat_index = ntohl(stat_index);
333 }));
334 /* *INDENT-ON* */
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100335}
336
Neale Ranns17dcec02019-01-09 21:22:20 -0800337static void vl_api_ipsec_sad_entry_add_del_t_handler
338 (vl_api_ipsec_sad_entry_add_del_t * mp)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100339{
340 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
Neale Ranns17dcec02019-01-09 21:22:20 -0800341 vl_api_ipsec_sad_entry_add_del_reply_t *rmp;
Neale Ranns8d7c5022019-02-06 01:41:05 -0800342 ip46_address_t tun_src = { }, tun_dst =
343 {
344 };
345 ipsec_key_t crypto_key, integ_key;
346 ipsec_crypto_alg_t crypto_alg;
347 ipsec_integ_alg_t integ_alg;
348 ipsec_protocol_t proto;
349 ipsec_sa_flags_t flags;
Dave Baracha5160d72019-03-13 15:29:15 -0400350 u32 id, spi, sa_index = ~0;
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100351 int rv;
Neale Ranns8d7c5022019-02-06 01:41:05 -0800352
Damjan Mariona9a951f2017-01-16 22:06:10 +0100353#if WITH_LIBSSL > 0
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100354
Neale Ranns8d7c5022019-02-06 01:41:05 -0800355 id = ntohl (mp->entry.sad_id);
356 spi = ntohl (mp->entry.spi);
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100357
Neale Ranns8d7c5022019-02-06 01:41:05 -0800358 rv = ipsec_proto_decode (mp->entry.protocol, &proto);
Neale Ranns17dcec02019-01-09 21:22:20 -0800359
360 if (rv)
361 goto out;
362
Neale Ranns8d7c5022019-02-06 01:41:05 -0800363 rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
Neale Ranns17dcec02019-01-09 21:22:20 -0800364
365 if (rv)
366 goto out;
367
Neale Ranns8d7c5022019-02-06 01:41:05 -0800368 rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
Neale Ranns17dcec02019-01-09 21:22:20 -0800369
370 if (rv)
371 goto out;
372
Neale Ranns8d7c5022019-02-06 01:41:05 -0800373 ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
374 ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
Neale Ranns17dcec02019-01-09 21:22:20 -0800375
Neale Ranns8d7c5022019-02-06 01:41:05 -0800376 flags = ipsec_sa_flags_decode (mp->entry.flags);
Neale Ranns17dcec02019-01-09 21:22:20 -0800377
Neale Ranns8d7c5022019-02-06 01:41:05 -0800378 ip_address_decode (&mp->entry.tunnel_src, &tun_src);
379 ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100380
Neale Ranns8d7c5022019-02-06 01:41:05 -0800381 if (mp->is_add)
Neale Ranns495d7ff2019-07-12 09:15:26 +0000382 rv = ipsec_sa_add_and_lock (id, spi, proto,
383 crypto_alg, &crypto_key,
384 integ_alg, &integ_key, flags,
385 0, mp->entry.salt, &tun_src, &tun_dst,
Neale Ranns041add72020-01-02 04:06:10 +0000386 TUNNEL_ENCAP_DECAP_FLAG_NONE,
387 IP_DSCP_CS0,
388 &sa_index,
389 htons (mp->entry.udp_src_port),
Neale Rannsabc56602020-04-01 09:45:23 +0000390 htons (mp->entry.udp_dst_port));
Neale Ranns8d7c5022019-02-06 01:41:05 -0800391 else
Neale Ranns495d7ff2019-07-12 09:15:26 +0000392 rv = ipsec_sa_unlock_id (id);
Neale Ranns8d7c5022019-02-06 01:41:05 -0800393
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100394#else
395 rv = VNET_API_ERROR_UNIMPLEMENTED;
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100396#endif
397
398out:
Neale Rannseba31ec2019-02-17 18:04:27 +0000399 /* *INDENT-OFF* */
400 REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
401 {
402 rmp->stat_index = htonl (sa_index);
403 });
404 /* *INDENT-ON* */
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100405}
406
Neale Ranns041add72020-01-02 04:06:10 +0000407static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
408 (vl_api_ipsec_sad_entry_add_del_v2_t * mp)
409{
410 vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
411 vl_api_ipsec_sad_entry_add_del_v2_reply_t *rmp;
412 ip46_address_t tun_src = { }, tun_dst =
413 {
414 };
415 tunnel_encap_decap_flags_t tunnel_flags;
416 ipsec_key_t crypto_key, integ_key;
417 ipsec_crypto_alg_t crypto_alg;
418 ipsec_integ_alg_t integ_alg;
419 ipsec_protocol_t proto;
420 ipsec_sa_flags_t flags;
421 u32 id, spi, sa_index = ~0;
422 int rv;
423
424#if WITH_LIBSSL > 0
425
426 id = ntohl (mp->entry.sad_id);
427 spi = ntohl (mp->entry.spi);
428
429 rv = ipsec_proto_decode (mp->entry.protocol, &proto);
430
431 if (rv)
432 goto out;
433
434 rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
435
436 if (rv)
437 goto out;
438
439 rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
440
441 if (rv)
442 goto out;
443
444 rv =
445 tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags, &tunnel_flags);
446
447 if (rv)
448 goto out;
449
450 ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
451 ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
452
453 flags = ipsec_sa_flags_decode (mp->entry.flags);
454
455 ip_address_decode (&mp->entry.tunnel_src, &tun_src);
456 ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
457
458 if (mp->is_add)
459 rv = ipsec_sa_add_and_lock (id, spi, proto,
460 crypto_alg, &crypto_key,
461 integ_alg, &integ_key, flags,
462 0, mp->entry.salt, &tun_src, &tun_dst,
463 tunnel_flags,
464 ip_dscp_decode (mp->entry.dscp),
465 &sa_index,
466 htons (mp->entry.udp_src_port),
467 htons (mp->entry.udp_dst_port));
468 else
469 rv = ipsec_sa_unlock_id (id);
470
471#else
472 rv = VNET_API_ERROR_UNIMPLEMENTED;
473#endif
474
475out:
476 /* *INDENT-OFF* */
477 REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V2_REPLY,
478 {
479 rmp->stat_index = htonl (sa_index);
480 });
481 /* *INDENT-ON* */
482}
483
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100484static void
Matus Fabiana9a0b2c2018-10-02 01:13:25 -0700485send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
486 u32 context)
487{
488 vl_api_ipsec_spds_details_t *mp;
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800489 u32 n_policies = 0;
Matus Fabiana9a0b2c2018-10-02 01:13:25 -0700490
491 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400492 clib_memset (mp, 0, sizeof (*mp));
Matus Fabiana9a0b2c2018-10-02 01:13:25 -0700493 mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPDS_DETAILS);
494 mp->context = context;
495
496 mp->spd_id = htonl (spd->id);
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800497#define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
498 foreach_ipsec_spd_policy_type
499#undef _
500 mp->npolicies = htonl (n_policies);
Matus Fabiana9a0b2c2018-10-02 01:13:25 -0700501
502 vl_api_send_msg (reg, (u8 *) mp);
503}
504
505static void
506vl_api_ipsec_spds_dump_t_handler (vl_api_ipsec_spds_dump_t * mp)
507{
508 vl_api_registration_t *reg;
509 ipsec_main_t *im = &ipsec_main;
510 ipsec_spd_t *spd;
511#if WITH_LIBSSL > 0
512 reg = vl_api_client_index_to_registration (mp->client_index);
513 if (!reg)
514 return;
515
516 /* *INDENT-OFF* */
517 pool_foreach (spd, im->spds, ({
518 send_ipsec_spds_details (spd, reg, mp->context);
519 }));
520 /* *INDENT-ON* */
521#else
522 clib_warning ("unimplemented");
523#endif
524}
525
Neale Ranns17dcec02019-01-09 21:22:20 -0800526vl_api_ipsec_spd_action_t
527ipsec_spd_action_encode (ipsec_policy_action_t in)
528{
529 vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
530
531 switch (in)
532 {
533#define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
534 out = IPSEC_API_SPD_ACTION_##f; \
535 break;
536 foreach_ipsec_policy_action
537#undef _
538 }
539 return (clib_host_to_net_u32 (out));
540}
541
Matus Fabiana9a0b2c2018-10-02 01:13:25 -0700542static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800543send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
544 u32 context)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100545{
546 vl_api_ipsec_spd_details_t *mp;
547
548 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400549 clib_memset (mp, 0, sizeof (*mp));
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100550 mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
551 mp->context = context;
552
Neale Ranns17dcec02019-01-09 21:22:20 -0800553 mp->entry.spd_id = htonl (p->id);
554 mp->entry.priority = htonl (p->priority);
Neale Ranns9f231d42019-03-19 10:06:00 +0000555 mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
556 (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
Neale Ranns17dcec02019-01-09 21:22:20 -0800557
558 ip_address_encode (&p->laddr.start, IP46_TYPE_ANY,
559 &mp->entry.local_address_start);
560 ip_address_encode (&p->laddr.stop, IP46_TYPE_ANY,
561 &mp->entry.local_address_stop);
562 ip_address_encode (&p->raddr.start, IP46_TYPE_ANY,
563 &mp->entry.remote_address_start);
564 ip_address_encode (&p->raddr.stop, IP46_TYPE_ANY,
565 &mp->entry.remote_address_stop);
Neale Rannsa4d24312019-07-10 13:46:21 +0000566 mp->entry.local_port_start = htons (p->lport.start);
567 mp->entry.local_port_stop = htons (p->lport.stop);
568 mp->entry.remote_port_start = htons (p->rport.start);
569 mp->entry.remote_port_stop = htons (p->rport.stop);
Neale Ranns17dcec02019-01-09 21:22:20 -0800570 mp->entry.protocol = p->protocol;
571 mp->entry.policy = ipsec_spd_action_encode (p->policy);
572 mp->entry.sa_id = htonl (p->sa_id);
573
Florin Coras6c4dae22018-01-09 06:39:23 -0800574 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100575}
576
577static void
578vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
579{
Florin Coras6c4dae22018-01-09 06:39:23 -0800580 vl_api_registration_t *reg;
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100581 ipsec_main_t *im = &ipsec_main;
Neale Ranns9f231d42019-03-19 10:06:00 +0000582 ipsec_spd_policy_type_t ptype;
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100583 ipsec_policy_t *policy;
584 ipsec_spd_t *spd;
585 uword *p;
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800586 u32 spd_index, *ii;
Damjan Mariona9a951f2017-01-16 22:06:10 +0100587#if WITH_LIBSSL > 0
Florin Coras6c4dae22018-01-09 06:39:23 -0800588 reg = vl_api_client_index_to_registration (mp->client_index);
589 if (!reg)
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100590 return;
591
592 p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
593 if (!p)
594 return;
595
596 spd_index = p[0];
597 spd = pool_elt_at_index (im->spds, spd_index);
598
599 /* *INDENT-OFF* */
Neale Rannsa09c1ff2019-02-04 01:10:30 -0800600 FOR_EACH_IPSEC_SPD_POLICY_TYPE(ptype) {
601 vec_foreach(ii, spd->policies[ptype])
602 {
603 policy = pool_elt_at_index(im->policies, *ii);
604
605 if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
606 send_ipsec_spd_details (policy, reg, mp->context);
607 }
608 }
Pavel Kotucek9c7ef032016-12-21 07:46:45 +0100609 /* *INDENT-ON* */
610#else
611 clib_warning ("unimplemented");
612#endif
613}
614
615static void
Filip Varga871bca92018-11-02 13:51:44 +0100616send_ipsec_spd_interface_details (vl_api_registration_t * reg, u32 spd_index,
617 u32 sw_if_index, u32 context)
618{
619 vl_api_ipsec_spd_interface_details_t *mp;
620
621 mp = vl_msg_api_alloc (sizeof (*mp));
622 clib_memset (mp, 0, sizeof (*mp));
623 mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_INTERFACE_DETAILS);
624 mp->context = context;
625
626 mp->spd_index = htonl (spd_index);
627 mp->sw_if_index = htonl (sw_if_index);
628
629 vl_api_send_msg (reg, (u8 *) mp);
630}
631
632static void
633vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t *
634 mp)
635{
636 ipsec_main_t *im = &ipsec_main;
637 vl_api_registration_t *reg;
638 u32 k, v, spd_index;
639
640#if WITH_LIBSSL > 0
641 reg = vl_api_client_index_to_registration (mp->client_index);
642 if (!reg)
643 return;
644
645 if (mp->spd_index_valid)
646 {
647 spd_index = ntohl (mp->spd_index);
648 /* *INDENT-OFF* */
649 hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
650 if (v == spd_index)
651 send_ipsec_spd_interface_details(reg, v, k, mp->context);
652 }));
653 /* *INDENT-ON* */
654 }
655 else
656 {
657 /* *INDENT-OFF* */
658 hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
659 send_ipsec_spd_interface_details(reg, v, k, mp->context);
660 }));
661 /* *INDENT-ON* */
662 }
663
664#else
665 clib_warning ("unimplemented");
666#endif
667}
668
Neale Ranns12989b52019-09-26 16:20:19 +0000669static u32
670ipsec_tun_mk_input_sa_id (u32 ti)
671{
672 return (0x80000000 | ti);
673}
674
675static u32
676ipsec_tun_mk_output_sa_id (u32 ti)
677{
678 return (0xc0000000 | ti);
679}
680
Filip Varga871bca92018-11-02 13:51:44 +0100681static void
Matthew Smithb0972cb2017-05-02 16:20:41 -0500682vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
683 mp)
684{
685 vl_api_ipsec_tunnel_if_add_del_reply_t *rmp;
Matthew Smithe04d09d2017-05-14 21:47:18 -0500686 u32 sw_if_index = ~0;
Matthew Smithb0972cb2017-05-02 16:20:41 -0500687 int rv;
688
689#if WITH_LIBSSL > 0
Neale Ranns12989b52019-09-26 16:20:19 +0000690 ip46_address_t local_ip = ip46_address_initializer;
691 ip46_address_t remote_ip = ip46_address_initializer;
692 ipsec_key_t crypto_key, integ_key;
693 ipsec_sa_flags_t flags;
694 ip46_type_t local_ip_type, remote_ip_type;
695 ipip_transport_t transport;
696 u32 fib_index;
Matthew Smithb0972cb2017-05-02 16:20:41 -0500697
Neale Ranns12989b52019-09-26 16:20:19 +0000698 local_ip_type = ip_address_decode (&mp->local_ip, &local_ip);
699 remote_ip_type = ip_address_decode (&mp->remote_ip, &remote_ip);
700 transport = (IP46_TYPE_IP6 == local_ip_type ?
701 IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4);
Matthew Smithb0972cb2017-05-02 16:20:41 -0500702
Neale Ranns12989b52019-09-26 16:20:19 +0000703 if (local_ip_type != remote_ip_type)
704 {
705 rv = VNET_API_ERROR_INVALID_VALUE;
706 goto done;
707 }
Matthew Smithb0972cb2017-05-02 16:20:41 -0500708
Neale Ranns12989b52019-09-26 16:20:19 +0000709 flags = IPSEC_SA_FLAG_NONE;
710
711 if (mp->udp_encap)
712 flags |= IPSEC_SA_FLAG_UDP_ENCAP;
713 if (mp->esn)
714 flags |= IPSEC_SA_FLAG_USE_ESN;
715 if (mp->anti_replay)
716 flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
717
718 ipsec_mk_key (&crypto_key, mp->remote_crypto_key,
719 mp->remote_crypto_key_len);
720 ipsec_mk_key (&integ_key, mp->remote_integ_key, mp->remote_integ_key_len);
721 ipsec_mk_key (&crypto_key, mp->local_crypto_key, mp->local_crypto_key_len);
722 ipsec_mk_key (&integ_key, mp->local_integ_key, mp->local_integ_key_len);
723
724 fib_index =
725 fib_table_find (fib_proto_from_ip46 (local_ip_type),
726 ntohl (mp->tx_table_id));
727
728 if (~0 == fib_index)
729 {
730 rv = VNET_API_ERROR_NO_SUCH_FIB;
731 goto done;
732 }
733
734 if (mp->is_add)
735 {
736 // remote = input, local = output
737 /* create an ip-ip tunnel, then the two SA, then bind them */
738 rv = ipip_add_tunnel (transport,
Neale Rannsa548d132019-11-20 08:34:58 +0000739 (mp->renumber ? ntohl (mp->show_instance) : ~0),
Neale Ranns12989b52019-09-26 16:20:19 +0000740 &local_ip,
Neale Ranns95346962019-11-25 13:04:44 +0000741 &remote_ip, fib_index,
Neale Ranns59ff9182019-12-29 23:55:18 +0000742 TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
Neale Ranns14053c92019-12-29 23:55:18 +0000743 TUNNEL_MODE_P2P, &sw_if_index);
Neale Ranns12989b52019-09-26 16:20:19 +0000744
745 if (rv)
746 goto done;
747
748 rv = ipsec_sa_add_and_lock (ipsec_tun_mk_input_sa_id (sw_if_index),
749 ntohl (mp->remote_spi),
750 IPSEC_PROTOCOL_ESP,
751 mp->crypto_alg,
752 &crypto_key,
753 mp->integ_alg,
754 &integ_key,
755 (flags | IPSEC_SA_FLAG_IS_INBOUND),
756 ntohl (mp->tx_table_id),
Neale Ranns041add72020-01-02 04:06:10 +0000757 mp->salt, &remote_ip, &local_ip,
758 TUNNEL_ENCAP_DECAP_FLAG_NONE,
759 IP_DSCP_CS0, NULL,
Neale Rannsabc56602020-04-01 09:45:23 +0000760 IPSEC_UDP_PORT_NONE, IPSEC_UDP_PORT_NONE);
Neale Ranns12989b52019-09-26 16:20:19 +0000761
762 if (rv)
763 goto done;
764
765 rv = ipsec_sa_add_and_lock (ipsec_tun_mk_output_sa_id (sw_if_index),
766 ntohl (mp->local_spi),
767 IPSEC_PROTOCOL_ESP,
768 mp->crypto_alg,
769 &crypto_key,
770 mp->integ_alg,
771 &integ_key,
772 flags,
773 ntohl (mp->tx_table_id),
Neale Ranns041add72020-01-02 04:06:10 +0000774 mp->salt, &local_ip, &remote_ip,
775 TUNNEL_ENCAP_DECAP_FLAG_NONE,
776 IP_DSCP_CS0, NULL,
Neale Rannsabc56602020-04-01 09:45:23 +0000777 IPSEC_UDP_PORT_NONE, IPSEC_UDP_PORT_NONE);
Neale Ranns12989b52019-09-26 16:20:19 +0000778
779 if (rv)
780 goto done;
781
Neale Ranns28287212019-12-16 00:53:11 +0000782 rv = ipsec_tun_protect_update_one (sw_if_index, NULL,
Neale Ranns12989b52019-09-26 16:20:19 +0000783 ipsec_tun_mk_output_sa_id
784 (sw_if_index),
785 ipsec_tun_mk_input_sa_id
786 (sw_if_index));
787 if (rv)
788 goto done;
789
790 /* the SAs are locked as a result of being used for proection,
791 * they cannot be removed from the API, since they cannot be refered
792 * to by the API. unlock them now, so that if the tunnel is rekeyed
793 * they-ll disapper
794 */
795 ipsec_sa_unlock_id (ipsec_tun_mk_input_sa_id (sw_if_index));
796 ipsec_sa_unlock_id (ipsec_tun_mk_output_sa_id (sw_if_index));
797 }
798 else
799 {
Neale Rannsd14fccd2019-11-15 15:03:27 +0000800 /* *INDENT-OFF* */
Neale Ranns12989b52019-09-26 16:20:19 +0000801 ipip_tunnel_key_t key = {
802 .transport = transport,
803 .fib_index = fib_index,
804 .src = local_ip,
805 .dst = remote_ip
806 };
Neale Rannsd14fccd2019-11-15 15:03:27 +0000807 /* *INDENT-ON* */
808
Neale Ranns12989b52019-09-26 16:20:19 +0000809 ipip_tunnel_t *t = ipip_tunnel_db_find (&key);
810
Neale Rannsd14fccd2019-11-15 15:03:27 +0000811 if (NULL != t)
812 {
Neale Ranns28287212019-12-16 00:53:11 +0000813 rv = ipsec_tun_protect_del (t->sw_if_index, NULL);
Neale Rannsd14fccd2019-11-15 15:03:27 +0000814 ipip_del_tunnel (t->sw_if_index);
815 }
816 else
817 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
Neale Ranns12989b52019-09-26 16:20:19 +0000818 }
Matthew Smithb0972cb2017-05-02 16:20:41 -0500819
820#else
821 rv = VNET_API_ERROR_UNIMPLEMENTED;
822#endif
Neale Ranns12989b52019-09-26 16:20:19 +0000823done:
Neale Ranns8d7c5022019-02-06 01:41:05 -0800824 /* *INDENT-OFF* */
825 REPLY_MACRO2 (VL_API_IPSEC_TUNNEL_IF_ADD_DEL_REPLY,
826 ({
827 rmp->sw_if_index = htonl (sw_if_index);
828 }));
829 /* *INDENT-ON* */
Matthew Smithb0972cb2017-05-02 16:20:41 -0500830}
831
Neale Rannsdd4ccf22020-06-30 07:47:14 +0000832static void
833vl_api_ipsec_itf_create_t_handler (vl_api_ipsec_itf_create_t * mp)
834{
835 vl_api_ipsec_itf_create_reply_t *rmp;
836 tunnel_mode_t mode;
837 u32 sw_if_index = ~0;
838 int rv;
839
840 rv = tunnel_mode_decode (mp->itf.mode, &mode);
841
842 if (!rv)
843 rv = ipsec_itf_create (ntohl (mp->itf.user_instance), mode, &sw_if_index);
844
845 /* *INDENT-OFF* */
846 REPLY_MACRO2 (VL_API_IPSEC_ITF_CREATE_REPLY,
847 ({
848 rmp->sw_if_index = htonl (sw_if_index);
849 }));
850 /* *INDENT-ON* */
851}
852
853static void
854vl_api_ipsec_itf_delete_t_handler (vl_api_ipsec_itf_delete_t * mp)
855{
856 vl_api_ipsec_itf_delete_reply_t *rmp;
857 int rv;
858
859 rv = ipsec_itf_delete (ntohl (mp->sw_if_index));
860
861 REPLY_MACRO (VL_API_IPSEC_ITF_DELETE_REPLY);
862}
863
864static void
865vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp)
866{
867}
868
Neale Ranns12989b52019-09-26 16:20:19 +0000869typedef struct ipsec_sa_dump_match_ctx_t_
Matthew Smith28029532017-09-26 13:33:44 -0500870{
Neale Ranns12989b52019-09-26 16:20:19 +0000871 index_t sai;
872 u32 sw_if_index;
873} ipsec_sa_dump_match_ctx_t;
874
875static walk_rc_t
876ipsec_sa_dump_match_sa (index_t itpi, void *arg)
877{
878 ipsec_sa_dump_match_ctx_t *ctx = arg;
879 ipsec_tun_protect_t *itp;
880 index_t sai;
881
882 itp = ipsec_tun_protect_get (itpi);
883
884 if (itp->itp_out_sa == ctx->sai)
885 {
886 ctx->sw_if_index = itp->itp_sw_if_index;
887 return (WALK_STOP);
888 }
889 /* *INDENT-OFF* */
890 FOR_EACH_IPSEC_PROTECT_INPUT_SAI (itp, sai,
891 ({
892 if (sai == ctx->sai)
893 {
894 ctx->sw_if_index = itp->itp_sw_if_index;
895 return (WALK_STOP);
896 }
897 }));
898 /* *INDENT-OFF* */
899
900 return (WALK_CONTINUE);
901}
902
903static walk_rc_t
904send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
905{
906 ipsec_dump_walk_ctx_t *ctx = arg;
Matthew Smith28029532017-09-26 13:33:44 -0500907 vl_api_ipsec_sa_details_t *mp;
Neale Ranns12989b52019-09-26 16:20:19 +0000908 ipsec_main_t *im = &ipsec_main;
Matthew Smith28029532017-09-26 13:33:44 -0500909
910 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400911 clib_memset (mp, 0, sizeof (*mp));
Matthew Smith28029532017-09-26 13:33:44 -0500912 mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
Neale Ranns12989b52019-09-26 16:20:19 +0000913 mp->context = ctx->context;
Matthew Smith28029532017-09-26 13:33:44 -0500914
Neale Ranns8d7c5022019-02-06 01:41:05 -0800915 mp->entry.sad_id = htonl (sa->id);
916 mp->entry.spi = htonl (sa->spi);
917 mp->entry.protocol = ipsec_proto_encode (sa->protocol);
918 mp->entry.tx_table_id =
919 htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
Matthew Smith28029532017-09-26 13:33:44 -0500920
Neale Ranns8d7c5022019-02-06 01:41:05 -0800921 mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
922 ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
Matthew Smith28029532017-09-26 13:33:44 -0500923
Neale Ranns8d7c5022019-02-06 01:41:05 -0800924 mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
925 ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
Matthew Smith28029532017-09-26 13:33:44 -0500926
Neale Ranns8d7c5022019-02-06 01:41:05 -0800927 mp->entry.flags = ipsec_sad_flags_encode (sa);
Neale Ranns12989b52019-09-26 16:20:19 +0000928 mp->entry.salt = clib_host_to_net_u32 (sa->salt);
929
930 if (ipsec_sa_is_set_IS_PROTECT (sa))
931 {
932 ipsec_sa_dump_match_ctx_t ctx = {
933 .sai = sa - im->sad,
934 .sw_if_index = ~0,
935 };
936 ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
937
938 mp->sw_if_index = htonl (ctx.sw_if_index);
939 }
940 else
941 mp->sw_if_index = ~0;
Matthew Smith28029532017-09-26 13:33:44 -0500942
Damjan Mariond709cbc2019-03-26 13:16:42 +0100943 if (ipsec_sa_is_set_IS_TUNNEL (sa))
Matthew Smith28029532017-09-26 13:33:44 -0500944 {
Neale Ranns8d7c5022019-02-06 01:41:05 -0800945 ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
946 &mp->entry.tunnel_src);
947 ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
948 &mp->entry.tunnel_dst);
Matthew Smith28029532017-09-26 13:33:44 -0500949 }
Neale Rannsabc56602020-04-01 09:45:23 +0000950 if (ipsec_sa_is_set_UDP_ENCAP (sa))
951 {
952 mp->entry.udp_src_port = sa->udp_hdr.src_port;
953 mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
954 }
Matthew Smith28029532017-09-26 13:33:44 -0500955
Matthew Smith28029532017-09-26 13:33:44 -0500956 mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
957 mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
Damjan Marion1e3aa5e2019-03-28 10:58:59 +0100958 if (ipsec_sa_is_set_USE_ESN (sa))
Matthew Smith28029532017-09-26 13:33:44 -0500959 {
960 mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
961 mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
962 }
Damjan Mariond709cbc2019-03-26 13:16:42 +0100963 if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
Matthew Smith28029532017-09-26 13:33:44 -0500964 mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
Pierre Pfister4c422f92018-12-10 11:19:08 +0100965
Matthew Smith48d32b42020-04-02 07:45:49 -0500966 mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
967
Neale Ranns12989b52019-09-26 16:20:19 +0000968 vl_api_send_msg (ctx->reg, (u8 *) mp);
Matthew Smith28029532017-09-26 13:33:44 -0500969
Neale Ranns12989b52019-09-26 16:20:19 +0000970 return (WALK_CONTINUE);
971}
Matthew Smith28029532017-09-26 13:33:44 -0500972
973static void
974vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
975{
Florin Coras6c4dae22018-01-09 06:39:23 -0800976 vl_api_registration_t *reg;
Matthew Smith28029532017-09-26 13:33:44 -0500977
978#if WITH_LIBSSL > 0
Florin Coras6c4dae22018-01-09 06:39:23 -0800979 reg = vl_api_client_index_to_registration (mp->client_index);
Neale Ranns12989b52019-09-26 16:20:19 +0000980 if (!reg)
Matthew Smith28029532017-09-26 13:33:44 -0500981 return;
982
Neale Ranns12989b52019-09-26 16:20:19 +0000983 ipsec_dump_walk_ctx_t ctx = {
984 .reg = reg,
985 .context = mp->context,
986 };
Matthew Smith28029532017-09-26 13:33:44 -0500987
Neale Ranns12989b52019-09-26 16:20:19 +0000988 ipsec_sa_walk (send_ipsec_sa_details, &ctx);
Matthew Smith28029532017-09-26 13:33:44 -0500989
Matthew Smith28029532017-09-26 13:33:44 -0500990#else
991 clib_warning ("unimplemented");
992#endif
993}
994
Neale Ranns041add72020-01-02 04:06:10 +0000995static walk_rc_t
996send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
997{
998 ipsec_dump_walk_ctx_t *ctx = arg;
999 vl_api_ipsec_sa_v2_details_t *mp;
1000 ipsec_main_t *im = &ipsec_main;
1001
1002 mp = vl_msg_api_alloc (sizeof (*mp));
1003 clib_memset (mp, 0, sizeof (*mp));
1004 mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_V2_DETAILS);
1005 mp->context = ctx->context;
1006
1007 mp->entry.sad_id = htonl (sa->id);
1008 mp->entry.spi = htonl (sa->spi);
1009 mp->entry.protocol = ipsec_proto_encode (sa->protocol);
1010 mp->entry.tx_table_id =
1011 htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
1012
1013 mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
1014 ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1015
1016 mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1017 ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1018
1019 mp->entry.flags = ipsec_sad_flags_encode (sa);
1020 mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1021
1022 if (ipsec_sa_is_set_IS_PROTECT (sa))
1023 {
1024 ipsec_sa_dump_match_ctx_t ctx = {
1025 .sai = sa - im->sad,
1026 .sw_if_index = ~0,
1027 };
1028 ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1029
1030 mp->sw_if_index = htonl (ctx.sw_if_index);
1031 }
1032 else
1033 mp->sw_if_index = ~0;
1034
1035 if (ipsec_sa_is_set_IS_TUNNEL (sa))
1036 {
1037 ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
1038 &mp->entry.tunnel_src);
1039 ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
1040 &mp->entry.tunnel_dst);
1041 }
1042 if (ipsec_sa_is_set_UDP_ENCAP (sa))
1043 {
1044 mp->entry.udp_src_port = sa->udp_hdr.src_port;
1045 mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1046 }
1047
1048 mp->entry.tunnel_flags = tunnel_encap_decap_flags_encode (sa->tunnel_flags);
1049 mp->entry.dscp = ip_dscp_encode (sa->dscp);
1050
1051 mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1052 mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
1053 if (ipsec_sa_is_set_USE_ESN (sa))
1054 {
1055 mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1056 mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
1057 }
1058 if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1059 mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1060
1061 mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1062
1063 vl_api_send_msg (ctx->reg, (u8 *) mp);
1064
1065 return (WALK_CONTINUE);
1066}
1067
1068static void
1069vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
1070{
1071 vl_api_registration_t *reg;
1072
1073#if WITH_LIBSSL > 0
1074 reg = vl_api_client_index_to_registration (mp->client_index);
1075 if (!reg)
1076 return;
1077
1078 ipsec_dump_walk_ctx_t ctx = {
1079 .reg = reg,
1080 .context = mp->context,
1081 };
1082
1083 ipsec_sa_walk (send_ipsec_sa_v2_details, &ctx);
1084
1085#else
1086 clib_warning ("unimplemented");
1087#endif
1088}
1089
Matthew Smith75d85602017-10-05 19:03:05 -05001090static void
Matthew Smithca514fd2017-10-12 12:06:59 -05001091vl_api_ipsec_tunnel_if_set_sa_t_handler (vl_api_ipsec_tunnel_if_set_sa_t * mp)
1092{
1093 vl_api_ipsec_tunnel_if_set_sa_reply_t *rmp;
Matthew Smithca514fd2017-10-12 12:06:59 -05001094 int rv;
1095
1096#if WITH_LIBSSL > 0
Neale Ranns12989b52019-09-26 16:20:19 +00001097 VALIDATE_SW_IF_INDEX(mp);
Matthew Smithca514fd2017-10-12 12:06:59 -05001098
Neale Ranns12989b52019-09-26 16:20:19 +00001099 if (mp->is_outbound)
Neale Ranns28287212019-12-16 00:53:11 +00001100 rv = ipsec_tun_protect_update_out (ntohl (mp->sw_if_index), NULL,
Neale Ranns12989b52019-09-26 16:20:19 +00001101 ntohl (mp->sa_id));
1102 else
Neale Ranns28287212019-12-16 00:53:11 +00001103 rv = ipsec_tun_protect_update_in (ntohl (mp->sw_if_index), NULL,
Neale Ranns12989b52019-09-26 16:20:19 +00001104 ntohl (mp->sa_id));
1105
Matthew Smithca514fd2017-10-12 12:06:59 -05001106#else
1107 clib_warning ("unimplemented");
1108#endif
1109
Neale Ranns12989b52019-09-26 16:20:19 +00001110 BAD_SW_IF_INDEX_LABEL;
1111
Matthew Smithca514fd2017-10-12 12:06:59 -05001112 REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_SA_REPLY);
1113}
1114
Klement Sekerab4d30532018-11-08 13:00:02 +01001115static void
1116vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
1117{
1118 vl_api_registration_t *rp;
1119 ipsec_main_t *im = &ipsec_main;
1120 u32 context = mp->context;
1121
1122 rp = vl_api_client_index_to_registration (mp->client_index);
1123
1124 if (rp == 0)
1125 {
1126 clib_warning ("Client %d AWOL", mp->client_index);
1127 return;
1128 }
1129
1130 ipsec_ah_backend_t *ab;
1131 ipsec_esp_backend_t *eb;
1132 /* *INDENT-OFF* */
1133 pool_foreach (ab, im->ah_backends, {
1134 vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1135 clib_memset (mp, 0, sizeof (*mp));
1136 mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1137 mp->context = context;
1138 snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
1139 ab->name);
Neale Ranns17dcec02019-01-09 21:22:20 -08001140 mp->protocol = ntohl (IPSEC_API_PROTO_AH);
Klement Sekerab4d30532018-11-08 13:00:02 +01001141 mp->index = ab - im->ah_backends;
1142 mp->active = mp->index == im->ah_current_backend ? 1 : 0;
1143 vl_api_send_msg (rp, (u8 *)mp);
1144 });
1145 pool_foreach (eb, im->esp_backends, {
1146 vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1147 clib_memset (mp, 0, sizeof (*mp));
1148 mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1149 mp->context = context;
1150 snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
1151 eb->name);
Neale Ranns17dcec02019-01-09 21:22:20 -08001152 mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
Klement Sekerab4d30532018-11-08 13:00:02 +01001153 mp->index = eb - im->esp_backends;
1154 mp->active = mp->index == im->esp_current_backend ? 1 : 0;
1155 vl_api_send_msg (rp, (u8 *)mp);
1156 });
1157 /* *INDENT-ON* */
1158}
1159
1160static void
1161vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
1162{
1163 ipsec_main_t *im = &ipsec_main;
1164 vl_api_ipsec_select_backend_reply_t *rmp;
Neale Ranns17dcec02019-01-09 21:22:20 -08001165 ipsec_protocol_t protocol;
Klement Sekerab4d30532018-11-08 13:00:02 +01001166 int rv = 0;
1167 if (pool_elts (im->sad) > 0)
1168 {
1169 rv = VNET_API_ERROR_INSTANCE_IN_USE;
1170 goto done;
1171 }
Neale Ranns17dcec02019-01-09 21:22:20 -08001172
1173 rv = ipsec_proto_decode (mp->protocol, &protocol);
1174
1175 if (rv)
1176 goto done;
1177
Klement Sekerab4d30532018-11-08 13:00:02 +01001178#if WITH_LIBSSL > 0
Neale Ranns17dcec02019-01-09 21:22:20 -08001179 switch (protocol)
Klement Sekerab4d30532018-11-08 13:00:02 +01001180 {
1181 case IPSEC_PROTOCOL_ESP:
Neale Rannse8915fc2019-04-23 20:57:55 -04001182 rv = ipsec_select_esp_backend (im, mp->index);
Klement Sekerab4d30532018-11-08 13:00:02 +01001183 break;
1184 case IPSEC_PROTOCOL_AH:
Neale Rannse8915fc2019-04-23 20:57:55 -04001185 rv = ipsec_select_ah_backend (im, mp->index);
Klement Sekerab4d30532018-11-08 13:00:02 +01001186 break;
1187 default:
Neale Rannse8915fc2019-04-23 20:57:55 -04001188 rv = VNET_API_ERROR_INVALID_PROTOCOL;
Klement Sekerab4d30532018-11-08 13:00:02 +01001189 break;
1190 }
1191#else
1192 clib_warning ("unimplemented"); /* FIXME */
1193#endif
1194done:
1195 REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1196}
1197
Yulong Pei2e84d662020-08-14 18:21:08 +08001198static void
1199vl_api_ipsec_set_async_mode_t_handler (vl_api_ipsec_set_async_mode_t * mp)
1200{
1201 vl_api_ipsec_set_async_mode_reply_t *rmp;
1202 int rv = 0;
1203
1204 vnet_crypto_request_async_mode (mp->async_enable);
1205 ipsec_set_async_mode (mp->async_enable);
1206
1207 REPLY_MACRO (VL_API_IPSEC_SET_ASYNC_MODE_REPLY);
1208}
1209
Neale Ranns7c44d782019-02-25 10:28:29 +00001210/*
1211 * ipsec_api_hookup
1212 * Add vpe's API message handlers to the table.
1213 * vlib has already mapped shared memory and
1214 * added the client registration handlers.
1215 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1216 */
1217#define vl_msg_name_crc_list
1218#include <vnet/vnet_all_api_h.h>
1219#undef vl_msg_name_crc_list
1220
1221static void
1222setup_message_id_table (api_main_t * am)
1223{
1224#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1225 foreach_vl_msg_name_crc_ipsec;
1226#undef _
1227}
1228
Pavel Kotucek9c7ef032016-12-21 07:46:45 +01001229static clib_error_t *
1230ipsec_api_hookup (vlib_main_t * vm)
1231{
Dave Barach39d69112019-11-27 11:42:13 -05001232 api_main_t *am = vlibapi_get_main ();
Pavel Kotucek9c7ef032016-12-21 07:46:45 +01001233
1234#define _(N,n) \
1235 vl_msg_api_set_handlers(VL_API_##N, #n, \
1236 vl_api_##n##_t_handler, \
1237 vl_noop_handler, \
1238 vl_api_##n##_t_endian, \
1239 vl_api_##n##_t_print, \
1240 sizeof(vl_api_##n##_t), 1);
1241 foreach_vpe_api_msg;
1242#undef _
1243
1244 /*
Pavel Kotucek9c7ef032016-12-21 07:46:45 +01001245 * Set up the (msg_name, crc, message-id) table
1246 */
1247 setup_message_id_table (am);
1248
1249 return 0;
1250}
1251
1252VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1253
1254/*
1255 * fd.io coding-style-patch-verification: ON
1256 *
1257 * Local Variables:
1258 * eval: (c-set-style "gnu")
1259 * End:
1260 */