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