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