Line data Source code
1 : /*
2 : * Copyright (c) 2020 Cisco and/or its affiliates.
3 : *
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at:
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 :
17 : #include <vnet/ip/ip_types_api.h>
18 : #include <vlibmemory/api.h>
19 :
20 : #include <vnet/fib/fib_table.h>
21 :
22 : #include <nat/lib/nat_inlines.h>
23 : #include <nat/lib/ipfix_logging.h>
24 :
25 : #include <nat/nat44-ei/nat44_ei.api_enum.h>
26 : #include <nat/nat44-ei/nat44_ei.api_types.h>
27 :
28 : #include <nat/nat44-ei/nat44_ei_ha.h>
29 : #include <nat/nat44-ei/nat44_ei.h>
30 :
31 : #define REPLY_MSG_ID_BASE nm->msg_id_base
32 : #include <vlibapi/api_helper_macros.h>
33 :
34 : static void
35 1 : vl_api_nat44_ei_show_running_config_t_handler (
36 : vl_api_nat44_ei_show_running_config_t *mp)
37 : {
38 : vl_api_nat44_ei_show_running_config_reply_t *rmp;
39 1 : nat44_ei_main_t *nm = &nat44_ei_main;
40 1 : nat44_ei_config_t *rc = &nm->rconfig;
41 1 : int rv = 0;
42 :
43 1 : REPLY_MACRO2_ZERO (
44 : VL_API_NAT44_EI_SHOW_RUNNING_CONFIG_REPLY, ({
45 : rmp->inside_vrf = htonl (rc->inside_vrf);
46 : rmp->outside_vrf = htonl (rc->outside_vrf);
47 : rmp->users = htonl (rc->users);
48 : rmp->sessions = htonl (rc->sessions);
49 : rmp->user_sessions = htonl (rc->user_sessions);
50 :
51 : rmp->user_buckets = htonl (nm->user_buckets);
52 : rmp->translation_buckets = htonl (nm->translation_buckets);
53 :
54 : rmp->timeouts.udp = htonl (nm->timeouts.udp);
55 : rmp->timeouts.tcp_established = htonl (nm->timeouts.tcp.established);
56 : rmp->timeouts.tcp_transitory = htonl (nm->timeouts.tcp.transitory);
57 : rmp->timeouts.icmp = htonl (nm->timeouts.icmp);
58 :
59 : rmp->forwarding_enabled = nm->forwarding_enabled == 1;
60 : // consider how to split functionality between subplugins
61 : rmp->ipfix_logging_enabled = nat_ipfix_logging_enabled ();
62 :
63 : if (rc->static_mapping_only)
64 : rmp->flags |= NAT44_EI_STATIC_MAPPING_ONLY;
65 : if (rc->connection_tracking)
66 : rmp->flags |= NAT44_EI_CONNECTION_TRACKING;
67 : if (rc->out2in_dpo)
68 : rmp->flags |= NAT44_EI_OUT2IN_DPO;
69 : }));
70 : }
71 :
72 : static void
73 0 : vl_api_nat44_ei_set_workers_t_handler (vl_api_nat44_ei_set_workers_t *mp)
74 : {
75 0 : nat44_ei_main_t *nm = &nat44_ei_main;
76 : vl_api_nat44_ei_set_workers_reply_t *rmp;
77 0 : int rv = 0;
78 0 : uword *bitmap = 0;
79 : u64 mask;
80 :
81 0 : mask = clib_net_to_host_u64 (mp->worker_mask);
82 :
83 0 : if (nm->num_workers < 2)
84 : {
85 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
86 0 : goto send_reply;
87 : }
88 :
89 0 : bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
90 0 : rv = nat44_ei_set_workers (bitmap);
91 0 : clib_bitmap_free (bitmap);
92 :
93 0 : send_reply:
94 0 : REPLY_MACRO (VL_API_NAT44_EI_SET_WORKERS_REPLY);
95 : }
96 :
97 : static void
98 0 : send_nat_worker_details (u32 worker_index, vl_api_registration_t *reg,
99 : u32 context)
100 : {
101 : vl_api_nat44_ei_worker_details_t *rmp;
102 0 : nat44_ei_main_t *nm = &nat44_ei_main;
103 0 : vlib_worker_thread_t *w =
104 0 : vlib_worker_threads + worker_index + nm->first_worker_index;
105 :
106 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
107 0 : clib_memset (rmp, 0, sizeof (*rmp));
108 0 : rmp->_vl_msg_id = ntohs (VL_API_NAT44_EI_WORKER_DETAILS + nm->msg_id_base);
109 0 : rmp->context = context;
110 0 : rmp->worker_index = htonl (worker_index);
111 0 : rmp->lcore_id = htonl (w->cpu_id);
112 0 : strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
113 :
114 0 : vl_api_send_msg (reg, (u8 *) rmp);
115 0 : }
116 :
117 : static void
118 0 : vl_api_nat44_ei_worker_dump_t_handler (vl_api_nat44_ei_worker_dump_t *mp)
119 : {
120 : vl_api_registration_t *reg;
121 0 : nat44_ei_main_t *nm = &nat44_ei_main;
122 : u32 *worker_index;
123 :
124 0 : reg = vl_api_client_index_to_registration (mp->client_index);
125 0 : if (!reg)
126 0 : return;
127 :
128 0 : vec_foreach (worker_index, nm->workers)
129 : {
130 0 : send_nat_worker_details (*worker_index, reg, mp->context);
131 : }
132 : }
133 :
134 : static void
135 0 : vl_api_nat44_ei_set_log_level_t_handler (vl_api_nat44_ei_set_log_level_t *mp)
136 : {
137 0 : nat44_ei_main_t *nm = &nat44_ei_main;
138 : vl_api_nat44_ei_set_log_level_reply_t *rmp;
139 0 : int rv = 0;
140 :
141 0 : if (nm->log_level > NAT_LOG_DEBUG)
142 0 : rv = VNET_API_ERROR_UNSUPPORTED;
143 : else
144 0 : nm->log_level = mp->log_level;
145 :
146 0 : REPLY_MACRO (VL_API_NAT44_EI_SET_LOG_LEVEL_REPLY);
147 : }
148 :
149 : static void
150 116 : vl_api_nat44_ei_plugin_enable_disable_t_handler (
151 : vl_api_nat44_ei_plugin_enable_disable_t *mp)
152 : {
153 116 : nat44_ei_main_t *nm = &nat44_ei_main;
154 116 : nat44_ei_config_t c = { 0 };
155 : vl_api_nat44_ei_plugin_enable_disable_reply_t *rmp;
156 116 : int rv = 0;
157 :
158 116 : if (mp->enable)
159 : {
160 58 : c.static_mapping_only = mp->flags & NAT44_EI_STATIC_MAPPING_ONLY;
161 58 : c.connection_tracking = mp->flags & NAT44_EI_CONNECTION_TRACKING;
162 58 : c.out2in_dpo = mp->flags & NAT44_EI_OUT2IN_DPO;
163 :
164 58 : c.inside_vrf = ntohl (mp->inside_vrf);
165 58 : c.outside_vrf = ntohl (mp->outside_vrf);
166 :
167 58 : c.users = ntohl (mp->users);
168 :
169 58 : c.sessions = ntohl (mp->sessions);
170 :
171 58 : c.user_sessions = ntohl (mp->user_sessions);
172 :
173 58 : rv = nat44_ei_plugin_enable (c);
174 : }
175 : else
176 : {
177 58 : rv = nat44_ei_plugin_disable ();
178 : }
179 :
180 116 : REPLY_MACRO (VL_API_NAT44_EI_PLUGIN_ENABLE_DISABLE_REPLY);
181 : }
182 :
183 : static void
184 60 : vl_api_nat44_ei_ipfix_enable_disable_t_handler (
185 : vl_api_nat44_ei_ipfix_enable_disable_t *mp)
186 : {
187 60 : nat44_ei_main_t *nm = &nat44_ei_main;
188 : vl_api_nat44_ei_ipfix_enable_disable_reply_t *rmp;
189 60 : int rv = 0;
190 :
191 60 : rv = nat_ipfix_logging_enable_disable (mp->enable,
192 : clib_host_to_net_u32 (mp->domain_id),
193 60 : clib_host_to_net_u16 (mp->src_port));
194 :
195 60 : REPLY_MACRO (VL_API_NAT44_EI_IPFIX_ENABLE_DISABLE_REPLY);
196 : }
197 :
198 : static void
199 0 : vl_api_nat44_ei_set_timeouts_t_handler (vl_api_nat44_ei_set_timeouts_t *mp)
200 : {
201 0 : nat44_ei_main_t *nm = &nat44_ei_main;
202 : vl_api_nat44_ei_set_timeouts_reply_t *rmp;
203 0 : int rv = 0;
204 :
205 0 : nm->timeouts.udp = ntohl (mp->udp);
206 0 : nm->timeouts.tcp.established = ntohl (mp->tcp_established);
207 0 : nm->timeouts.tcp.transitory = ntohl (mp->tcp_transitory);
208 0 : nm->timeouts.icmp = ntohl (mp->icmp);
209 :
210 0 : REPLY_MACRO (VL_API_NAT44_EI_SET_TIMEOUTS_REPLY);
211 : }
212 :
213 : static void
214 2 : vl_api_nat44_ei_set_addr_and_port_alloc_alg_t_handler (
215 : vl_api_nat44_ei_set_addr_and_port_alloc_alg_t *mp)
216 : {
217 2 : nat44_ei_main_t *nm = &nat44_ei_main;
218 : vl_api_nat44_ei_set_addr_and_port_alloc_alg_reply_t *rmp;
219 2 : int rv = 0;
220 : u16 port_start, port_end;
221 :
222 2 : switch (mp->alg)
223 : {
224 0 : case NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_DEFAULT:
225 0 : nat44_ei_set_alloc_default ();
226 0 : break;
227 1 : case NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_MAPE:
228 1 : nat44_ei_set_alloc_mape (ntohs (mp->psid), mp->psid_offset,
229 1 : mp->psid_length);
230 1 : break;
231 1 : case NAT44_EI_ADDR_AND_PORT_ALLOC_ALG_RANGE:
232 1 : port_start = ntohs (mp->start_port);
233 1 : port_end = ntohs (mp->end_port);
234 1 : if (port_end <= port_start)
235 : {
236 0 : rv = VNET_API_ERROR_INVALID_VALUE;
237 0 : goto send_reply;
238 : }
239 1 : nat44_ei_set_alloc_range (port_start, port_end);
240 1 : break;
241 0 : default:
242 0 : rv = VNET_API_ERROR_INVALID_VALUE;
243 0 : break;
244 : }
245 :
246 2 : send_reply:
247 2 : REPLY_MACRO (VL_API_NAT44_EI_SET_ADDR_AND_PORT_ALLOC_ALG_REPLY);
248 : }
249 :
250 : static void
251 0 : vl_api_nat44_ei_get_addr_and_port_alloc_alg_t_handler (
252 : vl_api_nat44_ei_get_addr_and_port_alloc_alg_t *mp)
253 : {
254 0 : nat44_ei_main_t *nm = &nat44_ei_main;
255 : vl_api_nat44_ei_get_addr_and_port_alloc_alg_reply_t *rmp;
256 0 : int rv = 0;
257 :
258 0 : REPLY_MACRO2 (VL_API_NAT44_EI_GET_ADDR_AND_PORT_ALLOC_ALG_REPLY, ({
259 : rmp->alg = nm->addr_and_port_alloc_alg;
260 : rmp->psid_offset = nm->psid_offset;
261 : rmp->psid_length = nm->psid_length;
262 : rmp->psid = htons (nm->psid);
263 : rmp->start_port = htons (nm->start_port);
264 : rmp->end_port = htons (nm->end_port);
265 : }))
266 : }
267 :
268 : static void
269 3 : vl_api_nat44_ei_set_mss_clamping_t_handler (
270 : vl_api_nat44_ei_set_mss_clamping_t *mp)
271 : {
272 3 : nat44_ei_main_t *nm = &nat44_ei_main;
273 : vl_api_nat44_ei_set_mss_clamping_reply_t *rmp;
274 3 : int rv = 0;
275 :
276 3 : if (mp->enable)
277 2 : nm->mss_clamping = ntohs (mp->mss_value);
278 : else
279 1 : nm->mss_clamping = 0;
280 :
281 3 : REPLY_MACRO (VL_API_NAT44_EI_SET_MSS_CLAMPING_REPLY);
282 : }
283 :
284 : static void
285 0 : vl_api_nat44_ei_get_mss_clamping_t_handler (
286 : vl_api_nat44_ei_get_mss_clamping_t *mp)
287 : {
288 0 : nat44_ei_main_t *nm = &nat44_ei_main;
289 : vl_api_nat44_ei_get_mss_clamping_reply_t *rmp;
290 0 : int rv = 0;
291 :
292 0 : REPLY_MACRO2 (VL_API_NAT44_EI_GET_MSS_CLAMPING_REPLY, ({
293 : rmp->enable = nm->mss_clamping ? 1 : 0;
294 : rmp->mss_value = htons (nm->mss_clamping);
295 : }))
296 : }
297 :
298 : static void
299 2 : vl_api_nat44_ei_ha_set_listener_t_handler (
300 : vl_api_nat44_ei_ha_set_listener_t *mp)
301 : {
302 2 : nat44_ei_main_t *nm = &nat44_ei_main;
303 : vl_api_nat44_ei_ha_set_listener_reply_t *rmp;
304 : ip4_address_t addr;
305 : int rv;
306 :
307 2 : memcpy (&addr, &mp->ip_address, sizeof (addr));
308 4 : rv = nat_ha_set_listener (vlib_get_main (), &addr,
309 2 : clib_net_to_host_u16 (mp->port),
310 : clib_net_to_host_u32 (mp->path_mtu));
311 :
312 2 : REPLY_MACRO (VL_API_NAT44_EI_HA_SET_LISTENER_REPLY);
313 : }
314 :
315 : static void
316 0 : vl_api_nat44_ei_ha_get_listener_t_handler (
317 : vl_api_nat44_ei_ha_get_listener_t *mp)
318 : {
319 0 : nat44_ei_main_t *nm = &nat44_ei_main;
320 : vl_api_nat44_ei_ha_get_listener_reply_t *rmp;
321 0 : int rv = 0;
322 : ip4_address_t addr;
323 : u16 port;
324 : u32 path_mtu;
325 :
326 0 : nat_ha_get_listener (&addr, &port, &path_mtu);
327 :
328 0 : REPLY_MACRO2 (VL_API_NAT44_EI_HA_GET_LISTENER_REPLY, ({
329 : clib_memcpy (rmp->ip_address, &addr, sizeof (ip4_address_t));
330 : rmp->port = clib_host_to_net_u16 (port);
331 : rmp->path_mtu = clib_host_to_net_u32 (path_mtu);
332 : }))
333 : }
334 :
335 : static void
336 1 : vl_api_nat44_ei_ha_set_failover_t_handler (
337 : vl_api_nat44_ei_ha_set_failover_t *mp)
338 : {
339 1 : nat44_ei_main_t *nm = &nat44_ei_main;
340 : vl_api_nat44_ei_ha_set_failover_reply_t *rmp;
341 : ip4_address_t addr;
342 : int rv;
343 :
344 1 : memcpy (&addr, &mp->ip_address, sizeof (addr));
345 2 : rv = nat_ha_set_failover (
346 1 : vlib_get_main (), &addr, clib_net_to_host_u16 (mp->port),
347 : clib_net_to_host_u32 (mp->session_refresh_interval));
348 :
349 1 : REPLY_MACRO (VL_API_NAT44_EI_HA_SET_FAILOVER_REPLY);
350 : }
351 :
352 : static void
353 0 : vl_api_nat44_ei_ha_get_failover_t_handler (
354 : vl_api_nat44_ei_ha_get_failover_t *mp)
355 : {
356 0 : nat44_ei_main_t *nm = &nat44_ei_main;
357 : vl_api_nat44_ei_ha_get_failover_reply_t *rmp;
358 0 : int rv = 0;
359 : ip4_address_t addr;
360 : u16 port;
361 : u32 session_refresh_interval;
362 :
363 0 : nat_ha_get_failover (&addr, &port, &session_refresh_interval);
364 :
365 0 : REPLY_MACRO2 (VL_API_NAT44_EI_HA_GET_FAILOVER_REPLY, ({
366 : clib_memcpy (rmp->ip_address, &addr, sizeof (ip4_address_t));
367 : rmp->port = clib_host_to_net_u16 (port);
368 : rmp->session_refresh_interval =
369 : clib_host_to_net_u32 (session_refresh_interval);
370 : }))
371 : }
372 :
373 : static void
374 3 : vl_api_nat44_ei_ha_flush_t_handler (vl_api_nat44_ei_ha_flush_t *mp)
375 : {
376 3 : nat44_ei_main_t *nm = &nat44_ei_main;
377 : vl_api_nat44_ei_ha_flush_reply_t *rmp;
378 3 : int rv = 0;
379 :
380 3 : nat_ha_flush (0);
381 :
382 3 : REPLY_MACRO (VL_API_NAT44_EI_HA_FLUSH_REPLY);
383 : }
384 :
385 : static void
386 0 : nat_ha_resync_completed_event_cb (u32 client_index, u32 pid, u32 missed_count)
387 : {
388 0 : nat44_ei_main_t *nm = &nat44_ei_main;
389 : vl_api_registration_t *reg;
390 : vl_api_nat44_ei_ha_resync_completed_event_t *mp;
391 :
392 0 : reg = vl_api_client_index_to_registration (client_index);
393 0 : if (!reg)
394 0 : return;
395 :
396 0 : mp = vl_msg_api_alloc (sizeof (*mp));
397 0 : clib_memset (mp, 0, sizeof (*mp));
398 0 : mp->client_index = client_index;
399 0 : mp->pid = pid;
400 0 : mp->missed_count = clib_host_to_net_u32 (missed_count);
401 0 : mp->_vl_msg_id =
402 0 : ntohs (VL_API_NAT44_EI_HA_RESYNC_COMPLETED_EVENT + nm->msg_id_base);
403 :
404 0 : vl_api_send_msg (reg, (u8 *) mp);
405 : }
406 :
407 : static void
408 0 : vl_api_nat44_ei_ha_resync_t_handler (vl_api_nat44_ei_ha_resync_t *mp)
409 : {
410 0 : nat44_ei_main_t *nm = &nat44_ei_main;
411 : vl_api_nat44_ei_ha_resync_reply_t *rmp;
412 : int rv;
413 :
414 0 : rv = nat_ha_resync (
415 : mp->client_index, mp->pid,
416 0 : mp->want_resync_event ? nat_ha_resync_completed_event_cb : NULL);
417 :
418 0 : REPLY_MACRO (VL_API_NAT44_EI_HA_RESYNC_REPLY);
419 : }
420 :
421 : static void
422 0 : vl_api_nat44_ei_del_user_t_handler (vl_api_nat44_ei_del_user_t *mp)
423 : {
424 0 : nat44_ei_main_t *nm = &nat44_ei_main;
425 : vl_api_nat44_ei_del_user_reply_t *rmp;
426 : ip4_address_t addr;
427 : int rv;
428 0 : memcpy (&addr.as_u8, mp->ip_address, 4);
429 0 : rv = nat44_ei_user_del (&addr, ntohl (mp->fib_index));
430 0 : REPLY_MACRO (VL_API_NAT44_EI_DEL_USER_REPLY);
431 : }
432 :
433 : static void
434 48 : vl_api_nat44_ei_add_del_address_range_t_handler (
435 : vl_api_nat44_ei_add_del_address_range_t *mp)
436 : {
437 48 : nat44_ei_main_t *nm = &nat44_ei_main;
438 : vl_api_nat44_ei_add_del_address_range_reply_t *rmp;
439 : ip4_address_t this_addr;
440 : u8 is_add;
441 : u32 start_host_order, end_host_order;
442 : u32 vrf_id;
443 : int i, count;
444 48 : int rv = 0;
445 : u32 *tmp;
446 :
447 48 : if (nm->static_mapping_only)
448 : {
449 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
450 0 : goto send_reply;
451 : }
452 :
453 48 : is_add = mp->is_add;
454 :
455 48 : tmp = (u32 *) mp->first_ip_address;
456 48 : start_host_order = clib_host_to_net_u32 (tmp[0]);
457 48 : tmp = (u32 *) mp->last_ip_address;
458 48 : end_host_order = clib_host_to_net_u32 (tmp[0]);
459 :
460 48 : count = (end_host_order - start_host_order) + 1;
461 :
462 48 : vrf_id = clib_host_to_net_u32 (mp->vrf_id);
463 :
464 48 : if (count > 1024)
465 0 : nat44_ei_log_info ("%U - %U, %d addresses...", format_ip4_address,
466 : mp->first_ip_address, format_ip4_address,
467 : mp->last_ip_address, count);
468 :
469 48 : memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
470 :
471 194 : for (i = 0; i < count; i++)
472 : {
473 146 : if (is_add)
474 142 : rv = nat44_ei_add_address (&this_addr, vrf_id);
475 : else
476 4 : rv = nat44_ei_del_address (this_addr, 0);
477 :
478 146 : if (rv)
479 0 : goto send_reply;
480 :
481 146 : if (nm->out2in_dpo)
482 0 : nat44_ei_add_del_address_dpo (this_addr, is_add);
483 :
484 146 : increment_v4_address (&this_addr);
485 : }
486 :
487 48 : send_reply:
488 48 : REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_ADDRESS_RANGE_REPLY);
489 : }
490 :
491 : static void
492 3 : send_nat44_ei_address_details (nat44_ei_address_t *a,
493 : vl_api_registration_t *reg, u32 context)
494 : {
495 : vl_api_nat44_ei_address_details_t *rmp;
496 3 : nat44_ei_main_t *nm = &nat44_ei_main;
497 :
498 3 : rmp = vl_msg_api_alloc (sizeof (*rmp));
499 3 : clib_memset (rmp, 0, sizeof (*rmp));
500 3 : rmp->_vl_msg_id = ntohs (VL_API_NAT44_EI_ADDRESS_DETAILS + nm->msg_id_base);
501 3 : clib_memcpy (rmp->ip_address, &(a->addr), 4);
502 3 : if (a->fib_index != ~0)
503 : {
504 0 : fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
505 0 : rmp->vrf_id = ntohl (fib->ft_table_id);
506 : }
507 : else
508 3 : rmp->vrf_id = ~0;
509 3 : rmp->context = context;
510 :
511 3 : vl_api_send_msg (reg, (u8 *) rmp);
512 3 : }
513 :
514 : static void
515 5 : vl_api_nat44_ei_address_dump_t_handler (vl_api_nat44_ei_address_dump_t *mp)
516 : {
517 : vl_api_registration_t *reg;
518 5 : nat44_ei_main_t *nm = &nat44_ei_main;
519 : nat44_ei_address_t *a;
520 :
521 5 : reg = vl_api_client_index_to_registration (mp->client_index);
522 5 : if (!reg)
523 0 : return;
524 :
525 8 : vec_foreach (a, nm->addresses)
526 : {
527 3 : send_nat44_ei_address_details (a, reg, mp->context);
528 : }
529 : }
530 :
531 : static void
532 106 : vl_api_nat44_ei_interface_add_del_feature_t_handler (
533 : vl_api_nat44_ei_interface_add_del_feature_t *mp)
534 : {
535 106 : nat44_ei_main_t *nm = &nat44_ei_main;
536 : vl_api_nat44_ei_interface_add_del_feature_reply_t *rmp;
537 106 : u32 sw_if_index = ntohl (mp->sw_if_index);
538 106 : int rv = 0;
539 :
540 106 : VALIDATE_SW_IF_INDEX (mp);
541 :
542 106 : if (mp->is_add)
543 : {
544 : rv =
545 106 : nat44_ei_add_interface (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE);
546 : }
547 : else
548 : {
549 : rv =
550 0 : nat44_ei_del_interface (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE);
551 : }
552 :
553 106 : BAD_SW_IF_INDEX_LABEL;
554 106 : REPLY_MACRO (VL_API_NAT44_EI_INTERFACE_ADD_DEL_FEATURE_REPLY);
555 : }
556 :
557 : static void
558 6 : send_nat44_ei_interface_details (nat44_ei_interface_t *i,
559 : vl_api_registration_t *reg, u32 context)
560 : {
561 : vl_api_nat44_ei_interface_details_t *rmp;
562 6 : nat44_ei_main_t *nm = &nat44_ei_main;
563 :
564 6 : rmp = vl_msg_api_alloc (sizeof (*rmp));
565 6 : clib_memset (rmp, 0, sizeof (*rmp));
566 6 : rmp->_vl_msg_id =
567 6 : ntohs (VL_API_NAT44_EI_INTERFACE_DETAILS + nm->msg_id_base);
568 6 : rmp->sw_if_index = ntohl (i->sw_if_index);
569 :
570 6 : if (nat44_ei_interface_is_inside (i))
571 5 : rmp->flags |= NAT44_EI_IF_INSIDE;
572 6 : if (nat44_ei_interface_is_outside (i))
573 1 : rmp->flags |= NAT44_EI_IF_OUTSIDE;
574 :
575 6 : rmp->context = context;
576 :
577 6 : vl_api_send_msg (reg, (u8 *) rmp);
578 6 : }
579 :
580 : static void
581 5 : vl_api_nat44_ei_interface_dump_t_handler (vl_api_nat44_ei_interface_dump_t *mp)
582 : {
583 : vl_api_registration_t *reg;
584 5 : nat44_ei_main_t *nm = &nat44_ei_main;
585 : nat44_ei_interface_t *i;
586 :
587 5 : reg = vl_api_client_index_to_registration (mp->client_index);
588 5 : if (!reg)
589 0 : return;
590 :
591 11 : pool_foreach (i, nm->interfaces)
592 : {
593 6 : send_nat44_ei_interface_details (i, reg, mp->context);
594 : }
595 : }
596 :
597 : static_always_inline int
598 0 : add_del_dummy_output_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
599 : {
600 0 : nat44_ei_main_t *nm = &nat44_ei_main;
601 : nat44_ei_interface_t *i;
602 0 : int rv = 1;
603 :
604 0 : pool_foreach (i, nm->output_feature_dummy_interfaces)
605 : {
606 0 : if (i->sw_if_index == sw_if_index)
607 : {
608 0 : if (!is_add)
609 : {
610 0 : pool_put (nm->output_feature_dummy_interfaces, i);
611 0 : rv = 0;
612 : }
613 0 : goto done;
614 : }
615 : }
616 :
617 0 : if (is_add)
618 : {
619 0 : pool_get (nm->output_feature_dummy_interfaces, i);
620 0 : i->sw_if_index = sw_if_index;
621 :
622 0 : if (is_inside)
623 : {
624 0 : i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
625 : }
626 : else
627 : {
628 0 : i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
629 : }
630 :
631 0 : rv = 0;
632 : }
633 :
634 0 : done:
635 0 : return rv;
636 : }
637 :
638 : static void
639 0 : vl_api_nat44_ei_interface_add_del_output_feature_t_handler (
640 : vl_api_nat44_ei_interface_add_del_output_feature_t *mp)
641 : {
642 : vl_api_nat44_ei_interface_add_del_output_feature_reply_t *rmp;
643 0 : nat44_ei_main_t *nm = &nat44_ei_main;
644 : u32 sw_if_index;
645 0 : int rv = 0;
646 :
647 0 : VALIDATE_SW_IF_INDEX (mp);
648 :
649 0 : sw_if_index = ntohl (mp->sw_if_index);
650 :
651 : // register all interfaces in the dummy structure
652 0 : rv = add_del_dummy_output_interface (
653 0 : sw_if_index, mp->flags & NAT44_EI_IF_INSIDE, mp->is_add);
654 :
655 0 : if (!(mp->flags & NAT44_EI_IF_INSIDE))
656 : {
657 0 : if (mp->is_add)
658 : {
659 0 : rv = nat44_ei_add_output_interface (sw_if_index);
660 : }
661 : else
662 : {
663 0 : rv = nat44_ei_del_output_interface (sw_if_index);
664 : }
665 : }
666 :
667 0 : BAD_SW_IF_INDEX_LABEL;
668 0 : REPLY_MACRO (VL_API_NAT44_EI_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
669 : }
670 :
671 : static void
672 0 : send_nat44_ei_interface_output_feature_details (nat44_ei_interface_t *i,
673 : vl_api_registration_t *reg,
674 : u32 context)
675 : {
676 : vl_api_nat44_ei_interface_output_feature_details_t *rmp;
677 0 : nat44_ei_main_t *nm = &nat44_ei_main;
678 :
679 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
680 0 : clib_memset (rmp, 0, sizeof (*rmp));
681 0 : rmp->_vl_msg_id =
682 0 : ntohs (VL_API_NAT44_EI_INTERFACE_OUTPUT_FEATURE_DETAILS + nm->msg_id_base);
683 0 : rmp->sw_if_index = ntohl (i->sw_if_index);
684 0 : rmp->context = context;
685 :
686 0 : if (nat44_ei_interface_is_inside (i))
687 : {
688 0 : rmp->flags |= NAT44_EI_IF_INSIDE;
689 : }
690 :
691 0 : vl_api_send_msg (reg, (u8 *) rmp);
692 0 : }
693 :
694 : static void
695 0 : vl_api_nat44_ei_interface_output_feature_dump_t_handler (
696 : vl_api_nat44_ei_interface_output_feature_dump_t *mp)
697 : {
698 : vl_api_registration_t *reg;
699 0 : nat44_ei_main_t *nm = &nat44_ei_main;
700 : nat44_ei_interface_t *i;
701 :
702 0 : reg = vl_api_client_index_to_registration (mp->client_index);
703 0 : if (!reg)
704 0 : return;
705 :
706 0 : pool_foreach (i, nm->output_feature_dummy_interfaces)
707 : {
708 0 : send_nat44_ei_interface_output_feature_details (i, reg, mp->context);
709 : }
710 : }
711 :
712 : static void
713 5 : vl_api_nat44_ei_add_del_output_interface_t_handler (
714 : vl_api_nat44_ei_add_del_output_interface_t *mp)
715 : {
716 : vl_api_nat44_ei_add_del_output_interface_reply_t *rmp;
717 5 : nat44_ei_main_t *nm = &nat44_ei_main;
718 5 : int rv = 0;
719 :
720 5 : VALIDATE_SW_IF_INDEX_END (mp);
721 :
722 5 : if (mp->is_add)
723 : {
724 5 : rv = nat44_ei_add_output_interface (mp->sw_if_index);
725 : }
726 : else
727 : {
728 0 : rv = nat44_ei_del_output_interface (mp->sw_if_index);
729 : }
730 :
731 5 : bad_sw_if_index:
732 5 : REPLY_MACRO_END (VL_API_NAT44_EI_ADD_DEL_OUTPUT_INTERFACE_REPLY);
733 : }
734 :
735 : #define vl_endianfun
736 : #include <nat/nat44-ei/nat44_ei.api.h>
737 : #undef vl_endianfun
738 : static void
739 4 : send_nat44_ei_output_interface_details (u32 index, vl_api_registration_t *rp,
740 : u32 context)
741 : {
742 4 : nat44_ei_main_t *nm = &nat44_ei_main;
743 : vl_api_nat44_ei_output_interface_details_t *rmp;
744 4 : nat44_ei_interface_t *i =
745 4 : pool_elt_at_index (nm->output_feature_interfaces, index);
746 :
747 : /* Make sure every field is initiated (or don't skip the clib_memset()) */
748 4 : REPLY_MACRO_DETAILS4 (
749 : VL_API_NAT44_EI_OUTPUT_INTERFACE_DETAILS, rp, context, ({
750 : rmp->sw_if_index = i->sw_if_index;
751 :
752 : /* Endian hack until apigen registers _details
753 : * endian functions */
754 : vl_api_nat44_ei_output_interface_details_t_endian (rmp);
755 : rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
756 : rmp->context = htonl (rmp->context);
757 : }));
758 4 : }
759 :
760 : static void
761 5 : vl_api_nat44_ei_output_interface_get_t_handler (
762 : vl_api_nat44_ei_output_interface_get_t *mp)
763 : {
764 : vl_api_nat44_ei_output_interface_get_reply_t *rmp;
765 5 : nat44_ei_main_t *nm = &nat44_ei_main;
766 5 : i32 rv = 0;
767 :
768 5 : if (pool_elts (nm->output_feature_interfaces) == 0)
769 : {
770 1 : REPLY_MACRO (VL_API_NAT44_EI_OUTPUT_INTERFACE_GET_REPLY);
771 1 : return;
772 : }
773 :
774 8 : REPLY_AND_DETAILS_MACRO (
775 : VL_API_NAT44_EI_OUTPUT_INTERFACE_GET_REPLY, nm->output_feature_interfaces,
776 : ({ send_nat44_ei_output_interface_details (cursor, rp, mp->context); }));
777 : }
778 :
779 : static void
780 38 : vl_api_nat44_ei_add_del_static_mapping_t_handler (
781 : vl_api_nat44_ei_add_del_static_mapping_t *mp)
782 : {
783 : vl_api_nat44_ei_add_del_static_mapping_reply_t *rmp;
784 :
785 38 : nat44_ei_main_t *nm = &nat44_ei_main;
786 38 : int rv = 0;
787 :
788 38 : ip4_address_t l_addr, e_addr, pool_addr = { 0 };
789 38 : u32 sw_if_index, flags = 0, vrf_id;
790 38 : u16 l_port = 0, e_port = 0;
791 38 : nat_protocol_t proto = 0;
792 38 : u8 *tag = 0;
793 :
794 38 : memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
795 :
796 38 : if (mp->flags & NAT44_EI_ADDR_ONLY_MAPPING)
797 : {
798 23 : flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
799 : }
800 : else
801 : {
802 15 : l_port = mp->local_port;
803 15 : e_port = mp->external_port;
804 15 : proto = ip_proto_to_nat_proto (mp->protocol);
805 : }
806 :
807 38 : sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
808 38 : if (sw_if_index != ~0)
809 : {
810 2 : flags |= NAT44_EI_SM_FLAG_SWITCH_ADDRESS;
811 : }
812 : else
813 : {
814 36 : memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
815 : }
816 :
817 38 : vrf_id = clib_net_to_host_u32 (mp->vrf_id);
818 :
819 38 : if (mp->is_add)
820 : {
821 35 : mp->tag[sizeof (mp->tag) - 1] = 0;
822 35 : tag = format (0, "%s", mp->tag);
823 35 : vec_terminate_c_string (tag);
824 :
825 35 : rv = nat44_ei_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
826 : vrf_id, sw_if_index, flags, pool_addr,
827 : tag);
828 35 : vec_free (tag);
829 : }
830 : else
831 : {
832 3 : rv = nat44_ei_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
833 : vrf_id, sw_if_index, flags);
834 : }
835 38 : REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_STATIC_MAPPING_REPLY);
836 : }
837 :
838 : static void
839 4 : send_nat44_ei_static_mapping_details (nat44_ei_static_mapping_t *m,
840 : vl_api_registration_t *reg, u32 context)
841 : {
842 : vl_api_nat44_ei_static_mapping_details_t *rmp;
843 4 : nat44_ei_main_t *nm = &nat44_ei_main;
844 4 : u32 len = sizeof (*rmp);
845 :
846 4 : rmp = vl_msg_api_alloc (len);
847 4 : clib_memset (rmp, 0, len);
848 4 : rmp->_vl_msg_id =
849 4 : ntohs (VL_API_NAT44_EI_STATIC_MAPPING_DETAILS + nm->msg_id_base);
850 :
851 4 : clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
852 4 : clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
853 4 : rmp->external_sw_if_index = ~0;
854 4 : rmp->vrf_id = htonl (m->vrf_id);
855 4 : rmp->context = context;
856 :
857 4 : if (is_sm_addr_only (m->flags))
858 : {
859 4 : rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
860 : }
861 : else
862 : {
863 0 : rmp->protocol = nat_proto_to_ip_proto (m->proto);
864 0 : rmp->external_port = m->external_port;
865 0 : rmp->local_port = m->local_port;
866 : }
867 :
868 4 : if (m->tag)
869 4 : strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
870 :
871 4 : vl_api_send_msg (reg, (u8 *) rmp);
872 4 : }
873 :
874 : static void
875 4 : send_nat44_ei_static_map_resolve_details (nat44_ei_static_map_resolve_t *m,
876 : vl_api_registration_t *reg,
877 : u32 context)
878 : {
879 : vl_api_nat44_ei_static_mapping_details_t *rmp;
880 4 : nat44_ei_main_t *nm = &nat44_ei_main;
881 :
882 4 : rmp = vl_msg_api_alloc (sizeof (*rmp));
883 4 : clib_memset (rmp, 0, sizeof (*rmp));
884 4 : rmp->_vl_msg_id =
885 4 : ntohs (VL_API_NAT44_EI_STATIC_MAPPING_DETAILS + nm->msg_id_base);
886 4 : clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
887 4 : rmp->external_sw_if_index = htonl (m->sw_if_index);
888 4 : rmp->vrf_id = htonl (m->vrf_id);
889 4 : rmp->context = context;
890 :
891 4 : if (is_sm_addr_only (m->flags))
892 : {
893 4 : rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
894 : }
895 : else
896 : {
897 0 : rmp->protocol = nat_proto_to_ip_proto (m->proto);
898 0 : rmp->external_port = m->e_port;
899 0 : rmp->local_port = m->l_port;
900 : }
901 4 : if (m->tag)
902 4 : strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
903 :
904 4 : vl_api_send_msg (reg, (u8 *) rmp);
905 4 : }
906 :
907 : static void
908 7 : vl_api_nat44_ei_static_mapping_dump_t_handler (
909 : vl_api_nat44_ei_static_mapping_dump_t *mp)
910 : {
911 : vl_api_registration_t *reg;
912 7 : nat44_ei_main_t *nm = &nat44_ei_main;
913 : nat44_ei_static_mapping_t *m;
914 : nat44_ei_static_map_resolve_t *rp;
915 : int j;
916 :
917 7 : reg = vl_api_client_index_to_registration (mp->client_index);
918 7 : if (!reg)
919 0 : return;
920 :
921 11 : pool_foreach (m, nm->static_mappings)
922 : {
923 4 : if (!is_sm_identity_nat (m->flags))
924 4 : send_nat44_ei_static_mapping_details (m, reg, mp->context);
925 : }
926 :
927 11 : for (j = 0; j < vec_len (nm->to_resolve); j++)
928 : {
929 4 : rp = nm->to_resolve + j;
930 4 : if (!is_sm_identity_nat (rp->flags))
931 4 : send_nat44_ei_static_map_resolve_details (rp, reg, mp->context);
932 : }
933 : }
934 :
935 : static void
936 3 : vl_api_nat44_ei_add_del_identity_mapping_t_handler (
937 : vl_api_nat44_ei_add_del_identity_mapping_t *mp)
938 : {
939 : vl_api_nat44_ei_add_del_identity_mapping_reply_t *rmp;
940 :
941 3 : nat44_ei_main_t *nm = &nat44_ei_main;
942 3 : int rv = 0;
943 :
944 3 : ip4_address_t addr, pool_addr = { 0 };
945 : u32 sw_if_index, flags, vrf_id;
946 3 : nat_protocol_t proto = 0;
947 3 : u16 port = 0;
948 3 : u8 *tag = 0;
949 :
950 3 : flags = NAT44_EI_SM_FLAG_IDENTITY_NAT;
951 :
952 3 : if (mp->flags & NAT44_EI_ADDR_ONLY_MAPPING)
953 : {
954 2 : flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
955 : }
956 : else
957 : {
958 1 : port = mp->port;
959 1 : proto = ip_proto_to_nat_proto (mp->protocol);
960 : }
961 :
962 3 : sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
963 3 : if (sw_if_index != ~0)
964 : {
965 1 : flags |= NAT44_EI_SM_FLAG_SWITCH_ADDRESS;
966 : }
967 : else
968 : {
969 2 : memcpy (&addr.as_u8, mp->ip_address, 4);
970 : }
971 :
972 3 : vrf_id = clib_net_to_host_u32 (mp->vrf_id);
973 :
974 3 : if (mp->is_add)
975 : {
976 3 : mp->tag[sizeof (mp->tag) - 1] = 0;
977 3 : tag = format (0, "%s", mp->tag);
978 3 : vec_terminate_c_string (tag);
979 :
980 3 : rv = nat44_ei_add_static_mapping (addr, addr, port, port, proto, vrf_id,
981 : sw_if_index, flags, pool_addr, tag);
982 3 : vec_free (tag);
983 : }
984 : else
985 : {
986 0 : rv = nat44_ei_del_static_mapping (addr, addr, port, port, proto, vrf_id,
987 : sw_if_index, flags);
988 : }
989 :
990 3 : REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_IDENTITY_MAPPING_REPLY);
991 : }
992 :
993 : static void
994 3 : send_nat44_ei_identity_mapping_details (nat44_ei_static_mapping_t *m,
995 : int index, vl_api_registration_t *reg,
996 : u32 context)
997 : {
998 : vl_api_nat44_ei_identity_mapping_details_t *rmp;
999 3 : nat44_ei_main_t *nm = &nat44_ei_main;
1000 3 : nat44_ei_lb_addr_port_t *local = pool_elt_at_index (m->locals, index);
1001 :
1002 3 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1003 3 : clib_memset (rmp, 0, sizeof (*rmp));
1004 3 : rmp->_vl_msg_id =
1005 3 : ntohs (VL_API_NAT44_EI_IDENTITY_MAPPING_DETAILS + nm->msg_id_base);
1006 :
1007 3 : if (is_sm_addr_only (m->flags))
1008 2 : rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
1009 :
1010 3 : clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
1011 3 : rmp->port = m->local_port;
1012 3 : rmp->sw_if_index = ~0;
1013 3 : rmp->vrf_id = htonl (local->vrf_id);
1014 3 : rmp->protocol = nat_proto_to_ip_proto (m->proto);
1015 3 : rmp->context = context;
1016 3 : if (m->tag)
1017 3 : strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1018 :
1019 3 : vl_api_send_msg (reg, (u8 *) rmp);
1020 3 : }
1021 :
1022 : static void
1023 3 : send_nat44_ei_identity_map_resolve_details (nat44_ei_static_map_resolve_t *m,
1024 : vl_api_registration_t *reg,
1025 : u32 context)
1026 : {
1027 : vl_api_nat44_ei_identity_mapping_details_t *rmp;
1028 3 : nat44_ei_main_t *nm = &nat44_ei_main;
1029 3 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1030 3 : clib_memset (rmp, 0, sizeof (*rmp));
1031 3 : rmp->_vl_msg_id =
1032 3 : ntohs (VL_API_NAT44_EI_IDENTITY_MAPPING_DETAILS + nm->msg_id_base);
1033 :
1034 3 : if (is_sm_addr_only (m->flags))
1035 0 : rmp->flags = (vl_api_nat44_ei_config_flags_t) NAT44_EI_ADDR_ONLY_MAPPING;
1036 :
1037 3 : rmp->port = m->l_port;
1038 3 : rmp->sw_if_index = htonl (m->sw_if_index);
1039 3 : rmp->vrf_id = htonl (m->vrf_id);
1040 3 : rmp->protocol = nat_proto_to_ip_proto (m->proto);
1041 3 : rmp->context = context;
1042 3 : if (m->tag)
1043 3 : strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1044 :
1045 3 : vl_api_send_msg (reg, (u8 *) rmp);
1046 3 : }
1047 :
1048 : static void
1049 4 : vl_api_nat44_ei_identity_mapping_dump_t_handler (
1050 : vl_api_nat44_ei_identity_mapping_dump_t *mp)
1051 : {
1052 : vl_api_registration_t *reg;
1053 4 : nat44_ei_main_t *nm = &nat44_ei_main;
1054 : nat44_ei_static_mapping_t *m;
1055 : nat44_ei_static_map_resolve_t *rp;
1056 : int j;
1057 :
1058 4 : reg = vl_api_client_index_to_registration (mp->client_index);
1059 4 : if (!reg)
1060 0 : return;
1061 :
1062 6 : pool_foreach (m, nm->static_mappings)
1063 : {
1064 2 : if (is_sm_identity_nat (m->flags))
1065 : {
1066 5 : pool_foreach_index (j, m->locals)
1067 : {
1068 3 : send_nat44_ei_identity_mapping_details (m, j, reg, mp->context);
1069 : }
1070 : }
1071 : }
1072 :
1073 7 : for (j = 0; j < vec_len (nm->to_resolve); j++)
1074 : {
1075 3 : rp = nm->to_resolve + j;
1076 3 : if (is_sm_identity_nat (rp->flags))
1077 3 : send_nat44_ei_identity_map_resolve_details (rp, reg, mp->context);
1078 : }
1079 : }
1080 :
1081 : static void
1082 4 : vl_api_nat44_ei_add_del_interface_addr_t_handler (
1083 : vl_api_nat44_ei_add_del_interface_addr_t *mp)
1084 : {
1085 4 : nat44_ei_main_t *nm = &nat44_ei_main;
1086 : vl_api_nat44_ei_add_del_interface_addr_reply_t *rmp;
1087 4 : u32 sw_if_index = ntohl (mp->sw_if_index);
1088 4 : int rv = 0;
1089 :
1090 4 : VALIDATE_SW_IF_INDEX (mp);
1091 :
1092 4 : if (mp->is_add)
1093 : {
1094 4 : rv = nat44_ei_add_interface_address (sw_if_index);
1095 : }
1096 : else
1097 : {
1098 0 : rv = nat44_ei_del_interface_address (sw_if_index);
1099 : }
1100 :
1101 4 : BAD_SW_IF_INDEX_LABEL;
1102 4 : REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_INTERFACE_ADDR_REPLY);
1103 : }
1104 :
1105 : static void
1106 0 : send_nat44_ei_interface_addr_details (u32 sw_if_index,
1107 : vl_api_registration_t *reg, u32 context)
1108 : {
1109 : vl_api_nat44_ei_interface_addr_details_t *rmp;
1110 0 : nat44_ei_main_t *nm = &nat44_ei_main;
1111 :
1112 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1113 0 : clib_memset (rmp, 0, sizeof (*rmp));
1114 0 : rmp->_vl_msg_id =
1115 0 : ntohs (VL_API_NAT44_EI_INTERFACE_ADDR_DETAILS + nm->msg_id_base);
1116 0 : rmp->sw_if_index = ntohl (sw_if_index);
1117 0 : rmp->context = context;
1118 :
1119 0 : vl_api_send_msg (reg, (u8 *) rmp);
1120 0 : }
1121 :
1122 : static void
1123 0 : vl_api_nat44_ei_interface_addr_dump_t_handler (
1124 : vl_api_nat44_ei_interface_addr_dump_t *mp)
1125 : {
1126 : vl_api_registration_t *reg;
1127 0 : nat44_ei_main_t *nm = &nat44_ei_main;
1128 : u32 *i;
1129 :
1130 0 : reg = vl_api_client_index_to_registration (mp->client_index);
1131 0 : if (!reg)
1132 0 : return;
1133 :
1134 0 : vec_foreach (i, nm->auto_add_sw_if_indices)
1135 0 : send_nat44_ei_interface_addr_details (*i, reg, mp->context);
1136 : }
1137 :
1138 : static void
1139 6 : send_nat44_ei_user_details (nat44_ei_user_t *u, vl_api_registration_t *reg,
1140 : u32 context)
1141 : {
1142 : vl_api_nat44_ei_user_details_t *rmp;
1143 6 : nat44_ei_main_t *nm = &nat44_ei_main;
1144 6 : ip4_main_t *im = &ip4_main;
1145 :
1146 6 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1147 6 : clib_memset (rmp, 0, sizeof (*rmp));
1148 6 : rmp->_vl_msg_id = ntohs (VL_API_NAT44_EI_USER_DETAILS + nm->msg_id_base);
1149 :
1150 6 : if (!pool_is_free_index (im->fibs, u->fib_index))
1151 : {
1152 6 : fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1153 6 : rmp->vrf_id = ntohl (fib->ft_table_id);
1154 : }
1155 :
1156 6 : clib_memcpy (rmp->ip_address, &(u->addr), 4);
1157 6 : rmp->nsessions = ntohl (u->nsessions);
1158 6 : rmp->nstaticsessions = ntohl (u->nstaticsessions);
1159 6 : rmp->context = context;
1160 :
1161 6 : vl_api_send_msg (reg, (u8 *) rmp);
1162 6 : }
1163 :
1164 : static void
1165 5 : vl_api_nat44_ei_user_dump_t_handler (vl_api_nat44_ei_user_dump_t *mp)
1166 : {
1167 : vl_api_registration_t *reg;
1168 5 : nat44_ei_main_t *nm = &nat44_ei_main;
1169 : nat44_ei_main_per_thread_data_t *tnm;
1170 : nat44_ei_user_t *u;
1171 :
1172 5 : reg = vl_api_client_index_to_registration (mp->client_index);
1173 5 : if (!reg)
1174 0 : return;
1175 :
1176 10 : vec_foreach (tnm, nm->per_thread_data)
1177 : {
1178 11 : pool_foreach (u, tnm->users)
1179 : {
1180 6 : send_nat44_ei_user_details (u, reg, mp->context);
1181 : }
1182 : }
1183 : }
1184 :
1185 : static void
1186 28 : send_nat44_ei_user_session_details (nat44_ei_session_t *s,
1187 : vl_api_registration_t *reg, u32 context)
1188 : {
1189 : vl_api_nat44_ei_user_session_details_t *rmp;
1190 28 : nat44_ei_main_t *nm = &nat44_ei_main;
1191 :
1192 28 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1193 28 : clib_memset (rmp, 0, sizeof (*rmp));
1194 28 : rmp->_vl_msg_id =
1195 28 : ntohs (VL_API_NAT44_EI_USER_SESSION_DETAILS + nm->msg_id_base);
1196 28 : clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1197 28 : clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1198 :
1199 28 : if (nat44_ei_is_session_static (s))
1200 6 : rmp->flags |= NAT44_EI_STATIC_MAPPING;
1201 :
1202 28 : rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1203 28 : rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1204 28 : rmp->total_pkts = ntohl (s->total_pkts);
1205 28 : rmp->context = context;
1206 28 : if (nat44_ei_is_unk_proto_session (s))
1207 : {
1208 0 : rmp->outside_port = 0;
1209 0 : rmp->inside_port = 0;
1210 0 : rmp->protocol = ntohs (s->in2out.port);
1211 : }
1212 : else
1213 : {
1214 28 : rmp->outside_port = s->out2in.port;
1215 28 : rmp->inside_port = s->in2out.port;
1216 28 : rmp->protocol = ntohs (nat_proto_to_ip_proto (s->nat_proto));
1217 : }
1218 28 : vl_api_send_msg (reg, (u8 *) rmp);
1219 28 : }
1220 :
1221 : static void
1222 0 : send_nat44_ei_user_session_v2_details (nat44_ei_session_t *s,
1223 : vl_api_registration_t *reg, u32 context)
1224 : {
1225 : vl_api_nat44_ei_user_session_v2_details_t *rmp;
1226 0 : nat44_ei_main_t *nm = &nat44_ei_main;
1227 :
1228 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1229 0 : clib_memset (rmp, 0, sizeof (*rmp));
1230 0 : rmp->_vl_msg_id =
1231 0 : ntohs (VL_API_NAT44_EI_USER_SESSION_V2_DETAILS + nm->msg_id_base);
1232 0 : clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1233 0 : clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1234 :
1235 0 : if (nat44_ei_is_session_static (s))
1236 0 : rmp->flags |= NAT44_EI_STATIC_MAPPING;
1237 :
1238 0 : rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1239 0 : rmp->time_since_last_heard = clib_host_to_net_u64 (
1240 0 : (u64) (vlib_time_now (vlib_get_main ()) - s->last_heard));
1241 0 : rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1242 0 : rmp->total_pkts = ntohl (s->total_pkts);
1243 0 : rmp->context = context;
1244 0 : if (nat44_ei_is_unk_proto_session (s))
1245 : {
1246 0 : rmp->outside_port = 0;
1247 0 : rmp->inside_port = 0;
1248 0 : rmp->protocol = ntohs (s->in2out.port);
1249 : }
1250 : else
1251 : {
1252 0 : rmp->outside_port = s->out2in.port;
1253 0 : rmp->inside_port = s->in2out.port;
1254 0 : rmp->protocol = ntohs (nat_proto_to_ip_proto (s->nat_proto));
1255 : }
1256 0 : vl_api_send_msg (reg, (u8 *) rmp);
1257 0 : }
1258 :
1259 : static void
1260 13 : vl_api_nat44_ei_user_session_dump_t_handler (
1261 : vl_api_nat44_ei_user_session_dump_t *mp)
1262 : {
1263 : vl_api_registration_t *reg;
1264 13 : nat44_ei_main_t *nm = &nat44_ei_main;
1265 : nat44_ei_main_per_thread_data_t *tnm;
1266 : nat44_ei_session_t *s;
1267 : clib_bihash_kv_8_8_t key, value;
1268 : nat44_ei_user_key_t ukey;
1269 : nat44_ei_user_t *u;
1270 : u32 session_index, head_index, elt_index;
1271 : dlist_elt_t *head, *elt;
1272 : ip4_header_t ip;
1273 :
1274 13 : reg = vl_api_client_index_to_registration (mp->client_index);
1275 13 : if (!reg)
1276 2 : return;
1277 :
1278 13 : clib_memcpy (&ukey.addr, mp->ip_address, 4);
1279 13 : ip.src_address.as_u32 = ukey.addr.as_u32;
1280 13 : ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1281 13 : key.key = ukey.as_u64;
1282 13 : if (nm->num_workers > 1)
1283 0 : tnm = vec_elt_at_index (
1284 : nm->per_thread_data,
1285 : nat44_ei_get_in2out_worker_index (&ip, ukey.fib_index, 0));
1286 : else
1287 13 : tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
1288 :
1289 13 : if (clib_bihash_search_8_8 (&tnm->user_hash, &key, &value))
1290 2 : return;
1291 11 : u = pool_elt_at_index (tnm->users, value.value);
1292 11 : if (!u->nsessions && !u->nstaticsessions)
1293 0 : return;
1294 :
1295 11 : head_index = u->sessions_per_user_list_head_index;
1296 11 : head = pool_elt_at_index (tnm->list_pool, head_index);
1297 11 : elt_index = head->next;
1298 11 : elt = pool_elt_at_index (tnm->list_pool, elt_index);
1299 11 : session_index = elt->value;
1300 39 : while (session_index != ~0)
1301 : {
1302 28 : s = pool_elt_at_index (tnm->sessions, session_index);
1303 :
1304 28 : send_nat44_ei_user_session_details (s, reg, mp->context);
1305 :
1306 28 : elt_index = elt->next;
1307 28 : elt = pool_elt_at_index (tnm->list_pool, elt_index);
1308 28 : session_index = elt->value;
1309 : }
1310 : }
1311 :
1312 : static void
1313 0 : vl_api_nat44_ei_user_session_v2_dump_t_handler (
1314 : vl_api_nat44_ei_user_session_dump_t *mp)
1315 : {
1316 : vl_api_registration_t *reg;
1317 0 : nat44_ei_main_t *nm = &nat44_ei_main;
1318 : nat44_ei_main_per_thread_data_t *tnm;
1319 : nat44_ei_session_t *s;
1320 : clib_bihash_kv_8_8_t key, value;
1321 : nat44_ei_user_key_t ukey;
1322 : nat44_ei_user_t *u;
1323 : u32 session_index, head_index, elt_index;
1324 : dlist_elt_t *head, *elt;
1325 : ip4_header_t ip;
1326 :
1327 0 : reg = vl_api_client_index_to_registration (mp->client_index);
1328 0 : if (!reg)
1329 0 : return;
1330 :
1331 0 : clib_memcpy (&ukey.addr, mp->ip_address, 4);
1332 0 : ip.src_address.as_u32 = ukey.addr.as_u32;
1333 0 : ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1334 0 : key.key = ukey.as_u64;
1335 0 : if (nm->num_workers > 1)
1336 0 : tnm = vec_elt_at_index (
1337 : nm->per_thread_data,
1338 : nat44_ei_get_in2out_worker_index (&ip, ukey.fib_index, 0));
1339 : else
1340 0 : tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
1341 :
1342 0 : if (clib_bihash_search_8_8 (&tnm->user_hash, &key, &value))
1343 0 : return;
1344 0 : u = pool_elt_at_index (tnm->users, value.value);
1345 0 : if (!u->nsessions && !u->nstaticsessions)
1346 0 : return;
1347 :
1348 0 : head_index = u->sessions_per_user_list_head_index;
1349 0 : head = pool_elt_at_index (tnm->list_pool, head_index);
1350 0 : elt_index = head->next;
1351 0 : elt = pool_elt_at_index (tnm->list_pool, elt_index);
1352 0 : session_index = elt->value;
1353 0 : while (session_index != ~0)
1354 : {
1355 0 : s = pool_elt_at_index (tnm->sessions, session_index);
1356 :
1357 0 : send_nat44_ei_user_session_v2_details (s, reg, mp->context);
1358 :
1359 0 : elt_index = elt->next;
1360 0 : elt = pool_elt_at_index (tnm->list_pool, elt_index);
1361 0 : session_index = elt->value;
1362 : }
1363 : }
1364 :
1365 : static void
1366 4 : vl_api_nat44_ei_del_session_t_handler (vl_api_nat44_ei_del_session_t *mp)
1367 : {
1368 4 : nat44_ei_main_t *nm = &nat44_ei_main;
1369 : vl_api_nat44_ei_del_session_reply_t *rmp;
1370 : ip4_address_t addr, eh_addr;
1371 : u16 port;
1372 : u32 vrf_id;
1373 4 : int rv = 0;
1374 : u8 is_in;
1375 : nat_protocol_t proto;
1376 :
1377 4 : memcpy (&addr.as_u8, mp->address, 4);
1378 4 : port = mp->port;
1379 4 : vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1380 4 : proto = ip_proto_to_nat_proto (mp->protocol);
1381 4 : memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1382 :
1383 : // is session inside ?
1384 4 : is_in = mp->flags & NAT44_EI_IF_INSIDE;
1385 :
1386 4 : rv = nat44_ei_del_session (nm, &addr, port, proto, vrf_id, is_in);
1387 :
1388 4 : REPLY_MACRO (VL_API_NAT44_EI_DEL_SESSION_REPLY);
1389 : }
1390 :
1391 : static void
1392 3 : vl_api_nat44_ei_forwarding_enable_disable_t_handler (
1393 : vl_api_nat44_ei_forwarding_enable_disable_t *mp)
1394 : {
1395 3 : nat44_ei_main_t *nm = &nat44_ei_main;
1396 : vl_api_nat44_ei_forwarding_enable_disable_reply_t *rmp;
1397 3 : int rv = 0;
1398 3 : u32 *ses_to_be_removed = 0, *ses_index;
1399 : nat44_ei_main_per_thread_data_t *tnm;
1400 : nat44_ei_session_t *s;
1401 :
1402 3 : nm->forwarding_enabled = mp->enable != 0;
1403 :
1404 3 : if (mp->enable == 0)
1405 : {
1406 2 : vec_foreach (tnm, nm->per_thread_data)
1407 : {
1408 1 : vec_foreach (ses_index, ses_to_be_removed)
1409 : {
1410 0 : s = pool_elt_at_index (tnm->sessions, ses_index[0]);
1411 0 : nat44_ei_free_session_data (nm, s, tnm - nm->per_thread_data, 0);
1412 0 : nat44_ei_delete_session (nm, s, tnm - nm->per_thread_data);
1413 : }
1414 :
1415 1 : vec_free (ses_to_be_removed);
1416 : }
1417 : }
1418 :
1419 3 : REPLY_MACRO (VL_API_NAT44_EI_FORWARDING_ENABLE_DISABLE_REPLY);
1420 : }
1421 :
1422 : static void
1423 1 : vl_api_nat44_ei_set_fq_options_t_handler (vl_api_nat44_ei_set_fq_options_t *mp)
1424 : {
1425 1 : nat44_ei_main_t *nm = &nat44_ei_main;
1426 : vl_api_nat44_ei_set_fq_options_reply_t *rmp;
1427 1 : int rv = 0;
1428 1 : u32 frame_queue_nelts = ntohl (mp->frame_queue_nelts);
1429 1 : rv = nat44_ei_set_frame_queue_nelts (frame_queue_nelts);
1430 1 : REPLY_MACRO (VL_API_NAT44_EI_SET_FQ_OPTIONS_REPLY);
1431 : }
1432 :
1433 : static void
1434 1 : vl_api_nat44_ei_show_fq_options_t_handler (
1435 : vl_api_nat44_ei_show_fq_options_t *mp)
1436 : {
1437 1 : nat44_ei_main_t *nm = &nat44_ei_main;
1438 : vl_api_nat44_ei_show_fq_options_reply_t *rmp;
1439 1 : int rv = 0;
1440 : /* clang-format off */
1441 1 : REPLY_MACRO2_ZERO (VL_API_NAT44_EI_SHOW_FQ_OPTIONS_REPLY,
1442 : ({
1443 : rmp->frame_queue_nelts = htonl (nm->frame_queue_nelts);
1444 : }));
1445 : /* clang-format on */
1446 : }
1447 :
1448 : /* API definitions */
1449 : #include <vnet/format_fns.h>
1450 : #include <nat/nat44-ei/nat44_ei.api.c>
1451 :
1452 : /* Set up the API message handling tables */
1453 : clib_error_t *
1454 575 : nat44_ei_api_hookup (vlib_main_t *vm)
1455 : {
1456 575 : nat44_ei_main_t *nm = &nat44_ei_main;
1457 575 : nm->msg_id_base = setup_message_id_table ();
1458 575 : return 0;
1459 : }
1460 :
1461 : /*
1462 : * fd.io coding-style-patch-verification: ON
1463 : *
1464 : * Local Variables:
1465 : * eval: (c-set-style "gnu")
1466 : * End:
1467 : */
|