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