NAT44: asymmetrical load balancing static mapping rule (VPP-1132)
[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                                      mp->out2in_only);
1243
1244   vec_free (locals);
1245
1246   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1247 }
1248
1249 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1250   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1251 {
1252   u8 *s;
1253
1254   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1255   s = format (s, "is_add %d twice_nat %d out2in_only ",
1256               mp->is_add, mp->twice_nat, mp->out2in_only);
1257
1258   FINISH;
1259 }
1260
1261 static void
1262 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1263                                       svm_queue_t * q, u32 context)
1264 {
1265   vl_api_nat44_lb_static_mapping_details_t *rmp;
1266   snat_main_t *sm = &snat_main;
1267   nat44_lb_addr_port_t *ap;
1268   vl_api_nat44_lb_addr_port_t *locals;
1269
1270   rmp =
1271     vl_msg_api_alloc (sizeof (*rmp) +
1272                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
1273   memset (rmp, 0, sizeof (*rmp));
1274   rmp->_vl_msg_id =
1275     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1276
1277   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1278   rmp->external_port = ntohs (m->external_port);
1279   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1280   rmp->vrf_id = ntohl (m->vrf_id);
1281   rmp->context = context;
1282   rmp->twice_nat = m->twice_nat;
1283   rmp->out2in_only = m->out2in_only;
1284
1285   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1286   vec_foreach (ap, m->locals)
1287   {
1288     clib_memcpy (locals->addr, &(ap->addr), 4);
1289     locals->port = htons (ap->port);
1290     locals->probability = ap->probability;
1291     locals++;
1292     rmp->local_num++;
1293   }
1294
1295   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1296 }
1297
1298 static void
1299   vl_api_nat44_lb_static_mapping_dump_t_handler
1300   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1301 {
1302   svm_queue_t *q;
1303   snat_main_t *sm = &snat_main;
1304   snat_static_mapping_t *m;
1305
1306   q = vl_api_client_index_to_input_queue (mp->client_index);
1307   if (q == 0)
1308     return;
1309
1310   /* *INDENT-OFF* */
1311   pool_foreach (m, sm->static_mappings,
1312   ({
1313       if (vec_len(m->locals))
1314         send_nat44_lb_static_mapping_details (m, q, mp->context);
1315   }));
1316   /* *INDENT-ON* */
1317 }
1318
1319 static void *vl_api_nat44_lb_static_mapping_dump_t_print
1320   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
1321 {
1322   u8 *s;
1323
1324   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
1325
1326   FINISH;
1327 }
1328
1329 static void
1330 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1331 {
1332   snat_main_t *sm = &snat_main;
1333   vl_api_nat44_del_session_reply_t *rmp;
1334   ip4_address_t addr;
1335   u16 port;
1336   u32 vrf_id;
1337   int rv = 0;
1338   snat_protocol_t proto;
1339
1340   memcpy (&addr.as_u8, mp->address, 4);
1341   port = clib_net_to_host_u16 (mp->port);
1342   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1343   proto = ip_proto_to_snat_proto (mp->protocol);
1344
1345   rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
1346
1347   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1348 }
1349
1350 static void *
1351 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
1352                                   void *handle)
1353 {
1354   u8 *s;
1355
1356   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1357   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
1358               format_ip4_address, mp->address,
1359               clib_net_to_host_u16 (mp->port),
1360               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
1361
1362   FINISH;
1363 }
1364
1365 static void
1366   vl_api_nat44_forwarding_enable_disable_t_handler
1367   (vl_api_nat44_forwarding_enable_disable_t * mp)
1368 {
1369   snat_main_t *sm = &snat_main;
1370   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1371   int rv = 0;
1372
1373   sm->forwarding_enabled = mp->enable != 0;
1374
1375   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1376 }
1377
1378 static void *vl_api_nat44_forwarding_enable_disable_t_print
1379   (vl_api_nat44_forwarding_enable_disable_t * mp, void *handle)
1380 {
1381   u8 *s;
1382
1383   s = format (0, "SCRIPT: nat44_forwarding_enable_disable ");
1384   s = format (s, "enable %d", mp->enable != 0);
1385
1386   FINISH;
1387 }
1388
1389 static void
1390   vl_api_nat44_forwarding_is_enabled_t_handler
1391   (vl_api_nat44_forwarding_is_enabled_t * mp)
1392 {
1393   svm_queue_t *q;
1394   snat_main_t *sm = &snat_main;
1395   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1396
1397   q = vl_api_client_index_to_input_queue (mp->client_index);
1398   if (q == 0)
1399     return;
1400
1401   rmp = vl_msg_api_alloc (sizeof (*rmp));
1402   memset (rmp, 0, sizeof (*rmp));
1403   rmp->_vl_msg_id =
1404     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1405   rmp->context = mp->context;
1406
1407   rmp->enabled = sm->forwarding_enabled;
1408
1409   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1410 }
1411
1412 static void *vl_api_nat44_forwarding_is_enabled_t_print
1413   (vl_api_nat44_forwarding_is_enabled_t * mp, void *handle)
1414 {
1415   u8 *s;
1416
1417   s = format (0, "SCRIPT: nat44_forwarding_is_enabled ");
1418
1419   FINISH;
1420 }
1421
1422 /*******************************/
1423 /*** Deterministic NAT (CGN) ***/
1424 /*******************************/
1425
1426 static void
1427 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
1428 {
1429   snat_main_t *sm = &snat_main;
1430   vl_api_nat_det_add_del_map_reply_t *rmp;
1431   int rv = 0;
1432   ip4_address_t in_addr, out_addr;
1433
1434   if (!mp->is_nat44)
1435     {
1436       rv = VNET_API_ERROR_UNIMPLEMENTED;
1437       goto send_reply;
1438     }
1439
1440   clib_memcpy (&in_addr, mp->in_addr, 4);
1441   clib_memcpy (&out_addr, mp->out_addr, 4);
1442   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
1443                          mp->out_plen, mp->is_add);
1444
1445 send_reply:
1446   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
1447 }
1448
1449 static void *
1450 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
1451                                     void *handle)
1452 {
1453   u8 *s;
1454
1455   s = format (0, "SCRIPT: nat_det_add_del_map ");
1456   s = format (s, "inside address %U/%d outside address %U/%d\n",
1457               format_ip4_address, mp->in_addr, mp->in_plen,
1458               format_ip4_address, mp->out_addr, mp->out_plen);
1459
1460   FINISH;
1461 }
1462
1463 static void
1464 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
1465 {
1466   snat_main_t *sm = &snat_main;
1467   vl_api_nat_det_forward_reply_t *rmp;
1468   int rv = 0;
1469   u16 lo_port = 0, hi_port = 0;
1470   snat_det_map_t *dm;
1471   ip4_address_t in_addr, out_addr;
1472
1473   if (!mp->is_nat44)
1474     {
1475       out_addr.as_u32 = 0;
1476       rv = VNET_API_ERROR_UNIMPLEMENTED;
1477       goto send_reply;
1478     }
1479
1480   out_addr.as_u32 = 0;
1481   clib_memcpy (&in_addr, mp->in_addr, 4);
1482   dm = snat_det_map_by_user (sm, &in_addr);
1483   if (!dm)
1484     {
1485       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1486       goto send_reply;
1487     }
1488
1489   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1490   hi_port = lo_port + dm->ports_per_host - 1;
1491
1492 send_reply:
1493   /* *INDENT-OFF* */
1494   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
1495   ({
1496     rmp->out_port_lo = ntohs (lo_port);
1497     rmp->out_port_hi = ntohs (hi_port);
1498     clib_memcpy (rmp->out_addr, &out_addr, 4);
1499   }))
1500   /* *INDENT-ON* */
1501 }
1502
1503 static void *
1504 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
1505 {
1506   u8 *s;
1507
1508   s = format (0, "SCRIPT: nat_det_forward");
1509   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
1510
1511   FINISH;
1512 }
1513
1514 static void
1515 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
1516 {
1517   snat_main_t *sm = &snat_main;
1518   vl_api_nat_det_reverse_reply_t *rmp;
1519   int rv = 0;
1520   ip4_address_t out_addr, in_addr;
1521   snat_det_map_t *dm;
1522
1523   in_addr.as_u32 = 0;
1524   clib_memcpy (&out_addr, mp->out_addr, 4);
1525   dm = snat_det_map_by_out (sm, &out_addr);
1526   if (!dm)
1527     {
1528       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1529       goto send_reply;
1530     }
1531
1532   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1533
1534 send_reply:
1535   /* *INDENT-OFF* */
1536   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
1537   ({
1538     rmp->is_nat44 = 1;
1539     memset (rmp->in_addr, 0, 16);
1540     clib_memcpy (rmp->in_addr, &in_addr, 4);
1541   }))
1542   /* *INDENT-ON* */
1543 }
1544
1545 static void *
1546 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
1547 {
1548   u8 *s;
1549
1550   s = format (0, "SCRIPT: nat_det_reverse");
1551   s = format (s, "outside ip address %U outside port %d",
1552               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1553
1554   FINISH;
1555 }
1556
1557 static void
1558 sent_nat_det_map_details (snat_det_map_t * m, svm_queue_t * q, u32 context)
1559 {
1560   vl_api_nat_det_map_details_t *rmp;
1561   snat_main_t *sm = &snat_main;
1562
1563   rmp = vl_msg_api_alloc (sizeof (*rmp));
1564   memset (rmp, 0, sizeof (*rmp));
1565   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
1566   rmp->is_nat44 = 1;
1567   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
1568   rmp->in_plen = m->in_plen;
1569   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
1570   rmp->out_plen = m->out_plen;
1571   rmp->sharing_ratio = htonl (m->sharing_ratio);
1572   rmp->ports_per_host = htons (m->ports_per_host);
1573   rmp->ses_num = htonl (m->ses_num);
1574   rmp->context = context;
1575
1576   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1577 }
1578
1579 static void
1580 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
1581 {
1582   svm_queue_t *q;
1583   snat_main_t *sm = &snat_main;
1584   snat_det_map_t *m;
1585
1586   q = vl_api_client_index_to_input_queue (mp->client_index);
1587   if (q == 0)
1588     return;
1589
1590   /* *INDENT-OFF* */
1591   vec_foreach(m, sm->det_maps)
1592     sent_nat_det_map_details(m, q, mp->context);
1593   /* *INDENT-ON* */
1594 }
1595
1596 static void *
1597 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
1598 {
1599   u8 *s;
1600
1601   s = format (0, "SCRIPT: nat_det_map_dump ");
1602
1603   FINISH;
1604 }
1605
1606 static void
1607 vl_api_nat_det_set_timeouts_t_handler (vl_api_nat_det_set_timeouts_t * mp)
1608 {
1609   snat_main_t *sm = &snat_main;
1610   vl_api_nat_det_set_timeouts_reply_t *rmp;
1611   int rv = 0;
1612
1613   sm->udp_timeout = ntohl (mp->udp);
1614   sm->tcp_established_timeout = ntohl (mp->tcp_established);
1615   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
1616   sm->icmp_timeout = ntohl (mp->icmp);
1617
1618   REPLY_MACRO (VL_API_NAT_DET_SET_TIMEOUTS_REPLY);
1619 }
1620
1621 static void *
1622 vl_api_nat_det_set_timeouts_t_print (vl_api_nat_det_set_timeouts_t * mp,
1623                                      void *handle)
1624 {
1625   u8 *s;
1626
1627   s = format (0, "SCRIPT: nat_det_set_timeouts ");
1628   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
1629               ntohl (mp->udp),
1630               ntohl (mp->tcp_established),
1631               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1632
1633   FINISH;
1634 }
1635
1636 static void
1637 vl_api_nat_det_get_timeouts_t_handler (vl_api_nat_det_get_timeouts_t * mp)
1638 {
1639   snat_main_t *sm = &snat_main;
1640   vl_api_nat_det_get_timeouts_reply_t *rmp;
1641   int rv = 0;
1642
1643   /* *INDENT-OFF* */
1644   REPLY_MACRO2 (VL_API_NAT_DET_GET_TIMEOUTS_REPLY,
1645   ({
1646     rmp->udp = htonl (sm->udp_timeout);
1647     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1648     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1649     rmp->icmp = htonl (sm->icmp_timeout);
1650   }))
1651   /* *INDENT-ON* */
1652 }
1653
1654 static void *
1655 vl_api_nat_det_get_timeouts_t_print (vl_api_nat_det_get_timeouts_t * mp,
1656                                      void *handle)
1657 {
1658   u8 *s;
1659
1660   s = format (0, "SCRIPT: nat_det_get_timeouts");
1661
1662   FINISH;
1663 }
1664
1665 static void
1666 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
1667                                             * mp)
1668 {
1669   snat_main_t *sm = &snat_main;
1670   vl_api_nat_det_close_session_out_reply_t *rmp;
1671   ip4_address_t out_addr, ext_addr, in_addr;
1672   snat_det_out_key_t key;
1673   snat_det_map_t *dm;
1674   snat_det_session_t *ses;
1675   int rv = 0;
1676
1677   clib_memcpy (&out_addr, mp->out_addr, 4);
1678   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1679
1680   dm = snat_det_map_by_out (sm, &out_addr);
1681   if (!dm)
1682     {
1683       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1684       goto send_reply;
1685     }
1686   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1687   key.ext_host_addr = ext_addr;
1688   key.ext_host_port = mp->ext_port;
1689   key.out_port = mp->out_port;
1690   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1691   if (!ses)
1692     {
1693       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1694       goto send_reply;
1695     }
1696   snat_det_ses_close (dm, ses);
1697
1698 send_reply:
1699   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
1700 }
1701
1702 static void *
1703 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
1704                                           mp, void *handle)
1705 {
1706   u8 *s;
1707
1708   s = format (0, "SCRIPT: nat_det_close_session_out ");
1709   s = format (s, "out_addr %U out_port %d "
1710               "ext_addr %U ext_port %d\n",
1711               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1712               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1713
1714   FINISH;
1715 }
1716
1717 static void
1718 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
1719                                            mp)
1720 {
1721   snat_main_t *sm = &snat_main;
1722   vl_api_nat_det_close_session_in_reply_t *rmp;
1723   ip4_address_t in_addr, ext_addr;
1724   snat_det_out_key_t key;
1725   snat_det_map_t *dm;
1726   snat_det_session_t *ses;
1727   int rv = 0;
1728
1729   if (!mp->is_nat44)
1730     {
1731       rv = VNET_API_ERROR_UNIMPLEMENTED;
1732       goto send_reply;
1733     }
1734
1735   clib_memcpy (&in_addr, mp->in_addr, 4);
1736   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1737
1738   dm = snat_det_map_by_user (sm, &in_addr);
1739   if (!dm)
1740     {
1741       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1742       goto send_reply;
1743     }
1744   key.ext_host_addr = ext_addr;
1745   key.ext_host_port = mp->ext_port;
1746   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1747   if (!ses)
1748     {
1749       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1750       goto send_reply;
1751     }
1752   snat_det_ses_close (dm, ses);
1753
1754 send_reply:
1755   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
1756 }
1757
1758 static void *
1759 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
1760                                          mp, void *handle)
1761 {
1762   u8 *s;
1763   s = format (0, "SCRIPT: nat_det_close_session_in ");
1764   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
1765               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
1766               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1767
1768   FINISH;
1769 }
1770
1771 static void
1772 send_nat_det_session_details (snat_det_session_t * s,
1773                               svm_queue_t * q, u32 context)
1774 {
1775   vl_api_nat_det_session_details_t *rmp;
1776   snat_main_t *sm = &snat_main;
1777
1778   rmp = vl_msg_api_alloc (sizeof (*rmp));
1779   memset (rmp, 0, sizeof (*rmp));
1780   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
1781   rmp->in_port = s->in_port;
1782   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
1783   rmp->ext_port = s->out.ext_host_port;
1784   rmp->out_port = s->out.out_port;
1785   rmp->state = s->state;
1786   rmp->expire = ntohl (s->expire);
1787   rmp->context = context;
1788
1789   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1790 }
1791
1792 static void
1793 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
1794 {
1795   svm_queue_t *q;
1796   snat_main_t *sm = &snat_main;
1797   ip4_address_t user_addr;
1798   snat_det_map_t *dm;
1799   snat_det_session_t *s, empty_ses;
1800   u16 i;
1801
1802   q = vl_api_client_index_to_input_queue (mp->client_index);
1803   if (q == 0)
1804     return;
1805   if (!mp->is_nat44)
1806     return;
1807
1808   memset (&empty_ses, 0, sizeof (empty_ses));
1809   clib_memcpy (&user_addr, mp->user_addr, 4);
1810   dm = snat_det_map_by_user (sm, &user_addr);
1811   if (!dm)
1812     return;
1813
1814   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
1815   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
1816     {
1817       if (s->out.as_u64)
1818         send_nat_det_session_details (s, q, mp->context);
1819       s++;
1820     }
1821 }
1822
1823 static void *
1824 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
1825                                      void *handle)
1826 {
1827   u8 *s;
1828
1829   s = format (0, "SCRIPT: nat_det_session_dump ");
1830   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
1831
1832   FINISH;
1833 }
1834
1835 /*************/
1836 /*** NAT64 ***/
1837 /*************/
1838
1839 static void
1840   vl_api_nat64_add_del_pool_addr_range_t_handler
1841   (vl_api_nat64_add_del_pool_addr_range_t * mp)
1842 {
1843   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
1844   snat_main_t *sm = &snat_main;
1845   int rv = 0;
1846   ip4_address_t this_addr;
1847   u32 start_host_order, end_host_order;
1848   u32 vrf_id;
1849   int i, count;
1850   u32 *tmp;
1851
1852   tmp = (u32 *) mp->start_addr;
1853   start_host_order = clib_host_to_net_u32 (tmp[0]);
1854   tmp = (u32 *) mp->end_addr;
1855   end_host_order = clib_host_to_net_u32 (tmp[0]);
1856
1857   count = (end_host_order - start_host_order) + 1;
1858
1859   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
1860
1861   memcpy (&this_addr.as_u8, mp->start_addr, 4);
1862
1863   for (i = 0; i < count; i++)
1864     {
1865       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
1866         goto send_reply;
1867
1868       increment_v4_address (&this_addr);
1869     }
1870
1871 send_reply:
1872   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
1873 }
1874
1875 static void *vl_api_nat64_add_del_pool_addr_range_t_print
1876   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
1877 {
1878   u8 *s;
1879
1880   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
1881   s = format (s, "%U - %U vrf_id %u %s\n",
1882               format_ip4_address, mp->start_addr,
1883               format_ip4_address, mp->end_addr,
1884               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
1885
1886   FINISH;
1887 }
1888
1889 typedef struct nat64_api_walk_ctx_t_
1890 {
1891   svm_queue_t *q;
1892   u32 context;
1893   nat64_db_t *db;
1894 } nat64_api_walk_ctx_t;
1895
1896 static int
1897 nat64_api_pool_walk (snat_address_t * a, void *arg)
1898 {
1899   vl_api_nat64_pool_addr_details_t *rmp;
1900   snat_main_t *sm = &snat_main;
1901   nat64_api_walk_ctx_t *ctx = arg;
1902
1903   rmp = vl_msg_api_alloc (sizeof (*rmp));
1904   memset (rmp, 0, sizeof (*rmp));
1905   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
1906   clib_memcpy (rmp->address, &(a->addr), 4);
1907   if (a->fib_index != ~0)
1908     {
1909       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
1910       if (!fib)
1911         return -1;
1912       rmp->vrf_id = ntohl (fib->ft_table_id);
1913     }
1914   else
1915     rmp->vrf_id = ~0;
1916   rmp->context = ctx->context;
1917
1918   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1919
1920   return 0;
1921 }
1922
1923 static void
1924 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
1925 {
1926   svm_queue_t *q;
1927
1928   q = vl_api_client_index_to_input_queue (mp->client_index);
1929   if (q == 0)
1930     return;
1931
1932   nat64_api_walk_ctx_t ctx = {
1933     .q = q,
1934     .context = mp->context,
1935   };
1936
1937   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
1938 }
1939
1940 static void *
1941 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
1942                                      void *handle)
1943 {
1944   u8 *s;
1945
1946   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
1947
1948   FINISH;
1949 }
1950
1951 static void
1952 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
1953                                           mp)
1954 {
1955   snat_main_t *sm = &snat_main;
1956   vl_api_nat64_add_del_interface_reply_t *rmp;
1957   int rv = 0;
1958
1959   VALIDATE_SW_IF_INDEX (mp);
1960
1961   rv =
1962     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
1963                              mp->is_add);
1964
1965   BAD_SW_IF_INDEX_LABEL;
1966
1967   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
1968 }
1969
1970 static void *
1971 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
1972                                         void *handle)
1973 {
1974   u8 *s;
1975
1976   s = format (0, "SCRIPT: nat64_add_del_interface ");
1977   s = format (s, "sw_if_index %d %s %s",
1978               clib_host_to_net_u32 (mp->sw_if_index),
1979               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1980
1981   FINISH;
1982 }
1983
1984 static int
1985 nat64_api_interface_walk (snat_interface_t * i, void *arg)
1986 {
1987   vl_api_nat64_interface_details_t *rmp;
1988   snat_main_t *sm = &snat_main;
1989   nat64_api_walk_ctx_t *ctx = arg;
1990
1991   rmp = vl_msg_api_alloc (sizeof (*rmp));
1992   memset (rmp, 0, sizeof (*rmp));
1993   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
1994   rmp->sw_if_index = ntohl (i->sw_if_index);
1995   rmp->is_inside = (nat_interface_is_inside (i)
1996                     && nat_interface_is_outside (i)) ? 2 :
1997     nat_interface_is_inside (i);
1998   rmp->context = ctx->context;
1999
2000   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2001
2002   return 0;
2003 }
2004
2005 static void
2006 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2007 {
2008   svm_queue_t *q;
2009
2010   q = vl_api_client_index_to_input_queue (mp->client_index);
2011   if (q == 0)
2012     return;
2013
2014   nat64_api_walk_ctx_t ctx = {
2015     .q = q,
2016     .context = mp->context,
2017   };
2018
2019   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2020 }
2021
2022 static void *
2023 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2024                                      void *handle)
2025 {
2026   u8 *s;
2027
2028   s = format (0, "SCRIPT: snat_interface_dump ");
2029
2030   FINISH;
2031 }
2032
2033 static void
2034   vl_api_nat64_add_del_static_bib_t_handler
2035   (vl_api_nat64_add_del_static_bib_t * mp)
2036 {
2037   snat_main_t *sm = &snat_main;
2038   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2039   ip6_address_t in_addr;
2040   ip4_address_t out_addr;
2041   int rv = 0;
2042
2043   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2044   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2045
2046   rv =
2047     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2048                                     clib_net_to_host_u16 (mp->i_port),
2049                                     clib_net_to_host_u16 (mp->o_port),
2050                                     mp->proto,
2051                                     clib_net_to_host_u32 (mp->vrf_id),
2052                                     mp->is_add);
2053
2054   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2055 }
2056
2057 static void *vl_api_nat64_add_del_static_bib_t_print
2058   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2059 {
2060   u8 *s;
2061
2062   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2063   s = format (s, "protocol %d i_addr %U o_addr %U ",
2064               mp->proto,
2065               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2066
2067   if (mp->vrf_id != ~0)
2068     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2069
2070   FINISH;
2071 }
2072
2073 static int
2074 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2075 {
2076   vl_api_nat64_bib_details_t *rmp;
2077   snat_main_t *sm = &snat_main;
2078   nat64_api_walk_ctx_t *ctx = arg;
2079   fib_table_t *fib;
2080
2081   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2082   if (!fib)
2083     return -1;
2084
2085   rmp = vl_msg_api_alloc (sizeof (*rmp));
2086   memset (rmp, 0, sizeof (*rmp));
2087   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2088   rmp->context = ctx->context;
2089   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2090   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2091   rmp->i_port = bibe->in_port;
2092   rmp->o_port = bibe->out_port;
2093   rmp->vrf_id = ntohl (fib->ft_table_id);
2094   rmp->proto = bibe->proto;
2095   rmp->is_static = bibe->is_static;
2096   rmp->ses_num = ntohl (bibe->ses_num);
2097
2098   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2099
2100   return 0;
2101 }
2102
2103 static void
2104 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2105 {
2106   svm_queue_t *q;
2107   nat64_main_t *nm = &nat64_main;
2108   nat64_db_t *db;
2109
2110   q = vl_api_client_index_to_input_queue (mp->client_index);
2111   if (q == 0)
2112     return;
2113
2114   nat64_api_walk_ctx_t ctx = {
2115     .q = q,
2116     .context = mp->context,
2117   };
2118
2119   /* *INDENT-OFF* */
2120   vec_foreach (db, nm->db)
2121     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2122   /* *INDENT-ON* */
2123 }
2124
2125 static void *
2126 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2127 {
2128   u8 *s;
2129
2130   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2131
2132   FINISH;
2133 }
2134
2135 static void
2136 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
2137 {
2138   snat_main_t *sm = &snat_main;
2139   vl_api_nat64_set_timeouts_reply_t *rmp;
2140   int rv = 0;
2141
2142   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
2143   if (rv)
2144     goto send_reply;
2145   rv = nat64_set_udp_timeout (ntohl (mp->udp));
2146   if (rv)
2147     goto send_reply;
2148   rv =
2149     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
2150                             ntohl (mp->tcp_incoming_syn));
2151
2152 send_reply:
2153   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
2154 }
2155
2156 static void *vl_api_nat64_set_timeouts_t_print
2157   (vl_api_nat64_set_timeouts_t * mp, void *handle)
2158 {
2159   u8 *s;
2160
2161   s = format (0, "SCRIPT: nat64_set_timeouts ");
2162   s =
2163     format (s,
2164             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
2165             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
2166             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
2167
2168   FINISH;
2169 }
2170
2171 static void
2172 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
2173 {
2174   snat_main_t *sm = &snat_main;
2175   vl_api_nat64_get_timeouts_reply_t *rmp;
2176   int rv = 0;
2177
2178   /* *INDENT-OFF* */
2179   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
2180   ({
2181     rmp->udp = htonl (nat64_get_udp_timeout());
2182     rmp->icmp = htonl (nat64_get_icmp_timeout());
2183     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
2184     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
2185     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
2186   }))
2187   /* *INDENT-ON* */
2188 }
2189
2190 static void *vl_api_nat64_get_timeouts_t_print
2191   (vl_api_nat64_get_timeouts_t * mp, void *handle)
2192 {
2193   u8 *s;
2194
2195   s = format (0, "SCRIPT: nat64_get_timeouts");
2196
2197   FINISH;
2198 }
2199
2200 static int
2201 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2202 {
2203   vl_api_nat64_st_details_t *rmp;
2204   snat_main_t *sm = &snat_main;
2205   nat64_api_walk_ctx_t *ctx = arg;
2206   nat64_db_bib_entry_t *bibe;
2207   fib_table_t *fib;
2208
2209   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2210   if (!bibe)
2211     return -1;
2212
2213   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2214   if (!fib)
2215     return -1;
2216
2217   rmp = vl_msg_api_alloc (sizeof (*rmp));
2218   memset (rmp, 0, sizeof (*rmp));
2219   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2220   rmp->context = ctx->context;
2221   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2222   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2223   rmp->il_port = bibe->in_port;
2224   rmp->ol_port = bibe->out_port;
2225   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2226   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2227   rmp->il_port = ste->r_port;
2228   rmp->vrf_id = ntohl (fib->ft_table_id);
2229   rmp->proto = ste->proto;
2230
2231   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2232
2233   return 0;
2234 }
2235
2236 static void
2237 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2238 {
2239   svm_queue_t *q;
2240   nat64_main_t *nm = &nat64_main;
2241   nat64_db_t *db;
2242
2243   q = vl_api_client_index_to_input_queue (mp->client_index);
2244   if (q == 0)
2245     return;
2246
2247   nat64_api_walk_ctx_t ctx = {
2248     .q = q,
2249     .context = mp->context,
2250   };
2251
2252   /* *INDENT-OFF* */
2253   vec_foreach (db, nm->db)
2254     {
2255       ctx.db = db;
2256       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2257     }
2258   /* *INDENT-ON* */
2259 }
2260
2261 static void *
2262 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2263 {
2264   u8 *s;
2265
2266   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2267
2268   FINISH;
2269 }
2270
2271 static void
2272 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2273 {
2274   vl_api_nat64_add_del_prefix_reply_t *rmp;
2275   snat_main_t *sm = &snat_main;
2276   ip6_address_t prefix;
2277   int rv = 0;
2278
2279   memcpy (&prefix.as_u8, mp->prefix, 16);
2280
2281   rv =
2282     nat64_add_del_prefix (&prefix, mp->prefix_len,
2283                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2284   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2285 }
2286
2287 static void *
2288 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2289                                      void *handle)
2290 {
2291   u8 *s;
2292
2293   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2294               format_ip6_address, mp->prefix, mp->prefix_len,
2295               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2296
2297   FINISH;
2298 }
2299
2300 static int
2301 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2302 {
2303   vl_api_nat64_prefix_details_t *rmp;
2304   snat_main_t *sm = &snat_main;
2305   nat64_api_walk_ctx_t *ctx = arg;
2306
2307   rmp = vl_msg_api_alloc (sizeof (*rmp));
2308   memset (rmp, 0, sizeof (*rmp));
2309   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2310   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2311   rmp->prefix_len = p->plen;
2312   rmp->vrf_id = ntohl (p->vrf_id);
2313   rmp->context = ctx->context;
2314
2315   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2316
2317   return 0;
2318 }
2319
2320 static void
2321 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2322 {
2323   svm_queue_t *q;
2324
2325   q = vl_api_client_index_to_input_queue (mp->client_index);
2326   if (q == 0)
2327     return;
2328
2329   nat64_api_walk_ctx_t ctx = {
2330     .q = q,
2331     .context = mp->context,
2332   };
2333
2334   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2335 }
2336
2337 static void *
2338 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2339                                   void *handle)
2340 {
2341   u8 *s;
2342
2343   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2344
2345   FINISH;
2346 }
2347
2348 static void
2349   vl_api_nat64_add_del_interface_addr_t_handler
2350   (vl_api_nat64_add_del_interface_addr_t * mp)
2351 {
2352   snat_main_t *sm = &snat_main;
2353   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2354   u32 sw_if_index = ntohl (mp->sw_if_index);
2355   int rv = 0;
2356
2357   VALIDATE_SW_IF_INDEX (mp);
2358
2359   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2360
2361   BAD_SW_IF_INDEX_LABEL;
2362
2363   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2364 }
2365
2366 static void *vl_api_nat64_add_del_interface_addr_t_print
2367   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2368 {
2369   u8 *s;
2370
2371   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2372   s = format (s, "sw_if_index %d %s",
2373               clib_host_to_net_u32 (mp->sw_if_index),
2374               mp->is_add ? "" : "del");
2375
2376   FINISH;
2377 }
2378
2379 /***************/
2380 /*** DS-Lite ***/
2381 /***************/
2382
2383 static void
2384 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2385 {
2386   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2387   snat_main_t *sm = &snat_main;
2388   dslite_main_t *dm = &dslite_main;
2389   int rv = 0;
2390   ip6_address_t ip6_addr;
2391   ip4_address_t ip4_addr;
2392
2393   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2394   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2395
2396   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2397   if (rv == 0)
2398     rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr);
2399
2400   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2401 }
2402
2403 static void *
2404 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2405                                      void *handle)
2406 {
2407   u8 *s;
2408
2409   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2410   s = format (s, "ip6_addr %U ip4_addr %U\n",
2411               format_ip6_address, mp->ip6_addr,
2412               format_ip4_address, mp->ip4_addr);
2413
2414   FINISH;
2415 }
2416
2417 static void
2418 vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp)
2419 {
2420   snat_main_t *sm = &snat_main;
2421   vl_api_dslite_get_aftr_addr_reply_t *rmp;
2422   dslite_main_t *dm = &dslite_main;
2423   int rv = 0;
2424
2425   /* *INDENT-OFF* */
2426   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2427   ({
2428     memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4);
2429     memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16);
2430   }))
2431   /* *INDENT-ON* */
2432 }
2433
2434 static void *
2435 vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp,
2436                                      void *handle)
2437 {
2438   u8 *s;
2439
2440   s = format (0, "SCRIPT: dslite_get_aftr_addr");
2441
2442   FINISH;
2443 }
2444
2445 static void
2446 vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp)
2447 {
2448   vl_api_dslite_set_b4_addr_reply_t *rmp;
2449   snat_main_t *sm = &snat_main;
2450   dslite_main_t *dm = &dslite_main;
2451   int rv = 0;
2452   ip6_address_t ip6_addr;
2453   ip4_address_t ip4_addr;
2454
2455   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2456   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2457
2458   rv = dslite_set_b4_ip6_addr (dm, &ip6_addr);
2459   if (rv == 0)
2460     rv = dslite_set_b4_ip4_addr (dm, &ip4_addr);
2461
2462   REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY);
2463 }
2464
2465 static void *
2466 vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp,
2467                                    void *handle)
2468 {
2469   u8 *s;
2470
2471   s = format (0, "SCRIPT: dslite_set_b4_addr ");
2472   s = format (s, "ip6_addr %U ip4_addr %U\n",
2473               format_ip6_address, mp->ip6_addr,
2474               format_ip6_address, mp->ip4_addr);
2475
2476   FINISH;
2477 }
2478
2479 static void
2480 vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp)
2481 {
2482   snat_main_t *sm = &snat_main;
2483   vl_api_dslite_get_b4_addr_reply_t *rmp;
2484   dslite_main_t *dm = &dslite_main;
2485   int rv = 0;
2486
2487   /* *INDENT-OFF* */
2488   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2489   ({
2490     memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4);
2491     memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16);
2492   }))
2493   /* *INDENT-ON* */
2494 }
2495
2496 static void *
2497 vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp,
2498                                    void *handle)
2499 {
2500   u8 *s;
2501
2502   s = format (0, "SCRIPT: dslite_get_b4_addr");
2503
2504   FINISH;
2505 }
2506
2507 static void
2508   vl_api_dslite_add_del_pool_addr_range_t_handler
2509   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2510 {
2511   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2512   snat_main_t *sm = &snat_main;
2513   dslite_main_t *dm = &dslite_main;
2514   int rv = 0;
2515   ip4_address_t this_addr;
2516   u32 start_host_order, end_host_order;
2517   int i, count;
2518   u32 *tmp;
2519
2520   tmp = (u32 *) mp->start_addr;
2521   start_host_order = clib_host_to_net_u32 (tmp[0]);
2522   tmp = (u32 *) mp->end_addr;
2523   end_host_order = clib_host_to_net_u32 (tmp[0]);
2524
2525   count = (end_host_order - start_host_order) + 1;
2526   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2527
2528   for (i = 0; i < count; i++)
2529     {
2530       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2531         goto send_reply;
2532
2533       increment_v4_address (&this_addr);
2534     }
2535
2536 send_reply:
2537   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2538 }
2539
2540 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2541   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2542 {
2543   u8 *s;
2544
2545   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2546   s = format (s, "%U - %U\n",
2547               format_ip4_address, mp->start_addr,
2548               format_ip4_address, mp->end_addr);
2549
2550   FINISH;
2551 }
2552
2553
2554 /* List of message types that this plugin understands */
2555 #define foreach_snat_plugin_api_msg                                     \
2556 _(NAT_CONTROL_PING, nat_control_ping)                                   \
2557 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
2558 _(NAT_SET_WORKERS, nat_set_workers)                                     \
2559 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
2560 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
2561 _(NAT_SET_REASS, nat_set_reass)                                         \
2562 _(NAT_GET_REASS, nat_get_reass)                                         \
2563 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
2564 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
2565 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
2566 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
2567 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
2568 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
2569 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
2570 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
2571 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
2572 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
2573 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
2574 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
2575 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
2576 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
2577   nat44_interface_add_del_output_feature)                               \
2578 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
2579   nat44_interface_output_feature_dump)                                  \
2580 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
2581 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
2582 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
2583 _(NAT44_FORWARDING_ENABLE_DISABLE, nat44_forwarding_enable_disable)     \
2584 _(NAT44_FORWARDING_IS_ENABLED, nat44_forwarding_is_enabled)             \
2585 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
2586 _(NAT_DET_FORWARD, nat_det_forward)                                     \
2587 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
2588 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
2589 _(NAT_DET_SET_TIMEOUTS, nat_det_set_timeouts)                           \
2590 _(NAT_DET_GET_TIMEOUTS, nat_det_get_timeouts)                           \
2591 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
2592 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
2593 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
2594 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
2595 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
2596 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
2597 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
2598 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
2599 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
2600 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
2601 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
2602 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
2603 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
2604 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
2605 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
2606 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
2607 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)                           \
2608 _(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr)                           \
2609 _(DSLITE_SET_B4_ADDR, dslite_set_b4_addr)                               \
2610 _(DSLITE_GET_B4_ADDR, dslite_get_b4_addr)
2611
2612 /* Set up the API message handling tables */
2613 static clib_error_t *
2614 snat_plugin_api_hookup (vlib_main_t * vm)
2615 {
2616   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
2617 #define _(N,n)                                                  \
2618     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
2619                            #n,                                  \
2620                            vl_api_##n##_t_handler,              \
2621                            vl_noop_handler,                     \
2622                            vl_api_##n##_t_endian,               \
2623                            vl_api_##n##_t_print,                \
2624                            sizeof(vl_api_##n##_t), 1);
2625   foreach_snat_plugin_api_msg;
2626 #undef _
2627
2628   return 0;
2629 }
2630
2631 #define vl_msg_name_crc_list
2632 #include <nat/nat_all_api_h.h>
2633 #undef vl_msg_name_crc_list
2634
2635 static void
2636 setup_message_id_table (snat_main_t * sm, api_main_t * am)
2637 {
2638 #define _(id,n,crc) \
2639   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
2640   foreach_vl_msg_name_crc_nat;
2641 #undef _
2642 }
2643
2644 static void
2645 plugin_custom_dump_configure (snat_main_t * sm)
2646 {
2647 #define _(n,f) sm->api_main->msg_print_handlers \
2648   [VL_API_##n + sm->msg_id_base]                \
2649     = (void *) vl_api_##f##_t_print;
2650   foreach_snat_plugin_api_msg;
2651 #undef _
2652 }
2653
2654 clib_error_t *
2655 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
2656 {
2657   u8 *name;
2658   clib_error_t *error = 0;
2659
2660   name = format (0, "nat_%08x%c", api_version, 0);
2661
2662   /* Ask for a correctly-sized block of API message decode slots */
2663   sm->msg_id_base =
2664     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
2665
2666   error = snat_plugin_api_hookup (vm);
2667
2668   /* Add our API messages to the global name_crc hash table */
2669   setup_message_id_table (sm, sm->api_main);
2670
2671   plugin_custom_dump_configure (sm);
2672
2673   vec_free (name);
2674
2675   return error;
2676 }
2677
2678 /*
2679  * fd.io coding-style-patch-verification: ON
2680  *
2681  * Local Variables:
2682  * eval: (c-set-style "gnu")
2683  * End:
2684  */