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