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