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