638f576c354daf4e7d7558dc534fa0fa6fba1b82
[vpp.git] / src / plugins / snat / snat_api.c
1 /*
2  * Copyright (c) 2017 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  * @file
18  * @brief SNAT plugin API implementation
19  */
20
21 #include <snat/snat.h>
22 #include <snat/snat_det.h>
23 #include <snat/nat64.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vlibsocket/api.h>
27 #include <snat/snat_msg_enum.h>
28 #include <vnet/fib/fib_table.h>
29
30 /* define message structures */
31 #define vl_typedefs
32 #include <snat/snat_all_api_h.h>
33 #undef vl_typedefs
34
35 /* define generated endian-swappers */
36 #define vl_endianfun
37 #include <snat/snat_all_api_h.h>
38 #undef vl_endianfun
39
40 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
41
42 #define REPLY_MSG_ID_BASE sm->msg_id_base
43 #include <vlibapi/api_helper_macros.h>
44
45 /* Get the API version number */
46 #define vl_api_version(n,v) static u32 api_version=(v);
47 #include <snat/snat_all_api_h.h>
48 #undef vl_api_version
49
50 /* Macro to finish up custom dump fns */
51 #define FINISH                                  \
52     vec_add1 (s, 0);                            \
53     vl_print (handle, (char *)s);               \
54     vec_free (s);                               \
55     return handle;
56
57 static void
58   vl_api_snat_add_address_range_t_handler
59   (vl_api_snat_add_address_range_t * mp)
60 {
61   snat_main_t *sm = &snat_main;
62   vl_api_snat_add_address_range_reply_t *rmp;
63   ip4_address_t this_addr;
64   u32 start_host_order, end_host_order;
65   u32 vrf_id;
66   int i, count;
67   int rv = 0;
68   u32 *tmp;
69
70   if (mp->is_ip4 != 1)
71     {
72       rv = VNET_API_ERROR_UNIMPLEMENTED;
73       goto send_reply;
74     }
75
76   if (sm->static_mapping_only)
77     {
78       rv = VNET_API_ERROR_FEATURE_DISABLED;
79       goto send_reply;
80     }
81
82   tmp = (u32 *) mp->first_ip_address;
83   start_host_order = clib_host_to_net_u32 (tmp[0]);
84   tmp = (u32 *) mp->last_ip_address;
85   end_host_order = clib_host_to_net_u32 (tmp[0]);
86
87   count = (end_host_order - start_host_order) + 1;
88
89   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
90
91   if (count > 1024)
92     clib_warning ("%U - %U, %d addresses...",
93                   format_ip4_address, mp->first_ip_address,
94                   format_ip4_address, mp->last_ip_address, count);
95
96   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
97
98   for (i = 0; i < count; i++)
99     {
100       if (mp->is_add)
101         snat_add_address (sm, &this_addr, vrf_id);
102       else
103         rv = snat_del_address (sm, this_addr, 0);
104
105       if (rv)
106         goto send_reply;
107
108       increment_v4_address (&this_addr);
109     }
110
111 send_reply:
112   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
113 }
114
115 static void *vl_api_snat_add_address_range_t_print
116   (vl_api_snat_add_address_range_t * mp, void *handle)
117 {
118   u8 *s;
119
120   s = format (0, "SCRIPT: snat_add_address_range ");
121   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
122   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
123     {
124       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
125     }
126   FINISH;
127 }
128
129 static void
130   send_snat_address_details
131   (snat_address_t * a, unix_shared_memory_queue_t * q, u32 context)
132 {
133   vl_api_snat_address_details_t *rmp;
134   snat_main_t *sm = &snat_main;
135
136   rmp = vl_msg_api_alloc (sizeof (*rmp));
137   memset (rmp, 0, sizeof (*rmp));
138   rmp->_vl_msg_id = ntohs (VL_API_SNAT_ADDRESS_DETAILS + sm->msg_id_base);
139   rmp->is_ip4 = 1;
140   clib_memcpy (rmp->ip_address, &(a->addr), 4);
141   if (a->fib_index != ~0)
142     {
143       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
144       rmp->vrf_id = ntohl (fib->ft_table_id);
145     }
146   else
147     rmp->vrf_id = ~0;
148   rmp->context = context;
149
150   vl_msg_api_send_shmem (q, (u8 *) & rmp);
151 }
152
153 static void
154 vl_api_snat_address_dump_t_handler (vl_api_snat_address_dump_t * mp)
155 {
156   unix_shared_memory_queue_t *q;
157   snat_main_t *sm = &snat_main;
158   snat_address_t *a;
159
160   q = vl_api_client_index_to_input_queue (mp->client_index);
161   if (q == 0)
162     return;
163
164   /* *INDENT-OFF* */
165   vec_foreach (a, sm->addresses)
166     send_snat_address_details (a, q, mp->context);
167   /* *INDENT-ON* */
168 }
169
170 static void *vl_api_snat_address_dump_t_print
171   (vl_api_snat_address_dump_t * mp, void *handle)
172 {
173   u8 *s;
174
175   s = format (0, "SCRIPT: snat_address_dump ");
176
177   FINISH;
178 }
179
180 static void
181   vl_api_snat_interface_add_del_feature_t_handler
182   (vl_api_snat_interface_add_del_feature_t * mp)
183 {
184   snat_main_t *sm = &snat_main;
185   vl_api_snat_interface_add_del_feature_reply_t *rmp;
186   u8 is_del = mp->is_add == 0;
187   u32 sw_if_index = ntohl (mp->sw_if_index);
188   int rv = 0;
189
190   VALIDATE_SW_IF_INDEX (mp);
191
192   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
193
194   BAD_SW_IF_INDEX_LABEL;
195
196   REPLY_MACRO (VL_API_SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY);
197 }
198
199 static void *vl_api_snat_interface_add_del_feature_t_print
200   (vl_api_snat_interface_add_del_feature_t * mp, void *handle)
201 {
202   u8 *s;
203
204   s = format (0, "SCRIPT: snat_interface_add_del_feature ");
205   s = format (s, "sw_if_index %d %s %s",
206               clib_host_to_net_u32 (mp->sw_if_index),
207               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
208
209   FINISH;
210 }
211
212 static void
213   send_snat_interface_details
214   (snat_interface_t * i, unix_shared_memory_queue_t * q, u32 context)
215 {
216   vl_api_snat_interface_details_t *rmp;
217   snat_main_t *sm = &snat_main;
218
219   rmp = vl_msg_api_alloc (sizeof (*rmp));
220   memset (rmp, 0, sizeof (*rmp));
221   rmp->_vl_msg_id = ntohs (VL_API_SNAT_INTERFACE_DETAILS + sm->msg_id_base);
222   rmp->sw_if_index = ntohl (i->sw_if_index);
223   rmp->is_inside = i->is_inside;
224   rmp->context = context;
225
226   vl_msg_api_send_shmem (q, (u8 *) & rmp);
227 }
228
229 static void
230 vl_api_snat_interface_dump_t_handler (vl_api_snat_interface_dump_t * mp)
231 {
232   unix_shared_memory_queue_t *q;
233   snat_main_t *sm = &snat_main;
234   snat_interface_t *i;
235
236   q = vl_api_client_index_to_input_queue (mp->client_index);
237   if (q == 0)
238     return;
239
240   /* *INDENT-OFF* */
241   pool_foreach (i, sm->interfaces,
242   ({
243     send_snat_interface_details(i, q, mp->context);
244   }));
245   /* *INDENT-ON* */
246 }
247
248 static void *vl_api_snat_interface_dump_t_print
249   (vl_api_snat_interface_dump_t * mp, void *handle)
250 {
251   u8 *s;
252
253   s = format (0, "SCRIPT: snat_interface_dump ");
254
255   FINISH;
256 } static void
257   vl_api_snat_add_static_mapping_t_handler
258   (vl_api_snat_add_static_mapping_t * mp)
259 {
260   snat_main_t *sm = &snat_main;
261   vl_api_snat_add_static_mapping_reply_t *rmp;
262   ip4_address_t local_addr, external_addr;
263   u16 local_port = 0, external_port = 0;
264   u32 vrf_id, external_sw_if_index;
265   int rv = 0;
266   snat_protocol_t proto;
267
268   if (mp->is_ip4 != 1)
269     {
270       rv = VNET_API_ERROR_UNIMPLEMENTED;
271       goto send_reply;
272     }
273
274   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
275   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
276   if (mp->addr_only == 0)
277     {
278       local_port = clib_net_to_host_u16 (mp->local_port);
279       external_port = clib_net_to_host_u16 (mp->external_port);
280     }
281   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
282   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
283   proto = ip_proto_to_snat_proto (mp->protocol);
284
285   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
286                                 external_port, vrf_id, mp->addr_only,
287                                 external_sw_if_index, proto, mp->is_add);
288
289 send_reply:
290   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
291 }
292
293 static void *vl_api_snat_add_static_mapping_t_print
294   (vl_api_snat_add_static_mapping_t * mp, void *handle)
295 {
296   u8 *s;
297
298   s = format (0, "SCRIPT: snat_add_static_mapping ");
299   s = format (s, "protocol %d local_addr %U external_addr %U ",
300               mp->protocol,
301               format_ip4_address, mp->local_ip_address,
302               format_ip4_address, mp->external_ip_address);
303
304   if (mp->addr_only == 0)
305     s = format (s, "local_port %d external_port %d ",
306                 clib_net_to_host_u16 (mp->local_port),
307                 clib_net_to_host_u16 (mp->external_port));
308
309   if (mp->vrf_id != ~0)
310     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
311
312   if (mp->external_sw_if_index != ~0)
313     s = format (s, "external_sw_if_index %d",
314                 clib_net_to_host_u32 (mp->external_sw_if_index));
315   FINISH;
316 }
317
318 static void
319   send_snat_static_mapping_details
320   (snat_static_mapping_t * m, unix_shared_memory_queue_t * q, u32 context)
321 {
322   vl_api_snat_static_mapping_details_t *rmp;
323   snat_main_t *sm = &snat_main;
324
325   rmp = vl_msg_api_alloc (sizeof (*rmp));
326   memset (rmp, 0, sizeof (*rmp));
327   rmp->_vl_msg_id =
328     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
329   rmp->is_ip4 = 1;
330   rmp->addr_only = m->addr_only;
331   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
332   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
333   rmp->local_port = htons (m->local_port);
334   rmp->external_port = htons (m->external_port);
335   rmp->external_sw_if_index = ~0;
336   rmp->vrf_id = htonl (m->vrf_id);
337   rmp->protocol = snat_proto_to_ip_proto (m->proto);
338   rmp->context = context;
339
340   vl_msg_api_send_shmem (q, (u8 *) & rmp);
341 }
342
343 static void
344   send_snat_static_map_resolve_details
345   (snat_static_map_resolve_t * m, unix_shared_memory_queue_t * q, u32 context)
346 {
347   vl_api_snat_static_mapping_details_t *rmp;
348   snat_main_t *sm = &snat_main;
349
350   rmp = vl_msg_api_alloc (sizeof (*rmp));
351   memset (rmp, 0, sizeof (*rmp));
352   rmp->_vl_msg_id =
353     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
354   rmp->is_ip4 = 1;
355   rmp->addr_only = m->addr_only;
356   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
357   rmp->local_port = htons (m->l_port);
358   rmp->external_port = htons (m->e_port);
359   rmp->external_sw_if_index = htonl (m->sw_if_index);
360   rmp->vrf_id = htonl (m->vrf_id);
361   rmp->protocol = snat_proto_to_ip_proto (m->proto);
362   rmp->context = context;
363
364   vl_msg_api_send_shmem (q, (u8 *) & rmp);
365 }
366
367 static void
368   vl_api_snat_static_mapping_dump_t_handler
369   (vl_api_snat_static_mapping_dump_t * mp)
370 {
371   unix_shared_memory_queue_t *q;
372   snat_main_t *sm = &snat_main;
373   snat_static_mapping_t *m;
374   snat_static_map_resolve_t *rp;
375   int j;
376
377   q = vl_api_client_index_to_input_queue (mp->client_index);
378   if (q == 0)
379     return;
380
381   /* *INDENT-OFF* */
382   pool_foreach (m, sm->static_mappings,
383   ({
384       send_snat_static_mapping_details (m, q, mp->context);
385   }));
386   /* *INDENT-ON* */
387
388   for (j = 0; j < vec_len (sm->to_resolve); j++)
389     {
390       rp = sm->to_resolve + j;
391       send_snat_static_map_resolve_details (rp, q, mp->context);
392     }
393 }
394
395 static void *vl_api_snat_static_mapping_dump_t_print
396   (vl_api_snat_static_mapping_dump_t * mp, void *handle)
397 {
398   u8 *s;
399
400   s = format (0, "SCRIPT: snat_static_mapping_dump ");
401
402   FINISH;
403 }
404
405 static void
406 vl_api_snat_control_ping_t_handler (vl_api_snat_control_ping_t * mp)
407 {
408   vl_api_snat_control_ping_reply_t *rmp;
409   snat_main_t *sm = &snat_main;
410   int rv = 0;
411
412   /* *INDENT-OFF* */
413   REPLY_MACRO2 (VL_API_SNAT_CONTROL_PING_REPLY,
414   ({
415     rmp->vpe_pid = ntohl (getpid ());
416   }));
417   /* *INDENT-ON* */
418 }
419
420 static void *vl_api_snat_control_ping_t_print
421   (vl_api_snat_control_ping_t * mp, void *handle)
422 {
423   u8 *s;
424
425   s = format (0, "SCRIPT: snat_control_ping ");
426
427   FINISH;
428 }
429
430 static void
431 vl_api_snat_show_config_t_handler (vl_api_snat_show_config_t * mp)
432 {
433   vl_api_snat_show_config_reply_t *rmp;
434   snat_main_t *sm = &snat_main;
435   int rv = 0;
436
437   /* *INDENT-OFF* */
438   REPLY_MACRO2 (VL_API_SNAT_SHOW_CONFIG_REPLY,
439   ({
440     rmp->translation_buckets = htonl (sm->translation_buckets);
441     rmp->translation_memory_size = htonl (sm->translation_memory_size);
442     rmp->user_buckets = htonl (sm->user_buckets);
443     rmp->user_memory_size = htonl (sm->user_memory_size);
444     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
445     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
446     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
447     rmp->static_mapping_only = sm->static_mapping_only;
448     rmp->static_mapping_connection_tracking =
449       sm->static_mapping_connection_tracking;
450     rmp->deterministic = sm->deterministic;
451   }));
452   /* *INDENT-ON* */
453 }
454
455 static void *vl_api_snat_show_config_t_print
456   (vl_api_snat_show_config_t * mp, void *handle)
457 {
458   u8 *s;
459
460   s = format (0, "SCRIPT: snat_show_config ");
461
462   FINISH;
463 }
464
465 static void
466 vl_api_snat_set_workers_t_handler (vl_api_snat_set_workers_t * mp)
467 {
468   snat_main_t *sm = &snat_main;
469   vl_api_snat_set_workers_reply_t *rmp;
470   int rv = 0;
471   uword *bitmap = 0;
472   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
473
474   if (sm->num_workers < 2)
475     {
476       rv = VNET_API_ERROR_FEATURE_DISABLED;
477       goto send_reply;
478     }
479
480   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
481   rv = snat_set_workers (bitmap);
482   clib_bitmap_free (bitmap);
483
484 send_reply:
485   REPLY_MACRO (VL_API_SNAT_SET_WORKERS_REPLY);
486 }
487
488 static void *vl_api_snat_set_workers_t_print
489   (vl_api_snat_set_workers_t * mp, void *handle)
490 {
491   u8 *s;
492   uword *bitmap = 0;
493   u8 first = 1;
494   int i;
495   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
496
497   s = format (0, "SCRIPT: snat_set_workers ");
498   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
499   /* *INDENT-OFF* */
500   clib_bitmap_foreach (i, bitmap,
501     ({
502       if (first)
503         s = format (s, "%d", i);
504       else
505         s = format (s, ",%d", i);
506       first = 0;
507     }));
508   /* *INDENT-ON* */
509   clib_bitmap_free (bitmap);
510   FINISH;
511 }
512
513 static void
514   send_snat_worker_details
515   (u32 worker_index, unix_shared_memory_queue_t * q, u32 context)
516 {
517   vl_api_snat_worker_details_t *rmp;
518   snat_main_t *sm = &snat_main;
519   vlib_worker_thread_t *w =
520     vlib_worker_threads + worker_index + sm->first_worker_index;
521
522   rmp = vl_msg_api_alloc (sizeof (*rmp));
523   memset (rmp, 0, sizeof (*rmp));
524   rmp->_vl_msg_id = ntohs (VL_API_SNAT_WORKER_DETAILS + sm->msg_id_base);
525   rmp->context = context;
526   rmp->worker_index = htonl (worker_index);
527   rmp->lcore_id = htonl (w->lcore_id);
528   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
529
530   vl_msg_api_send_shmem (q, (u8 *) & rmp);
531 }
532
533 static void
534 vl_api_snat_worker_dump_t_handler (vl_api_snat_worker_dump_t * mp)
535 {
536   unix_shared_memory_queue_t *q;
537   snat_main_t *sm = &snat_main;
538   u32 *worker_index;
539
540   q = vl_api_client_index_to_input_queue (mp->client_index);
541   if (q == 0)
542     return;
543
544   /* *INDENT-OFF* */
545   vec_foreach (worker_index, sm->workers)
546     send_snat_worker_details(*worker_index, q, mp->context);
547   /* *INDENT-ON* */
548 }
549
550 static void *vl_api_snat_worker_dump_t_print
551   (vl_api_snat_worker_dump_t * mp, void *handle)
552 {
553   u8 *s;
554
555   s = format (0, "SCRIPT: snat_worker_dump ");
556
557   FINISH;
558 }
559
560 static void
561   vl_api_snat_add_del_interface_addr_t_handler
562   (vl_api_snat_add_del_interface_addr_t * mp)
563 {
564   snat_main_t *sm = &snat_main;
565   vl_api_snat_add_del_interface_addr_reply_t *rmp;
566   u8 is_del = mp->is_add == 0;
567   u32 sw_if_index = ntohl (mp->sw_if_index);
568   int rv = 0;
569
570   VALIDATE_SW_IF_INDEX (mp);
571
572   rv = snat_add_interface_address (sm, sw_if_index, is_del);
573
574   BAD_SW_IF_INDEX_LABEL;
575
576   REPLY_MACRO (VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
577 }
578
579 static void *vl_api_snat_add_del_interface_addr_t_print
580   (vl_api_snat_add_del_interface_addr_t * mp, void *handle)
581 {
582   u8 *s;
583
584   s = format (0, "SCRIPT: snat_add_del_interface_addr ");
585   s = format (s, "sw_if_index %d %s",
586               clib_host_to_net_u32 (mp->sw_if_index),
587               mp->is_add ? "" : "del");
588
589   FINISH;
590 }
591
592 static void
593   send_snat_interface_addr_details
594   (u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
595 {
596   vl_api_snat_interface_addr_details_t *rmp;
597   snat_main_t *sm = &snat_main;
598
599   rmp = vl_msg_api_alloc (sizeof (*rmp));
600   memset (rmp, 0, sizeof (*rmp));
601   rmp->_vl_msg_id =
602     ntohs (VL_API_SNAT_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
603   rmp->sw_if_index = ntohl (sw_if_index);
604   rmp->context = context;
605
606   vl_msg_api_send_shmem (q, (u8 *) & rmp);
607 }
608
609 static void
610   vl_api_snat_interface_addr_dump_t_handler
611   (vl_api_snat_interface_addr_dump_t * mp)
612 {
613   unix_shared_memory_queue_t *q;
614   snat_main_t *sm = &snat_main;
615   u32 *i;
616
617   q = vl_api_client_index_to_input_queue (mp->client_index);
618   if (q == 0)
619     return;
620
621   /* *INDENT-OFF* */
622   vec_foreach (i, sm->auto_add_sw_if_indices)
623     send_snat_interface_addr_details(*i, q, mp->context);
624   /* *INDENT-ON* */
625 }
626
627 static void *vl_api_snat_interface_addr_dump_t_print
628   (vl_api_snat_interface_addr_dump_t * mp, void *handle)
629 {
630   u8 *s;
631
632   s = format (0, "SCRIPT: snat_interface_addr_dump ");
633
634   FINISH;
635 }
636
637 static void
638   vl_api_snat_ipfix_enable_disable_t_handler
639   (vl_api_snat_ipfix_enable_disable_t * mp)
640 {
641   snat_main_t *sm = &snat_main;
642   vl_api_snat_ipfix_enable_disable_reply_t *rmp;
643   int rv = 0;
644
645   rv = snat_ipfix_logging_enable_disable (mp->enable,
646                                           clib_host_to_net_u32
647                                           (mp->domain_id),
648                                           clib_host_to_net_u16
649                                           (mp->src_port));
650
651   REPLY_MACRO (VL_API_SNAT_IPFIX_ENABLE_DISABLE_REPLY);
652 }
653
654 static void *vl_api_snat_ipfix_enable_disable_t_print
655   (vl_api_snat_ipfix_enable_disable_t * mp, void *handle)
656 {
657   u8 *s;
658
659   s = format (0, "SCRIPT: snat_ipfix_enable_disable ");
660   if (mp->domain_id)
661     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
662   if (mp->src_port)
663     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
664   if (!mp->enable)
665     s = format (s, "disable ");
666
667   FINISH;
668 }
669
670 static void
671   send_snat_user_details
672   (snat_user_t * u, unix_shared_memory_queue_t * q, u32 context)
673 {
674   vl_api_snat_user_details_t *rmp;
675   snat_main_t *sm = &snat_main;
676   fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
677
678   rmp = vl_msg_api_alloc (sizeof (*rmp));
679   memset (rmp, 0, sizeof (*rmp));
680   rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS + sm->msg_id_base);
681
682   rmp->vrf_id = ntohl (fib->ft_table_id);
683
684   rmp->is_ip4 = 1;
685   clib_memcpy (rmp->ip_address, &(u->addr), 4);
686   rmp->nsessions = ntohl (u->nsessions);
687   rmp->nstaticsessions = ntohl (u->nstaticsessions);
688   rmp->context = context;
689
690   vl_msg_api_send_shmem (q, (u8 *) & rmp);
691 }
692
693 static void
694 vl_api_snat_user_dump_t_handler (vl_api_snat_user_dump_t * mp)
695 {
696   unix_shared_memory_queue_t *q;
697   snat_main_t *sm = &snat_main;
698   snat_main_per_thread_data_t *tsm;
699   snat_user_t *u;
700
701   q = vl_api_client_index_to_input_queue (mp->client_index);
702   if (q == 0)
703     return;
704
705   /* *INDENT-OFF* */
706   vec_foreach (tsm, sm->per_thread_data)
707     vec_foreach (u, tsm->users)
708       send_snat_user_details (u, q, mp->context);
709   /* *INDENT-ON* */
710 }
711
712 static void *vl_api_snat_user_dump_t_print
713   (vl_api_snat_user_dump_t * mp, void *handle)
714 {
715   u8 *s;
716
717   s = format (0, "SCRIPT: snat_user_dump ");
718
719   FINISH;
720 }
721
722 static void
723   send_snat_user_session_details
724   (snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
725 {
726   vl_api_snat_user_session_details_t *rmp;
727   snat_main_t *sm = &snat_main;
728
729   rmp = vl_msg_api_alloc (sizeof (*rmp));
730   memset (rmp, 0, sizeof (*rmp));
731   rmp->_vl_msg_id =
732     ntohs (VL_API_SNAT_USER_SESSION_DETAILS + sm->msg_id_base);
733   rmp->is_ip4 = 1;
734   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
735   rmp->outside_port = s->out2in.port;
736   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
737   rmp->inside_port = s->in2out.port;
738   rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
739   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
740   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
741   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
742   rmp->total_pkts = ntohl (s->total_pkts);
743   rmp->context = context;
744
745   vl_msg_api_send_shmem (q, (u8 *) & rmp);
746 }
747
748 static void
749   vl_api_snat_user_session_dump_t_handler
750   (vl_api_snat_user_session_dump_t * mp)
751 {
752   unix_shared_memory_queue_t *q;
753   snat_main_t *sm = &snat_main;
754   snat_main_per_thread_data_t *tsm;
755   snat_session_t *s;
756   clib_bihash_kv_8_8_t key, value;
757   snat_user_key_t ukey;
758   snat_user_t *u;
759   u32 session_index, head_index, elt_index;
760   dlist_elt_t *head, *elt;
761
762   q = vl_api_client_index_to_input_queue (mp->client_index);
763   if (q == 0)
764     return;
765   if (!mp->is_ip4)
766     return;
767
768   clib_memcpy (&ukey.addr, mp->ip_address, 4);
769   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
770   key.key = ukey.as_u64;
771   if (!clib_bihash_search_8_8 (&sm->worker_by_in, &key, &value))
772     tsm = vec_elt_at_index (sm->per_thread_data, value.value);
773   else
774     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
775   if (clib_bihash_search_8_8 (&sm->user_hash, &key, &value))
776     return;
777   u = pool_elt_at_index (tsm->users, value.value);
778   if (!u->nsessions && !u->nstaticsessions)
779     return;
780
781   head_index = u->sessions_per_user_list_head_index;
782   head = pool_elt_at_index (tsm->list_pool, head_index);
783   elt_index = head->next;
784   elt = pool_elt_at_index (tsm->list_pool, elt_index);
785   session_index = elt->value;
786   while (session_index != ~0)
787     {
788       s = pool_elt_at_index (tsm->sessions, session_index);
789
790       send_snat_user_session_details (s, q, mp->context);
791
792       elt_index = elt->next;
793       elt = pool_elt_at_index (tsm->list_pool, elt_index);
794       session_index = elt->value;
795     }
796 }
797
798 static void *vl_api_snat_user_session_dump_t_print
799   (vl_api_snat_user_session_dump_t * mp, void *handle)
800 {
801   u8 *s;
802
803   s = format (0, "SCRIPT: snat_user_session_dump ");
804   s = format (s, "ip_address %U vrf_id %d\n",
805               format_ip4_address, mp->ip_address,
806               clib_net_to_host_u32 (mp->vrf_id));
807
808   FINISH;
809 }
810
811 /****************************/
812 /*** detrministic NAT/CGN ***/
813 /****************************/
814
815 static void
816 vl_api_snat_add_det_map_t_handler (vl_api_snat_add_det_map_t * mp)
817 {
818   snat_main_t *sm = &snat_main;
819   vl_api_snat_add_det_map_reply_t *rmp;
820   int rv = 0;
821   ip4_address_t in_addr, out_addr;
822
823   clib_memcpy (&in_addr, mp->in_addr, 4);
824   clib_memcpy (&out_addr, mp->out_addr, 4);
825   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
826                          mp->out_plen, mp->is_add);
827
828   REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
829 }
830
831 static void *vl_api_snat_add_det_map_t_print
832   (vl_api_snat_add_det_map_t * mp, void *handle)
833 {
834   u8 *s;
835
836   s = format (0, "SCRIPT: snat_add_det_map ");
837   s = format (s, "inside address %U/%d outside address %U/%d\n",
838               format_ip4_address, mp->in_addr, mp->in_plen,
839               format_ip4_address, mp->out_addr, mp->out_plen);
840
841   FINISH;
842 }
843
844 static void
845 vl_api_snat_det_forward_t_handler (vl_api_snat_det_forward_t * mp)
846 {
847   snat_main_t *sm = &snat_main;
848   vl_api_snat_det_forward_reply_t *rmp;
849   int rv = 0;
850   u16 lo_port = 0, hi_port = 0;
851   snat_det_map_t *dm;
852   ip4_address_t in_addr, out_addr;
853
854   out_addr.as_u32 = 0;
855   clib_memcpy (&in_addr, mp->in_addr, 4);
856   dm = snat_det_map_by_user (sm, &in_addr);
857   if (!dm)
858     {
859       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
860       goto send_reply;
861     }
862
863   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
864   hi_port = lo_port + dm->ports_per_host - 1;
865
866 send_reply:
867   /* *INDENT-OFF* */
868   REPLY_MACRO2 (VL_API_SNAT_DET_FORWARD_REPLY,
869   ({
870     rmp->out_port_lo = ntohs (lo_port);
871     rmp->out_port_hi = ntohs (hi_port);
872     rmp->is_ip4 = 1;
873     memset (rmp->out_addr, 0, 16);
874     clib_memcpy (rmp->out_addr, &out_addr, 4);
875   }))
876   /* *INDENT-ON* */
877 }
878
879 static void *vl_api_snat_det_forward_t_print
880   (vl_api_snat_det_forward_t * mp, void *handle)
881 {
882   u8 *s;
883
884   s = format (0, "SCRIPT: smat_det_forward_t");
885   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
886
887   FINISH;
888 }
889
890 static void
891 vl_api_snat_det_reverse_t_handler (vl_api_snat_det_reverse_t * mp)
892 {
893   snat_main_t *sm = &snat_main;
894   vl_api_snat_det_reverse_reply_t *rmp;
895   int rv = 0;
896   ip4_address_t out_addr, in_addr;
897   snat_det_map_t *dm;
898
899   in_addr.as_u32 = 0;
900   clib_memcpy (&out_addr, mp->out_addr, 4);
901   dm = snat_det_map_by_out (sm, &out_addr);
902   if (!dm)
903     {
904       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
905       goto send_reply;
906     }
907
908   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
909
910 send_reply:
911   /* *INDENT-OFF* */
912   REPLY_MACRO2 (VL_API_SNAT_DET_REVERSE_REPLY,
913   ({
914     rmp->is_ip4 = 1;
915     memset (rmp->in_addr, 0, 16);
916     clib_memcpy (rmp->in_addr, &in_addr, 4);
917   }))
918   /* *INDENT-ON* */
919 }
920
921 static void *vl_api_snat_det_reverse_t_print
922   (vl_api_snat_det_reverse_t * mp, void *handle)
923 {
924   u8 *s;
925
926   s = format (0, "SCRIPT: smat_det_reverse_t");
927   s = format (s, "outside ip address %U outside port %d",
928               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
929
930   FINISH;
931 }
932
933 static void
934   sent_snat_det_map_details
935   (snat_det_map_t * m, unix_shared_memory_queue_t * q, u32 context)
936 {
937   vl_api_snat_det_map_details_t *rmp;
938   snat_main_t *sm = &snat_main;
939
940   rmp = vl_msg_api_alloc (sizeof (*rmp));
941   memset (rmp, 0, sizeof (*rmp));
942   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS + sm->msg_id_base);
943   rmp->is_ip4 = 1;
944   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
945   rmp->in_plen = m->in_plen;
946   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
947   rmp->out_plen = m->out_plen;
948   rmp->sharing_ratio = htonl (m->sharing_ratio);
949   rmp->ports_per_host = htons (m->ports_per_host);
950   rmp->ses_num = htonl (m->ses_num);
951   rmp->context = context;
952
953   vl_msg_api_send_shmem (q, (u8 *) & rmp);
954 }
955
956 static void
957 vl_api_snat_det_map_dump_t_handler (vl_api_snat_det_map_dump_t * mp)
958 {
959   unix_shared_memory_queue_t *q;
960   snat_main_t *sm = &snat_main;
961   snat_det_map_t *m;
962
963   q = vl_api_client_index_to_input_queue (mp->client_index);
964   if (q == 0)
965     return;
966
967   /* *INDENT-OFF* */
968   vec_foreach(m, sm->det_maps)
969     sent_snat_det_map_details(m, q, mp->context);
970   /* *INDENT-ON* */
971 }
972
973 static void *vl_api_snat_det_map_dump_t_print
974   (vl_api_snat_det_map_dump_t * mp, void *handle)
975 {
976   u8 *s;
977
978   s = format (0, "SCRIPT: snat_det_map_dump ");
979
980   FINISH;
981 }
982
983 static void
984 vl_api_snat_det_set_timeouts_t_handler (vl_api_snat_det_set_timeouts_t * mp)
985 {
986   snat_main_t *sm = &snat_main;
987   vl_api_snat_det_set_timeouts_reply_t *rmp;
988   int rv = 0;
989
990   sm->udp_timeout = ntohl (mp->udp);
991   sm->tcp_established_timeout = ntohl (mp->tcp_established);
992   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
993   sm->icmp_timeout = ntohl (mp->icmp);
994
995   REPLY_MACRO (VL_API_SNAT_DET_SET_TIMEOUTS_REPLY);
996 }
997
998 static void *vl_api_snat_det_set_timeouts_t_print
999   (vl_api_snat_det_set_timeouts_t * mp, void *handle)
1000 {
1001   u8 *s;
1002
1003   s = format (0, "SCRIPT: snat_det_set_timeouts ");
1004   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
1005               ntohl (mp->udp),
1006               ntohl (mp->tcp_established),
1007               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1008
1009   FINISH;
1010 }
1011
1012 static void
1013 vl_api_snat_det_get_timeouts_t_handler (vl_api_snat_det_get_timeouts_t * mp)
1014 {
1015   snat_main_t *sm = &snat_main;
1016   vl_api_snat_det_get_timeouts_reply_t *rmp;
1017   int rv = 0;
1018
1019   /* *INDENT-OFF* */
1020   REPLY_MACRO2 (VL_API_SNAT_DET_GET_TIMEOUTS_REPLY,
1021   ({
1022     rmp->udp = htonl (sm->udp_timeout);
1023     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1024     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1025     rmp->icmp = htonl (sm->icmp_timeout);
1026   }))
1027   /* *INDENT-ON* */
1028 }
1029
1030 static void *vl_api_snat_det_get_timeouts_t_print
1031   (vl_api_snat_det_get_timeouts_t * mp, void *handle)
1032 {
1033   u8 *s;
1034
1035   s = format (0, "SCRIPT: snat_det_get_timeouts");
1036
1037   FINISH;
1038 }
1039
1040 static void
1041   vl_api_snat_det_close_session_out_t_handler
1042   (vl_api_snat_det_close_session_out_t * mp)
1043 {
1044   snat_main_t *sm = &snat_main;
1045   vl_api_snat_det_close_session_out_reply_t *rmp;
1046   ip4_address_t out_addr, ext_addr, in_addr;
1047   snat_det_out_key_t key;
1048   snat_det_map_t *dm;
1049   snat_det_session_t *ses;
1050   int rv = 0;
1051
1052   clib_memcpy (&out_addr, mp->out_addr, 4);
1053   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1054
1055   dm = snat_det_map_by_out (sm, &out_addr);
1056   if (!dm)
1057     {
1058       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1059       goto send_reply;
1060     }
1061   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1062   key.ext_host_addr = ext_addr;
1063   key.ext_host_port = mp->ext_port;
1064   key.out_port = mp->out_port;
1065   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1066   if (!ses)
1067     {
1068       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1069       goto send_reply;
1070     }
1071   snat_det_ses_close (dm, ses);
1072
1073 send_reply:
1074   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1075 }
1076
1077 static void *vl_api_snat_det_close_session_out_t_print
1078   (vl_api_snat_det_close_session_out_t * mp, void *handle)
1079 {
1080   u8 *s;
1081
1082   s = format (0, "SCRIPT: snat_det_close_session_out ");
1083   s = format (s, "out_addr %U out_port %d "
1084               "ext_addr %U ext_port %d\n",
1085               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1086               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1087
1088   FINISH;
1089 }
1090
1091 static void
1092   vl_api_snat_det_close_session_in_t_handler
1093   (vl_api_snat_det_close_session_in_t * mp)
1094 {
1095   snat_main_t *sm = &snat_main;
1096   vl_api_snat_det_close_session_in_reply_t *rmp;
1097   ip4_address_t in_addr, ext_addr;
1098   snat_det_out_key_t key;
1099   snat_det_map_t *dm;
1100   snat_det_session_t *ses;
1101   int rv = 0;
1102
1103   clib_memcpy (&in_addr, mp->in_addr, 4);
1104   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1105
1106   dm = snat_det_map_by_user (sm, &in_addr);
1107   if (!dm)
1108     {
1109       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1110       goto send_reply;
1111     }
1112   key.ext_host_addr = ext_addr;
1113   key.ext_host_port = mp->ext_port;
1114   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1115   if (!ses)
1116     {
1117       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1118       goto send_reply;
1119     }
1120   snat_det_ses_close (dm, ses);
1121
1122 send_reply:
1123   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1124 }
1125
1126 static void *vl_api_snat_det_close_session_in_t_print
1127   (vl_api_snat_det_close_session_in_t * mp, void *handle)
1128 {
1129   u8 *s;
1130   s = format (0, "SCRIPT: snat_det_close_session_in ");
1131   s = format (s, "in_addr %U in_port %d "
1132               "ext_addr %U ext_port %d\n",
1133               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
1134               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1135
1136   FINISH;
1137 }
1138
1139 static void
1140   send_snat_det_session_details
1141   (snat_det_session_t * s, unix_shared_memory_queue_t * q, u32 context)
1142 {
1143   vl_api_snat_det_session_details_t *rmp;
1144   snat_main_t *sm = &snat_main;
1145
1146   rmp = vl_msg_api_alloc (sizeof (*rmp));
1147   memset (rmp, 0, sizeof (*rmp));
1148   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_SESSION_DETAILS + sm->msg_id_base);
1149   rmp->is_ip4 = 1;
1150   rmp->in_port = s->in_port;
1151   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
1152   rmp->ext_port = s->out.ext_host_port;
1153   rmp->out_port = s->out.out_port;
1154   rmp->state = s->state;
1155   rmp->expire = ntohl (s->expire);
1156   rmp->context = context;
1157
1158   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1159 }
1160
1161 static void
1162 vl_api_snat_det_session_dump_t_handler (vl_api_snat_det_session_dump_t * mp)
1163 {
1164   unix_shared_memory_queue_t *q;
1165   snat_main_t *sm = &snat_main;
1166   ip4_address_t user_addr;
1167   snat_det_map_t *dm;
1168   snat_det_session_t *s, empty_ses;
1169   u16 i;
1170
1171   q = vl_api_client_index_to_input_queue (mp->client_index);
1172   if (q == 0)
1173     return;
1174   if (!mp->is_ip4)
1175     return;
1176
1177   memset (&empty_ses, 0, sizeof (empty_ses));
1178   clib_memcpy (&user_addr, mp->user_addr, 4);
1179   dm = snat_det_map_by_user (sm, &user_addr);
1180   if (!dm)
1181     return;
1182
1183   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
1184   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
1185     {
1186       if (s->out.as_u64)
1187         send_snat_det_session_details (s, q, mp->context);
1188       s++;
1189     }
1190 }
1191
1192 static void *vl_api_snat_det_session_dump_t_print
1193   (vl_api_snat_det_session_dump_t * mp, void *handle)
1194 {
1195   u8 *s;
1196
1197   s = format (0, "SCRIPT: snat_det_session_dump ");
1198   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
1199
1200   FINISH;
1201 }
1202
1203 /*************/
1204 /*** NAT64 ***/
1205 /*************/
1206
1207 static void
1208   vl_api_nat64_add_del_pool_addr_range_t_handler
1209   (vl_api_nat64_add_del_pool_addr_range_t * mp)
1210 {
1211   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
1212   snat_main_t *sm = &snat_main;
1213   nat64_main_t *nm = &nat64_main;
1214   int rv = 0;
1215   ip4_address_t this_addr;
1216   u32 start_host_order, end_host_order;
1217   u32 vrf_id;
1218   int i, count;
1219   u32 *tmp;
1220
1221   if (nm->is_disabled)
1222     {
1223       rv = VNET_API_ERROR_FEATURE_DISABLED;
1224       goto send_reply;
1225     }
1226
1227   tmp = (u32 *) mp->start_addr;
1228   start_host_order = clib_host_to_net_u32 (tmp[0]);
1229   tmp = (u32 *) mp->end_addr;
1230   end_host_order = clib_host_to_net_u32 (tmp[0]);
1231
1232   count = (end_host_order - start_host_order) + 1;
1233
1234   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
1235
1236   memcpy (&this_addr.as_u8, mp->start_addr, 4);
1237
1238   for (i = 0; i < count; i++)
1239     {
1240       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
1241         goto send_reply;
1242
1243       increment_v4_address (&this_addr);
1244     }
1245
1246 send_reply:
1247   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
1248 }
1249
1250 static void *vl_api_nat64_add_del_pool_addr_range_t_print
1251   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
1252 {
1253   u8 *s;
1254
1255   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
1256   s = format (s, "%U - %U vrf_id %u %s\n",
1257               format_ip4_address, mp->start_addr,
1258               format_ip4_address, mp->end_addr,
1259               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
1260
1261   FINISH;
1262 }
1263
1264 typedef struct nat64_api_walk_ctx_t_
1265 {
1266   unix_shared_memory_queue_t *q;
1267   u32 context;
1268 } nat64_api_walk_ctx_t;
1269
1270 static int
1271 nat64_api_pool_walk (snat_address_t * a, void *arg)
1272 {
1273   vl_api_nat64_pool_addr_details_t *rmp;
1274   snat_main_t *sm = &snat_main;
1275   nat64_api_walk_ctx_t *ctx = arg;
1276
1277   rmp = vl_msg_api_alloc (sizeof (*rmp));
1278   memset (rmp, 0, sizeof (*rmp));
1279   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
1280   clib_memcpy (rmp->address, &(a->addr), 4);
1281   if (a->fib_index != ~0)
1282     {
1283       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
1284       if (!fib)
1285         return -1;
1286       rmp->vrf_id = ntohl (fib->ft_table_id);
1287     }
1288   else
1289     rmp->vrf_id = ~0;
1290   rmp->context = ctx->context;
1291
1292   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1293
1294   return 0;
1295 }
1296
1297 static void
1298 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
1299 {
1300   unix_shared_memory_queue_t *q;
1301   nat64_main_t *nm = &nat64_main;
1302
1303   if (nm->is_disabled)
1304     return;
1305
1306   q = vl_api_client_index_to_input_queue (mp->client_index);
1307   if (q == 0)
1308     return;
1309
1310   nat64_api_walk_ctx_t ctx = {
1311     .q = q,
1312     .context = mp->context,
1313   };
1314
1315   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
1316 }
1317
1318 static void *
1319 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
1320                                      void *handle)
1321 {
1322   u8 *s;
1323
1324   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
1325
1326   FINISH;
1327 }
1328
1329 static void
1330 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
1331                                           mp)
1332 {
1333   snat_main_t *sm = &snat_main;
1334   nat64_main_t *nm = &nat64_main;
1335   vl_api_nat64_add_del_interface_reply_t *rmp;
1336   int rv = 0;
1337
1338   if (nm->is_disabled)
1339     {
1340       rv = VNET_API_ERROR_FEATURE_DISABLED;
1341       goto send_reply;
1342     }
1343
1344   VALIDATE_SW_IF_INDEX (mp);
1345
1346   rv =
1347     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
1348                              mp->is_add);
1349
1350   BAD_SW_IF_INDEX_LABEL;
1351
1352 send_reply:
1353   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
1354 }
1355
1356 static void *
1357 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
1358                                         void *handle)
1359 {
1360   u8 *s;
1361
1362   s = format (0, "SCRIPT: nat64_add_del_interface ");
1363   s = format (s, "sw_if_index %d %s %s",
1364               clib_host_to_net_u32 (mp->sw_if_index),
1365               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1366
1367   FINISH;
1368 }
1369
1370 static int
1371 nat64_api_interface_walk (snat_interface_t * i, void *arg)
1372 {
1373   vl_api_nat64_interface_details_t *rmp;
1374   snat_main_t *sm = &snat_main;
1375   nat64_api_walk_ctx_t *ctx = arg;
1376
1377   rmp = vl_msg_api_alloc (sizeof (*rmp));
1378   memset (rmp, 0, sizeof (*rmp));
1379   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
1380   rmp->sw_if_index = ntohl (i->sw_if_index);
1381   rmp->is_inside = i->is_inside;
1382   rmp->context = ctx->context;
1383
1384   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1385
1386   return 0;
1387 }
1388
1389 static void
1390 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
1391 {
1392   unix_shared_memory_queue_t *q;
1393   nat64_main_t *nm = &nat64_main;
1394
1395   if (nm->is_disabled)
1396     return;
1397
1398   q = vl_api_client_index_to_input_queue (mp->client_index);
1399   if (q == 0)
1400     return;
1401
1402   nat64_api_walk_ctx_t ctx = {
1403     .q = q,
1404     .context = mp->context,
1405   };
1406
1407   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
1408 }
1409
1410 static void *
1411 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
1412                                      void *handle)
1413 {
1414   u8 *s;
1415
1416   s = format (0, "SCRIPT: snat_interface_dump ");
1417
1418   FINISH;
1419 }
1420
1421 static void
1422   vl_api_nat64_add_del_static_bib_t_handler
1423   (vl_api_nat64_add_del_static_bib_t * mp)
1424 {
1425   snat_main_t *sm = &snat_main;
1426   nat64_main_t *nm = &nat64_main;
1427   vl_api_nat64_add_del_static_bib_reply_t *rmp;
1428   ip6_address_t in_addr;
1429   ip4_address_t out_addr;
1430   int rv = 0;
1431
1432   if (nm->is_disabled)
1433     {
1434       rv = VNET_API_ERROR_FEATURE_DISABLED;
1435       goto send_reply;
1436     }
1437
1438   memcpy (&in_addr.as_u8, mp->i_addr, 16);
1439   memcpy (&out_addr.as_u8, mp->o_addr, 4);
1440
1441   rv =
1442     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
1443                                     clib_net_to_host_u16 (mp->i_port),
1444                                     clib_net_to_host_u16 (mp->o_port),
1445                                     mp->proto,
1446                                     clib_net_to_host_u32 (mp->vrf_id),
1447                                     mp->is_add);
1448
1449 send_reply:
1450   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
1451 }
1452
1453 static void *vl_api_nat64_add_del_static_bib_t_print
1454   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
1455 {
1456   u8 *s;
1457
1458   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
1459   s = format (s, "protocol %d i_addr %U o_addr %U ",
1460               mp->proto,
1461               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
1462
1463   if (mp->vrf_id != ~0)
1464     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1465
1466   FINISH;
1467 }
1468
1469 static int
1470 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
1471 {
1472   vl_api_nat64_bib_details_t *rmp;
1473   snat_main_t *sm = &snat_main;
1474   nat64_api_walk_ctx_t *ctx = arg;
1475   fib_table_t *fib;
1476
1477   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
1478   if (!fib)
1479     return -1;
1480
1481   rmp = vl_msg_api_alloc (sizeof (*rmp));
1482   memset (rmp, 0, sizeof (*rmp));
1483   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
1484   rmp->context = ctx->context;
1485   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
1486   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
1487   rmp->i_port = bibe->in_port;
1488   rmp->o_port = bibe->out_port;
1489   rmp->vrf_id = ntohl (fib->ft_table_id);
1490   rmp->proto = snat_proto_to_ip_proto (bibe->proto);
1491   rmp->is_static = bibe->is_static;
1492   rmp->ses_num = ntohl (bibe->ses_num);
1493
1494   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1495
1496   return 0;
1497 }
1498
1499 static void
1500 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
1501 {
1502   unix_shared_memory_queue_t *q;
1503   nat64_main_t *nm = &nat64_main;
1504   snat_protocol_t proto;
1505
1506   if (nm->is_disabled)
1507     return;
1508
1509   q = vl_api_client_index_to_input_queue (mp->client_index);
1510   if (q == 0)
1511     return;
1512
1513   nat64_api_walk_ctx_t ctx = {
1514     .q = q,
1515     .context = mp->context,
1516   };
1517
1518   proto = ip_proto_to_snat_proto (mp->proto);
1519
1520   nat64_db_bib_walk (&nm->db, proto, nat64_api_bib_walk, &ctx);
1521 }
1522
1523 static void *
1524 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
1525 {
1526   u8 *s;
1527
1528   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
1529
1530   FINISH;
1531 }
1532
1533 static void
1534 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
1535 {
1536   snat_main_t *sm = &snat_main;
1537   nat64_main_t *nm = &nat64_main;
1538   vl_api_nat64_set_timeouts_reply_t *rmp;
1539   int rv = 0;
1540
1541   if (nm->is_disabled)
1542     {
1543       rv = VNET_API_ERROR_FEATURE_DISABLED;
1544       goto send_reply;
1545     }
1546
1547   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
1548   if (rv)
1549     goto send_reply;
1550   rv = nat64_set_udp_timeout (ntohl (mp->udp));
1551   if (rv)
1552     goto send_reply;
1553   rv =
1554     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
1555                             ntohl (mp->tcp_incoming_syn));
1556
1557 send_reply:
1558   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
1559 }
1560
1561 static void *vl_api_nat64_set_timeouts_t_print
1562   (vl_api_nat64_set_timeouts_t * mp, void *handle)
1563 {
1564   u8 *s;
1565
1566   s = format (0, "SCRIPT: nat64_set_timeouts ");
1567   s =
1568     format (s,
1569             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
1570             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
1571             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
1572
1573   FINISH;
1574 }
1575
1576 static void
1577 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
1578 {
1579   snat_main_t *sm = &snat_main;
1580   nat64_main_t *nm = &nat64_main;
1581   vl_api_nat64_get_timeouts_reply_t *rmp;
1582   int rv = 0;
1583
1584   if (nm->is_disabled)
1585     return;
1586
1587   /* *INDENT-OFF* */
1588   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
1589   ({
1590     rmp->udp = htonl (nat64_get_udp_timeout());
1591     rmp->icmp = htonl (nat64_get_icmp_timeout());
1592     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
1593     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
1594     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
1595   }))
1596   /* *INDENT-ON* */
1597 }
1598
1599 static void *vl_api_nat64_get_timeouts_t_print
1600   (vl_api_nat64_get_timeouts_t * mp, void *handle)
1601 {
1602   u8 *s;
1603
1604   s = format (0, "SCRIPT: nat64_get_timeouts");
1605
1606   FINISH;
1607 }
1608
1609 static int
1610 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
1611 {
1612   vl_api_nat64_st_details_t *rmp;
1613   snat_main_t *sm = &snat_main;
1614   nat64_api_walk_ctx_t *ctx = arg;
1615   nat64_main_t *nm = &nat64_main;
1616   nat64_db_bib_entry_t *bibe;
1617   fib_table_t *fib;
1618
1619   bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
1620   if (!bibe)
1621     return -1;
1622
1623   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
1624   if (!fib)
1625     return -1;
1626
1627   rmp = vl_msg_api_alloc (sizeof (*rmp));
1628   memset (rmp, 0, sizeof (*rmp));
1629   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
1630   rmp->context = ctx->context;
1631   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
1632   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
1633   rmp->il_port = bibe->in_port;
1634   rmp->ol_port = bibe->out_port;
1635   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
1636   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
1637   rmp->il_port = ste->r_port;
1638   rmp->vrf_id = ntohl (fib->ft_table_id);
1639   rmp->proto = snat_proto_to_ip_proto (ste->proto);
1640
1641   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1642
1643   return 0;
1644 }
1645
1646 static void
1647 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
1648 {
1649   unix_shared_memory_queue_t *q;
1650   nat64_main_t *nm = &nat64_main;
1651   snat_protocol_t proto;
1652
1653   if (nm->is_disabled)
1654     return;
1655
1656   q = vl_api_client_index_to_input_queue (mp->client_index);
1657   if (q == 0)
1658     return;
1659
1660   nat64_api_walk_ctx_t ctx = {
1661     .q = q,
1662     .context = mp->context,
1663   };
1664
1665   proto = ip_proto_to_snat_proto (mp->proto);
1666
1667   nat64_db_st_walk (&nm->db, proto, nat64_api_st_walk, &ctx);
1668 }
1669
1670 static void *
1671 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
1672 {
1673   u8 *s;
1674
1675   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
1676
1677   FINISH;
1678 }
1679
1680 static void
1681 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
1682 {
1683   vl_api_nat64_add_del_prefix_reply_t *rmp;
1684   snat_main_t *sm = &snat_main;
1685   nat64_main_t *nm = &nat64_main;
1686   ip6_address_t prefix;
1687   int rv = 0;
1688
1689   if (nm->is_disabled)
1690     {
1691       rv = VNET_API_ERROR_FEATURE_DISABLED;
1692       goto send_reply;
1693     }
1694
1695   memcpy (&prefix.as_u8, mp->prefix, 16);
1696
1697   rv =
1698     nat64_add_del_prefix (&prefix, mp->prefix_len,
1699                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
1700 send_reply:
1701   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
1702 }
1703
1704 static void *
1705 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
1706                                      void *handle)
1707 {
1708   u8 *s;
1709
1710   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
1711               format_ip6_address, mp->prefix, mp->prefix_len,
1712               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
1713
1714   FINISH;
1715 }
1716
1717 static int
1718 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
1719 {
1720   vl_api_nat64_prefix_details_t *rmp;
1721   snat_main_t *sm = &snat_main;
1722   nat64_api_walk_ctx_t *ctx = arg;
1723
1724   rmp = vl_msg_api_alloc (sizeof (*rmp));
1725   memset (rmp, 0, sizeof (*rmp));
1726   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
1727   clib_memcpy (rmp->prefix, &(p->prefix), 16);
1728   rmp->prefix_len = p->plen;
1729   rmp->vrf_id = ntohl (p->vrf_id);
1730   rmp->context = ctx->context;
1731
1732   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1733
1734   return 0;
1735 }
1736
1737 static void
1738 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
1739 {
1740   unix_shared_memory_queue_t *q;
1741   nat64_main_t *nm = &nat64_main;
1742
1743   if (nm->is_disabled)
1744     return;
1745
1746   q = vl_api_client_index_to_input_queue (mp->client_index);
1747   if (q == 0)
1748     return;
1749
1750   nat64_api_walk_ctx_t ctx = {
1751     .q = q,
1752     .context = mp->context,
1753   };
1754
1755   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
1756 }
1757
1758 static void *
1759 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
1760                                   void *handle)
1761 {
1762   u8 *s;
1763
1764   s = format (0, "SCRIPT: nat64_prefix_dump\n");
1765
1766   FINISH;
1767 }
1768
1769 /* List of message types that this plugin understands */
1770 #define foreach_snat_plugin_api_msg                                     \
1771 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range)                       \
1772 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature)       \
1773 _(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping)                     \
1774 _(SNAT_CONTROL_PING, snat_control_ping)                                 \
1775 _(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump)                   \
1776 _(SNAT_SHOW_CONFIG, snat_show_config)                                   \
1777 _(SNAT_ADDRESS_DUMP, snat_address_dump)                                 \
1778 _(SNAT_INTERFACE_DUMP, snat_interface_dump)                             \
1779 _(SNAT_SET_WORKERS, snat_set_workers)                                   \
1780 _(SNAT_WORKER_DUMP, snat_worker_dump)                                   \
1781 _(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr)             \
1782 _(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump)                   \
1783 _(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable)                 \
1784 _(SNAT_USER_DUMP, snat_user_dump)                                       \
1785 _(SNAT_USER_SESSION_DUMP, snat_user_session_dump)                       \
1786 _(SNAT_ADD_DET_MAP, snat_add_det_map)                                   \
1787 _(SNAT_DET_FORWARD, snat_det_forward)                                   \
1788 _(SNAT_DET_REVERSE, snat_det_reverse)                                   \
1789 _(SNAT_DET_MAP_DUMP, snat_det_map_dump)                                 \
1790 _(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts)                         \
1791 _(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts)                         \
1792 _(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out)               \
1793 _(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in)                 \
1794 _(SNAT_DET_SESSION_DUMP, snat_det_session_dump)                         \
1795 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
1796 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
1797 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
1798 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
1799 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
1800 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
1801 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
1802 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
1803 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
1804 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
1805 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)
1806
1807 /* Set up the API message handling tables */
1808 static clib_error_t *
1809 snat_plugin_api_hookup (vlib_main_t * vm)
1810 {
1811   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
1812 #define _(N,n)                                                  \
1813     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
1814                            #n,                                  \
1815                            vl_api_##n##_t_handler,              \
1816                            vl_noop_handler,                     \
1817                            vl_api_##n##_t_endian,               \
1818                            vl_api_##n##_t_print,                \
1819                            sizeof(vl_api_##n##_t), 1);
1820   foreach_snat_plugin_api_msg;
1821 #undef _
1822
1823   return 0;
1824 }
1825
1826 #define vl_msg_name_crc_list
1827 #include <snat/snat_all_api_h.h>
1828 #undef vl_msg_name_crc_list
1829
1830 static void
1831 setup_message_id_table (snat_main_t * sm, api_main_t * am)
1832 {
1833 #define _(id,n,crc) \
1834   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
1835   foreach_vl_msg_name_crc_snat;
1836 #undef _
1837 }
1838
1839 static void
1840 plugin_custom_dump_configure (snat_main_t * sm)
1841 {
1842 #define _(n,f) sm->api_main->msg_print_handlers \
1843   [VL_API_##n + sm->msg_id_base]                \
1844     = (void *) vl_api_##f##_t_print;
1845   foreach_snat_plugin_api_msg;
1846 #undef _
1847 }
1848
1849 clib_error_t *
1850 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
1851 {
1852   u8 *name;
1853   clib_error_t *error = 0;
1854
1855   name = format (0, "snat_%08x%c", api_version, 0);
1856
1857   /* Ask for a correctly-sized block of API message decode slots */
1858   sm->msg_id_base =
1859     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
1860
1861   error = snat_plugin_api_hookup (vm);
1862
1863   /* Add our API messages to the global name_crc hash table */
1864   setup_message_id_table (sm, sm->api_main);
1865
1866   plugin_custom_dump_configure (sm);
1867
1868   vec_free (name);
1869
1870   return error;
1871 }
1872
1873 /*
1874  * fd.io coding-style-patch-verification: ON
1875  *
1876  * Local Variables:
1877  * eval: (c-set-style "gnu")
1878  * End:
1879  */