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