NAT44: LB NAT - local backends in multiple VRFs (VPP-1345)
[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     vec_foreach (u, tsm->users)
1199       send_nat44_user_details (u, reg, mp->context);
1200   /* *INDENT-ON* */
1201 }
1202
1203 static void *
1204 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
1205 {
1206   u8 *s;
1207
1208   s = format (0, "SCRIPT: nat44_user_dump ");
1209
1210   FINISH;
1211 }
1212
1213 static void
1214 send_nat44_user_session_details (snat_session_t * s,
1215                                  vl_api_registration_t * reg, u32 context)
1216 {
1217   vl_api_nat44_user_session_details_t *rmp;
1218   snat_main_t *sm = &snat_main;
1219
1220   rmp = vl_msg_api_alloc (sizeof (*rmp));
1221   memset (rmp, 0, sizeof (*rmp));
1222   rmp->_vl_msg_id =
1223     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1224   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1225   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1226   rmp->is_static = snat_is_session_static (s) ? 1 : 0;
1227   rmp->is_twicenat = is_twice_nat_session (s) ? 1 : 0;
1228   rmp->ext_host_valid = is_ed_session (s)
1229     || is_fwd_bypass_session (s) ? 1 : 0;
1230   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1231   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1232   rmp->total_pkts = ntohl (s->total_pkts);
1233   rmp->context = context;
1234   if (snat_is_unk_proto_session (s))
1235     {
1236       rmp->outside_port = 0;
1237       rmp->inside_port = 0;
1238       rmp->protocol = ntohs (s->in2out.port);
1239     }
1240   else
1241     {
1242       rmp->outside_port = s->out2in.port;
1243       rmp->inside_port = s->in2out.port;
1244       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
1245     }
1246   if (is_ed_session (s) || is_fwd_bypass_session (s))
1247     {
1248       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1249       rmp->ext_host_port = s->ext_host_port;
1250       if (is_twice_nat_session (s))
1251         {
1252           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1253           rmp->ext_host_nat_port = s->ext_host_nat_port;
1254         }
1255     }
1256
1257   vl_api_send_msg (reg, (u8 *) rmp);
1258 }
1259
1260 static void
1261 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1262                                           mp)
1263 {
1264   vl_api_registration_t *reg;
1265   snat_main_t *sm = &snat_main;
1266   snat_main_per_thread_data_t *tsm;
1267   snat_session_t *s;
1268   clib_bihash_kv_8_8_t key, value;
1269   snat_user_key_t ukey;
1270   snat_user_t *u;
1271   u32 session_index, head_index, elt_index;
1272   dlist_elt_t *head, *elt;
1273   ip4_header_t ip;
1274
1275   if (sm->deterministic)
1276     return;
1277
1278   reg = vl_api_client_index_to_registration (mp->client_index);
1279   if (!reg)
1280     return;
1281
1282   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1283   ip.src_address.as_u32 = ukey.addr.as_u32;
1284   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1285   key.key = ukey.as_u64;
1286   if (sm->num_workers > 1)
1287     tsm =
1288       vec_elt_at_index (sm->per_thread_data,
1289                         sm->worker_in2out_cb (&ip, ukey.fib_index));
1290   else
1291     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1292   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1293     return;
1294   u = pool_elt_at_index (tsm->users, value.value);
1295   if (!u->nsessions && !u->nstaticsessions)
1296     return;
1297
1298   head_index = u->sessions_per_user_list_head_index;
1299   head = pool_elt_at_index (tsm->list_pool, head_index);
1300   elt_index = head->next;
1301   elt = pool_elt_at_index (tsm->list_pool, elt_index);
1302   session_index = elt->value;
1303   while (session_index != ~0)
1304     {
1305       s = pool_elt_at_index (tsm->sessions, session_index);
1306
1307       send_nat44_user_session_details (s, reg, mp->context);
1308
1309       elt_index = elt->next;
1310       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1311       session_index = elt->value;
1312     }
1313 }
1314
1315 static void *
1316 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
1317                                         void *handle)
1318 {
1319   u8 *s;
1320
1321   s = format (0, "SCRIPT: nat44_user_session_dump ");
1322   s = format (s, "ip_address %U vrf_id %d\n",
1323               format_ip4_address, mp->ip_address,
1324               clib_net_to_host_u32 (mp->vrf_id));
1325
1326   FINISH;
1327 }
1328
1329 static nat44_lb_addr_port_t *
1330 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1331                              u8 addr_port_pair_num)
1332 {
1333   u8 i;
1334   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1335   vl_api_nat44_lb_addr_port_t *ap;
1336
1337   for (i = 0; i < addr_port_pair_num; i++)
1338     {
1339       ap = &addr_port_pairs[i];
1340       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1341       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1342       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
1343       lb_addr_port.probability = ap->probability;
1344       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1345       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1346     }
1347
1348   return lb_addr_port_pairs;
1349 }
1350
1351 static void
1352   vl_api_nat44_add_del_lb_static_mapping_t_handler
1353   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1354 {
1355   snat_main_t *sm = &snat_main;
1356   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1357   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1358   int rv = 0;
1359   nat44_lb_addr_port_t *locals = 0;
1360   ip4_address_t e_addr;
1361   snat_protocol_t proto;
1362   u8 *tag = 0;
1363
1364   if (!sm->endpoint_dependent)
1365     {
1366       rv = VNET_API_ERROR_UNSUPPORTED;
1367       goto send_reply;
1368     }
1369
1370   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
1371   clib_memcpy (&e_addr, mp->external_addr, 4);
1372   proto = ip_proto_to_snat_proto (mp->protocol);
1373   if (mp->twice_nat)
1374     twice_nat = TWICE_NAT;
1375   else if (mp->self_twice_nat)
1376     twice_nat = TWICE_NAT_SELF;
1377   mp->tag[sizeof (mp->tag) - 1] = 0;
1378   tag = format (0, "%s", mp->tag);
1379   vec_terminate_c_string (tag);
1380
1381   rv =
1382     nat44_add_del_lb_static_mapping (e_addr,
1383                                      clib_net_to_host_u16 (mp->external_port),
1384                                      proto, locals, mp->is_add, twice_nat,
1385                                      mp->out2in_only, tag);
1386
1387   vec_free (locals);
1388   vec_free (tag);
1389
1390 send_reply:
1391   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1392 }
1393
1394 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1395   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1396 {
1397   u8 *s;
1398
1399   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1400   s = format (s, "is_add %d twice_nat %d out2in_only %d ",
1401               mp->is_add, mp->twice_nat, mp->out2in_only);
1402
1403   FINISH;
1404 }
1405
1406 static void
1407 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1408                                       vl_api_registration_t * reg,
1409                                       u32 context)
1410 {
1411   vl_api_nat44_lb_static_mapping_details_t *rmp;
1412   snat_main_t *sm = &snat_main;
1413   nat44_lb_addr_port_t *ap;
1414   vl_api_nat44_lb_addr_port_t *locals;
1415
1416   rmp =
1417     vl_msg_api_alloc (sizeof (*rmp) +
1418                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
1419   memset (rmp, 0, sizeof (*rmp));
1420   rmp->_vl_msg_id =
1421     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1422
1423   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1424   rmp->external_port = ntohs (m->external_port);
1425   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1426   rmp->context = context;
1427   if (m->twice_nat == TWICE_NAT)
1428     rmp->twice_nat = 1;
1429   else if (m->twice_nat == TWICE_NAT_SELF)
1430     rmp->self_twice_nat = 1;
1431   rmp->out2in_only = m->out2in_only;
1432   if (m->tag)
1433     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1434
1435   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1436   vec_foreach (ap, m->locals)
1437   {
1438     clib_memcpy (locals->addr, &(ap->addr), 4);
1439     locals->port = htons (ap->port);
1440     locals->probability = ap->probability;
1441     locals->vrf_id = ntohl (ap->vrf_id);
1442     locals++;
1443     rmp->local_num++;
1444   }
1445
1446   vl_api_send_msg (reg, (u8 *) rmp);
1447 }
1448
1449 static void
1450   vl_api_nat44_lb_static_mapping_dump_t_handler
1451   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1452 {
1453   vl_api_registration_t *reg;
1454   snat_main_t *sm = &snat_main;
1455   snat_static_mapping_t *m;
1456
1457   if (!sm->endpoint_dependent)
1458     return;
1459
1460   reg = vl_api_client_index_to_registration (mp->client_index);
1461   if (!reg)
1462     return;
1463
1464   /* *INDENT-OFF* */
1465   pool_foreach (m, sm->static_mappings,
1466   ({
1467       if (vec_len(m->locals))
1468         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1469   }));
1470   /* *INDENT-ON* */
1471 }
1472
1473 static void *vl_api_nat44_lb_static_mapping_dump_t_print
1474   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
1475 {
1476   u8 *s;
1477
1478   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
1479
1480   FINISH;
1481 }
1482
1483 static void
1484 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1485 {
1486   snat_main_t *sm = &snat_main;
1487   vl_api_nat44_del_session_reply_t *rmp;
1488   ip4_address_t addr, eh_addr;
1489   u16 port, eh_port;
1490   u32 vrf_id;
1491   int rv = 0;
1492   snat_protocol_t proto;
1493
1494   if (sm->deterministic)
1495     {
1496       rv = VNET_API_ERROR_UNSUPPORTED;
1497       goto send_reply;
1498     }
1499
1500   memcpy (&addr.as_u8, mp->address, 4);
1501   port = clib_net_to_host_u16 (mp->port);
1502   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1503   proto = ip_proto_to_snat_proto (mp->protocol);
1504   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1505   eh_port = clib_net_to_host_u16 (mp->ext_host_port);
1506
1507   if (mp->ext_host_valid)
1508     rv =
1509       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1510                             vrf_id, mp->is_in);
1511   else
1512     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
1513
1514 send_reply:
1515   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1516 }
1517
1518 static void *
1519 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
1520                                   void *handle)
1521 {
1522   u8 *s;
1523
1524   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1525   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
1526               format_ip4_address, mp->address,
1527               clib_net_to_host_u16 (mp->port),
1528               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
1529   if (mp->ext_host_valid)
1530     s = format (s, "ext_host_address %U ext_host_port %d",
1531                 format_ip4_address, mp->ext_host_address,
1532                 clib_net_to_host_u16 (mp->ext_host_port));
1533
1534   FINISH;
1535 }
1536
1537 static void
1538   vl_api_nat44_forwarding_enable_disable_t_handler
1539   (vl_api_nat44_forwarding_enable_disable_t * mp)
1540 {
1541   snat_main_t *sm = &snat_main;
1542   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1543   int rv = 0;
1544   u32 *ses_to_be_removed = 0, *ses_index;
1545   snat_main_per_thread_data_t *tsm;
1546   snat_session_t *s;
1547
1548   sm->forwarding_enabled = mp->enable != 0;
1549
1550   if (mp->enable == 0)
1551     {
1552       /* *INDENT-OFF* */
1553       vec_foreach (tsm, sm->per_thread_data)
1554       {
1555         pool_foreach (s, tsm->sessions,
1556         ({
1557           if (is_fwd_bypass_session(s))
1558             {
1559               vec_add1 (ses_to_be_removed, s - tsm->sessions);
1560             }
1561         }));
1562         vec_foreach (ses_index, ses_to_be_removed)
1563         {
1564           s = pool_elt_at_index(tsm->sessions, ses_index[0]);
1565           nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1566           nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1567         }
1568         vec_free (ses_to_be_removed);
1569       }
1570       /* *INDENT-ON* */
1571     }
1572
1573   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1574 }
1575
1576 static void *vl_api_nat44_forwarding_enable_disable_t_print
1577   (vl_api_nat44_forwarding_enable_disable_t * mp, void *handle)
1578 {
1579   u8 *s;
1580
1581   s = format (0, "SCRIPT: nat44_forwarding_enable_disable ");
1582   s = format (s, "enable %d", mp->enable != 0);
1583
1584   FINISH;
1585 }
1586
1587 static void
1588   vl_api_nat44_forwarding_is_enabled_t_handler
1589   (vl_api_nat44_forwarding_is_enabled_t * mp)
1590 {
1591   vl_api_registration_t *reg;
1592   snat_main_t *sm = &snat_main;
1593   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1594
1595   reg = vl_api_client_index_to_registration (mp->client_index);
1596   if (!reg)
1597     return;
1598
1599   rmp = vl_msg_api_alloc (sizeof (*rmp));
1600   memset (rmp, 0, sizeof (*rmp));
1601   rmp->_vl_msg_id =
1602     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1603   rmp->context = mp->context;
1604
1605   rmp->enabled = sm->forwarding_enabled;
1606
1607   vl_api_send_msg (reg, (u8 *) rmp);
1608 }
1609
1610 static void *vl_api_nat44_forwarding_is_enabled_t_print
1611   (vl_api_nat44_forwarding_is_enabled_t * mp, void *handle)
1612 {
1613   u8 *s;
1614
1615   s = format (0, "SCRIPT: nat44_forwarding_is_enabled ");
1616
1617   FINISH;
1618 }
1619
1620 /*******************************/
1621 /*** Deterministic NAT (CGN) ***/
1622 /*******************************/
1623
1624 static void
1625 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
1626 {
1627   snat_main_t *sm = &snat_main;
1628   vl_api_nat_det_add_del_map_reply_t *rmp;
1629   int rv = 0;
1630   ip4_address_t in_addr, out_addr;
1631
1632   if (!sm->deterministic)
1633     {
1634       rv = VNET_API_ERROR_UNSUPPORTED;
1635       goto send_reply;
1636     }
1637
1638   if (!mp->is_nat44)
1639     {
1640       rv = VNET_API_ERROR_UNIMPLEMENTED;
1641       goto send_reply;
1642     }
1643
1644   clib_memcpy (&in_addr, mp->in_addr, 4);
1645   clib_memcpy (&out_addr, mp->out_addr, 4);
1646   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
1647                          mp->out_plen, mp->is_add);
1648
1649 send_reply:
1650   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
1651 }
1652
1653 static void *
1654 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
1655                                     void *handle)
1656 {
1657   u8 *s;
1658
1659   s = format (0, "SCRIPT: nat_det_add_del_map ");
1660   s = format (s, "inside address %U/%d outside address %U/%d\n",
1661               format_ip4_address, mp->in_addr, mp->in_plen,
1662               format_ip4_address, mp->out_addr, mp->out_plen);
1663
1664   FINISH;
1665 }
1666
1667 static void
1668 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
1669 {
1670   snat_main_t *sm = &snat_main;
1671   vl_api_nat_det_forward_reply_t *rmp;
1672   int rv = 0;
1673   u16 lo_port = 0, hi_port = 0;
1674   snat_det_map_t *dm;
1675   ip4_address_t in_addr, out_addr;
1676
1677   if (!sm->deterministic)
1678     {
1679       rv = VNET_API_ERROR_UNSUPPORTED;
1680       REPLY_MACRO (VL_API_NAT_DET_FORWARD_REPLY);
1681       return;
1682     }
1683
1684   if (!mp->is_nat44)
1685     {
1686       out_addr.as_u32 = 0;
1687       rv = VNET_API_ERROR_UNIMPLEMENTED;
1688       goto send_reply;
1689     }
1690
1691   out_addr.as_u32 = 0;
1692   clib_memcpy (&in_addr, mp->in_addr, 4);
1693   dm = snat_det_map_by_user (sm, &in_addr);
1694   if (!dm)
1695     {
1696       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1697       goto send_reply;
1698     }
1699
1700   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1701   hi_port = lo_port + dm->ports_per_host - 1;
1702
1703 send_reply:
1704   /* *INDENT-OFF* */
1705   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
1706   ({
1707     rmp->out_port_lo = ntohs (lo_port);
1708     rmp->out_port_hi = ntohs (hi_port);
1709     clib_memcpy (rmp->out_addr, &out_addr, 4);
1710   }))
1711   /* *INDENT-ON* */
1712 }
1713
1714 static void *
1715 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
1716 {
1717   u8 *s;
1718
1719   s = format (0, "SCRIPT: nat_det_forward");
1720   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
1721
1722   FINISH;
1723 }
1724
1725 static void
1726 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
1727 {
1728   snat_main_t *sm = &snat_main;
1729   vl_api_nat_det_reverse_reply_t *rmp;
1730   int rv = 0;
1731   ip4_address_t out_addr, in_addr;
1732   snat_det_map_t *dm;
1733
1734   if (!sm->deterministic)
1735     {
1736       rv = VNET_API_ERROR_UNSUPPORTED;
1737       REPLY_MACRO (VL_API_NAT_DET_REVERSE_REPLY);
1738       return;
1739     }
1740
1741   in_addr.as_u32 = 0;
1742   clib_memcpy (&out_addr, mp->out_addr, 4);
1743   dm = snat_det_map_by_out (sm, &out_addr);
1744   if (!dm)
1745     {
1746       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1747       goto send_reply;
1748     }
1749
1750   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1751
1752 send_reply:
1753   /* *INDENT-OFF* */
1754   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
1755   ({
1756     rmp->is_nat44 = 1;
1757     memset (rmp->in_addr, 0, 16);
1758     clib_memcpy (rmp->in_addr, &in_addr, 4);
1759   }))
1760   /* *INDENT-ON* */
1761 }
1762
1763 static void *
1764 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
1765 {
1766   u8 *s;
1767
1768   s = format (0, "SCRIPT: nat_det_reverse");
1769   s = format (s, "outside ip address %U outside port %d",
1770               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1771
1772   FINISH;
1773 }
1774
1775 static void
1776 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
1777                           u32 context)
1778 {
1779   vl_api_nat_det_map_details_t *rmp;
1780   snat_main_t *sm = &snat_main;
1781
1782   rmp = vl_msg_api_alloc (sizeof (*rmp));
1783   memset (rmp, 0, sizeof (*rmp));
1784   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
1785   rmp->is_nat44 = 1;
1786   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
1787   rmp->in_plen = m->in_plen;
1788   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
1789   rmp->out_plen = m->out_plen;
1790   rmp->sharing_ratio = htonl (m->sharing_ratio);
1791   rmp->ports_per_host = htons (m->ports_per_host);
1792   rmp->ses_num = htonl (m->ses_num);
1793   rmp->context = context;
1794
1795   vl_api_send_msg (reg, (u8 *) rmp);
1796 }
1797
1798 static void
1799 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
1800 {
1801   vl_api_registration_t *reg;
1802   snat_main_t *sm = &snat_main;
1803   snat_det_map_t *m;
1804
1805   if (!sm->deterministic)
1806     return;
1807
1808   reg = vl_api_client_index_to_registration (mp->client_index);
1809   if (!reg)
1810     return;
1811
1812   /* *INDENT-OFF* */
1813   vec_foreach(m, sm->det_maps)
1814     sent_nat_det_map_details(m, reg, mp->context);
1815   /* *INDENT-ON* */
1816 }
1817
1818 static void *
1819 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
1820 {
1821   u8 *s;
1822
1823   s = format (0, "SCRIPT: nat_det_map_dump ");
1824
1825   FINISH;
1826 }
1827
1828 static void
1829 vl_api_nat_det_set_timeouts_t_handler (vl_api_nat_det_set_timeouts_t * mp)
1830 {
1831   snat_main_t *sm = &snat_main;
1832   vl_api_nat_det_set_timeouts_reply_t *rmp;
1833   int rv = 0;
1834
1835   if (!sm->deterministic)
1836     {
1837       rv = VNET_API_ERROR_UNSUPPORTED;
1838       goto send_reply;
1839     }
1840
1841   sm->udp_timeout = ntohl (mp->udp);
1842   sm->tcp_established_timeout = ntohl (mp->tcp_established);
1843   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
1844   sm->icmp_timeout = ntohl (mp->icmp);
1845
1846 send_reply:
1847   REPLY_MACRO (VL_API_NAT_DET_SET_TIMEOUTS_REPLY);
1848 }
1849
1850 static void *
1851 vl_api_nat_det_set_timeouts_t_print (vl_api_nat_det_set_timeouts_t * mp,
1852                                      void *handle)
1853 {
1854   u8 *s;
1855
1856   s = format (0, "SCRIPT: nat_det_set_timeouts ");
1857   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
1858               ntohl (mp->udp),
1859               ntohl (mp->tcp_established),
1860               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1861
1862   FINISH;
1863 }
1864
1865 static void
1866 vl_api_nat_det_get_timeouts_t_handler (vl_api_nat_det_get_timeouts_t * mp)
1867 {
1868   snat_main_t *sm = &snat_main;
1869   vl_api_nat_det_get_timeouts_reply_t *rmp;
1870   int rv = 0;
1871
1872   if (!sm->deterministic)
1873     {
1874       rv = VNET_API_ERROR_UNSUPPORTED;
1875       REPLY_MACRO (VL_API_NAT_DET_GET_TIMEOUTS_REPLY);
1876       return;
1877     }
1878
1879   /* *INDENT-OFF* */
1880   REPLY_MACRO2 (VL_API_NAT_DET_GET_TIMEOUTS_REPLY,
1881   ({
1882     rmp->udp = htonl (sm->udp_timeout);
1883     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1884     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1885     rmp->icmp = htonl (sm->icmp_timeout);
1886   }))
1887   /* *INDENT-ON* */
1888 }
1889
1890 static void *
1891 vl_api_nat_det_get_timeouts_t_print (vl_api_nat_det_get_timeouts_t * mp,
1892                                      void *handle)
1893 {
1894   u8 *s;
1895
1896   s = format (0, "SCRIPT: nat_det_get_timeouts");
1897
1898   FINISH;
1899 }
1900
1901 static void
1902 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
1903                                             * mp)
1904 {
1905   snat_main_t *sm = &snat_main;
1906   vl_api_nat_det_close_session_out_reply_t *rmp;
1907   ip4_address_t out_addr, ext_addr, in_addr;
1908   snat_det_out_key_t key;
1909   snat_det_map_t *dm;
1910   snat_det_session_t *ses;
1911   int rv = 0;
1912
1913   if (!sm->deterministic)
1914     {
1915       rv = VNET_API_ERROR_UNSUPPORTED;
1916       goto send_reply;
1917     }
1918
1919   clib_memcpy (&out_addr, mp->out_addr, 4);
1920   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1921
1922   dm = snat_det_map_by_out (sm, &out_addr);
1923   if (!dm)
1924     {
1925       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1926       goto send_reply;
1927     }
1928   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1929   key.ext_host_addr = ext_addr;
1930   key.ext_host_port = mp->ext_port;
1931   key.out_port = mp->out_port;
1932   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1933   if (!ses)
1934     {
1935       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1936       goto send_reply;
1937     }
1938   snat_det_ses_close (dm, ses);
1939
1940 send_reply:
1941   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
1942 }
1943
1944 static void *
1945 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
1946                                           mp, void *handle)
1947 {
1948   u8 *s;
1949
1950   s = format (0, "SCRIPT: nat_det_close_session_out ");
1951   s = format (s, "out_addr %U out_port %d "
1952               "ext_addr %U ext_port %d\n",
1953               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1954               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1955
1956   FINISH;
1957 }
1958
1959 static void
1960 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
1961                                            mp)
1962 {
1963   snat_main_t *sm = &snat_main;
1964   vl_api_nat_det_close_session_in_reply_t *rmp;
1965   ip4_address_t in_addr, ext_addr;
1966   snat_det_out_key_t key;
1967   snat_det_map_t *dm;
1968   snat_det_session_t *ses;
1969   int rv = 0;
1970
1971   if (!sm->deterministic)
1972     {
1973       rv = VNET_API_ERROR_UNSUPPORTED;
1974       goto send_reply;
1975     }
1976
1977   if (!mp->is_nat44)
1978     {
1979       rv = VNET_API_ERROR_UNIMPLEMENTED;
1980       goto send_reply;
1981     }
1982
1983   clib_memcpy (&in_addr, mp->in_addr, 4);
1984   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1985
1986   dm = snat_det_map_by_user (sm, &in_addr);
1987   if (!dm)
1988     {
1989       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1990       goto send_reply;
1991     }
1992   key.ext_host_addr = ext_addr;
1993   key.ext_host_port = mp->ext_port;
1994   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1995   if (!ses)
1996     {
1997       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1998       goto send_reply;
1999     }
2000   snat_det_ses_close (dm, ses);
2001
2002 send_reply:
2003   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2004 }
2005
2006 static void *
2007 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2008                                          mp, void *handle)
2009 {
2010   u8 *s;
2011   s = format (0, "SCRIPT: nat_det_close_session_in ");
2012   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2013               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2014               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2015
2016   FINISH;
2017 }
2018
2019 static void
2020 send_nat_det_session_details (snat_det_session_t * s,
2021                               vl_api_registration_t * reg, u32 context)
2022 {
2023   vl_api_nat_det_session_details_t *rmp;
2024   snat_main_t *sm = &snat_main;
2025
2026   rmp = vl_msg_api_alloc (sizeof (*rmp));
2027   memset (rmp, 0, sizeof (*rmp));
2028   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2029   rmp->in_port = s->in_port;
2030   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2031   rmp->ext_port = s->out.ext_host_port;
2032   rmp->out_port = s->out.out_port;
2033   rmp->state = s->state;
2034   rmp->expire = ntohl (s->expire);
2035   rmp->context = context;
2036
2037   vl_api_send_msg (reg, (u8 *) rmp);
2038 }
2039
2040 static void
2041 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2042 {
2043   vl_api_registration_t *reg;
2044   snat_main_t *sm = &snat_main;
2045   ip4_address_t user_addr;
2046   snat_det_map_t *dm;
2047   snat_det_session_t *s, empty_ses;
2048   u16 i;
2049
2050   if (!sm->deterministic)
2051     return;
2052
2053   reg = vl_api_client_index_to_registration (mp->client_index);
2054   if (!reg)
2055     return;
2056   if (!mp->is_nat44)
2057     return;
2058
2059   memset (&empty_ses, 0, sizeof (empty_ses));
2060   clib_memcpy (&user_addr, mp->user_addr, 4);
2061   dm = snat_det_map_by_user (sm, &user_addr);
2062   if (!dm)
2063     return;
2064
2065   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2066   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2067     {
2068       if (s->out.as_u64)
2069         send_nat_det_session_details (s, reg, mp->context);
2070       s++;
2071     }
2072 }
2073
2074 static void *
2075 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2076                                      void *handle)
2077 {
2078   u8 *s;
2079
2080   s = format (0, "SCRIPT: nat_det_session_dump ");
2081   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2082
2083   FINISH;
2084 }
2085
2086 /*************/
2087 /*** NAT64 ***/
2088 /*************/
2089
2090 static void
2091   vl_api_nat64_add_del_pool_addr_range_t_handler
2092   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2093 {
2094   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2095   snat_main_t *sm = &snat_main;
2096   int rv = 0;
2097   ip4_address_t this_addr;
2098   u32 start_host_order, end_host_order;
2099   u32 vrf_id;
2100   int i, count;
2101   u32 *tmp;
2102
2103   tmp = (u32 *) mp->start_addr;
2104   start_host_order = clib_host_to_net_u32 (tmp[0]);
2105   tmp = (u32 *) mp->end_addr;
2106   end_host_order = clib_host_to_net_u32 (tmp[0]);
2107
2108   count = (end_host_order - start_host_order) + 1;
2109
2110   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2111
2112   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2113
2114   for (i = 0; i < count; i++)
2115     {
2116       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
2117         goto send_reply;
2118
2119       increment_v4_address (&this_addr);
2120     }
2121
2122 send_reply:
2123   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2124 }
2125
2126 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2127   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2128 {
2129   u8 *s;
2130
2131   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2132   s = format (s, "%U - %U vrf_id %u %s\n",
2133               format_ip4_address, mp->start_addr,
2134               format_ip4_address, mp->end_addr,
2135               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2136
2137   FINISH;
2138 }
2139
2140 typedef struct nat64_api_walk_ctx_t_
2141 {
2142   vl_api_registration_t *reg;
2143   u32 context;
2144   nat64_db_t *db;
2145 } nat64_api_walk_ctx_t;
2146
2147 static int
2148 nat64_api_pool_walk (snat_address_t * a, void *arg)
2149 {
2150   vl_api_nat64_pool_addr_details_t *rmp;
2151   snat_main_t *sm = &snat_main;
2152   nat64_api_walk_ctx_t *ctx = arg;
2153
2154   rmp = vl_msg_api_alloc (sizeof (*rmp));
2155   memset (rmp, 0, sizeof (*rmp));
2156   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2157   clib_memcpy (rmp->address, &(a->addr), 4);
2158   if (a->fib_index != ~0)
2159     {
2160       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2161       if (!fib)
2162         return -1;
2163       rmp->vrf_id = ntohl (fib->ft_table_id);
2164     }
2165   else
2166     rmp->vrf_id = ~0;
2167   rmp->context = ctx->context;
2168
2169   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2170
2171   return 0;
2172 }
2173
2174 static void
2175 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2176 {
2177   vl_api_registration_t *reg;
2178
2179   reg = vl_api_client_index_to_registration (mp->client_index);
2180   if (!reg)
2181     return;
2182
2183   nat64_api_walk_ctx_t ctx = {
2184     .reg = reg,
2185     .context = mp->context,
2186   };
2187
2188   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2189 }
2190
2191 static void *
2192 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2193                                      void *handle)
2194 {
2195   u8 *s;
2196
2197   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2198
2199   FINISH;
2200 }
2201
2202 static void
2203 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2204                                           mp)
2205 {
2206   snat_main_t *sm = &snat_main;
2207   vl_api_nat64_add_del_interface_reply_t *rmp;
2208   int rv = 0;
2209
2210   VALIDATE_SW_IF_INDEX (mp);
2211
2212   rv =
2213     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
2214                              mp->is_add);
2215
2216   BAD_SW_IF_INDEX_LABEL;
2217
2218   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2219 }
2220
2221 static void *
2222 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2223                                         void *handle)
2224 {
2225   u8 *s;
2226
2227   s = format (0, "SCRIPT: nat64_add_del_interface ");
2228   s = format (s, "sw_if_index %d %s %s",
2229               clib_host_to_net_u32 (mp->sw_if_index),
2230               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2231
2232   FINISH;
2233 }
2234
2235 static int
2236 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2237 {
2238   vl_api_nat64_interface_details_t *rmp;
2239   snat_main_t *sm = &snat_main;
2240   nat64_api_walk_ctx_t *ctx = arg;
2241
2242   rmp = vl_msg_api_alloc (sizeof (*rmp));
2243   memset (rmp, 0, sizeof (*rmp));
2244   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2245   rmp->sw_if_index = ntohl (i->sw_if_index);
2246   rmp->is_inside = (nat_interface_is_inside (i)
2247                     && nat_interface_is_outside (i)) ? 2 :
2248     nat_interface_is_inside (i);
2249   rmp->context = ctx->context;
2250
2251   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2252
2253   return 0;
2254 }
2255
2256 static void
2257 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2258 {
2259   vl_api_registration_t *reg;
2260
2261   reg = vl_api_client_index_to_registration (mp->client_index);
2262   if (!reg)
2263     return;
2264
2265   nat64_api_walk_ctx_t ctx = {
2266     .reg = reg,
2267     .context = mp->context,
2268   };
2269
2270   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2271 }
2272
2273 static void *
2274 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2275                                      void *handle)
2276 {
2277   u8 *s;
2278
2279   s = format (0, "SCRIPT: snat_interface_dump ");
2280
2281   FINISH;
2282 }
2283
2284 static void
2285   vl_api_nat64_add_del_static_bib_t_handler
2286   (vl_api_nat64_add_del_static_bib_t * mp)
2287 {
2288   snat_main_t *sm = &snat_main;
2289   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2290   ip6_address_t in_addr;
2291   ip4_address_t out_addr;
2292   int rv = 0;
2293
2294   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2295   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2296
2297   rv =
2298     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2299                                     clib_net_to_host_u16 (mp->i_port),
2300                                     clib_net_to_host_u16 (mp->o_port),
2301                                     mp->proto,
2302                                     clib_net_to_host_u32 (mp->vrf_id),
2303                                     mp->is_add);
2304
2305   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2306 }
2307
2308 static void *vl_api_nat64_add_del_static_bib_t_print
2309   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2310 {
2311   u8 *s;
2312
2313   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2314   s = format (s, "protocol %d i_addr %U o_addr %U ",
2315               mp->proto,
2316               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2317
2318   if (mp->vrf_id != ~0)
2319     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2320
2321   FINISH;
2322 }
2323
2324 static int
2325 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2326 {
2327   vl_api_nat64_bib_details_t *rmp;
2328   snat_main_t *sm = &snat_main;
2329   nat64_api_walk_ctx_t *ctx = arg;
2330   fib_table_t *fib;
2331
2332   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2333   if (!fib)
2334     return -1;
2335
2336   rmp = vl_msg_api_alloc (sizeof (*rmp));
2337   memset (rmp, 0, sizeof (*rmp));
2338   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2339   rmp->context = ctx->context;
2340   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2341   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2342   rmp->i_port = bibe->in_port;
2343   rmp->o_port = bibe->out_port;
2344   rmp->vrf_id = ntohl (fib->ft_table_id);
2345   rmp->proto = bibe->proto;
2346   rmp->is_static = bibe->is_static;
2347   rmp->ses_num = ntohl (bibe->ses_num);
2348
2349   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2350
2351   return 0;
2352 }
2353
2354 static void
2355 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2356 {
2357   vl_api_registration_t *reg;
2358   nat64_main_t *nm = &nat64_main;
2359   nat64_db_t *db;
2360
2361   reg = vl_api_client_index_to_registration (mp->client_index);
2362   if (!reg)
2363     return;
2364
2365   nat64_api_walk_ctx_t ctx = {
2366     .reg = reg,
2367     .context = mp->context,
2368   };
2369
2370   /* *INDENT-OFF* */
2371   vec_foreach (db, nm->db)
2372     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2373   /* *INDENT-ON* */
2374 }
2375
2376 static void *
2377 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2378 {
2379   u8 *s;
2380
2381   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2382
2383   FINISH;
2384 }
2385
2386 static void
2387 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
2388 {
2389   snat_main_t *sm = &snat_main;
2390   vl_api_nat64_set_timeouts_reply_t *rmp;
2391   int rv = 0;
2392
2393   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
2394   if (rv)
2395     goto send_reply;
2396   rv = nat64_set_udp_timeout (ntohl (mp->udp));
2397   if (rv)
2398     goto send_reply;
2399   rv =
2400     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
2401                             ntohl (mp->tcp_incoming_syn));
2402
2403 send_reply:
2404   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
2405 }
2406
2407 static void *vl_api_nat64_set_timeouts_t_print
2408   (vl_api_nat64_set_timeouts_t * mp, void *handle)
2409 {
2410   u8 *s;
2411
2412   s = format (0, "SCRIPT: nat64_set_timeouts ");
2413   s =
2414     format (s,
2415             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
2416             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
2417             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
2418
2419   FINISH;
2420 }
2421
2422 static void
2423 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
2424 {
2425   snat_main_t *sm = &snat_main;
2426   vl_api_nat64_get_timeouts_reply_t *rmp;
2427   int rv = 0;
2428
2429   /* *INDENT-OFF* */
2430   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
2431   ({
2432     rmp->udp = htonl (nat64_get_udp_timeout());
2433     rmp->icmp = htonl (nat64_get_icmp_timeout());
2434     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
2435     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
2436     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
2437   }))
2438   /* *INDENT-ON* */
2439 }
2440
2441 static void *vl_api_nat64_get_timeouts_t_print
2442   (vl_api_nat64_get_timeouts_t * mp, void *handle)
2443 {
2444   u8 *s;
2445
2446   s = format (0, "SCRIPT: nat64_get_timeouts");
2447
2448   FINISH;
2449 }
2450
2451 static int
2452 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2453 {
2454   vl_api_nat64_st_details_t *rmp;
2455   snat_main_t *sm = &snat_main;
2456   nat64_api_walk_ctx_t *ctx = arg;
2457   nat64_db_bib_entry_t *bibe;
2458   fib_table_t *fib;
2459
2460   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2461   if (!bibe)
2462     return -1;
2463
2464   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2465   if (!fib)
2466     return -1;
2467
2468   rmp = vl_msg_api_alloc (sizeof (*rmp));
2469   memset (rmp, 0, sizeof (*rmp));
2470   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2471   rmp->context = ctx->context;
2472   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2473   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2474   rmp->il_port = bibe->in_port;
2475   rmp->ol_port = bibe->out_port;
2476   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2477   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2478   rmp->il_port = ste->r_port;
2479   rmp->vrf_id = ntohl (fib->ft_table_id);
2480   rmp->proto = ste->proto;
2481
2482   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2483
2484   return 0;
2485 }
2486
2487 static void
2488 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2489 {
2490   vl_api_registration_t *reg;
2491   nat64_main_t *nm = &nat64_main;
2492   nat64_db_t *db;
2493
2494   reg = vl_api_client_index_to_registration (mp->client_index);
2495   if (!reg)
2496     return;
2497
2498   nat64_api_walk_ctx_t ctx = {
2499     .reg = reg,
2500     .context = mp->context,
2501   };
2502
2503   /* *INDENT-OFF* */
2504   vec_foreach (db, nm->db)
2505     {
2506       ctx.db = db;
2507       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2508     }
2509   /* *INDENT-ON* */
2510 }
2511
2512 static void *
2513 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2514 {
2515   u8 *s;
2516
2517   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2518
2519   FINISH;
2520 }
2521
2522 static void
2523 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2524 {
2525   vl_api_nat64_add_del_prefix_reply_t *rmp;
2526   snat_main_t *sm = &snat_main;
2527   ip6_address_t prefix;
2528   int rv = 0;
2529
2530   memcpy (&prefix.as_u8, mp->prefix, 16);
2531
2532   rv =
2533     nat64_add_del_prefix (&prefix, mp->prefix_len,
2534                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2535   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2536 }
2537
2538 static void *
2539 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2540                                      void *handle)
2541 {
2542   u8 *s;
2543
2544   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2545               format_ip6_address, mp->prefix, mp->prefix_len,
2546               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2547
2548   FINISH;
2549 }
2550
2551 static int
2552 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2553 {
2554   vl_api_nat64_prefix_details_t *rmp;
2555   snat_main_t *sm = &snat_main;
2556   nat64_api_walk_ctx_t *ctx = arg;
2557
2558   rmp = vl_msg_api_alloc (sizeof (*rmp));
2559   memset (rmp, 0, sizeof (*rmp));
2560   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2561   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2562   rmp->prefix_len = p->plen;
2563   rmp->vrf_id = ntohl (p->vrf_id);
2564   rmp->context = ctx->context;
2565
2566   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2567
2568   return 0;
2569 }
2570
2571 static void
2572 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2573 {
2574   vl_api_registration_t *reg;
2575
2576   reg = vl_api_client_index_to_registration (mp->client_index);
2577   if (!reg)
2578     return;
2579
2580   nat64_api_walk_ctx_t ctx = {
2581     .reg = reg,
2582     .context = mp->context,
2583   };
2584
2585   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2586 }
2587
2588 static void *
2589 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2590                                   void *handle)
2591 {
2592   u8 *s;
2593
2594   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2595
2596   FINISH;
2597 }
2598
2599 static void
2600   vl_api_nat64_add_del_interface_addr_t_handler
2601   (vl_api_nat64_add_del_interface_addr_t * mp)
2602 {
2603   snat_main_t *sm = &snat_main;
2604   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2605   u32 sw_if_index = ntohl (mp->sw_if_index);
2606   int rv = 0;
2607
2608   VALIDATE_SW_IF_INDEX (mp);
2609
2610   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2611
2612   BAD_SW_IF_INDEX_LABEL;
2613
2614   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2615 }
2616
2617 static void *vl_api_nat64_add_del_interface_addr_t_print
2618   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2619 {
2620   u8 *s;
2621
2622   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2623   s = format (s, "sw_if_index %d %s",
2624               clib_host_to_net_u32 (mp->sw_if_index),
2625               mp->is_add ? "" : "del");
2626
2627   FINISH;
2628 }
2629
2630 /***************/
2631 /*** DS-Lite ***/
2632 /***************/
2633
2634 static void
2635 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2636 {
2637   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2638   snat_main_t *sm = &snat_main;
2639   dslite_main_t *dm = &dslite_main;
2640   int rv = 0;
2641   ip6_address_t ip6_addr;
2642   ip4_address_t ip4_addr;
2643
2644   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2645   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2646
2647   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2648   if (rv == 0)
2649     rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr);
2650
2651   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2652 }
2653
2654 static void *
2655 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2656                                      void *handle)
2657 {
2658   u8 *s;
2659
2660   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2661   s = format (s, "ip6_addr %U ip4_addr %U\n",
2662               format_ip6_address, mp->ip6_addr,
2663               format_ip4_address, mp->ip4_addr);
2664
2665   FINISH;
2666 }
2667
2668 static void
2669 vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp)
2670 {
2671   snat_main_t *sm = &snat_main;
2672   vl_api_dslite_get_aftr_addr_reply_t *rmp;
2673   dslite_main_t *dm = &dslite_main;
2674   int rv = 0;
2675
2676   /* *INDENT-OFF* */
2677   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2678   ({
2679     memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4);
2680     memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16);
2681   }))
2682   /* *INDENT-ON* */
2683 }
2684
2685 static void *
2686 vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp,
2687                                      void *handle)
2688 {
2689   u8 *s;
2690
2691   s = format (0, "SCRIPT: dslite_get_aftr_addr");
2692
2693   FINISH;
2694 }
2695
2696 static void
2697 vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp)
2698 {
2699   vl_api_dslite_set_b4_addr_reply_t *rmp;
2700   snat_main_t *sm = &snat_main;
2701   dslite_main_t *dm = &dslite_main;
2702   int rv = 0;
2703   ip6_address_t ip6_addr;
2704   ip4_address_t ip4_addr;
2705
2706   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2707   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2708
2709   rv = dslite_set_b4_ip6_addr (dm, &ip6_addr);
2710   if (rv == 0)
2711     rv = dslite_set_b4_ip4_addr (dm, &ip4_addr);
2712
2713   REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY);
2714 }
2715
2716 static void *
2717 vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp,
2718                                    void *handle)
2719 {
2720   u8 *s;
2721
2722   s = format (0, "SCRIPT: dslite_set_b4_addr ");
2723   s = format (s, "ip6_addr %U ip4_addr %U\n",
2724               format_ip6_address, mp->ip6_addr,
2725               format_ip6_address, mp->ip4_addr);
2726
2727   FINISH;
2728 }
2729
2730 static void
2731 vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp)
2732 {
2733   snat_main_t *sm = &snat_main;
2734   vl_api_dslite_get_b4_addr_reply_t *rmp;
2735   dslite_main_t *dm = &dslite_main;
2736   int rv = 0;
2737
2738   /* *INDENT-OFF* */
2739   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2740   ({
2741     memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4);
2742     memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16);
2743   }))
2744   /* *INDENT-ON* */
2745 }
2746
2747 static void *
2748 vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp,
2749                                    void *handle)
2750 {
2751   u8 *s;
2752
2753   s = format (0, "SCRIPT: dslite_get_b4_addr");
2754
2755   FINISH;
2756 }
2757
2758 static void
2759   vl_api_dslite_add_del_pool_addr_range_t_handler
2760   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2761 {
2762   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2763   snat_main_t *sm = &snat_main;
2764   dslite_main_t *dm = &dslite_main;
2765   int rv = 0;
2766   ip4_address_t this_addr;
2767   u32 start_host_order, end_host_order;
2768   int i, count;
2769   u32 *tmp;
2770
2771   tmp = (u32 *) mp->start_addr;
2772   start_host_order = clib_host_to_net_u32 (tmp[0]);
2773   tmp = (u32 *) mp->end_addr;
2774   end_host_order = clib_host_to_net_u32 (tmp[0]);
2775
2776   count = (end_host_order - start_host_order) + 1;
2777   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2778
2779   for (i = 0; i < count; i++)
2780     {
2781       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2782         goto send_reply;
2783
2784       increment_v4_address (&this_addr);
2785     }
2786
2787 send_reply:
2788   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2789 }
2790
2791 static void
2792 send_dslite_address_details (snat_address_t * ap,
2793                              vl_api_registration_t * reg, u32 context)
2794 {
2795   vl_api_dslite_address_details_t *rmp;
2796   snat_main_t *sm = &snat_main;
2797
2798   rmp = vl_msg_api_alloc (sizeof (*rmp));
2799
2800   memset (rmp, 0, sizeof (*rmp));
2801
2802   rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + sm->msg_id_base);
2803   clib_memcpy (rmp->ip_address, &(ap->addr), 4);
2804   rmp->context = context;
2805
2806   vl_api_send_msg (reg, (u8 *) rmp);
2807 }
2808
2809 static void
2810 vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp)
2811 {
2812   vl_api_registration_t *reg;
2813   dslite_main_t *dm = &dslite_main;
2814   snat_address_t *ap;
2815
2816   reg = vl_api_client_index_to_registration (mp->client_index);
2817   if (!reg)
2818     return;
2819
2820   /* *INDENT-OFF* */
2821   vec_foreach (ap, dm->addr_pool)
2822     {
2823       send_dslite_address_details (ap, reg, mp->context);
2824     }
2825   /* *INDENT-ON* */
2826 }
2827
2828 static void *
2829 vl_api_dslite_address_dump_t_print (vl_api_dslite_address_dump_t * mp,
2830                                     void *handle)
2831 {
2832   u8 *s;
2833
2834   s = format (0, "SCRIPT: dslite_address_dump ");
2835
2836   FINISH;
2837 }
2838
2839 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2840   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2841 {
2842   u8 *s;
2843
2844   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2845   s = format (s, "%U - %U\n",
2846               format_ip4_address, mp->start_addr,
2847               format_ip4_address, mp->end_addr);
2848
2849   FINISH;
2850 }
2851
2852
2853 /*************/
2854 /*** NAT66 ***/
2855 /*************/
2856
2857 static void
2858 vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
2859                                           mp)
2860 {
2861   snat_main_t *sm = &snat_main;
2862   vl_api_nat66_add_del_interface_reply_t *rmp;
2863   int rv = 0;
2864
2865   VALIDATE_SW_IF_INDEX (mp);
2866
2867   rv =
2868     nat66_interface_add_del (ntohl (mp->sw_if_index), mp->is_inside,
2869                              mp->is_add);
2870
2871   BAD_SW_IF_INDEX_LABEL;
2872
2873   REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
2874 }
2875
2876 static void *
2877 vl_api_nat66_add_del_interface_t_print (vl_api_nat66_add_del_interface_t * mp,
2878                                         void *handle)
2879 {
2880   u8 *s;
2881
2882   s = format (0, "SCRIPT: nat66_add_del_interface ");
2883   s = format (s, "sw_if_index %d %s %s",
2884               clib_host_to_net_u32 (mp->sw_if_index),
2885               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2886
2887   FINISH;
2888 }
2889
2890 static void
2891   vl_api_nat66_add_del_static_mapping_t_handler
2892   (vl_api_nat66_add_del_static_mapping_t * mp)
2893 {
2894   snat_main_t *sm = &snat_main;
2895   vl_api_nat66_add_del_static_mapping_reply_t *rmp;
2896   ip6_address_t l_addr, e_addr;
2897   int rv = 0;
2898
2899   memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
2900   memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
2901
2902   rv =
2903     nat66_static_mapping_add_del (&l_addr, &e_addr,
2904                                   clib_net_to_host_u32 (mp->vrf_id),
2905                                   mp->is_add);
2906
2907   REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
2908 }
2909
2910 static void *vl_api_nat66_add_del_static_mapping_t_print
2911   (vl_api_nat66_add_del_static_mapping_t * mp, void *handle)
2912 {
2913   u8 *s;
2914
2915   s = format (0, "SCRIPT: nat66_add_del_static_mapping ");
2916   s = format (s, "local_ip_address %U external_ip_address %U vrf_id %d %s",
2917               format_ip6_address, mp->local_ip_address,
2918               format_ip6_address, mp->external_ip_address,
2919               clib_net_to_host_u32 (mp->vrf_id), mp->is_add ? "" : "del");
2920
2921   FINISH;
2922 }
2923
2924 typedef struct nat66_api_walk_ctx_t_
2925 {
2926   svm_queue_t *q;
2927   u32 context;
2928 } nat66_api_walk_ctx_t;
2929
2930 static int
2931 nat66_api_interface_walk (snat_interface_t * i, void *arg)
2932 {
2933   vl_api_nat66_interface_details_t *rmp;
2934   snat_main_t *sm = &snat_main;
2935   nat66_api_walk_ctx_t *ctx = arg;
2936
2937   rmp = vl_msg_api_alloc (sizeof (*rmp));
2938   memset (rmp, 0, sizeof (*rmp));
2939   rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + sm->msg_id_base);
2940   rmp->sw_if_index = ntohl (i->sw_if_index);
2941   rmp->is_inside = nat_interface_is_inside (i);
2942   rmp->context = ctx->context;
2943
2944   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2945
2946   return 0;
2947 }
2948
2949 static void
2950 vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
2951 {
2952   svm_queue_t *q;
2953
2954   q = vl_api_client_index_to_input_queue (mp->client_index);
2955   if (q == 0)
2956     return;
2957
2958   nat66_api_walk_ctx_t ctx = {
2959     .q = q,
2960     .context = mp->context,
2961   };
2962
2963   nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
2964 }
2965
2966 static void *
2967 vl_api_nat66_interface_dump_t_print (vl_api_nat66_interface_dump_t * mp,
2968                                      void *handle)
2969 {
2970   u8 *s;
2971
2972   s = format (0, "SCRIPT: nat66_interface_dump ");
2973
2974   FINISH;
2975 }
2976
2977 static int
2978 nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
2979 {
2980   vl_api_nat66_static_mapping_details_t *rmp;
2981   nat66_main_t *nm = &nat66_main;
2982   snat_main_t *sm = &snat_main;
2983   nat66_api_walk_ctx_t *ctx = arg;
2984   fib_table_t *fib;
2985   vlib_counter_t vc;
2986
2987   fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
2988   if (!fib)
2989     return -1;
2990
2991   vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
2992
2993   rmp = vl_msg_api_alloc (sizeof (*rmp));
2994   memset (rmp, 0, sizeof (*rmp));
2995   rmp->_vl_msg_id =
2996     ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + sm->msg_id_base);
2997   clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
2998   clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
2999   rmp->vrf_id = ntohl (fib->ft_table_id);
3000   rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
3001   rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
3002   rmp->context = ctx->context;
3003
3004   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3005
3006   return 0;
3007 }
3008
3009 static void
3010 vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
3011                                             * mp)
3012 {
3013   svm_queue_t *q;
3014
3015   q = vl_api_client_index_to_input_queue (mp->client_index);
3016   if (q == 0)
3017     return;
3018
3019   nat66_api_walk_ctx_t ctx = {
3020     .q = q,
3021     .context = mp->context,
3022   };
3023
3024   nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
3025 }
3026
3027 static void *
3028 vl_api_nat66_static_mapping_dump_t_print (vl_api_nat66_static_mapping_dump_t *
3029                                           mp, void *handle)
3030 {
3031   u8 *s;
3032
3033   s = format (0, "SCRIPT: nat66_static_mapping_dump ");
3034
3035   FINISH;
3036 }
3037
3038
3039 /* List of message types that this plugin understands */
3040 #define foreach_snat_plugin_api_msg                                     \
3041 _(NAT_CONTROL_PING, nat_control_ping)                                   \
3042 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
3043 _(NAT_SET_WORKERS, nat_set_workers)                                     \
3044 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
3045 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
3046 _(NAT_SET_REASS, nat_set_reass)                                         \
3047 _(NAT_GET_REASS, nat_get_reass)                                         \
3048 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
3049 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
3050 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
3051 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
3052 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
3053 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3054 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
3055 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3056 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3057 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3058 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3059 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3060 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3061 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3062   nat44_interface_add_del_output_feature)                               \
3063 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3064   nat44_interface_output_feature_dump)                                  \
3065 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3066 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3067 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
3068 _(NAT44_FORWARDING_ENABLE_DISABLE, nat44_forwarding_enable_disable)     \
3069 _(NAT44_FORWARDING_IS_ENABLED, nat44_forwarding_is_enabled)             \
3070 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3071 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3072 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3073 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3074 _(NAT_DET_SET_TIMEOUTS, nat_det_set_timeouts)                           \
3075 _(NAT_DET_GET_TIMEOUTS, nat_det_get_timeouts)                           \
3076 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3077 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3078 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3079 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3080 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3081 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3082 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3083 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3084 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3085 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
3086 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
3087 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3088 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3089 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
3090 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
3091 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
3092 _(DSLITE_ADDRESS_DUMP, dslite_address_dump)                             \
3093 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)                           \
3094 _(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr)                           \
3095 _(DSLITE_SET_B4_ADDR, dslite_set_b4_addr)                               \
3096 _(DSLITE_GET_B4_ADDR, dslite_get_b4_addr)                               \
3097 _(NAT66_ADD_DEL_INTERFACE, nat66_add_del_interface)                     \
3098 _(NAT66_INTERFACE_DUMP, nat66_interface_dump)                           \
3099 _(NAT66_ADD_DEL_STATIC_MAPPING, nat66_add_del_static_mapping)           \
3100 _(NAT66_STATIC_MAPPING_DUMP, nat66_static_mapping_dump)
3101
3102 /* Set up the API message handling tables */
3103 static clib_error_t *
3104 snat_plugin_api_hookup (vlib_main_t * vm)
3105 {
3106   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3107 #define _(N,n)                                                  \
3108     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3109                            #n,                                  \
3110                            vl_api_##n##_t_handler,              \
3111                            vl_noop_handler,                     \
3112                            vl_api_##n##_t_endian,               \
3113                            vl_api_##n##_t_print,                \
3114                            sizeof(vl_api_##n##_t), 1);
3115   foreach_snat_plugin_api_msg;
3116 #undef _
3117
3118   return 0;
3119 }
3120
3121 #define vl_msg_name_crc_list
3122 #include <nat/nat_all_api_h.h>
3123 #undef vl_msg_name_crc_list
3124
3125 static void
3126 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3127 {
3128 #define _(id,n,crc) \
3129   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3130   foreach_vl_msg_name_crc_nat;
3131 #undef _
3132 }
3133
3134 static void
3135 plugin_custom_dump_configure (snat_main_t * sm)
3136 {
3137 #define _(n,f) sm->api_main->msg_print_handlers \
3138   [VL_API_##n + sm->msg_id_base]                \
3139     = (void *) vl_api_##f##_t_print;
3140   foreach_snat_plugin_api_msg;
3141 #undef _
3142 }
3143
3144 clib_error_t *
3145 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3146 {
3147   u8 *name;
3148   clib_error_t *error = 0;
3149
3150   name = format (0, "nat_%08x%c", api_version, 0);
3151
3152   /* Ask for a correctly-sized block of API message decode slots */
3153   sm->msg_id_base =
3154     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3155
3156   error = snat_plugin_api_hookup (vm);
3157
3158   /* Add our API messages to the global name_crc hash table */
3159   setup_message_id_table (sm, sm->api_main);
3160
3161   plugin_custom_dump_configure (sm);
3162
3163   vec_free (name);
3164
3165   return error;
3166 }
3167
3168 /*
3169  * fd.io coding-style-patch-verification: ON
3170  *
3171  * Local Variables:
3172  * eval: (c-set-style "gnu")
3173  * End:
3174  */