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