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