NAT44: identity NAT (VPP-1073)
[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   nat64_main_t *nm = &nat64_main;
1780   int rv = 0;
1781   ip4_address_t this_addr;
1782   u32 start_host_order, end_host_order;
1783   u32 vrf_id;
1784   int i, count;
1785   u32 *tmp;
1786
1787   if (nm->is_disabled)
1788     {
1789       rv = VNET_API_ERROR_FEATURE_DISABLED;
1790       goto send_reply;
1791     }
1792
1793   tmp = (u32 *) mp->start_addr;
1794   start_host_order = clib_host_to_net_u32 (tmp[0]);
1795   tmp = (u32 *) mp->end_addr;
1796   end_host_order = clib_host_to_net_u32 (tmp[0]);
1797
1798   count = (end_host_order - start_host_order) + 1;
1799
1800   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
1801
1802   memcpy (&this_addr.as_u8, mp->start_addr, 4);
1803
1804   for (i = 0; i < count; i++)
1805     {
1806       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
1807         goto send_reply;
1808
1809       increment_v4_address (&this_addr);
1810     }
1811
1812 send_reply:
1813   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
1814 }
1815
1816 static void *vl_api_nat64_add_del_pool_addr_range_t_print
1817   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
1818 {
1819   u8 *s;
1820
1821   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
1822   s = format (s, "%U - %U vrf_id %u %s\n",
1823               format_ip4_address, mp->start_addr,
1824               format_ip4_address, mp->end_addr,
1825               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
1826
1827   FINISH;
1828 }
1829
1830 typedef struct nat64_api_walk_ctx_t_
1831 {
1832   unix_shared_memory_queue_t *q;
1833   u32 context;
1834 } nat64_api_walk_ctx_t;
1835
1836 static int
1837 nat64_api_pool_walk (snat_address_t * a, void *arg)
1838 {
1839   vl_api_nat64_pool_addr_details_t *rmp;
1840   snat_main_t *sm = &snat_main;
1841   nat64_api_walk_ctx_t *ctx = arg;
1842
1843   rmp = vl_msg_api_alloc (sizeof (*rmp));
1844   memset (rmp, 0, sizeof (*rmp));
1845   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
1846   clib_memcpy (rmp->address, &(a->addr), 4);
1847   if (a->fib_index != ~0)
1848     {
1849       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
1850       if (!fib)
1851         return -1;
1852       rmp->vrf_id = ntohl (fib->ft_table_id);
1853     }
1854   else
1855     rmp->vrf_id = ~0;
1856   rmp->context = ctx->context;
1857
1858   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1859
1860   return 0;
1861 }
1862
1863 static void
1864 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
1865 {
1866   unix_shared_memory_queue_t *q;
1867   nat64_main_t *nm = &nat64_main;
1868
1869   if (nm->is_disabled)
1870     return;
1871
1872   q = vl_api_client_index_to_input_queue (mp->client_index);
1873   if (q == 0)
1874     return;
1875
1876   nat64_api_walk_ctx_t ctx = {
1877     .q = q,
1878     .context = mp->context,
1879   };
1880
1881   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
1882 }
1883
1884 static void *
1885 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
1886                                      void *handle)
1887 {
1888   u8 *s;
1889
1890   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
1891
1892   FINISH;
1893 }
1894
1895 static void
1896 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
1897                                           mp)
1898 {
1899   snat_main_t *sm = &snat_main;
1900   nat64_main_t *nm = &nat64_main;
1901   vl_api_nat64_add_del_interface_reply_t *rmp;
1902   int rv = 0;
1903
1904   if (nm->is_disabled)
1905     {
1906       rv = VNET_API_ERROR_FEATURE_DISABLED;
1907       goto send_reply;
1908     }
1909
1910   VALIDATE_SW_IF_INDEX (mp);
1911
1912   rv =
1913     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
1914                              mp->is_add);
1915
1916   BAD_SW_IF_INDEX_LABEL;
1917
1918 send_reply:
1919   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
1920 }
1921
1922 static void *
1923 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
1924                                         void *handle)
1925 {
1926   u8 *s;
1927
1928   s = format (0, "SCRIPT: nat64_add_del_interface ");
1929   s = format (s, "sw_if_index %d %s %s",
1930               clib_host_to_net_u32 (mp->sw_if_index),
1931               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1932
1933   FINISH;
1934 }
1935
1936 static int
1937 nat64_api_interface_walk (snat_interface_t * i, void *arg)
1938 {
1939   vl_api_nat64_interface_details_t *rmp;
1940   snat_main_t *sm = &snat_main;
1941   nat64_api_walk_ctx_t *ctx = arg;
1942
1943   rmp = vl_msg_api_alloc (sizeof (*rmp));
1944   memset (rmp, 0, sizeof (*rmp));
1945   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
1946   rmp->sw_if_index = ntohl (i->sw_if_index);
1947   rmp->is_inside = (nat_interface_is_inside (i)
1948                     && nat_interface_is_outside (i)) ? 2 :
1949     nat_interface_is_inside (i);
1950   rmp->context = ctx->context;
1951
1952   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1953
1954   return 0;
1955 }
1956
1957 static void
1958 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
1959 {
1960   unix_shared_memory_queue_t *q;
1961   nat64_main_t *nm = &nat64_main;
1962
1963   if (nm->is_disabled)
1964     return;
1965
1966   q = vl_api_client_index_to_input_queue (mp->client_index);
1967   if (q == 0)
1968     return;
1969
1970   nat64_api_walk_ctx_t ctx = {
1971     .q = q,
1972     .context = mp->context,
1973   };
1974
1975   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
1976 }
1977
1978 static void *
1979 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
1980                                      void *handle)
1981 {
1982   u8 *s;
1983
1984   s = format (0, "SCRIPT: snat_interface_dump ");
1985
1986   FINISH;
1987 }
1988
1989 static void
1990   vl_api_nat64_add_del_static_bib_t_handler
1991   (vl_api_nat64_add_del_static_bib_t * mp)
1992 {
1993   snat_main_t *sm = &snat_main;
1994   nat64_main_t *nm = &nat64_main;
1995   vl_api_nat64_add_del_static_bib_reply_t *rmp;
1996   ip6_address_t in_addr;
1997   ip4_address_t out_addr;
1998   int rv = 0;
1999
2000   if (nm->is_disabled)
2001     {
2002       rv = VNET_API_ERROR_FEATURE_DISABLED;
2003       goto send_reply;
2004     }
2005
2006   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2007   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2008
2009   rv =
2010     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2011                                     clib_net_to_host_u16 (mp->i_port),
2012                                     clib_net_to_host_u16 (mp->o_port),
2013                                     mp->proto,
2014                                     clib_net_to_host_u32 (mp->vrf_id),
2015                                     mp->is_add);
2016
2017 send_reply:
2018   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2019 }
2020
2021 static void *vl_api_nat64_add_del_static_bib_t_print
2022   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2023 {
2024   u8 *s;
2025
2026   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2027   s = format (s, "protocol %d i_addr %U o_addr %U ",
2028               mp->proto,
2029               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2030
2031   if (mp->vrf_id != ~0)
2032     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2033
2034   FINISH;
2035 }
2036
2037 static int
2038 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2039 {
2040   vl_api_nat64_bib_details_t *rmp;
2041   snat_main_t *sm = &snat_main;
2042   nat64_api_walk_ctx_t *ctx = arg;
2043   fib_table_t *fib;
2044
2045   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2046   if (!fib)
2047     return -1;
2048
2049   rmp = vl_msg_api_alloc (sizeof (*rmp));
2050   memset (rmp, 0, sizeof (*rmp));
2051   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2052   rmp->context = ctx->context;
2053   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2054   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2055   rmp->i_port = bibe->in_port;
2056   rmp->o_port = bibe->out_port;
2057   rmp->vrf_id = ntohl (fib->ft_table_id);
2058   rmp->proto = bibe->proto;
2059   rmp->is_static = bibe->is_static;
2060   rmp->ses_num = ntohl (bibe->ses_num);
2061
2062   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2063
2064   return 0;
2065 }
2066
2067 static void
2068 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2069 {
2070   unix_shared_memory_queue_t *q;
2071   nat64_main_t *nm = &nat64_main;
2072
2073   if (nm->is_disabled)
2074     return;
2075
2076   q = vl_api_client_index_to_input_queue (mp->client_index);
2077   if (q == 0)
2078     return;
2079
2080   nat64_api_walk_ctx_t ctx = {
2081     .q = q,
2082     .context = mp->context,
2083   };
2084
2085   nat64_db_bib_walk (&nm->db, mp->proto, nat64_api_bib_walk, &ctx);
2086 }
2087
2088 static void *
2089 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2090 {
2091   u8 *s;
2092
2093   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2094
2095   FINISH;
2096 }
2097
2098 static void
2099 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
2100 {
2101   snat_main_t *sm = &snat_main;
2102   nat64_main_t *nm = &nat64_main;
2103   vl_api_nat64_set_timeouts_reply_t *rmp;
2104   int rv = 0;
2105
2106   if (nm->is_disabled)
2107     {
2108       rv = VNET_API_ERROR_FEATURE_DISABLED;
2109       goto send_reply;
2110     }
2111
2112   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
2113   if (rv)
2114     goto send_reply;
2115   rv = nat64_set_udp_timeout (ntohl (mp->udp));
2116   if (rv)
2117     goto send_reply;
2118   rv =
2119     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
2120                             ntohl (mp->tcp_incoming_syn));
2121
2122 send_reply:
2123   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
2124 }
2125
2126 static void *vl_api_nat64_set_timeouts_t_print
2127   (vl_api_nat64_set_timeouts_t * mp, void *handle)
2128 {
2129   u8 *s;
2130
2131   s = format (0, "SCRIPT: nat64_set_timeouts ");
2132   s =
2133     format (s,
2134             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
2135             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
2136             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
2137
2138   FINISH;
2139 }
2140
2141 static void
2142 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
2143 {
2144   snat_main_t *sm = &snat_main;
2145   nat64_main_t *nm = &nat64_main;
2146   vl_api_nat64_get_timeouts_reply_t *rmp;
2147   int rv = 0;
2148
2149   if (nm->is_disabled)
2150     return;
2151
2152   /* *INDENT-OFF* */
2153   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
2154   ({
2155     rmp->udp = htonl (nat64_get_udp_timeout());
2156     rmp->icmp = htonl (nat64_get_icmp_timeout());
2157     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
2158     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
2159     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
2160   }))
2161   /* *INDENT-ON* */
2162 }
2163
2164 static void *vl_api_nat64_get_timeouts_t_print
2165   (vl_api_nat64_get_timeouts_t * mp, void *handle)
2166 {
2167   u8 *s;
2168
2169   s = format (0, "SCRIPT: nat64_get_timeouts");
2170
2171   FINISH;
2172 }
2173
2174 static int
2175 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2176 {
2177   vl_api_nat64_st_details_t *rmp;
2178   snat_main_t *sm = &snat_main;
2179   nat64_api_walk_ctx_t *ctx = arg;
2180   nat64_main_t *nm = &nat64_main;
2181   nat64_db_bib_entry_t *bibe;
2182   fib_table_t *fib;
2183
2184   bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
2185   if (!bibe)
2186     return -1;
2187
2188   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2189   if (!fib)
2190     return -1;
2191
2192   rmp = vl_msg_api_alloc (sizeof (*rmp));
2193   memset (rmp, 0, sizeof (*rmp));
2194   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2195   rmp->context = ctx->context;
2196   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2197   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2198   rmp->il_port = bibe->in_port;
2199   rmp->ol_port = bibe->out_port;
2200   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2201   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2202   rmp->il_port = ste->r_port;
2203   rmp->vrf_id = ntohl (fib->ft_table_id);
2204   rmp->proto = ste->proto;
2205
2206   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2207
2208   return 0;
2209 }
2210
2211 static void
2212 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2213 {
2214   unix_shared_memory_queue_t *q;
2215   nat64_main_t *nm = &nat64_main;
2216
2217   if (nm->is_disabled)
2218     return;
2219
2220   q = vl_api_client_index_to_input_queue (mp->client_index);
2221   if (q == 0)
2222     return;
2223
2224   nat64_api_walk_ctx_t ctx = {
2225     .q = q,
2226     .context = mp->context,
2227   };
2228
2229   nat64_db_st_walk (&nm->db, mp->proto, nat64_api_st_walk, &ctx);
2230 }
2231
2232 static void *
2233 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2234 {
2235   u8 *s;
2236
2237   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2238
2239   FINISH;
2240 }
2241
2242 static void
2243 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2244 {
2245   vl_api_nat64_add_del_prefix_reply_t *rmp;
2246   snat_main_t *sm = &snat_main;
2247   nat64_main_t *nm = &nat64_main;
2248   ip6_address_t prefix;
2249   int rv = 0;
2250
2251   if (nm->is_disabled)
2252     {
2253       rv = VNET_API_ERROR_FEATURE_DISABLED;
2254       goto send_reply;
2255     }
2256
2257   memcpy (&prefix.as_u8, mp->prefix, 16);
2258
2259   rv =
2260     nat64_add_del_prefix (&prefix, mp->prefix_len,
2261                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2262 send_reply:
2263   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2264 }
2265
2266 static void *
2267 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2268                                      void *handle)
2269 {
2270   u8 *s;
2271
2272   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2273               format_ip6_address, mp->prefix, mp->prefix_len,
2274               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2275
2276   FINISH;
2277 }
2278
2279 static int
2280 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2281 {
2282   vl_api_nat64_prefix_details_t *rmp;
2283   snat_main_t *sm = &snat_main;
2284   nat64_api_walk_ctx_t *ctx = arg;
2285
2286   rmp = vl_msg_api_alloc (sizeof (*rmp));
2287   memset (rmp, 0, sizeof (*rmp));
2288   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2289   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2290   rmp->prefix_len = p->plen;
2291   rmp->vrf_id = ntohl (p->vrf_id);
2292   rmp->context = ctx->context;
2293
2294   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2295
2296   return 0;
2297 }
2298
2299 static void
2300 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2301 {
2302   unix_shared_memory_queue_t *q;
2303   nat64_main_t *nm = &nat64_main;
2304
2305   if (nm->is_disabled)
2306     return;
2307
2308   q = vl_api_client_index_to_input_queue (mp->client_index);
2309   if (q == 0)
2310     return;
2311
2312   nat64_api_walk_ctx_t ctx = {
2313     .q = q,
2314     .context = mp->context,
2315   };
2316
2317   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2318 }
2319
2320 static void *
2321 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2322                                   void *handle)
2323 {
2324   u8 *s;
2325
2326   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2327
2328   FINISH;
2329 }
2330
2331 static void
2332   vl_api_nat64_add_del_interface_addr_t_handler
2333   (vl_api_nat64_add_del_interface_addr_t * mp)
2334 {
2335   nat64_main_t *nm = &nat64_main;
2336   snat_main_t *sm = &snat_main;
2337   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2338   u32 sw_if_index = ntohl (mp->sw_if_index);
2339   int rv = 0;
2340
2341   if (nm->is_disabled)
2342     {
2343       rv = VNET_API_ERROR_FEATURE_DISABLED;
2344       goto send_reply;
2345     }
2346
2347   VALIDATE_SW_IF_INDEX (mp);
2348
2349   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2350
2351   BAD_SW_IF_INDEX_LABEL;
2352 send_reply:
2353   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2354 }
2355
2356 static void *vl_api_nat64_add_del_interface_addr_t_print
2357   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2358 {
2359   u8 *s;
2360
2361   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2362   s = format (s, "sw_if_index %d %s",
2363               clib_host_to_net_u32 (mp->sw_if_index),
2364               mp->is_add ? "" : "del");
2365
2366   FINISH;
2367 }
2368
2369 /***************/
2370 /*** DS-Lite ***/
2371 /***************/
2372
2373 static void
2374 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2375 {
2376   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2377   snat_main_t *sm = &snat_main;
2378   dslite_main_t *dm = &dslite_main;
2379   int rv = 0;
2380   ip6_address_t ip6_addr;
2381
2382   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2383
2384   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2385
2386   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2387 }
2388
2389 static void *
2390 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2391                                      void *handle)
2392 {
2393   u8 *s;
2394
2395   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2396   s = format (s, "ip6_addr %U ip4_addr %U\n",
2397               format_ip6_address, mp->ip6_addr,
2398               format_ip4_address, mp->ip4_addr);
2399
2400   FINISH;
2401 }
2402
2403 static void
2404   vl_api_dslite_add_del_pool_addr_range_t_handler
2405   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2406 {
2407   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2408   snat_main_t *sm = &snat_main;
2409   dslite_main_t *dm = &dslite_main;
2410   int rv = 0;
2411   ip4_address_t this_addr;
2412   u32 start_host_order, end_host_order;
2413   int i, count;
2414   u32 *tmp;
2415
2416   tmp = (u32 *) mp->start_addr;
2417   start_host_order = clib_host_to_net_u32 (tmp[0]);
2418   tmp = (u32 *) mp->end_addr;
2419   end_host_order = clib_host_to_net_u32 (tmp[0]);
2420
2421   count = (end_host_order - start_host_order) + 1;
2422   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2423
2424   for (i = 0; i < count; i++)
2425     {
2426       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2427         goto send_reply;
2428
2429       increment_v4_address (&this_addr);
2430     }
2431
2432 send_reply:
2433   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2434 }
2435
2436 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2437   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2438 {
2439   u8 *s;
2440
2441   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2442   s = format (s, "%U - %U\n",
2443               format_ip4_address, mp->start_addr,
2444               format_ip4_address, mp->end_addr);
2445
2446   FINISH;
2447 }
2448
2449
2450 /* List of message types that this plugin understands */
2451 #define foreach_snat_plugin_api_msg                                     \
2452 _(NAT_CONTROL_PING, nat_control_ping)                                   \
2453 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
2454 _(NAT_SET_WORKERS, nat_set_workers)                                     \
2455 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
2456 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
2457 _(NAT_SET_REASS, nat_set_reass)                                         \
2458 _(NAT_GET_REASS, nat_get_reass)                                         \
2459 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
2460 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
2461 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
2462 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
2463 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
2464 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
2465 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
2466 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
2467 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
2468 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
2469 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
2470 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
2471 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
2472 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
2473   nat44_interface_add_del_output_feature)                               \
2474 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
2475   nat44_interface_output_feature_dump)                                  \
2476 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
2477 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
2478 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
2479 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
2480 _(NAT_DET_FORWARD, nat_det_forward)                                     \
2481 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
2482 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
2483 _(NAT_DET_SET_TIMEOUTS, nat_det_set_timeouts)                           \
2484 _(NAT_DET_GET_TIMEOUTS, nat_det_get_timeouts)                           \
2485 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
2486 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
2487 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
2488 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
2489 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
2490 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
2491 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
2492 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
2493 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
2494 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
2495 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
2496 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
2497 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
2498 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
2499 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
2500 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
2501 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)
2502
2503 /* Set up the API message handling tables */
2504 static clib_error_t *
2505 snat_plugin_api_hookup (vlib_main_t * vm)
2506 {
2507   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
2508 #define _(N,n)                                                  \
2509     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
2510                            #n,                                  \
2511                            vl_api_##n##_t_handler,              \
2512                            vl_noop_handler,                     \
2513                            vl_api_##n##_t_endian,               \
2514                            vl_api_##n##_t_print,                \
2515                            sizeof(vl_api_##n##_t), 1);
2516   foreach_snat_plugin_api_msg;
2517 #undef _
2518
2519   return 0;
2520 }
2521
2522 #define vl_msg_name_crc_list
2523 #include <nat/nat_all_api_h.h>
2524 #undef vl_msg_name_crc_list
2525
2526 static void
2527 setup_message_id_table (snat_main_t * sm, api_main_t * am)
2528 {
2529 #define _(id,n,crc) \
2530   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
2531   foreach_vl_msg_name_crc_nat;
2532 #undef _
2533 }
2534
2535 static void
2536 plugin_custom_dump_configure (snat_main_t * sm)
2537 {
2538 #define _(n,f) sm->api_main->msg_print_handlers \
2539   [VL_API_##n + sm->msg_id_base]                \
2540     = (void *) vl_api_##f##_t_print;
2541   foreach_snat_plugin_api_msg;
2542 #undef _
2543 }
2544
2545 clib_error_t *
2546 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
2547 {
2548   u8 *name;
2549   clib_error_t *error = 0;
2550
2551   name = format (0, "nat_%08x%c", api_version, 0);
2552
2553   /* Ask for a correctly-sized block of API message decode slots */
2554   sm->msg_id_base =
2555     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
2556
2557   error = snat_plugin_api_hookup (vm);
2558
2559   /* Add our API messages to the global name_crc hash table */
2560   setup_message_id_table (sm, sm->api_main);
2561
2562   plugin_custom_dump_configure (sm);
2563
2564   vec_free (name);
2565
2566   return error;
2567 }
2568
2569 /*
2570  * fd.io coding-style-patch-verification: ON
2571  *
2572  * Local Variables:
2573  * eval: (c-set-style "gnu")
2574  * End:
2575  */