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