NAT64: multi-thread support (VPP-891)
[vpp.git] / src / plugins / nat / nat_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 NAT plugin API implementation
19  */
20
21 #include <nat/nat.h>
22 #include <nat/nat_det.h>
23 #include <nat/nat64.h>
24 #include <nat/dslite.h>
25 #include <nat/nat_reass.h>
26 #include <vlibapi/api.h>
27 #include <vlibmemory/api.h>
28
29 #include <nat/nat_msg_enum.h>
30 #include <vnet/fib/fib_table.h>
31
32 #define vl_api_nat44_lb_addr_port_t_endian vl_noop_handler
33 #define vl_api_nat44_add_del_lb_static_mapping_t_endian vl_noop_handler
34 #define vl_api_nat44_nat44_lb_static_mapping_details_t_endian vl_noop_handler
35
36 /* define message structures */
37 #define vl_typedefs
38 #include <nat/nat_all_api_h.h>
39 #undef vl_typedefs
40
41 /* define generated endian-swappers */
42 #define vl_endianfun
43 #include <nat/nat_all_api_h.h>
44 #undef vl_endianfun
45
46 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
47
48 #define REPLY_MSG_ID_BASE sm->msg_id_base
49 #include <vlibapi/api_helper_macros.h>
50
51 /* Get the API version number */
52 #define vl_api_version(n,v) static u32 api_version=(v);
53 #include <nat/nat_all_api_h.h>
54 #undef vl_api_version
55
56 /* Macro to finish up custom dump fns */
57 #define FINISH                                  \
58     vec_add1 (s, 0);                            \
59     vl_print (handle, (char *)s);               \
60     vec_free (s);                               \
61     return handle;
62
63
64 /******************************/
65 /*** Common NAT plugin APIs ***/
66 /******************************/
67
68 static void
69 vl_api_nat_control_ping_t_handler (vl_api_nat_control_ping_t * mp)
70 {
71   vl_api_nat_control_ping_reply_t *rmp;
72   snat_main_t *sm = &snat_main;
73   int rv = 0;
74
75   /* *INDENT-OFF* */
76   REPLY_MACRO2 (VL_API_NAT_CONTROL_PING_REPLY,
77   ({
78     rmp->vpe_pid = ntohl (getpid ());
79   }));
80   /* *INDENT-ON* */
81 }
82
83 static void *
84 vl_api_nat_control_ping_t_print (vl_api_nat_control_ping_t * mp, void *handle)
85 {
86   u8 *s;
87
88   s = format (0, "SCRIPT: nat_control_ping ");
89
90   FINISH;
91 }
92
93 static void
94 vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t * mp)
95 {
96   vl_api_nat_show_config_reply_t *rmp;
97   snat_main_t *sm = &snat_main;
98   int rv = 0;
99
100   /* *INDENT-OFF* */
101   REPLY_MACRO2 (VL_API_NAT_SHOW_CONFIG_REPLY,
102   ({
103     rmp->translation_buckets = htonl (sm->translation_buckets);
104     rmp->translation_memory_size = htonl (sm->translation_memory_size);
105     rmp->user_buckets = htonl (sm->user_buckets);
106     rmp->user_memory_size = htonl (sm->user_memory_size);
107     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
108     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
109     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
110     rmp->static_mapping_only = sm->static_mapping_only;
111     rmp->static_mapping_connection_tracking =
112       sm->static_mapping_connection_tracking;
113     rmp->deterministic = sm->deterministic;
114   }));
115   /* *INDENT-ON* */
116 }
117
118 static void *
119 vl_api_nat_show_config_t_print (vl_api_nat_show_config_t * mp, void *handle)
120 {
121   u8 *s;
122
123   s = format (0, "SCRIPT: nat_show_config ");
124
125   FINISH;
126 }
127
128 static void
129 vl_api_nat_set_workers_t_handler (vl_api_nat_set_workers_t * mp)
130 {
131   snat_main_t *sm = &snat_main;
132   vl_api_nat_set_workers_reply_t *rmp;
133   int rv = 0;
134   uword *bitmap = 0;
135   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
136
137   if (sm->num_workers < 2)
138     {
139       rv = VNET_API_ERROR_FEATURE_DISABLED;
140       goto send_reply;
141     }
142
143   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
144   rv = snat_set_workers (bitmap);
145   clib_bitmap_free (bitmap);
146
147 send_reply:
148   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
149 }
150
151 static void *
152 vl_api_nat_set_workers_t_print (vl_api_nat_set_workers_t * mp, void *handle)
153 {
154   u8 *s;
155   uword *bitmap = 0;
156   u8 first = 1;
157   int i;
158   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
159
160   s = format (0, "SCRIPT: nat_set_workers ");
161   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
162   /* *INDENT-OFF* */
163   clib_bitmap_foreach (i, bitmap,
164     ({
165       if (first)
166         s = format (s, "%d", i);
167       else
168         s = format (s, ",%d", i);
169       first = 0;
170     }));
171   /* *INDENT-ON* */
172   clib_bitmap_free (bitmap);
173   FINISH;
174 }
175
176 static void
177 send_nat_worker_details (u32 worker_index, unix_shared_memory_queue_t * q,
178                          u32 context)
179 {
180   vl_api_nat_worker_details_t *rmp;
181   snat_main_t *sm = &snat_main;
182   vlib_worker_thread_t *w =
183     vlib_worker_threads + worker_index + sm->first_worker_index;
184
185   rmp = vl_msg_api_alloc (sizeof (*rmp));
186   memset (rmp, 0, sizeof (*rmp));
187   rmp->_vl_msg_id = ntohs (VL_API_NAT_WORKER_DETAILS + sm->msg_id_base);
188   rmp->context = context;
189   rmp->worker_index = htonl (worker_index);
190   rmp->lcore_id = htonl (w->lcore_id);
191   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
192
193   vl_msg_api_send_shmem (q, (u8 *) & rmp);
194 }
195
196 static void
197 vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp)
198 {
199   unix_shared_memory_queue_t *q;
200   snat_main_t *sm = &snat_main;
201   u32 *worker_index;
202
203   q = vl_api_client_index_to_input_queue (mp->client_index);
204   if (q == 0)
205     return;
206
207   /* *INDENT-OFF* */
208   vec_foreach (worker_index, sm->workers)
209     send_nat_worker_details(*worker_index, q, mp->context);
210   /* *INDENT-ON* */
211 }
212
213 static void *
214 vl_api_nat_worker_dump_t_print (vl_api_nat_worker_dump_t * mp, void *handle)
215 {
216   u8 *s;
217
218   s = format (0, "SCRIPT: nat_worker_dump ");
219
220   FINISH;
221 }
222
223 static void
224 vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t *
225                                            mp)
226 {
227   snat_main_t *sm = &snat_main;
228   vl_api_nat_ipfix_enable_disable_reply_t *rmp;
229   int rv = 0;
230
231   rv = snat_ipfix_logging_enable_disable (mp->enable,
232                                           clib_host_to_net_u32
233                                           (mp->domain_id),
234                                           clib_host_to_net_u16
235                                           (mp->src_port));
236
237   REPLY_MACRO (VL_API_NAT_IPFIX_ENABLE_DISABLE_REPLY);
238 }
239
240 static void *
241 vl_api_nat_ipfix_enable_disable_t_print (vl_api_nat_ipfix_enable_disable_t *
242                                          mp, void *handle)
243 {
244   u8 *s;
245
246   s = format (0, "SCRIPT: nat_ipfix_enable_disable ");
247   if (mp->domain_id)
248     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
249   if (mp->src_port)
250     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
251   if (!mp->enable)
252     s = format (s, "disable ");
253
254   FINISH;
255 }
256
257 static void
258 vl_api_nat_set_reass_t_handler (vl_api_nat_set_reass_t * mp)
259 {
260   snat_main_t *sm = &snat_main;
261   vl_api_nat_set_reass_reply_t *rmp;
262   int rv = 0;
263
264   rv =
265     nat_reass_set (ntohl (mp->timeout), ntohs (mp->max_reass), mp->max_frag,
266                    mp->drop_frag, mp->is_ip6);
267
268   REPLY_MACRO (VL_API_NAT_SET_REASS_REPLY);
269 }
270
271 static void *
272 vl_api_nat_set_reass_t_print (vl_api_nat_set_reass_t * mp, void *handle)
273 {
274   u8 *s;
275
276   s = format (0, "SCRIPT: nat_set_reass ");
277   s = format (s, "timeout %d max_reass %d max_frag %d drop_frag %d is_ip6 %d",
278               clib_host_to_net_u32 (mp->timeout),
279               clib_host_to_net_u16 (mp->max_reass),
280               mp->max_frag, mp->drop_frag, mp->is_ip6);
281
282   FINISH;
283 }
284
285 static void
286 vl_api_nat_get_reass_t_handler (vl_api_nat_get_reass_t * mp)
287 {
288   snat_main_t *sm = &snat_main;
289   vl_api_nat_get_reass_reply_t *rmp;
290   int rv = 0;
291
292   /* *INDENT-OFF* */
293   REPLY_MACRO2 (VL_API_NAT_GET_REASS_REPLY,
294   ({
295     rmp->ip4_timeout = htonl (nat_reass_get_timeout(0));
296     rmp->ip4_max_reass = htons (nat_reass_get_max_reass(0));
297     rmp->ip4_max_frag = nat_reass_get_max_frag(0);
298     rmp->ip4_drop_frag = nat_reass_is_drop_frag(0);
299     rmp->ip6_timeout = htonl (nat_reass_get_timeout(1));
300     rmp->ip6_max_reass = htons (nat_reass_get_max_reass(1));
301     rmp->ip6_max_frag = nat_reass_get_max_frag(1);
302     rmp->ip6_drop_frag = nat_reass_is_drop_frag(1);
303   }))
304   /* *INDENT-ON* */
305 }
306
307 static void *
308 vl_api_nat_get_reass_t_print (vl_api_nat_get_reass_t * mp, void *handle)
309 {
310   u8 *s;
311
312   s = format (0, "SCRIPT: nat_get_reass");
313
314   FINISH;
315 }
316
317 typedef struct nat_api_walk_ctx_t_
318 {
319   unix_shared_memory_queue_t *q;
320   u32 context;
321 } nat_api_walk_ctx_t;
322
323 static int
324 nat_ip4_reass_walk_api (nat_reass_ip4_t * reass, void *arg)
325 {
326   vl_api_nat_reass_details_t *rmp;
327   snat_main_t *sm = &snat_main;
328   nat_api_walk_ctx_t *ctx = arg;
329
330   rmp = vl_msg_api_alloc (sizeof (*rmp));
331   memset (rmp, 0, sizeof (*rmp));
332   rmp->_vl_msg_id = ntohs (VL_API_NAT_REASS_DETAILS + sm->msg_id_base);
333   rmp->context = ctx->context;
334   clib_memcpy (rmp->src_addr, &(reass->key.src), 4);
335   clib_memcpy (rmp->dst_addr, &(reass->key.dst), 4);
336   rmp->proto = reass->key.proto;
337   rmp->frag_id = ntohl (reass->key.frag_id);
338   rmp->frag_n = reass->frag_n;
339   rmp->is_ip4 = 1;
340
341   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
342
343   return 0;
344 }
345
346 static int
347 nat_ip6_reass_walk_api (nat_reass_ip6_t * reass, void *arg)
348 {
349   vl_api_nat_reass_details_t *rmp;
350   snat_main_t *sm = &snat_main;
351   nat_api_walk_ctx_t *ctx = arg;
352
353   rmp = vl_msg_api_alloc (sizeof (*rmp));
354   memset (rmp, 0, sizeof (*rmp));
355   rmp->_vl_msg_id = ntohs (VL_API_NAT_REASS_DETAILS + sm->msg_id_base);
356   rmp->context = ctx->context;
357   clib_memcpy (rmp->src_addr, &(reass->key.src), 16);
358   clib_memcpy (rmp->dst_addr, &(reass->key.dst), 16);
359   rmp->proto = reass->key.proto;
360   rmp->frag_id = ntohl (reass->key.frag_id);
361   rmp->frag_n = reass->frag_n;
362   rmp->is_ip4 = 0;
363
364   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
365
366   return 0;
367 }
368
369 static void
370 vl_api_nat_reass_dump_t_handler (vl_api_nat_reass_dump_t * mp)
371 {
372   unix_shared_memory_queue_t *q;
373
374   q = vl_api_client_index_to_input_queue (mp->client_index);
375   if (q == 0)
376     return;
377
378   nat_api_walk_ctx_t ctx = {
379     .q = q,
380     .context = mp->context,
381   };
382
383   nat_ip4_reass_walk (nat_ip4_reass_walk_api, &ctx);
384   nat_ip6_reass_walk (nat_ip6_reass_walk_api, &ctx);
385 }
386
387 static void *
388 vl_api_nat_reass_dump_t_print (vl_api_nat_reass_dump_t * mp, void *handle)
389 {
390   u8 *s;
391
392   s = format (0, "SCRIPT: nat_reass_dump");
393
394   FINISH;
395 }
396
397 /*************/
398 /*** NAT44 ***/
399 /*************/
400 static void
401   vl_api_nat44_add_del_address_range_t_handler
402   (vl_api_nat44_add_del_address_range_t * mp)
403 {
404   snat_main_t *sm = &snat_main;
405   vl_api_nat44_add_del_address_range_reply_t *rmp;
406   ip4_address_t this_addr;
407   u32 start_host_order, end_host_order;
408   u32 vrf_id;
409   int i, count;
410   int rv = 0;
411   u32 *tmp;
412
413   if (sm->static_mapping_only)
414     {
415       rv = VNET_API_ERROR_FEATURE_DISABLED;
416       goto send_reply;
417     }
418
419   tmp = (u32 *) mp->first_ip_address;
420   start_host_order = clib_host_to_net_u32 (tmp[0]);
421   tmp = (u32 *) mp->last_ip_address;
422   end_host_order = clib_host_to_net_u32 (tmp[0]);
423
424   count = (end_host_order - start_host_order) + 1;
425
426   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
427
428   if (count > 1024)
429     clib_warning ("%U - %U, %d addresses...",
430                   format_ip4_address, mp->first_ip_address,
431                   format_ip4_address, mp->last_ip_address, count);
432
433   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
434
435   for (i = 0; i < count; i++)
436     {
437       if (mp->is_add)
438         snat_add_address (sm, &this_addr, vrf_id);
439       else
440         rv = snat_del_address (sm, this_addr, 0);
441
442       if (rv)
443         goto send_reply;
444
445       increment_v4_address (&this_addr);
446     }
447
448 send_reply:
449   REPLY_MACRO (VL_API_NAT44_ADD_DEL_ADDRESS_RANGE_REPLY);
450 }
451
452 static void *vl_api_nat44_add_del_address_range_t_print
453   (vl_api_nat44_add_del_address_range_t * mp, void *handle)
454 {
455   u8 *s;
456
457   s = format (0, "SCRIPT: nat44_add_address_range ");
458   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
459   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
460     {
461       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
462     }
463   FINISH;
464 }
465
466 static void
467 send_nat44_address_details (snat_address_t * a,
468                             unix_shared_memory_queue_t * q, u32 context)
469 {
470   vl_api_nat44_address_details_t *rmp;
471   snat_main_t *sm = &snat_main;
472
473   rmp = vl_msg_api_alloc (sizeof (*rmp));
474   memset (rmp, 0, sizeof (*rmp));
475   rmp->_vl_msg_id = ntohs (VL_API_NAT44_ADDRESS_DETAILS + sm->msg_id_base);
476   clib_memcpy (rmp->ip_address, &(a->addr), 4);
477   if (a->fib_index != ~0)
478     {
479       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
480       rmp->vrf_id = ntohl (fib->ft_table_id);
481     }
482   else
483     rmp->vrf_id = ~0;
484   rmp->context = context;
485
486   vl_msg_api_send_shmem (q, (u8 *) & rmp);
487 }
488
489 static void
490 vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp)
491 {
492   unix_shared_memory_queue_t *q;
493   snat_main_t *sm = &snat_main;
494   snat_address_t *a;
495
496   q = vl_api_client_index_to_input_queue (mp->client_index);
497   if (q == 0)
498     return;
499
500   /* *INDENT-OFF* */
501   vec_foreach (a, sm->addresses)
502     send_nat44_address_details (a, q, mp->context);
503   /* *INDENT-ON* */
504 }
505
506 static void *
507 vl_api_nat44_address_dump_t_print (vl_api_nat44_address_dump_t * mp,
508                                    void *handle)
509 {
510   u8 *s;
511
512   s = format (0, "SCRIPT: nat44_address_dump ");
513
514   FINISH;
515 }
516
517 static void
518   vl_api_nat44_interface_add_del_feature_t_handler
519   (vl_api_nat44_interface_add_del_feature_t * mp)
520 {
521   snat_main_t *sm = &snat_main;
522   vl_api_nat44_interface_add_del_feature_reply_t *rmp;
523   u8 is_del = mp->is_add == 0;
524   u32 sw_if_index = ntohl (mp->sw_if_index);
525   int rv = 0;
526
527   VALIDATE_SW_IF_INDEX (mp);
528
529   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
530
531   BAD_SW_IF_INDEX_LABEL;
532
533   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY);
534 }
535
536 static void *vl_api_nat44_interface_add_del_feature_t_print
537   (vl_api_nat44_interface_add_del_feature_t * mp, void *handle)
538 {
539   u8 *s;
540
541   s = format (0, "SCRIPT: nat44_interface_add_del_feature ");
542   s = format (s, "sw_if_index %d %s %s",
543               clib_host_to_net_u32 (mp->sw_if_index),
544               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
545
546   FINISH;
547 }
548
549 static void
550 send_nat44_interface_details (snat_interface_t * i,
551                               unix_shared_memory_queue_t * q, u32 context)
552 {
553   vl_api_nat44_interface_details_t *rmp;
554   snat_main_t *sm = &snat_main;
555
556   rmp = vl_msg_api_alloc (sizeof (*rmp));
557   memset (rmp, 0, sizeof (*rmp));
558   rmp->_vl_msg_id = ntohs (VL_API_NAT44_INTERFACE_DETAILS + sm->msg_id_base);
559   rmp->sw_if_index = ntohl (i->sw_if_index);
560   rmp->is_inside = (nat_interface_is_inside (i)
561                     && nat_interface_is_outside (i)) ? 2 :
562     nat_interface_is_inside (i);
563   rmp->context = context;
564
565   vl_msg_api_send_shmem (q, (u8 *) & rmp);
566 }
567
568 static void
569 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
570 {
571   unix_shared_memory_queue_t *q;
572   snat_main_t *sm = &snat_main;
573   snat_interface_t *i;
574
575   q = vl_api_client_index_to_input_queue (mp->client_index);
576   if (q == 0)
577     return;
578
579   /* *INDENT-OFF* */
580   pool_foreach (i, sm->interfaces,
581   ({
582     send_nat44_interface_details(i, q, mp->context);
583   }));
584   /* *INDENT-ON* */
585 }
586
587 static void *
588 vl_api_nat44_interface_dump_t_print (vl_api_nat44_interface_dump_t * mp,
589                                      void *handle)
590 {
591   u8 *s;
592
593   s = format (0, "SCRIPT: nat44_interface_dump ");
594
595   FINISH;
596 }
597
598 static void
599   vl_api_nat44_interface_add_del_output_feature_t_handler
600   (vl_api_nat44_interface_add_del_output_feature_t * mp)
601 {
602   snat_main_t *sm = &snat_main;
603   vl_api_nat44_interface_add_del_output_feature_reply_t *rmp;
604   u8 is_del = mp->is_add == 0;
605   u32 sw_if_index = ntohl (mp->sw_if_index);
606   int rv = 0;
607
608   VALIDATE_SW_IF_INDEX (mp);
609
610   rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
611                                               is_del);
612
613   BAD_SW_IF_INDEX_LABEL;
614
615   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
616 }
617
618 static void *vl_api_nat44_interface_add_del_output_feature_t_print
619   (vl_api_nat44_interface_add_del_output_feature_t * mp, void *handle)
620 {
621   u8 *s;
622
623   s = format (0, "SCRIPT: nat44_interface_add_del_output_feature ");
624   s = format (s, "sw_if_index %d %s %s",
625               clib_host_to_net_u32 (mp->sw_if_index),
626               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
627
628   FINISH;
629 }
630
631 static void
632 send_nat44_interface_output_feature_details (snat_interface_t * i,
633                                              unix_shared_memory_queue_t * q,
634                                              u32 context)
635 {
636   vl_api_nat44_interface_output_feature_details_t *rmp;
637   snat_main_t *sm = &snat_main;
638
639   rmp = vl_msg_api_alloc (sizeof (*rmp));
640   memset (rmp, 0, sizeof (*rmp));
641   rmp->_vl_msg_id =
642     ntohs (VL_API_NAT44_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
643   rmp->sw_if_index = ntohl (i->sw_if_index);
644   rmp->context = context;
645   rmp->is_inside = nat_interface_is_inside (i);
646
647   vl_msg_api_send_shmem (q, (u8 *) & rmp);
648 }
649
650 static void
651   vl_api_nat44_interface_output_feature_dump_t_handler
652   (vl_api_nat44_interface_output_feature_dump_t * mp)
653 {
654   unix_shared_memory_queue_t *q;
655   snat_main_t *sm = &snat_main;
656   snat_interface_t *i;
657
658   q = vl_api_client_index_to_input_queue (mp->client_index);
659   if (q == 0)
660     return;
661
662   /* *INDENT-OFF* */
663   pool_foreach (i, sm->output_feature_interfaces,
664   ({
665     send_nat44_interface_output_feature_details(i, q, mp->context);
666   }));
667   /* *INDENT-ON* */
668 }
669
670 static void *vl_api_nat44_interface_output_feature_dump_t_print
671   (vl_api_nat44_interface_output_feature_dump_t * mp, void *handle)
672 {
673   u8 *s;
674
675   s = format (0, "SCRIPT: nat44_interface_output_feature_dump ");
676
677   FINISH;
678 }
679
680 static void
681   vl_api_nat44_add_del_static_mapping_t_handler
682   (vl_api_nat44_add_del_static_mapping_t * mp)
683 {
684   snat_main_t *sm = &snat_main;
685   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
686   ip4_address_t local_addr, external_addr;
687   u16 local_port = 0, external_port = 0;
688   u32 vrf_id, external_sw_if_index;
689   int rv = 0;
690   snat_protocol_t proto;
691
692   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
693   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
694   if (mp->addr_only == 0)
695     {
696       local_port = clib_net_to_host_u16 (mp->local_port);
697       external_port = clib_net_to_host_u16 (mp->external_port);
698     }
699   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
700   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
701   proto = ip_proto_to_snat_proto (mp->protocol);
702
703   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
704                                 external_port, vrf_id, mp->addr_only,
705                                 external_sw_if_index, proto, mp->is_add);
706
707   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
708 }
709
710 static void *vl_api_nat44_add_del_static_mapping_t_print
711   (vl_api_nat44_add_del_static_mapping_t * mp, void *handle)
712 {
713   u8 *s;
714
715   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
716   s = format (s, "protocol %d local_addr %U external_addr %U ",
717               mp->protocol,
718               format_ip4_address, mp->local_ip_address,
719               format_ip4_address, mp->external_ip_address);
720
721   if (mp->addr_only == 0)
722     s = format (s, "local_port %d external_port %d ",
723                 clib_net_to_host_u16 (mp->local_port),
724                 clib_net_to_host_u16 (mp->external_port));
725
726   if (mp->vrf_id != ~0)
727     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
728
729   if (mp->external_sw_if_index != ~0)
730     s = format (s, "external_sw_if_index %d",
731                 clib_net_to_host_u32 (mp->external_sw_if_index));
732   FINISH;
733 }
734
735 static void
736 send_nat44_static_mapping_details (snat_static_mapping_t * m,
737                                    unix_shared_memory_queue_t * q,
738                                    u32 context)
739 {
740   vl_api_nat44_static_mapping_details_t *rmp;
741   snat_main_t *sm = &snat_main;
742
743   rmp = vl_msg_api_alloc (sizeof (*rmp));
744   memset (rmp, 0, sizeof (*rmp));
745   rmp->_vl_msg_id =
746     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
747   rmp->addr_only = m->addr_only;
748   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
749   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
750   rmp->local_port = htons (m->local_port);
751   rmp->external_port = htons (m->external_port);
752   rmp->external_sw_if_index = ~0;
753   rmp->vrf_id = htonl (m->vrf_id);
754   rmp->protocol = snat_proto_to_ip_proto (m->proto);
755   rmp->context = context;
756
757   vl_msg_api_send_shmem (q, (u8 *) & rmp);
758 }
759
760 static void
761 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
762                                        unix_shared_memory_queue_t * q,
763                                        u32 context)
764 {
765   vl_api_nat44_static_mapping_details_t *rmp;
766   snat_main_t *sm = &snat_main;
767
768   rmp = vl_msg_api_alloc (sizeof (*rmp));
769   memset (rmp, 0, sizeof (*rmp));
770   rmp->_vl_msg_id =
771     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
772   rmp->addr_only = m->addr_only;
773   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
774   rmp->local_port = htons (m->l_port);
775   rmp->external_port = htons (m->e_port);
776   rmp->external_sw_if_index = htonl (m->sw_if_index);
777   rmp->vrf_id = htonl (m->vrf_id);
778   rmp->protocol = snat_proto_to_ip_proto (m->proto);
779   rmp->context = context;
780
781   vl_msg_api_send_shmem (q, (u8 *) & rmp);
782 }
783
784 static void
785 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
786                                             * mp)
787 {
788   unix_shared_memory_queue_t *q;
789   snat_main_t *sm = &snat_main;
790   snat_static_mapping_t *m;
791   snat_static_map_resolve_t *rp;
792   int j;
793
794   q = vl_api_client_index_to_input_queue (mp->client_index);
795   if (q == 0)
796     return;
797
798   /* *INDENT-OFF* */
799   pool_foreach (m, sm->static_mappings,
800   ({
801       if (!vec_len(m->locals) && (m->local_addr.as_u32 != m->external_addr.as_u32))
802         send_nat44_static_mapping_details (m, q, mp->context);
803   }));
804   /* *INDENT-ON* */
805
806   for (j = 0; j < vec_len (sm->to_resolve); j++)
807     {
808       rp = sm->to_resolve + j;
809       if (rp->l_addr.as_u32 != 0)
810         send_nat44_static_map_resolve_details (rp, q, mp->context);
811     }
812 }
813
814 static void *
815 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
816                                           mp, void *handle)
817 {
818   u8 *s;
819
820   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
821
822   FINISH;
823 }
824
825 static void
826   vl_api_nat44_add_del_identity_mapping_t_handler
827   (vl_api_nat44_add_del_identity_mapping_t * mp)
828 {
829   snat_main_t *sm = &snat_main;
830   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
831   ip4_address_t addr;
832   u16 port = 0;
833   u32 vrf_id, sw_if_index;
834   int rv = 0;
835   snat_protocol_t proto = ~0;
836
837   if (mp->addr_only == 0)
838     {
839       port = clib_net_to_host_u16 (mp->port);
840       proto = ip_proto_to_snat_proto (mp->protocol);
841     }
842   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
843   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
844   if (sw_if_index != ~0)
845     addr.as_u32 = 0;
846   else
847     memcpy (&addr.as_u8, mp->ip_address, 4);
848
849
850   rv =
851     snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only,
852                              sw_if_index, proto, mp->is_add);
853
854   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
855 }
856
857 static void *vl_api_nat44_add_del_identity_mapping_t_print
858   (vl_api_nat44_add_del_identity_mapping_t * mp, void *handle)
859 {
860   u8 *s;
861
862   s = format (0, "SCRIPT: nat44_add_del_identity_mapping ");
863   if (mp->sw_if_index != ~0)
864     s = format (s, "sw_if_index %d", clib_net_to_host_u32 (mp->sw_if_index));
865   else
866     s = format (s, "addr %U", format_ip4_address, mp->ip_address);
867
868   if (mp->addr_only == 0)
869     s =
870       format (s, "protocol %d port %d", mp->protocol,
871               clib_net_to_host_u16 (mp->port));
872
873   if (mp->vrf_id != ~0)
874     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
875
876   FINISH;
877 }
878
879 static void
880 send_nat44_identity_mapping_details (snat_static_mapping_t * m,
881                                      unix_shared_memory_queue_t * q,
882                                      u32 context)
883 {
884   vl_api_nat44_identity_mapping_details_t *rmp;
885   snat_main_t *sm = &snat_main;
886
887   rmp = vl_msg_api_alloc (sizeof (*rmp));
888   memset (rmp, 0, sizeof (*rmp));
889   rmp->_vl_msg_id =
890     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
891   rmp->addr_only = m->addr_only;
892   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
893   rmp->port = htons (m->local_port);
894   rmp->sw_if_index = ~0;
895   rmp->vrf_id = htonl (m->vrf_id);
896   rmp->protocol = snat_proto_to_ip_proto (m->proto);
897   rmp->context = context;
898
899   vl_msg_api_send_shmem (q, (u8 *) & rmp);
900 }
901
902 static void
903 send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
904                                          unix_shared_memory_queue_t * q,
905                                          u32 context)
906 {
907   vl_api_nat44_identity_mapping_details_t *rmp;
908   snat_main_t *sm = &snat_main;
909
910   rmp = vl_msg_api_alloc (sizeof (*rmp));
911   memset (rmp, 0, sizeof (*rmp));
912   rmp->_vl_msg_id =
913     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
914   rmp->addr_only = m->addr_only;
915   rmp->port = htons (m->l_port);
916   rmp->sw_if_index = htonl (m->sw_if_index);
917   rmp->vrf_id = htonl (m->vrf_id);
918   rmp->protocol = snat_proto_to_ip_proto (m->proto);
919   rmp->context = context;
920
921   vl_msg_api_send_shmem (q, (u8 *) & rmp);
922 }
923
924 static void
925   vl_api_nat44_identity_mapping_dump_t_handler
926   (vl_api_nat44_identity_mapping_dump_t * mp)
927 {
928   unix_shared_memory_queue_t *q;
929   snat_main_t *sm = &snat_main;
930   snat_static_mapping_t *m;
931   snat_static_map_resolve_t *rp;
932   int j;
933
934   q = vl_api_client_index_to_input_queue (mp->client_index);
935   if (q == 0)
936     return;
937
938   /* *INDENT-OFF* */
939   pool_foreach (m, sm->static_mappings,
940   ({
941       if (!vec_len(m->locals) && (m->local_addr.as_u32 == m->external_addr.as_u32))
942         send_nat44_identity_mapping_details (m, q, mp->context);
943   }));
944   /* *INDENT-ON* */
945
946   for (j = 0; j < vec_len (sm->to_resolve); j++)
947     {
948       rp = sm->to_resolve + j;
949       if (rp->l_addr.as_u32 == 0)
950         send_nat44_identity_map_resolve_details (rp, q, mp->context);
951     }
952 }
953
954 static void *vl_api_nat44_identity_mapping_dump_t_print
955   (vl_api_nat44_identity_mapping_dump_t * mp, void *handle)
956 {
957   u8 *s;
958
959   s = format (0, "SCRIPT: nat44_identity_mapping_dump ");
960
961   FINISH;
962 }
963
964 static void
965   vl_api_nat44_add_del_interface_addr_t_handler
966   (vl_api_nat44_add_del_interface_addr_t * mp)
967 {
968   snat_main_t *sm = &snat_main;
969   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
970   u8 is_del = mp->is_add == 0;
971   u32 sw_if_index = ntohl (mp->sw_if_index);
972   int rv = 0;
973
974   VALIDATE_SW_IF_INDEX (mp);
975
976   rv = snat_add_interface_address (sm, sw_if_index, is_del);
977
978   BAD_SW_IF_INDEX_LABEL;
979
980   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
981 }
982
983 static void *vl_api_nat44_add_del_interface_addr_t_print
984   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
985 {
986   u8 *s;
987
988   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
989   s = format (s, "sw_if_index %d %s",
990               clib_host_to_net_u32 (mp->sw_if_index),
991               mp->is_add ? "" : "del");
992
993   FINISH;
994 }
995
996 static void
997 send_nat44_interface_addr_details (u32 sw_if_index,
998                                    unix_shared_memory_queue_t * q,
999                                    u32 context)
1000 {
1001   vl_api_nat44_interface_addr_details_t *rmp;
1002   snat_main_t *sm = &snat_main;
1003
1004   rmp = vl_msg_api_alloc (sizeof (*rmp));
1005   memset (rmp, 0, sizeof (*rmp));
1006   rmp->_vl_msg_id =
1007     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1008   rmp->sw_if_index = ntohl (sw_if_index);
1009   rmp->context = context;
1010
1011   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1012 }
1013
1014 static void
1015 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1016                                             * mp)
1017 {
1018   unix_shared_memory_queue_t *q;
1019   snat_main_t *sm = &snat_main;
1020   u32 *i;
1021
1022   q = vl_api_client_index_to_input_queue (mp->client_index);
1023   if (q == 0)
1024     return;
1025
1026   /* *INDENT-OFF* */
1027   vec_foreach (i, sm->auto_add_sw_if_indices)
1028     send_nat44_interface_addr_details(*i, q, mp->context);
1029   /* *INDENT-ON* */
1030 }
1031
1032 static void *
1033 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1034                                           mp, void *handle)
1035 {
1036   u8 *s;
1037
1038   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
1039
1040   FINISH;
1041 }
1042
1043 static void
1044 send_nat44_user_details (snat_user_t * u, unix_shared_memory_queue_t * q,
1045                          u32 context)
1046 {
1047   vl_api_nat44_user_details_t *rmp;
1048   snat_main_t *sm = &snat_main;
1049   fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1050
1051   rmp = vl_msg_api_alloc (sizeof (*rmp));
1052   memset (rmp, 0, sizeof (*rmp));
1053   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1054
1055   rmp->vrf_id = ntohl (fib->ft_table_id);
1056
1057   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1058   rmp->nsessions = ntohl (u->nsessions);
1059   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1060   rmp->context = context;
1061
1062   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1063 }
1064
1065 static void
1066 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1067 {
1068   unix_shared_memory_queue_t *q;
1069   snat_main_t *sm = &snat_main;
1070   snat_main_per_thread_data_t *tsm;
1071   snat_user_t *u;
1072
1073   q = vl_api_client_index_to_input_queue (mp->client_index);
1074   if (q == 0)
1075     return;
1076
1077   /* *INDENT-OFF* */
1078   vec_foreach (tsm, sm->per_thread_data)
1079     vec_foreach (u, tsm->users)
1080       send_nat44_user_details (u, q, mp->context);
1081   /* *INDENT-ON* */
1082 }
1083
1084 static void *
1085 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
1086 {
1087   u8 *s;
1088
1089   s = format (0, "SCRIPT: nat44_user_dump ");
1090
1091   FINISH;
1092 }
1093
1094 static void
1095 send_nat44_user_session_details (snat_session_t * s,
1096                                  unix_shared_memory_queue_t * q, u32 context)
1097 {
1098   vl_api_nat44_user_session_details_t *rmp;
1099   snat_main_t *sm = &snat_main;
1100
1101   rmp = vl_msg_api_alloc (sizeof (*rmp));
1102   memset (rmp, 0, sizeof (*rmp));
1103   rmp->_vl_msg_id =
1104     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1105   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1106   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1107   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
1108   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1109   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1110   rmp->total_pkts = ntohl (s->total_pkts);
1111   rmp->context = context;
1112   if (snat_is_unk_proto_session (s))
1113     {
1114       rmp->outside_port = 0;
1115       rmp->inside_port = 0;
1116       rmp->protocol = ntohs (s->in2out.port);
1117     }
1118   else
1119     {
1120       rmp->outside_port = s->out2in.port;
1121       rmp->inside_port = s->in2out.port;
1122       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
1123     }
1124
1125   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1126 }
1127
1128 static void
1129 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1130                                           mp)
1131 {
1132   unix_shared_memory_queue_t *q;
1133   snat_main_t *sm = &snat_main;
1134   snat_main_per_thread_data_t *tsm;
1135   snat_session_t *s;
1136   clib_bihash_kv_8_8_t key, value;
1137   snat_user_key_t ukey;
1138   snat_user_t *u;
1139   u32 session_index, head_index, elt_index;
1140   dlist_elt_t *head, *elt;
1141   ip4_header_t ip;
1142
1143   q = vl_api_client_index_to_input_queue (mp->client_index);
1144   if (q == 0)
1145     return;
1146
1147   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1148   ip.src_address.as_u32 = ukey.addr.as_u32;
1149   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1150   key.key = ukey.as_u64;
1151   if (sm->num_workers)
1152     tsm =
1153       vec_elt_at_index (sm->per_thread_data,
1154                         sm->worker_in2out_cb (&ip, ukey.fib_index));
1155   else
1156     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1157   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1158     return;
1159   u = pool_elt_at_index (tsm->users, value.value);
1160   if (!u->nsessions && !u->nstaticsessions)
1161     return;
1162
1163   head_index = u->sessions_per_user_list_head_index;
1164   head = pool_elt_at_index (tsm->list_pool, head_index);
1165   elt_index = head->next;
1166   elt = pool_elt_at_index (tsm->list_pool, elt_index);
1167   session_index = elt->value;
1168   while (session_index != ~0)
1169     {
1170       s = pool_elt_at_index (tsm->sessions, session_index);
1171
1172       send_nat44_user_session_details (s, q, mp->context);
1173
1174       elt_index = elt->next;
1175       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1176       session_index = elt->value;
1177     }
1178 }
1179
1180 static void *
1181 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
1182                                         void *handle)
1183 {
1184   u8 *s;
1185
1186   s = format (0, "SCRIPT: nat44_user_session_dump ");
1187   s = format (s, "ip_address %U vrf_id %d\n",
1188               format_ip4_address, mp->ip_address,
1189               clib_net_to_host_u32 (mp->vrf_id));
1190
1191   FINISH;
1192 }
1193
1194 static nat44_lb_addr_port_t *
1195 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1196                              u8 addr_port_pair_num)
1197 {
1198   u8 i;
1199   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1200   vl_api_nat44_lb_addr_port_t *ap;
1201
1202   for (i = 0; i < addr_port_pair_num; i++)
1203     {
1204       ap = &addr_port_pairs[i];
1205       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1206       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1207       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
1208       lb_addr_port.probability = ap->probability;
1209       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1210     }
1211
1212   return lb_addr_port_pairs;
1213 }
1214
1215 static void
1216   vl_api_nat44_add_del_lb_static_mapping_t_handler
1217   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1218 {
1219   snat_main_t *sm = &snat_main;
1220   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1221   int rv = 0;
1222   nat44_lb_addr_port_t *locals = 0;
1223   ip4_address_t e_addr;
1224   snat_protocol_t proto;
1225
1226   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
1227   clib_memcpy (&e_addr, mp->external_addr, 4);
1228   proto = ip_proto_to_snat_proto (mp->protocol);
1229
1230   rv =
1231     nat44_add_del_lb_static_mapping (e_addr,
1232                                      clib_net_to_host_u16 (mp->external_port),
1233                                      proto, clib_net_to_host_u32 (mp->vrf_id),
1234                                      locals, mp->is_add);
1235
1236   vec_free (locals);
1237
1238   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1239 }
1240
1241 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1242   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1243 {
1244   u8 *s;
1245
1246   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1247   s = format (s, "is_add %d\n", mp->is_add);
1248
1249   FINISH;
1250 }
1251
1252 static void
1253 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1254                                       unix_shared_memory_queue_t * q,
1255                                       u32 context)
1256 {
1257   vl_api_nat44_lb_static_mapping_details_t *rmp;
1258   snat_main_t *sm = &snat_main;
1259   nat44_lb_addr_port_t *ap;
1260   vl_api_nat44_lb_addr_port_t *locals;
1261
1262   rmp =
1263     vl_msg_api_alloc (sizeof (*rmp) +
1264                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
1265   memset (rmp, 0, sizeof (*rmp));
1266   rmp->_vl_msg_id =
1267     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1268
1269   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1270   rmp->external_port = ntohs (m->external_port);
1271   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1272   rmp->vrf_id = ntohl (m->vrf_id);
1273   rmp->context = context;
1274
1275   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1276   vec_foreach (ap, m->locals)
1277   {
1278     clib_memcpy (locals->addr, &(ap->addr), 4);
1279     locals->port = htons (ap->port);
1280     locals->probability = ap->probability;
1281     locals++;
1282     rmp->local_num++;
1283   }
1284
1285   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1286 }
1287
1288 static void
1289   vl_api_nat44_lb_static_mapping_dump_t_handler
1290   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1291 {
1292   unix_shared_memory_queue_t *q;
1293   snat_main_t *sm = &snat_main;
1294   snat_static_mapping_t *m;
1295
1296   q = vl_api_client_index_to_input_queue (mp->client_index);
1297   if (q == 0)
1298     return;
1299
1300   /* *INDENT-OFF* */
1301   pool_foreach (m, sm->static_mappings,
1302   ({
1303       if (vec_len(m->locals))
1304         send_nat44_lb_static_mapping_details (m, q, mp->context);
1305   }));
1306   /* *INDENT-ON* */
1307 }
1308
1309 static void *vl_api_nat44_lb_static_mapping_dump_t_print
1310   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
1311 {
1312   u8 *s;
1313
1314   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
1315
1316   FINISH;
1317 }
1318
1319 static void
1320 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1321 {
1322   snat_main_t *sm = &snat_main;
1323   vl_api_nat44_del_session_reply_t *rmp;
1324   ip4_address_t addr;
1325   u16 port;
1326   u32 vrf_id;
1327   int rv = 0;
1328   snat_protocol_t proto;
1329
1330   memcpy (&addr.as_u8, mp->address, 4);
1331   port = clib_net_to_host_u16 (mp->port);
1332   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1333   proto = ip_proto_to_snat_proto (mp->protocol);
1334
1335   rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
1336
1337   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1338 }
1339
1340 static void *
1341 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
1342                                   void *handle)
1343 {
1344   u8 *s;
1345
1346   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1347   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
1348               format_ip4_address, mp->address,
1349               clib_net_to_host_u16 (mp->port),
1350               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
1351
1352   FINISH;
1353 }
1354
1355 /*******************************/
1356 /*** Deterministic NAT (CGN) ***/
1357 /*******************************/
1358
1359 static void
1360 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
1361 {
1362   snat_main_t *sm = &snat_main;
1363   vl_api_nat_det_add_del_map_reply_t *rmp;
1364   int rv = 0;
1365   ip4_address_t in_addr, out_addr;
1366
1367   if (!mp->is_nat44)
1368     {
1369       rv = VNET_API_ERROR_UNIMPLEMENTED;
1370       goto send_reply;
1371     }
1372
1373   clib_memcpy (&in_addr, mp->in_addr, 4);
1374   clib_memcpy (&out_addr, mp->out_addr, 4);
1375   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
1376                          mp->out_plen, mp->is_add);
1377
1378 send_reply:
1379   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
1380 }
1381
1382 static void *
1383 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
1384                                     void *handle)
1385 {
1386   u8 *s;
1387
1388   s = format (0, "SCRIPT: nat_det_add_del_map ");
1389   s = format (s, "inside address %U/%d outside address %U/%d\n",
1390               format_ip4_address, mp->in_addr, mp->in_plen,
1391               format_ip4_address, mp->out_addr, mp->out_plen);
1392
1393   FINISH;
1394 }
1395
1396 static void
1397 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
1398 {
1399   snat_main_t *sm = &snat_main;
1400   vl_api_nat_det_forward_reply_t *rmp;
1401   int rv = 0;
1402   u16 lo_port = 0, hi_port = 0;
1403   snat_det_map_t *dm;
1404   ip4_address_t in_addr, out_addr;
1405
1406   if (!mp->is_nat44)
1407     {
1408       out_addr.as_u32 = 0;
1409       rv = VNET_API_ERROR_UNIMPLEMENTED;
1410       goto send_reply;
1411     }
1412
1413   out_addr.as_u32 = 0;
1414   clib_memcpy (&in_addr, mp->in_addr, 4);
1415   dm = snat_det_map_by_user (sm, &in_addr);
1416   if (!dm)
1417     {
1418       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1419       goto send_reply;
1420     }
1421
1422   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1423   hi_port = lo_port + dm->ports_per_host - 1;
1424
1425 send_reply:
1426   /* *INDENT-OFF* */
1427   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
1428   ({
1429     rmp->out_port_lo = ntohs (lo_port);
1430     rmp->out_port_hi = ntohs (hi_port);
1431     clib_memcpy (rmp->out_addr, &out_addr, 4);
1432   }))
1433   /* *INDENT-ON* */
1434 }
1435
1436 static void *
1437 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
1438 {
1439   u8 *s;
1440
1441   s = format (0, "SCRIPT: nat_det_forward");
1442   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
1443
1444   FINISH;
1445 }
1446
1447 static void
1448 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
1449 {
1450   snat_main_t *sm = &snat_main;
1451   vl_api_nat_det_reverse_reply_t *rmp;
1452   int rv = 0;
1453   ip4_address_t out_addr, in_addr;
1454   snat_det_map_t *dm;
1455
1456   in_addr.as_u32 = 0;
1457   clib_memcpy (&out_addr, mp->out_addr, 4);
1458   dm = snat_det_map_by_out (sm, &out_addr);
1459   if (!dm)
1460     {
1461       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1462       goto send_reply;
1463     }
1464
1465   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1466
1467 send_reply:
1468   /* *INDENT-OFF* */
1469   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
1470   ({
1471     rmp->is_nat44 = 1;
1472     memset (rmp->in_addr, 0, 16);
1473     clib_memcpy (rmp->in_addr, &in_addr, 4);
1474   }))
1475   /* *INDENT-ON* */
1476 }
1477
1478 static void *
1479 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
1480 {
1481   u8 *s;
1482
1483   s = format (0, "SCRIPT: nat_det_reverse");
1484   s = format (s, "outside ip address %U outside port %d",
1485               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1486
1487   FINISH;
1488 }
1489
1490 static void
1491 sent_nat_det_map_details (snat_det_map_t * m, unix_shared_memory_queue_t * q,
1492                           u32 context)
1493 {
1494   vl_api_nat_det_map_details_t *rmp;
1495   snat_main_t *sm = &snat_main;
1496
1497   rmp = vl_msg_api_alloc (sizeof (*rmp));
1498   memset (rmp, 0, sizeof (*rmp));
1499   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
1500   rmp->is_nat44 = 1;
1501   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
1502   rmp->in_plen = m->in_plen;
1503   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
1504   rmp->out_plen = m->out_plen;
1505   rmp->sharing_ratio = htonl (m->sharing_ratio);
1506   rmp->ports_per_host = htons (m->ports_per_host);
1507   rmp->ses_num = htonl (m->ses_num);
1508   rmp->context = context;
1509
1510   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1511 }
1512
1513 static void
1514 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
1515 {
1516   unix_shared_memory_queue_t *q;
1517   snat_main_t *sm = &snat_main;
1518   snat_det_map_t *m;
1519
1520   q = vl_api_client_index_to_input_queue (mp->client_index);
1521   if (q == 0)
1522     return;
1523
1524   /* *INDENT-OFF* */
1525   vec_foreach(m, sm->det_maps)
1526     sent_nat_det_map_details(m, q, mp->context);
1527   /* *INDENT-ON* */
1528 }
1529
1530 static void *
1531 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
1532 {
1533   u8 *s;
1534
1535   s = format (0, "SCRIPT: nat_det_map_dump ");
1536
1537   FINISH;
1538 }
1539
1540 static void
1541 vl_api_nat_det_set_timeouts_t_handler (vl_api_nat_det_set_timeouts_t * mp)
1542 {
1543   snat_main_t *sm = &snat_main;
1544   vl_api_nat_det_set_timeouts_reply_t *rmp;
1545   int rv = 0;
1546
1547   sm->udp_timeout = ntohl (mp->udp);
1548   sm->tcp_established_timeout = ntohl (mp->tcp_established);
1549   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
1550   sm->icmp_timeout = ntohl (mp->icmp);
1551
1552   REPLY_MACRO (VL_API_NAT_DET_SET_TIMEOUTS_REPLY);
1553 }
1554
1555 static void *
1556 vl_api_nat_det_set_timeouts_t_print (vl_api_nat_det_set_timeouts_t * mp,
1557                                      void *handle)
1558 {
1559   u8 *s;
1560
1561   s = format (0, "SCRIPT: nat_det_set_timeouts ");
1562   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
1563               ntohl (mp->udp),
1564               ntohl (mp->tcp_established),
1565               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1566
1567   FINISH;
1568 }
1569
1570 static void
1571 vl_api_nat_det_get_timeouts_t_handler (vl_api_nat_det_get_timeouts_t * mp)
1572 {
1573   snat_main_t *sm = &snat_main;
1574   vl_api_nat_det_get_timeouts_reply_t *rmp;
1575   int rv = 0;
1576
1577   /* *INDENT-OFF* */
1578   REPLY_MACRO2 (VL_API_NAT_DET_GET_TIMEOUTS_REPLY,
1579   ({
1580     rmp->udp = htonl (sm->udp_timeout);
1581     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1582     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1583     rmp->icmp = htonl (sm->icmp_timeout);
1584   }))
1585   /* *INDENT-ON* */
1586 }
1587
1588 static void *
1589 vl_api_nat_det_get_timeouts_t_print (vl_api_nat_det_get_timeouts_t * mp,
1590                                      void *handle)
1591 {
1592   u8 *s;
1593
1594   s = format (0, "SCRIPT: nat_det_get_timeouts");
1595
1596   FINISH;
1597 }
1598
1599 static void
1600 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
1601                                             * mp)
1602 {
1603   snat_main_t *sm = &snat_main;
1604   vl_api_nat_det_close_session_out_reply_t *rmp;
1605   ip4_address_t out_addr, ext_addr, in_addr;
1606   snat_det_out_key_t key;
1607   snat_det_map_t *dm;
1608   snat_det_session_t *ses;
1609   int rv = 0;
1610
1611   clib_memcpy (&out_addr, mp->out_addr, 4);
1612   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1613
1614   dm = snat_det_map_by_out (sm, &out_addr);
1615   if (!dm)
1616     {
1617       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1618       goto send_reply;
1619     }
1620   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1621   key.ext_host_addr = ext_addr;
1622   key.ext_host_port = mp->ext_port;
1623   key.out_port = mp->out_port;
1624   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1625   if (!ses)
1626     {
1627       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1628       goto send_reply;
1629     }
1630   snat_det_ses_close (dm, ses);
1631
1632 send_reply:
1633   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
1634 }
1635
1636 static void *
1637 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
1638                                           mp, void *handle)
1639 {
1640   u8 *s;
1641
1642   s = format (0, "SCRIPT: nat_det_close_session_out ");
1643   s = format (s, "out_addr %U out_port %d "
1644               "ext_addr %U ext_port %d\n",
1645               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1646               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1647
1648   FINISH;
1649 }
1650
1651 static void
1652 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
1653                                            mp)
1654 {
1655   snat_main_t *sm = &snat_main;
1656   vl_api_nat_det_close_session_in_reply_t *rmp;
1657   ip4_address_t in_addr, ext_addr;
1658   snat_det_out_key_t key;
1659   snat_det_map_t *dm;
1660   snat_det_session_t *ses;
1661   int rv = 0;
1662
1663   if (!mp->is_nat44)
1664     {
1665       rv = VNET_API_ERROR_UNIMPLEMENTED;
1666       goto send_reply;
1667     }
1668
1669   clib_memcpy (&in_addr, mp->in_addr, 4);
1670   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1671
1672   dm = snat_det_map_by_user (sm, &in_addr);
1673   if (!dm)
1674     {
1675       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1676       goto send_reply;
1677     }
1678   key.ext_host_addr = ext_addr;
1679   key.ext_host_port = mp->ext_port;
1680   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1681   if (!ses)
1682     {
1683       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1684       goto send_reply;
1685     }
1686   snat_det_ses_close (dm, ses);
1687
1688 send_reply:
1689   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
1690 }
1691
1692 static void *
1693 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
1694                                          mp, void *handle)
1695 {
1696   u8 *s;
1697   s = format (0, "SCRIPT: nat_det_close_session_in ");
1698   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
1699               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
1700               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1701
1702   FINISH;
1703 }
1704
1705 static void
1706 send_nat_det_session_details (snat_det_session_t * s,
1707                               unix_shared_memory_queue_t * q, u32 context)
1708 {
1709   vl_api_nat_det_session_details_t *rmp;
1710   snat_main_t *sm = &snat_main;
1711
1712   rmp = vl_msg_api_alloc (sizeof (*rmp));
1713   memset (rmp, 0, sizeof (*rmp));
1714   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
1715   rmp->in_port = s->in_port;
1716   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
1717   rmp->ext_port = s->out.ext_host_port;
1718   rmp->out_port = s->out.out_port;
1719   rmp->state = s->state;
1720   rmp->expire = ntohl (s->expire);
1721   rmp->context = context;
1722
1723   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1724 }
1725
1726 static void
1727 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
1728 {
1729   unix_shared_memory_queue_t *q;
1730   snat_main_t *sm = &snat_main;
1731   ip4_address_t user_addr;
1732   snat_det_map_t *dm;
1733   snat_det_session_t *s, empty_ses;
1734   u16 i;
1735
1736   q = vl_api_client_index_to_input_queue (mp->client_index);
1737   if (q == 0)
1738     return;
1739   if (!mp->is_nat44)
1740     return;
1741
1742   memset (&empty_ses, 0, sizeof (empty_ses));
1743   clib_memcpy (&user_addr, mp->user_addr, 4);
1744   dm = snat_det_map_by_user (sm, &user_addr);
1745   if (!dm)
1746     return;
1747
1748   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
1749   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
1750     {
1751       if (s->out.as_u64)
1752         send_nat_det_session_details (s, q, mp->context);
1753       s++;
1754     }
1755 }
1756
1757 static void *
1758 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
1759                                      void *handle)
1760 {
1761   u8 *s;
1762
1763   s = format (0, "SCRIPT: nat_det_session_dump ");
1764   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
1765
1766   FINISH;
1767 }
1768
1769 /*************/
1770 /*** NAT64 ***/
1771 /*************/
1772
1773 static void
1774   vl_api_nat64_add_del_pool_addr_range_t_handler
1775   (vl_api_nat64_add_del_pool_addr_range_t * mp)
1776 {
1777   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
1778   snat_main_t *sm = &snat_main;
1779   int rv = 0;
1780   ip4_address_t this_addr;
1781   u32 start_host_order, end_host_order;
1782   u32 vrf_id;
1783   int i, count;
1784   u32 *tmp;
1785
1786   tmp = (u32 *) mp->start_addr;
1787   start_host_order = clib_host_to_net_u32 (tmp[0]);
1788   tmp = (u32 *) mp->end_addr;
1789   end_host_order = clib_host_to_net_u32 (tmp[0]);
1790
1791   count = (end_host_order - start_host_order) + 1;
1792
1793   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
1794
1795   memcpy (&this_addr.as_u8, mp->start_addr, 4);
1796
1797   for (i = 0; i < count; i++)
1798     {
1799       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
1800         goto send_reply;
1801
1802       increment_v4_address (&this_addr);
1803     }
1804
1805 send_reply:
1806   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
1807 }
1808
1809 static void *vl_api_nat64_add_del_pool_addr_range_t_print
1810   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
1811 {
1812   u8 *s;
1813
1814   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
1815   s = format (s, "%U - %U vrf_id %u %s\n",
1816               format_ip4_address, mp->start_addr,
1817               format_ip4_address, mp->end_addr,
1818               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
1819
1820   FINISH;
1821 }
1822
1823 typedef struct nat64_api_walk_ctx_t_
1824 {
1825   unix_shared_memory_queue_t *q;
1826   u32 context;
1827   nat64_db_t *db;
1828 } nat64_api_walk_ctx_t;
1829
1830 static int
1831 nat64_api_pool_walk (snat_address_t * a, void *arg)
1832 {
1833   vl_api_nat64_pool_addr_details_t *rmp;
1834   snat_main_t *sm = &snat_main;
1835   nat64_api_walk_ctx_t *ctx = arg;
1836
1837   rmp = vl_msg_api_alloc (sizeof (*rmp));
1838   memset (rmp, 0, sizeof (*rmp));
1839   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
1840   clib_memcpy (rmp->address, &(a->addr), 4);
1841   if (a->fib_index != ~0)
1842     {
1843       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
1844       if (!fib)
1845         return -1;
1846       rmp->vrf_id = ntohl (fib->ft_table_id);
1847     }
1848   else
1849     rmp->vrf_id = ~0;
1850   rmp->context = ctx->context;
1851
1852   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1853
1854   return 0;
1855 }
1856
1857 static void
1858 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
1859 {
1860   unix_shared_memory_queue_t *q;
1861
1862   q = vl_api_client_index_to_input_queue (mp->client_index);
1863   if (q == 0)
1864     return;
1865
1866   nat64_api_walk_ctx_t ctx = {
1867     .q = q,
1868     .context = mp->context,
1869   };
1870
1871   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
1872 }
1873
1874 static void *
1875 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
1876                                      void *handle)
1877 {
1878   u8 *s;
1879
1880   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
1881
1882   FINISH;
1883 }
1884
1885 static void
1886 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
1887                                           mp)
1888 {
1889   snat_main_t *sm = &snat_main;
1890   vl_api_nat64_add_del_interface_reply_t *rmp;
1891   int rv = 0;
1892
1893   VALIDATE_SW_IF_INDEX (mp);
1894
1895   rv =
1896     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
1897                              mp->is_add);
1898
1899   BAD_SW_IF_INDEX_LABEL;
1900
1901   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
1902 }
1903
1904 static void *
1905 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
1906                                         void *handle)
1907 {
1908   u8 *s;
1909
1910   s = format (0, "SCRIPT: nat64_add_del_interface ");
1911   s = format (s, "sw_if_index %d %s %s",
1912               clib_host_to_net_u32 (mp->sw_if_index),
1913               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1914
1915   FINISH;
1916 }
1917
1918 static int
1919 nat64_api_interface_walk (snat_interface_t * i, void *arg)
1920 {
1921   vl_api_nat64_interface_details_t *rmp;
1922   snat_main_t *sm = &snat_main;
1923   nat64_api_walk_ctx_t *ctx = arg;
1924
1925   rmp = vl_msg_api_alloc (sizeof (*rmp));
1926   memset (rmp, 0, sizeof (*rmp));
1927   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
1928   rmp->sw_if_index = ntohl (i->sw_if_index);
1929   rmp->is_inside = (nat_interface_is_inside (i)
1930                     && nat_interface_is_outside (i)) ? 2 :
1931     nat_interface_is_inside (i);
1932   rmp->context = ctx->context;
1933
1934   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1935
1936   return 0;
1937 }
1938
1939 static void
1940 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
1941 {
1942   unix_shared_memory_queue_t *q;
1943
1944   q = vl_api_client_index_to_input_queue (mp->client_index);
1945   if (q == 0)
1946     return;
1947
1948   nat64_api_walk_ctx_t ctx = {
1949     .q = q,
1950     .context = mp->context,
1951   };
1952
1953   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
1954 }
1955
1956 static void *
1957 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
1958                                      void *handle)
1959 {
1960   u8 *s;
1961
1962   s = format (0, "SCRIPT: snat_interface_dump ");
1963
1964   FINISH;
1965 }
1966
1967 static void
1968   vl_api_nat64_add_del_static_bib_t_handler
1969   (vl_api_nat64_add_del_static_bib_t * mp)
1970 {
1971   snat_main_t *sm = &snat_main;
1972   vl_api_nat64_add_del_static_bib_reply_t *rmp;
1973   ip6_address_t in_addr;
1974   ip4_address_t out_addr;
1975   int rv = 0;
1976
1977   memcpy (&in_addr.as_u8, mp->i_addr, 16);
1978   memcpy (&out_addr.as_u8, mp->o_addr, 4);
1979
1980   rv =
1981     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
1982                                     clib_net_to_host_u16 (mp->i_port),
1983                                     clib_net_to_host_u16 (mp->o_port),
1984                                     mp->proto,
1985                                     clib_net_to_host_u32 (mp->vrf_id),
1986                                     mp->is_add);
1987
1988   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
1989 }
1990
1991 static void *vl_api_nat64_add_del_static_bib_t_print
1992   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
1993 {
1994   u8 *s;
1995
1996   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
1997   s = format (s, "protocol %d i_addr %U o_addr %U ",
1998               mp->proto,
1999               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2000
2001   if (mp->vrf_id != ~0)
2002     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2003
2004   FINISH;
2005 }
2006
2007 static int
2008 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2009 {
2010   vl_api_nat64_bib_details_t *rmp;
2011   snat_main_t *sm = &snat_main;
2012   nat64_api_walk_ctx_t *ctx = arg;
2013   fib_table_t *fib;
2014
2015   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2016   if (!fib)
2017     return -1;
2018
2019   rmp = vl_msg_api_alloc (sizeof (*rmp));
2020   memset (rmp, 0, sizeof (*rmp));
2021   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2022   rmp->context = ctx->context;
2023   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2024   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2025   rmp->i_port = bibe->in_port;
2026   rmp->o_port = bibe->out_port;
2027   rmp->vrf_id = ntohl (fib->ft_table_id);
2028   rmp->proto = bibe->proto;
2029   rmp->is_static = bibe->is_static;
2030   rmp->ses_num = ntohl (bibe->ses_num);
2031
2032   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2033
2034   return 0;
2035 }
2036
2037 static void
2038 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2039 {
2040   unix_shared_memory_queue_t *q;
2041   nat64_main_t *nm = &nat64_main;
2042   nat64_db_t *db;
2043
2044   q = vl_api_client_index_to_input_queue (mp->client_index);
2045   if (q == 0)
2046     return;
2047
2048   nat64_api_walk_ctx_t ctx = {
2049     .q = q,
2050     .context = mp->context,
2051   };
2052
2053   /* *INDENT-OFF* */
2054   vec_foreach (db, nm->db)
2055     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2056   /* *INDENT-ON* */
2057 }
2058
2059 static void *
2060 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2061 {
2062   u8 *s;
2063
2064   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2065
2066   FINISH;
2067 }
2068
2069 static void
2070 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
2071 {
2072   snat_main_t *sm = &snat_main;
2073   vl_api_nat64_set_timeouts_reply_t *rmp;
2074   int rv = 0;
2075
2076   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
2077   if (rv)
2078     goto send_reply;
2079   rv = nat64_set_udp_timeout (ntohl (mp->udp));
2080   if (rv)
2081     goto send_reply;
2082   rv =
2083     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
2084                             ntohl (mp->tcp_incoming_syn));
2085
2086 send_reply:
2087   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
2088 }
2089
2090 static void *vl_api_nat64_set_timeouts_t_print
2091   (vl_api_nat64_set_timeouts_t * mp, void *handle)
2092 {
2093   u8 *s;
2094
2095   s = format (0, "SCRIPT: nat64_set_timeouts ");
2096   s =
2097     format (s,
2098             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
2099             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
2100             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
2101
2102   FINISH;
2103 }
2104
2105 static void
2106 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
2107 {
2108   snat_main_t *sm = &snat_main;
2109   vl_api_nat64_get_timeouts_reply_t *rmp;
2110   int rv = 0;
2111
2112   /* *INDENT-OFF* */
2113   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
2114   ({
2115     rmp->udp = htonl (nat64_get_udp_timeout());
2116     rmp->icmp = htonl (nat64_get_icmp_timeout());
2117     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
2118     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
2119     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
2120   }))
2121   /* *INDENT-ON* */
2122 }
2123
2124 static void *vl_api_nat64_get_timeouts_t_print
2125   (vl_api_nat64_get_timeouts_t * mp, void *handle)
2126 {
2127   u8 *s;
2128
2129   s = format (0, "SCRIPT: nat64_get_timeouts");
2130
2131   FINISH;
2132 }
2133
2134 static int
2135 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2136 {
2137   vl_api_nat64_st_details_t *rmp;
2138   snat_main_t *sm = &snat_main;
2139   nat64_api_walk_ctx_t *ctx = arg;
2140   nat64_db_bib_entry_t *bibe;
2141   fib_table_t *fib;
2142
2143   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2144   if (!bibe)
2145     return -1;
2146
2147   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2148   if (!fib)
2149     return -1;
2150
2151   rmp = vl_msg_api_alloc (sizeof (*rmp));
2152   memset (rmp, 0, sizeof (*rmp));
2153   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2154   rmp->context = ctx->context;
2155   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2156   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2157   rmp->il_port = bibe->in_port;
2158   rmp->ol_port = bibe->out_port;
2159   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2160   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2161   rmp->il_port = ste->r_port;
2162   rmp->vrf_id = ntohl (fib->ft_table_id);
2163   rmp->proto = ste->proto;
2164
2165   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2166
2167   return 0;
2168 }
2169
2170 static void
2171 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2172 {
2173   unix_shared_memory_queue_t *q;
2174   nat64_main_t *nm = &nat64_main;
2175   nat64_db_t *db;
2176
2177   q = vl_api_client_index_to_input_queue (mp->client_index);
2178   if (q == 0)
2179     return;
2180
2181   nat64_api_walk_ctx_t ctx = {
2182     .q = q,
2183     .context = mp->context,
2184   };
2185
2186   /* *INDENT-OFF* */
2187   vec_foreach (db, nm->db)
2188     {
2189       ctx.db = db;
2190       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2191     }
2192   /* *INDENT-ON* */
2193 }
2194
2195 static void *
2196 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2197 {
2198   u8 *s;
2199
2200   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2201
2202   FINISH;
2203 }
2204
2205 static void
2206 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2207 {
2208   vl_api_nat64_add_del_prefix_reply_t *rmp;
2209   snat_main_t *sm = &snat_main;
2210   ip6_address_t prefix;
2211   int rv = 0;
2212
2213   memcpy (&prefix.as_u8, mp->prefix, 16);
2214
2215   rv =
2216     nat64_add_del_prefix (&prefix, mp->prefix_len,
2217                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2218   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2219 }
2220
2221 static void *
2222 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2223                                      void *handle)
2224 {
2225   u8 *s;
2226
2227   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2228               format_ip6_address, mp->prefix, mp->prefix_len,
2229               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2230
2231   FINISH;
2232 }
2233
2234 static int
2235 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2236 {
2237   vl_api_nat64_prefix_details_t *rmp;
2238   snat_main_t *sm = &snat_main;
2239   nat64_api_walk_ctx_t *ctx = arg;
2240
2241   rmp = vl_msg_api_alloc (sizeof (*rmp));
2242   memset (rmp, 0, sizeof (*rmp));
2243   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2244   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2245   rmp->prefix_len = p->plen;
2246   rmp->vrf_id = ntohl (p->vrf_id);
2247   rmp->context = ctx->context;
2248
2249   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2250
2251   return 0;
2252 }
2253
2254 static void
2255 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2256 {
2257   unix_shared_memory_queue_t *q;
2258
2259   q = vl_api_client_index_to_input_queue (mp->client_index);
2260   if (q == 0)
2261     return;
2262
2263   nat64_api_walk_ctx_t ctx = {
2264     .q = q,
2265     .context = mp->context,
2266   };
2267
2268   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2269 }
2270
2271 static void *
2272 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2273                                   void *handle)
2274 {
2275   u8 *s;
2276
2277   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2278
2279   FINISH;
2280 }
2281
2282 static void
2283   vl_api_nat64_add_del_interface_addr_t_handler
2284   (vl_api_nat64_add_del_interface_addr_t * mp)
2285 {
2286   snat_main_t *sm = &snat_main;
2287   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2288   u32 sw_if_index = ntohl (mp->sw_if_index);
2289   int rv = 0;
2290
2291   VALIDATE_SW_IF_INDEX (mp);
2292
2293   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2294
2295   BAD_SW_IF_INDEX_LABEL;
2296
2297   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2298 }
2299
2300 static void *vl_api_nat64_add_del_interface_addr_t_print
2301   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2302 {
2303   u8 *s;
2304
2305   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2306   s = format (s, "sw_if_index %d %s",
2307               clib_host_to_net_u32 (mp->sw_if_index),
2308               mp->is_add ? "" : "del");
2309
2310   FINISH;
2311 }
2312
2313 /***************/
2314 /*** DS-Lite ***/
2315 /***************/
2316
2317 static void
2318 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2319 {
2320   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2321   snat_main_t *sm = &snat_main;
2322   dslite_main_t *dm = &dslite_main;
2323   int rv = 0;
2324   ip6_address_t ip6_addr;
2325
2326   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2327
2328   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2329
2330   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2331 }
2332
2333 static void *
2334 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2335                                      void *handle)
2336 {
2337   u8 *s;
2338
2339   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2340   s = format (s, "ip6_addr %U ip4_addr %U\n",
2341               format_ip6_address, mp->ip6_addr,
2342               format_ip4_address, mp->ip4_addr);
2343
2344   FINISH;
2345 }
2346
2347 static void
2348   vl_api_dslite_add_del_pool_addr_range_t_handler
2349   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2350 {
2351   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2352   snat_main_t *sm = &snat_main;
2353   dslite_main_t *dm = &dslite_main;
2354   int rv = 0;
2355   ip4_address_t this_addr;
2356   u32 start_host_order, end_host_order;
2357   int i, count;
2358   u32 *tmp;
2359
2360   tmp = (u32 *) mp->start_addr;
2361   start_host_order = clib_host_to_net_u32 (tmp[0]);
2362   tmp = (u32 *) mp->end_addr;
2363   end_host_order = clib_host_to_net_u32 (tmp[0]);
2364
2365   count = (end_host_order - start_host_order) + 1;
2366   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2367
2368   for (i = 0; i < count; i++)
2369     {
2370       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2371         goto send_reply;
2372
2373       increment_v4_address (&this_addr);
2374     }
2375
2376 send_reply:
2377   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2378 }
2379
2380 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2381   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2382 {
2383   u8 *s;
2384
2385   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2386   s = format (s, "%U - %U\n",
2387               format_ip4_address, mp->start_addr,
2388               format_ip4_address, mp->end_addr);
2389
2390   FINISH;
2391 }
2392
2393
2394 /* List of message types that this plugin understands */
2395 #define foreach_snat_plugin_api_msg                                     \
2396 _(NAT_CONTROL_PING, nat_control_ping)                                   \
2397 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
2398 _(NAT_SET_WORKERS, nat_set_workers)                                     \
2399 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
2400 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
2401 _(NAT_SET_REASS, nat_set_reass)                                         \
2402 _(NAT_GET_REASS, nat_get_reass)                                         \
2403 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
2404 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
2405 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
2406 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
2407 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
2408 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
2409 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
2410 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
2411 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
2412 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
2413 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
2414 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
2415 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
2416 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
2417   nat44_interface_add_del_output_feature)                               \
2418 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
2419   nat44_interface_output_feature_dump)                                  \
2420 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
2421 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
2422 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
2423 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
2424 _(NAT_DET_FORWARD, nat_det_forward)                                     \
2425 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
2426 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
2427 _(NAT_DET_SET_TIMEOUTS, nat_det_set_timeouts)                           \
2428 _(NAT_DET_GET_TIMEOUTS, nat_det_get_timeouts)                           \
2429 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
2430 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
2431 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
2432 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
2433 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
2434 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
2435 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
2436 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
2437 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
2438 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
2439 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
2440 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
2441 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
2442 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
2443 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
2444 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
2445 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)
2446
2447 /* Set up the API message handling tables */
2448 static clib_error_t *
2449 snat_plugin_api_hookup (vlib_main_t * vm)
2450 {
2451   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
2452 #define _(N,n)                                                  \
2453     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
2454                            #n,                                  \
2455                            vl_api_##n##_t_handler,              \
2456                            vl_noop_handler,                     \
2457                            vl_api_##n##_t_endian,               \
2458                            vl_api_##n##_t_print,                \
2459                            sizeof(vl_api_##n##_t), 1);
2460   foreach_snat_plugin_api_msg;
2461 #undef _
2462
2463   return 0;
2464 }
2465
2466 #define vl_msg_name_crc_list
2467 #include <nat/nat_all_api_h.h>
2468 #undef vl_msg_name_crc_list
2469
2470 static void
2471 setup_message_id_table (snat_main_t * sm, api_main_t * am)
2472 {
2473 #define _(id,n,crc) \
2474   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
2475   foreach_vl_msg_name_crc_nat;
2476 #undef _
2477 }
2478
2479 static void
2480 plugin_custom_dump_configure (snat_main_t * sm)
2481 {
2482 #define _(n,f) sm->api_main->msg_print_handlers \
2483   [VL_API_##n + sm->msg_id_base]                \
2484     = (void *) vl_api_##f##_t_print;
2485   foreach_snat_plugin_api_msg;
2486 #undef _
2487 }
2488
2489 clib_error_t *
2490 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
2491 {
2492   u8 *name;
2493   clib_error_t *error = 0;
2494
2495   name = format (0, "nat_%08x%c", api_version, 0);
2496
2497   /* Ask for a correctly-sized block of API message decode slots */
2498   sm->msg_id_base =
2499     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
2500
2501   error = snat_plugin_api_hookup (vm);
2502
2503   /* Add our API messages to the global name_crc hash table */
2504   setup_message_id_table (sm, sm->api_main);
2505
2506   plugin_custom_dump_configure (sm);
2507
2508   vec_free (name);
2509
2510   return error;
2511 }
2512
2513 /*
2514  * fd.io coding-style-patch-verification: ON
2515  *
2516  * Local Variables:
2517  * eval: (c-set-style "gnu")
2518  * End:
2519  */