NAT: remove worker_by_in lookup hash table (VPP-992)
[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 <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vlibsocket/api.h>
27 #include <nat/nat_msg_enum.h>
28 #include <vnet/fib/fib_table.h>
29
30 #define vl_api_nat44_lb_addr_port_t_endian vl_noop_handler
31 #define vl_api_nat44_add_del_lb_static_mapping_t_endian vl_noop_handler
32 #define vl_api_nat44_nat44_lb_static_mapping_details_t_endian vl_noop_handler
33
34 /* define message structures */
35 #define vl_typedefs
36 #include <nat/nat_all_api_h.h>
37 #undef vl_typedefs
38
39 /* define generated endian-swappers */
40 #define vl_endianfun
41 #include <nat/nat_all_api_h.h>
42 #undef vl_endianfun
43
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45
46 #define REPLY_MSG_ID_BASE sm->msg_id_base
47 #include <vlibapi/api_helper_macros.h>
48
49 /* Get the API version number */
50 #define vl_api_version(n,v) static u32 api_version=(v);
51 #include <nat/nat_all_api_h.h>
52 #undef vl_api_version
53
54 /* Macro to finish up custom dump fns */
55 #define FINISH                                  \
56     vec_add1 (s, 0);                            \
57     vl_print (handle, (char *)s);               \
58     vec_free (s);                               \
59     return handle;
60
61 static void
62   vl_api_snat_add_address_range_t_handler
63   (vl_api_snat_add_address_range_t * mp)
64 {
65   snat_main_t *sm = &snat_main;
66   vl_api_snat_add_address_range_reply_t *rmp;
67   ip4_address_t this_addr;
68   u32 start_host_order, end_host_order;
69   u32 vrf_id;
70   int i, count;
71   int rv = 0;
72   u32 *tmp;
73
74   if (mp->is_ip4 != 1)
75     {
76       rv = VNET_API_ERROR_UNIMPLEMENTED;
77       goto send_reply;
78     }
79
80   if (sm->static_mapping_only)
81     {
82       rv = VNET_API_ERROR_FEATURE_DISABLED;
83       goto send_reply;
84     }
85
86   tmp = (u32 *) mp->first_ip_address;
87   start_host_order = clib_host_to_net_u32 (tmp[0]);
88   tmp = (u32 *) mp->last_ip_address;
89   end_host_order = clib_host_to_net_u32 (tmp[0]);
90
91   count = (end_host_order - start_host_order) + 1;
92
93   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
94
95   if (count > 1024)
96     clib_warning ("%U - %U, %d addresses...",
97                   format_ip4_address, mp->first_ip_address,
98                   format_ip4_address, mp->last_ip_address, count);
99
100   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
101
102   for (i = 0; i < count; i++)
103     {
104       if (mp->is_add)
105         snat_add_address (sm, &this_addr, vrf_id);
106       else
107         rv = snat_del_address (sm, this_addr, 0);
108
109       if (rv)
110         goto send_reply;
111
112       increment_v4_address (&this_addr);
113     }
114
115 send_reply:
116   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
117 }
118
119 static void *vl_api_snat_add_address_range_t_print
120   (vl_api_snat_add_address_range_t * mp, void *handle)
121 {
122   u8 *s;
123
124   s = format (0, "SCRIPT: snat_add_address_range ");
125   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
126   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
127     {
128       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
129     }
130   FINISH;
131 }
132
133 static void
134   send_snat_address_details
135   (snat_address_t * a, unix_shared_memory_queue_t * q, u32 context)
136 {
137   vl_api_snat_address_details_t *rmp;
138   snat_main_t *sm = &snat_main;
139
140   rmp = vl_msg_api_alloc (sizeof (*rmp));
141   memset (rmp, 0, sizeof (*rmp));
142   rmp->_vl_msg_id = ntohs (VL_API_SNAT_ADDRESS_DETAILS + sm->msg_id_base);
143   rmp->is_ip4 = 1;
144   clib_memcpy (rmp->ip_address, &(a->addr), 4);
145   if (a->fib_index != ~0)
146     {
147       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
148       rmp->vrf_id = ntohl (fib->ft_table_id);
149     }
150   else
151     rmp->vrf_id = ~0;
152   rmp->context = context;
153
154   vl_msg_api_send_shmem (q, (u8 *) & rmp);
155 }
156
157 static void
158 vl_api_snat_address_dump_t_handler (vl_api_snat_address_dump_t * mp)
159 {
160   unix_shared_memory_queue_t *q;
161   snat_main_t *sm = &snat_main;
162   snat_address_t *a;
163
164   q = vl_api_client_index_to_input_queue (mp->client_index);
165   if (q == 0)
166     return;
167
168   /* *INDENT-OFF* */
169   vec_foreach (a, sm->addresses)
170     send_snat_address_details (a, q, mp->context);
171   /* *INDENT-ON* */
172 }
173
174 static void *vl_api_snat_address_dump_t_print
175   (vl_api_snat_address_dump_t * mp, void *handle)
176 {
177   u8 *s;
178
179   s = format (0, "SCRIPT: snat_address_dump ");
180
181   FINISH;
182 }
183
184 static void
185   vl_api_snat_interface_add_del_feature_t_handler
186   (vl_api_snat_interface_add_del_feature_t * mp)
187 {
188   snat_main_t *sm = &snat_main;
189   vl_api_snat_interface_add_del_feature_reply_t *rmp;
190   u8 is_del = mp->is_add == 0;
191   u32 sw_if_index = ntohl (mp->sw_if_index);
192   int rv = 0;
193
194   VALIDATE_SW_IF_INDEX (mp);
195
196   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
197
198   BAD_SW_IF_INDEX_LABEL;
199
200   REPLY_MACRO (VL_API_SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY);
201 }
202
203 static void *vl_api_snat_interface_add_del_feature_t_print
204   (vl_api_snat_interface_add_del_feature_t * mp, void *handle)
205 {
206   u8 *s;
207
208   s = format (0, "SCRIPT: snat_interface_add_del_feature ");
209   s = format (s, "sw_if_index %d %s %s",
210               clib_host_to_net_u32 (mp->sw_if_index),
211               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
212
213   FINISH;
214 }
215
216 static void
217   send_snat_interface_details
218   (snat_interface_t * i, unix_shared_memory_queue_t * q, u32 context)
219 {
220   vl_api_snat_interface_details_t *rmp;
221   snat_main_t *sm = &snat_main;
222
223   rmp = vl_msg_api_alloc (sizeof (*rmp));
224   memset (rmp, 0, sizeof (*rmp));
225   rmp->_vl_msg_id = ntohs (VL_API_SNAT_INTERFACE_DETAILS + sm->msg_id_base);
226   rmp->sw_if_index = ntohl (i->sw_if_index);
227   rmp->is_inside = i->is_inside;
228   rmp->context = context;
229
230   vl_msg_api_send_shmem (q, (u8 *) & rmp);
231 }
232
233 static void
234 vl_api_snat_interface_dump_t_handler (vl_api_snat_interface_dump_t * mp)
235 {
236   unix_shared_memory_queue_t *q;
237   snat_main_t *sm = &snat_main;
238   snat_interface_t *i;
239
240   q = vl_api_client_index_to_input_queue (mp->client_index);
241   if (q == 0)
242     return;
243
244   /* *INDENT-OFF* */
245   pool_foreach (i, sm->interfaces,
246   ({
247     send_snat_interface_details(i, q, mp->context);
248   }));
249   /* *INDENT-ON* */
250 }
251
252 static void *vl_api_snat_interface_dump_t_print
253   (vl_api_snat_interface_dump_t * mp, void *handle)
254 {
255   u8 *s;
256
257   s = format (0, "SCRIPT: snat_interface_dump ");
258
259   FINISH;
260 }
261
262 static void
263   vl_api_snat_interface_add_del_output_feature_t_handler
264   (vl_api_snat_interface_add_del_output_feature_t * mp)
265 {
266   snat_main_t *sm = &snat_main;
267   vl_api_snat_interface_add_del_output_feature_reply_t *rmp;
268   u8 is_del = mp->is_add == 0;
269   u32 sw_if_index = ntohl (mp->sw_if_index);
270   int rv = 0;
271
272   VALIDATE_SW_IF_INDEX (mp);
273
274   rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
275                                               is_del);
276
277   BAD_SW_IF_INDEX_LABEL;
278
279   REPLY_MACRO (VL_API_SNAT_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
280 }
281
282 static void *vl_api_snat_interface_add_del_output_feature_t_print
283   (vl_api_snat_interface_add_del_output_feature_t * mp, void *handle)
284 {
285   u8 *s;
286
287   s = format (0, "SCRIPT: snat_interface_add_del_output_feature ");
288   s = format (s, "sw_if_index %d %s %s",
289               clib_host_to_net_u32 (mp->sw_if_index),
290               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
291
292   FINISH;
293 }
294
295 static void
296 send_snat_interface_output_feature_details (snat_interface_t * i,
297                                             unix_shared_memory_queue_t * q,
298                                             u32 context)
299 {
300   vl_api_snat_interface_output_feature_details_t *rmp;
301   snat_main_t *sm = &snat_main;
302
303   rmp = vl_msg_api_alloc (sizeof (*rmp));
304   memset (rmp, 0, sizeof (*rmp));
305   rmp->_vl_msg_id =
306     ntohs (VL_API_SNAT_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
307   rmp->sw_if_index = ntohl (i->sw_if_index);
308   rmp->context = context;
309   rmp->is_inside = i->is_inside;
310
311   vl_msg_api_send_shmem (q, (u8 *) & rmp);
312 }
313
314 static void
315   vl_api_snat_interface_output_feature_dump_t_handler
316   (vl_api_snat_interface_output_feature_dump_t * mp)
317 {
318   unix_shared_memory_queue_t *q;
319   snat_main_t *sm = &snat_main;
320   snat_interface_t *i;
321
322   q = vl_api_client_index_to_input_queue (mp->client_index);
323   if (q == 0)
324     return;
325
326   /* *INDENT-OFF* */
327   pool_foreach (i, sm->output_feature_interfaces,
328   ({
329     send_snat_interface_output_feature_details(i, q, mp->context);
330   }));
331   /* *INDENT-ON* */
332 }
333
334 static void *vl_api_snat_interface_output_feature_dump_t_print
335   (vl_api_snat_interface_output_feature_dump_t * mp, void *handle)
336 {
337   u8 *s;
338
339   s = format (0, "SCRIPT: snat_interface_output_feature_dump ");
340
341   FINISH;
342 }
343
344 static void
345   vl_api_snat_add_static_mapping_t_handler
346   (vl_api_snat_add_static_mapping_t * mp)
347 {
348   snat_main_t *sm = &snat_main;
349   vl_api_snat_add_static_mapping_reply_t *rmp;
350   ip4_address_t local_addr, external_addr;
351   u16 local_port = 0, external_port = 0;
352   u32 vrf_id, external_sw_if_index;
353   int rv = 0;
354   snat_protocol_t proto;
355
356   if (mp->is_ip4 != 1)
357     {
358       rv = VNET_API_ERROR_UNIMPLEMENTED;
359       goto send_reply;
360     }
361
362   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
363   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
364   if (mp->addr_only == 0)
365     {
366       local_port = clib_net_to_host_u16 (mp->local_port);
367       external_port = clib_net_to_host_u16 (mp->external_port);
368     }
369   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
370   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
371   proto = ip_proto_to_snat_proto (mp->protocol);
372
373   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
374                                 external_port, vrf_id, mp->addr_only,
375                                 external_sw_if_index, proto, mp->is_add);
376
377 send_reply:
378   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
379 }
380
381 static void *vl_api_snat_add_static_mapping_t_print
382   (vl_api_snat_add_static_mapping_t * mp, void *handle)
383 {
384   u8 *s;
385
386   s = format (0, "SCRIPT: snat_add_static_mapping ");
387   s = format (s, "protocol %d local_addr %U external_addr %U ",
388               mp->protocol,
389               format_ip4_address, mp->local_ip_address,
390               format_ip4_address, mp->external_ip_address);
391
392   if (mp->addr_only == 0)
393     s = format (s, "local_port %d external_port %d ",
394                 clib_net_to_host_u16 (mp->local_port),
395                 clib_net_to_host_u16 (mp->external_port));
396
397   if (mp->vrf_id != ~0)
398     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
399
400   if (mp->external_sw_if_index != ~0)
401     s = format (s, "external_sw_if_index %d",
402                 clib_net_to_host_u32 (mp->external_sw_if_index));
403   FINISH;
404 }
405
406 static void
407   send_snat_static_mapping_details
408   (snat_static_mapping_t * m, unix_shared_memory_queue_t * q, u32 context)
409 {
410   vl_api_snat_static_mapping_details_t *rmp;
411   snat_main_t *sm = &snat_main;
412
413   rmp = vl_msg_api_alloc (sizeof (*rmp));
414   memset (rmp, 0, sizeof (*rmp));
415   rmp->_vl_msg_id =
416     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
417   rmp->is_ip4 = 1;
418   rmp->addr_only = m->addr_only;
419   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
420   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
421   rmp->local_port = htons (m->local_port);
422   rmp->external_port = htons (m->external_port);
423   rmp->external_sw_if_index = ~0;
424   rmp->vrf_id = htonl (m->vrf_id);
425   rmp->protocol = snat_proto_to_ip_proto (m->proto);
426   rmp->context = context;
427
428   vl_msg_api_send_shmem (q, (u8 *) & rmp);
429 }
430
431 static void
432   send_snat_static_map_resolve_details
433   (snat_static_map_resolve_t * m, unix_shared_memory_queue_t * q, u32 context)
434 {
435   vl_api_snat_static_mapping_details_t *rmp;
436   snat_main_t *sm = &snat_main;
437
438   rmp = vl_msg_api_alloc (sizeof (*rmp));
439   memset (rmp, 0, sizeof (*rmp));
440   rmp->_vl_msg_id =
441     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
442   rmp->is_ip4 = 1;
443   rmp->addr_only = m->addr_only;
444   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
445   rmp->local_port = htons (m->l_port);
446   rmp->external_port = htons (m->e_port);
447   rmp->external_sw_if_index = htonl (m->sw_if_index);
448   rmp->vrf_id = htonl (m->vrf_id);
449   rmp->protocol = snat_proto_to_ip_proto (m->proto);
450   rmp->context = context;
451
452   vl_msg_api_send_shmem (q, (u8 *) & rmp);
453 }
454
455 static void
456   vl_api_snat_static_mapping_dump_t_handler
457   (vl_api_snat_static_mapping_dump_t * mp)
458 {
459   unix_shared_memory_queue_t *q;
460   snat_main_t *sm = &snat_main;
461   snat_static_mapping_t *m;
462   snat_static_map_resolve_t *rp;
463   int j;
464
465   q = vl_api_client_index_to_input_queue (mp->client_index);
466   if (q == 0)
467     return;
468
469   /* *INDENT-OFF* */
470   pool_foreach (m, sm->static_mappings,
471   ({
472       if (!vec_len(m->locals))
473         send_snat_static_mapping_details (m, q, mp->context);
474   }));
475   /* *INDENT-ON* */
476
477   for (j = 0; j < vec_len (sm->to_resolve); j++)
478     {
479       rp = sm->to_resolve + j;
480       send_snat_static_map_resolve_details (rp, q, mp->context);
481     }
482 }
483
484 static void *vl_api_snat_static_mapping_dump_t_print
485   (vl_api_snat_static_mapping_dump_t * mp, void *handle)
486 {
487   u8 *s;
488
489   s = format (0, "SCRIPT: snat_static_mapping_dump ");
490
491   FINISH;
492 }
493
494 static void
495 vl_api_snat_control_ping_t_handler (vl_api_snat_control_ping_t * mp)
496 {
497   vl_api_snat_control_ping_reply_t *rmp;
498   snat_main_t *sm = &snat_main;
499   int rv = 0;
500
501   /* *INDENT-OFF* */
502   REPLY_MACRO2 (VL_API_SNAT_CONTROL_PING_REPLY,
503   ({
504     rmp->vpe_pid = ntohl (getpid ());
505   }));
506   /* *INDENT-ON* */
507 }
508
509 static void *vl_api_snat_control_ping_t_print
510   (vl_api_snat_control_ping_t * mp, void *handle)
511 {
512   u8 *s;
513
514   s = format (0, "SCRIPT: snat_control_ping ");
515
516   FINISH;
517 }
518
519 static void
520 vl_api_snat_show_config_t_handler (vl_api_snat_show_config_t * mp)
521 {
522   vl_api_snat_show_config_reply_t *rmp;
523   snat_main_t *sm = &snat_main;
524   int rv = 0;
525
526   /* *INDENT-OFF* */
527   REPLY_MACRO2 (VL_API_SNAT_SHOW_CONFIG_REPLY,
528   ({
529     rmp->translation_buckets = htonl (sm->translation_buckets);
530     rmp->translation_memory_size = htonl (sm->translation_memory_size);
531     rmp->user_buckets = htonl (sm->user_buckets);
532     rmp->user_memory_size = htonl (sm->user_memory_size);
533     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
534     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
535     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
536     rmp->static_mapping_only = sm->static_mapping_only;
537     rmp->static_mapping_connection_tracking =
538       sm->static_mapping_connection_tracking;
539     rmp->deterministic = sm->deterministic;
540   }));
541   /* *INDENT-ON* */
542 }
543
544 static void *vl_api_snat_show_config_t_print
545   (vl_api_snat_show_config_t * mp, void *handle)
546 {
547   u8 *s;
548
549   s = format (0, "SCRIPT: snat_show_config ");
550
551   FINISH;
552 }
553
554 static void
555 vl_api_snat_set_workers_t_handler (vl_api_snat_set_workers_t * mp)
556 {
557   snat_main_t *sm = &snat_main;
558   vl_api_snat_set_workers_reply_t *rmp;
559   int rv = 0;
560   uword *bitmap = 0;
561   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
562
563   if (sm->num_workers < 2)
564     {
565       rv = VNET_API_ERROR_FEATURE_DISABLED;
566       goto send_reply;
567     }
568
569   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
570   rv = snat_set_workers (bitmap);
571   clib_bitmap_free (bitmap);
572
573 send_reply:
574   REPLY_MACRO (VL_API_SNAT_SET_WORKERS_REPLY);
575 }
576
577 static void *vl_api_snat_set_workers_t_print
578   (vl_api_snat_set_workers_t * mp, void *handle)
579 {
580   u8 *s;
581   uword *bitmap = 0;
582   u8 first = 1;
583   int i;
584   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
585
586   s = format (0, "SCRIPT: snat_set_workers ");
587   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
588   /* *INDENT-OFF* */
589   clib_bitmap_foreach (i, bitmap,
590     ({
591       if (first)
592         s = format (s, "%d", i);
593       else
594         s = format (s, ",%d", i);
595       first = 0;
596     }));
597   /* *INDENT-ON* */
598   clib_bitmap_free (bitmap);
599   FINISH;
600 }
601
602 static void
603   send_snat_worker_details
604   (u32 worker_index, unix_shared_memory_queue_t * q, u32 context)
605 {
606   vl_api_snat_worker_details_t *rmp;
607   snat_main_t *sm = &snat_main;
608   vlib_worker_thread_t *w =
609     vlib_worker_threads + worker_index + sm->first_worker_index;
610
611   rmp = vl_msg_api_alloc (sizeof (*rmp));
612   memset (rmp, 0, sizeof (*rmp));
613   rmp->_vl_msg_id = ntohs (VL_API_SNAT_WORKER_DETAILS + sm->msg_id_base);
614   rmp->context = context;
615   rmp->worker_index = htonl (worker_index);
616   rmp->lcore_id = htonl (w->lcore_id);
617   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
618
619   vl_msg_api_send_shmem (q, (u8 *) & rmp);
620 }
621
622 static void
623 vl_api_snat_worker_dump_t_handler (vl_api_snat_worker_dump_t * mp)
624 {
625   unix_shared_memory_queue_t *q;
626   snat_main_t *sm = &snat_main;
627   u32 *worker_index;
628
629   q = vl_api_client_index_to_input_queue (mp->client_index);
630   if (q == 0)
631     return;
632
633   /* *INDENT-OFF* */
634   vec_foreach (worker_index, sm->workers)
635     send_snat_worker_details(*worker_index, q, mp->context);
636   /* *INDENT-ON* */
637 }
638
639 static void *vl_api_snat_worker_dump_t_print
640   (vl_api_snat_worker_dump_t * mp, void *handle)
641 {
642   u8 *s;
643
644   s = format (0, "SCRIPT: snat_worker_dump ");
645
646   FINISH;
647 }
648
649 static void
650   vl_api_snat_add_del_interface_addr_t_handler
651   (vl_api_snat_add_del_interface_addr_t * mp)
652 {
653   snat_main_t *sm = &snat_main;
654   vl_api_snat_add_del_interface_addr_reply_t *rmp;
655   u8 is_del = mp->is_add == 0;
656   u32 sw_if_index = ntohl (mp->sw_if_index);
657   int rv = 0;
658
659   VALIDATE_SW_IF_INDEX (mp);
660
661   rv = snat_add_interface_address (sm, sw_if_index, is_del);
662
663   BAD_SW_IF_INDEX_LABEL;
664
665   REPLY_MACRO (VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
666 }
667
668 static void *vl_api_snat_add_del_interface_addr_t_print
669   (vl_api_snat_add_del_interface_addr_t * mp, void *handle)
670 {
671   u8 *s;
672
673   s = format (0, "SCRIPT: snat_add_del_interface_addr ");
674   s = format (s, "sw_if_index %d %s",
675               clib_host_to_net_u32 (mp->sw_if_index),
676               mp->is_add ? "" : "del");
677
678   FINISH;
679 }
680
681 static void
682   send_snat_interface_addr_details
683   (u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
684 {
685   vl_api_snat_interface_addr_details_t *rmp;
686   snat_main_t *sm = &snat_main;
687
688   rmp = vl_msg_api_alloc (sizeof (*rmp));
689   memset (rmp, 0, sizeof (*rmp));
690   rmp->_vl_msg_id =
691     ntohs (VL_API_SNAT_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
692   rmp->sw_if_index = ntohl (sw_if_index);
693   rmp->context = context;
694
695   vl_msg_api_send_shmem (q, (u8 *) & rmp);
696 }
697
698 static void
699   vl_api_snat_interface_addr_dump_t_handler
700   (vl_api_snat_interface_addr_dump_t * mp)
701 {
702   unix_shared_memory_queue_t *q;
703   snat_main_t *sm = &snat_main;
704   u32 *i;
705
706   q = vl_api_client_index_to_input_queue (mp->client_index);
707   if (q == 0)
708     return;
709
710   /* *INDENT-OFF* */
711   vec_foreach (i, sm->auto_add_sw_if_indices)
712     send_snat_interface_addr_details(*i, q, mp->context);
713   /* *INDENT-ON* */
714 }
715
716 static void *vl_api_snat_interface_addr_dump_t_print
717   (vl_api_snat_interface_addr_dump_t * mp, void *handle)
718 {
719   u8 *s;
720
721   s = format (0, "SCRIPT: snat_interface_addr_dump ");
722
723   FINISH;
724 }
725
726 static void
727   vl_api_snat_ipfix_enable_disable_t_handler
728   (vl_api_snat_ipfix_enable_disable_t * mp)
729 {
730   snat_main_t *sm = &snat_main;
731   vl_api_snat_ipfix_enable_disable_reply_t *rmp;
732   int rv = 0;
733
734   rv = snat_ipfix_logging_enable_disable (mp->enable,
735                                           clib_host_to_net_u32
736                                           (mp->domain_id),
737                                           clib_host_to_net_u16
738                                           (mp->src_port));
739
740   REPLY_MACRO (VL_API_SNAT_IPFIX_ENABLE_DISABLE_REPLY);
741 }
742
743 static void *vl_api_snat_ipfix_enable_disable_t_print
744   (vl_api_snat_ipfix_enable_disable_t * mp, void *handle)
745 {
746   u8 *s;
747
748   s = format (0, "SCRIPT: snat_ipfix_enable_disable ");
749   if (mp->domain_id)
750     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
751   if (mp->src_port)
752     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
753   if (!mp->enable)
754     s = format (s, "disable ");
755
756   FINISH;
757 }
758
759 static void
760   send_snat_user_details
761   (snat_user_t * u, unix_shared_memory_queue_t * q, u32 context)
762 {
763   vl_api_snat_user_details_t *rmp;
764   snat_main_t *sm = &snat_main;
765   fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
766
767   rmp = vl_msg_api_alloc (sizeof (*rmp));
768   memset (rmp, 0, sizeof (*rmp));
769   rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS + sm->msg_id_base);
770
771   rmp->vrf_id = ntohl (fib->ft_table_id);
772
773   rmp->is_ip4 = 1;
774   clib_memcpy (rmp->ip_address, &(u->addr), 4);
775   rmp->nsessions = ntohl (u->nsessions);
776   rmp->nstaticsessions = ntohl (u->nstaticsessions);
777   rmp->context = context;
778
779   vl_msg_api_send_shmem (q, (u8 *) & rmp);
780 }
781
782 static void
783 vl_api_snat_user_dump_t_handler (vl_api_snat_user_dump_t * mp)
784 {
785   unix_shared_memory_queue_t *q;
786   snat_main_t *sm = &snat_main;
787   snat_main_per_thread_data_t *tsm;
788   snat_user_t *u;
789
790   q = vl_api_client_index_to_input_queue (mp->client_index);
791   if (q == 0)
792     return;
793
794   /* *INDENT-OFF* */
795   vec_foreach (tsm, sm->per_thread_data)
796     vec_foreach (u, tsm->users)
797       send_snat_user_details (u, q, mp->context);
798   /* *INDENT-ON* */
799 }
800
801 static void *vl_api_snat_user_dump_t_print
802   (vl_api_snat_user_dump_t * mp, void *handle)
803 {
804   u8 *s;
805
806   s = format (0, "SCRIPT: snat_user_dump ");
807
808   FINISH;
809 }
810
811 static void
812   send_snat_user_session_details
813   (snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
814 {
815   vl_api_snat_user_session_details_t *rmp;
816   snat_main_t *sm = &snat_main;
817
818   rmp = vl_msg_api_alloc (sizeof (*rmp));
819   memset (rmp, 0, sizeof (*rmp));
820   rmp->_vl_msg_id =
821     ntohs (VL_API_SNAT_USER_SESSION_DETAILS + sm->msg_id_base);
822   rmp->is_ip4 = 1;
823   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
824   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
825   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
826   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
827   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
828   rmp->total_pkts = ntohl (s->total_pkts);
829   rmp->context = context;
830   if (snat_is_unk_proto_session (s))
831     {
832       rmp->outside_port = 0;
833       rmp->inside_port = 0;
834       rmp->protocol = ntohs (s->in2out.port);
835     }
836   else
837     {
838       rmp->outside_port = s->out2in.port;
839       rmp->inside_port = s->in2out.port;
840       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
841     }
842
843   vl_msg_api_send_shmem (q, (u8 *) & rmp);
844 }
845
846 static void
847   vl_api_snat_user_session_dump_t_handler
848   (vl_api_snat_user_session_dump_t * mp)
849 {
850   unix_shared_memory_queue_t *q;
851   snat_main_t *sm = &snat_main;
852   snat_main_per_thread_data_t *tsm;
853   snat_session_t *s;
854   clib_bihash_kv_8_8_t key, value;
855   snat_user_key_t ukey;
856   snat_user_t *u;
857   u32 session_index, head_index, elt_index;
858   dlist_elt_t *head, *elt;
859   ip4_header_t ip;
860
861   q = vl_api_client_index_to_input_queue (mp->client_index);
862   if (q == 0)
863     return;
864   if (!mp->is_ip4)
865     return;
866
867   clib_memcpy (&ukey.addr, mp->ip_address, 4);
868   ip.src_address.as_u32 = ukey.addr.as_u32;
869   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
870   key.key = ukey.as_u64;
871   if (sm->num_workers)
872     tsm =
873       vec_elt_at_index (sm->per_thread_data,
874                         sm->worker_in2out_cb (&ip, ukey.fib_index));
875   else
876     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
877   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
878     return;
879   u = pool_elt_at_index (tsm->users, value.value);
880   if (!u->nsessions && !u->nstaticsessions)
881     return;
882
883   head_index = u->sessions_per_user_list_head_index;
884   head = pool_elt_at_index (tsm->list_pool, head_index);
885   elt_index = head->next;
886   elt = pool_elt_at_index (tsm->list_pool, elt_index);
887   session_index = elt->value;
888   while (session_index != ~0)
889     {
890       s = pool_elt_at_index (tsm->sessions, session_index);
891
892       send_snat_user_session_details (s, q, mp->context);
893
894       elt_index = elt->next;
895       elt = pool_elt_at_index (tsm->list_pool, elt_index);
896       session_index = elt->value;
897     }
898 }
899
900 static void *vl_api_snat_user_session_dump_t_print
901   (vl_api_snat_user_session_dump_t * mp, void *handle)
902 {
903   u8 *s;
904
905   s = format (0, "SCRIPT: snat_user_session_dump ");
906   s = format (s, "ip_address %U vrf_id %d\n",
907               format_ip4_address, mp->ip_address,
908               clib_net_to_host_u32 (mp->vrf_id));
909
910   FINISH;
911 }
912
913 /******************************************************************/
914 /*** detrministic NAT/CGN (old, will be deprecated after 17.10) ***/
915 /******************************************************************/
916
917 static void
918 vl_api_snat_add_det_map_t_handler (vl_api_snat_add_det_map_t * mp)
919 {
920   snat_main_t *sm = &snat_main;
921   vl_api_snat_add_det_map_reply_t *rmp;
922   int rv = 0;
923   ip4_address_t in_addr, out_addr;
924
925   clib_memcpy (&in_addr, mp->in_addr, 4);
926   clib_memcpy (&out_addr, mp->out_addr, 4);
927   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
928                          mp->out_plen, mp->is_add);
929
930   REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
931 }
932
933 static void *vl_api_snat_add_det_map_t_print
934   (vl_api_snat_add_det_map_t * mp, void *handle)
935 {
936   u8 *s;
937
938   s = format (0, "SCRIPT: snat_add_det_map ");
939   s = format (s, "inside address %U/%d outside address %U/%d\n",
940               format_ip4_address, mp->in_addr, mp->in_plen,
941               format_ip4_address, mp->out_addr, mp->out_plen);
942
943   FINISH;
944 }
945
946 static void
947 vl_api_snat_det_forward_t_handler (vl_api_snat_det_forward_t * mp)
948 {
949   snat_main_t *sm = &snat_main;
950   vl_api_snat_det_forward_reply_t *rmp;
951   int rv = 0;
952   u16 lo_port = 0, hi_port = 0;
953   snat_det_map_t *dm;
954   ip4_address_t in_addr, out_addr;
955
956   out_addr.as_u32 = 0;
957   clib_memcpy (&in_addr, mp->in_addr, 4);
958   dm = snat_det_map_by_user (sm, &in_addr);
959   if (!dm)
960     {
961       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
962       goto send_reply;
963     }
964
965   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
966   hi_port = lo_port + dm->ports_per_host - 1;
967
968 send_reply:
969   /* *INDENT-OFF* */
970   REPLY_MACRO2 (VL_API_SNAT_DET_FORWARD_REPLY,
971   ({
972     rmp->out_port_lo = ntohs (lo_port);
973     rmp->out_port_hi = ntohs (hi_port);
974     rmp->is_ip4 = 1;
975     memset (rmp->out_addr, 0, 16);
976     clib_memcpy (rmp->out_addr, &out_addr, 4);
977   }))
978   /* *INDENT-ON* */
979 }
980
981 static void *vl_api_snat_det_forward_t_print
982   (vl_api_snat_det_forward_t * mp, void *handle)
983 {
984   u8 *s;
985
986   s = format (0, "SCRIPT: smat_det_forward_t");
987   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
988
989   FINISH;
990 }
991
992 static void
993 vl_api_snat_det_reverse_t_handler (vl_api_snat_det_reverse_t * mp)
994 {
995   snat_main_t *sm = &snat_main;
996   vl_api_snat_det_reverse_reply_t *rmp;
997   int rv = 0;
998   ip4_address_t out_addr, in_addr;
999   snat_det_map_t *dm;
1000
1001   in_addr.as_u32 = 0;
1002   clib_memcpy (&out_addr, mp->out_addr, 4);
1003   dm = snat_det_map_by_out (sm, &out_addr);
1004   if (!dm)
1005     {
1006       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1007       goto send_reply;
1008     }
1009
1010   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1011
1012 send_reply:
1013   /* *INDENT-OFF* */
1014   REPLY_MACRO2 (VL_API_SNAT_DET_REVERSE_REPLY,
1015   ({
1016     rmp->is_ip4 = 1;
1017     memset (rmp->in_addr, 0, 16);
1018     clib_memcpy (rmp->in_addr, &in_addr, 4);
1019   }))
1020   /* *INDENT-ON* */
1021 }
1022
1023 static void *vl_api_snat_det_reverse_t_print
1024   (vl_api_snat_det_reverse_t * mp, void *handle)
1025 {
1026   u8 *s;
1027
1028   s = format (0, "SCRIPT: smat_det_reverse_t");
1029   s = format (s, "outside ip address %U outside port %d",
1030               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1031
1032   FINISH;
1033 }
1034
1035 static void
1036   sent_snat_det_map_details
1037   (snat_det_map_t * m, unix_shared_memory_queue_t * q, u32 context)
1038 {
1039   vl_api_snat_det_map_details_t *rmp;
1040   snat_main_t *sm = &snat_main;
1041
1042   rmp = vl_msg_api_alloc (sizeof (*rmp));
1043   memset (rmp, 0, sizeof (*rmp));
1044   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS + sm->msg_id_base);
1045   rmp->is_ip4 = 1;
1046   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
1047   rmp->in_plen = m->in_plen;
1048   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
1049   rmp->out_plen = m->out_plen;
1050   rmp->sharing_ratio = htonl (m->sharing_ratio);
1051   rmp->ports_per_host = htons (m->ports_per_host);
1052   rmp->ses_num = htonl (m->ses_num);
1053   rmp->context = context;
1054
1055   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1056 }
1057
1058 static void
1059 vl_api_snat_det_map_dump_t_handler (vl_api_snat_det_map_dump_t * mp)
1060 {
1061   unix_shared_memory_queue_t *q;
1062   snat_main_t *sm = &snat_main;
1063   snat_det_map_t *m;
1064
1065   q = vl_api_client_index_to_input_queue (mp->client_index);
1066   if (q == 0)
1067     return;
1068
1069   /* *INDENT-OFF* */
1070   vec_foreach(m, sm->det_maps)
1071     sent_snat_det_map_details(m, q, mp->context);
1072   /* *INDENT-ON* */
1073 }
1074
1075 static void *vl_api_snat_det_map_dump_t_print
1076   (vl_api_snat_det_map_dump_t * mp, void *handle)
1077 {
1078   u8 *s;
1079
1080   s = format (0, "SCRIPT: snat_det_map_dump ");
1081
1082   FINISH;
1083 }
1084
1085 static void
1086 vl_api_snat_det_set_timeouts_t_handler (vl_api_snat_det_set_timeouts_t * mp)
1087 {
1088   snat_main_t *sm = &snat_main;
1089   vl_api_snat_det_set_timeouts_reply_t *rmp;
1090   int rv = 0;
1091
1092   sm->udp_timeout = ntohl (mp->udp);
1093   sm->tcp_established_timeout = ntohl (mp->tcp_established);
1094   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
1095   sm->icmp_timeout = ntohl (mp->icmp);
1096
1097   REPLY_MACRO (VL_API_SNAT_DET_SET_TIMEOUTS_REPLY);
1098 }
1099
1100 static void *vl_api_snat_det_set_timeouts_t_print
1101   (vl_api_snat_det_set_timeouts_t * mp, void *handle)
1102 {
1103   u8 *s;
1104
1105   s = format (0, "SCRIPT: snat_det_set_timeouts ");
1106   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
1107               ntohl (mp->udp),
1108               ntohl (mp->tcp_established),
1109               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1110
1111   FINISH;
1112 }
1113
1114 static void
1115 vl_api_snat_det_get_timeouts_t_handler (vl_api_snat_det_get_timeouts_t * mp)
1116 {
1117   snat_main_t *sm = &snat_main;
1118   vl_api_snat_det_get_timeouts_reply_t *rmp;
1119   int rv = 0;
1120
1121   /* *INDENT-OFF* */
1122   REPLY_MACRO2 (VL_API_SNAT_DET_GET_TIMEOUTS_REPLY,
1123   ({
1124     rmp->udp = htonl (sm->udp_timeout);
1125     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1126     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1127     rmp->icmp = htonl (sm->icmp_timeout);
1128   }))
1129   /* *INDENT-ON* */
1130 }
1131
1132 static void *vl_api_snat_det_get_timeouts_t_print
1133   (vl_api_snat_det_get_timeouts_t * mp, void *handle)
1134 {
1135   u8 *s;
1136
1137   s = format (0, "SCRIPT: snat_det_get_timeouts");
1138
1139   FINISH;
1140 }
1141
1142 static void
1143   vl_api_snat_det_close_session_out_t_handler
1144   (vl_api_snat_det_close_session_out_t * mp)
1145 {
1146   snat_main_t *sm = &snat_main;
1147   vl_api_snat_det_close_session_out_reply_t *rmp;
1148   ip4_address_t out_addr, ext_addr, in_addr;
1149   snat_det_out_key_t key;
1150   snat_det_map_t *dm;
1151   snat_det_session_t *ses;
1152   int rv = 0;
1153
1154   clib_memcpy (&out_addr, mp->out_addr, 4);
1155   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1156
1157   dm = snat_det_map_by_out (sm, &out_addr);
1158   if (!dm)
1159     {
1160       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1161       goto send_reply;
1162     }
1163   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1164   key.ext_host_addr = ext_addr;
1165   key.ext_host_port = mp->ext_port;
1166   key.out_port = mp->out_port;
1167   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1168   if (!ses)
1169     {
1170       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1171       goto send_reply;
1172     }
1173   snat_det_ses_close (dm, ses);
1174
1175 send_reply:
1176   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1177 }
1178
1179 static void *vl_api_snat_det_close_session_out_t_print
1180   (vl_api_snat_det_close_session_out_t * mp, void *handle)
1181 {
1182   u8 *s;
1183
1184   s = format (0, "SCRIPT: snat_det_close_session_out ");
1185   s = format (s, "out_addr %U out_port %d "
1186               "ext_addr %U ext_port %d\n",
1187               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1188               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1189
1190   FINISH;
1191 }
1192
1193 static void
1194   vl_api_snat_det_close_session_in_t_handler
1195   (vl_api_snat_det_close_session_in_t * mp)
1196 {
1197   snat_main_t *sm = &snat_main;
1198   vl_api_snat_det_close_session_in_reply_t *rmp;
1199   ip4_address_t in_addr, ext_addr;
1200   snat_det_out_key_t key;
1201   snat_det_map_t *dm;
1202   snat_det_session_t *ses;
1203   int rv = 0;
1204
1205   clib_memcpy (&in_addr, mp->in_addr, 4);
1206   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1207
1208   dm = snat_det_map_by_user (sm, &in_addr);
1209   if (!dm)
1210     {
1211       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1212       goto send_reply;
1213     }
1214   key.ext_host_addr = ext_addr;
1215   key.ext_host_port = mp->ext_port;
1216   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1217   if (!ses)
1218     {
1219       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1220       goto send_reply;
1221     }
1222   snat_det_ses_close (dm, ses);
1223
1224 send_reply:
1225   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1226 }
1227
1228 static void *vl_api_snat_det_close_session_in_t_print
1229   (vl_api_snat_det_close_session_in_t * mp, void *handle)
1230 {
1231   u8 *s;
1232   s = format (0, "SCRIPT: snat_det_close_session_in ");
1233   s = format (s, "in_addr %U in_port %d "
1234               "ext_addr %U ext_port %d\n",
1235               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
1236               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1237
1238   FINISH;
1239 }
1240
1241 static void
1242   send_snat_det_session_details
1243   (snat_det_session_t * s, unix_shared_memory_queue_t * q, u32 context)
1244 {
1245   vl_api_snat_det_session_details_t *rmp;
1246   snat_main_t *sm = &snat_main;
1247
1248   rmp = vl_msg_api_alloc (sizeof (*rmp));
1249   memset (rmp, 0, sizeof (*rmp));
1250   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_SESSION_DETAILS + sm->msg_id_base);
1251   rmp->is_ip4 = 1;
1252   rmp->in_port = s->in_port;
1253   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
1254   rmp->ext_port = s->out.ext_host_port;
1255   rmp->out_port = s->out.out_port;
1256   rmp->state = s->state;
1257   rmp->expire = ntohl (s->expire);
1258   rmp->context = context;
1259
1260   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1261 }
1262
1263 static void
1264 vl_api_snat_det_session_dump_t_handler (vl_api_snat_det_session_dump_t * mp)
1265 {
1266   unix_shared_memory_queue_t *q;
1267   snat_main_t *sm = &snat_main;
1268   ip4_address_t user_addr;
1269   snat_det_map_t *dm;
1270   snat_det_session_t *s, empty_ses;
1271   u16 i;
1272
1273   q = vl_api_client_index_to_input_queue (mp->client_index);
1274   if (q == 0)
1275     return;
1276   if (!mp->is_ip4)
1277     return;
1278
1279   memset (&empty_ses, 0, sizeof (empty_ses));
1280   clib_memcpy (&user_addr, mp->user_addr, 4);
1281   dm = snat_det_map_by_user (sm, &user_addr);
1282   if (!dm)
1283     return;
1284
1285   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
1286   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
1287     {
1288       if (s->out.as_u64)
1289         send_snat_det_session_details (s, q, mp->context);
1290       s++;
1291     }
1292 }
1293
1294 static void *vl_api_snat_det_session_dump_t_print
1295   (vl_api_snat_det_session_dump_t * mp, void *handle)
1296 {
1297   u8 *s;
1298
1299   s = format (0, "SCRIPT: snat_det_session_dump ");
1300   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
1301
1302   FINISH;
1303 }
1304
1305 /******************************/
1306 /*** Common NAT plugin APIs ***/
1307 /******************************/
1308
1309 static void
1310 vl_api_nat_control_ping_t_handler (vl_api_nat_control_ping_t * mp)
1311 {
1312   vl_api_nat_control_ping_reply_t *rmp;
1313   snat_main_t *sm = &snat_main;
1314   int rv = 0;
1315
1316   /* *INDENT-OFF* */
1317   REPLY_MACRO2 (VL_API_NAT_CONTROL_PING_REPLY,
1318   ({
1319     rmp->vpe_pid = ntohl (getpid ());
1320   }));
1321   /* *INDENT-ON* */
1322 }
1323
1324 static void *
1325 vl_api_nat_control_ping_t_print (vl_api_nat_control_ping_t * mp, void *handle)
1326 {
1327   u8 *s;
1328
1329   s = format (0, "SCRIPT: nat_control_ping ");
1330
1331   FINISH;
1332 }
1333
1334 static void
1335 vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t * mp)
1336 {
1337   vl_api_nat_show_config_reply_t *rmp;
1338   snat_main_t *sm = &snat_main;
1339   int rv = 0;
1340
1341   /* *INDENT-OFF* */
1342   REPLY_MACRO2 (VL_API_NAT_SHOW_CONFIG_REPLY,
1343   ({
1344     rmp->translation_buckets = htonl (sm->translation_buckets);
1345     rmp->translation_memory_size = htonl (sm->translation_memory_size);
1346     rmp->user_buckets = htonl (sm->user_buckets);
1347     rmp->user_memory_size = htonl (sm->user_memory_size);
1348     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
1349     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
1350     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
1351     rmp->static_mapping_only = sm->static_mapping_only;
1352     rmp->static_mapping_connection_tracking =
1353       sm->static_mapping_connection_tracking;
1354     rmp->deterministic = sm->deterministic;
1355   }));
1356   /* *INDENT-ON* */
1357 }
1358
1359 static void *
1360 vl_api_nat_show_config_t_print (vl_api_nat_show_config_t * mp, void *handle)
1361 {
1362   u8 *s;
1363
1364   s = format (0, "SCRIPT: nat_show_config ");
1365
1366   FINISH;
1367 }
1368
1369 static void
1370 vl_api_nat_set_workers_t_handler (vl_api_nat_set_workers_t * mp)
1371 {
1372   snat_main_t *sm = &snat_main;
1373   vl_api_snat_set_workers_reply_t *rmp;
1374   int rv = 0;
1375   uword *bitmap = 0;
1376   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
1377
1378   if (sm->num_workers < 2)
1379     {
1380       rv = VNET_API_ERROR_FEATURE_DISABLED;
1381       goto send_reply;
1382     }
1383
1384   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
1385   rv = snat_set_workers (bitmap);
1386   clib_bitmap_free (bitmap);
1387
1388 send_reply:
1389   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
1390 }
1391
1392 static void *
1393 vl_api_nat_set_workers_t_print (vl_api_nat_set_workers_t * mp, void *handle)
1394 {
1395   u8 *s;
1396   uword *bitmap = 0;
1397   u8 first = 1;
1398   int i;
1399   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
1400
1401   s = format (0, "SCRIPT: nat_set_workers ");
1402   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
1403   /* *INDENT-OFF* */
1404   clib_bitmap_foreach (i, bitmap,
1405     ({
1406       if (first)
1407         s = format (s, "%d", i);
1408       else
1409         s = format (s, ",%d", i);
1410       first = 0;
1411     }));
1412   /* *INDENT-ON* */
1413   clib_bitmap_free (bitmap);
1414   FINISH;
1415 }
1416
1417 static void
1418 send_nat_worker_details (u32 worker_index, unix_shared_memory_queue_t * q,
1419                          u32 context)
1420 {
1421   vl_api_nat_worker_details_t *rmp;
1422   snat_main_t *sm = &snat_main;
1423   vlib_worker_thread_t *w =
1424     vlib_worker_threads + worker_index + sm->first_worker_index;
1425
1426   rmp = vl_msg_api_alloc (sizeof (*rmp));
1427   memset (rmp, 0, sizeof (*rmp));
1428   rmp->_vl_msg_id = ntohs (VL_API_NAT_WORKER_DETAILS + sm->msg_id_base);
1429   rmp->context = context;
1430   rmp->worker_index = htonl (worker_index);
1431   rmp->lcore_id = htonl (w->lcore_id);
1432   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
1433
1434   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1435 }
1436
1437 static void
1438 vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp)
1439 {
1440   unix_shared_memory_queue_t *q;
1441   snat_main_t *sm = &snat_main;
1442   u32 *worker_index;
1443
1444   q = vl_api_client_index_to_input_queue (mp->client_index);
1445   if (q == 0)
1446     return;
1447
1448   /* *INDENT-OFF* */
1449   vec_foreach (worker_index, sm->workers)
1450     send_nat_worker_details(*worker_index, q, mp->context);
1451   /* *INDENT-ON* */
1452 }
1453
1454 static void *
1455 vl_api_nat_worker_dump_t_print (vl_api_nat_worker_dump_t * mp, void *handle)
1456 {
1457   u8 *s;
1458
1459   s = format (0, "SCRIPT: nat_worker_dump ");
1460
1461   FINISH;
1462 }
1463
1464 static void
1465 vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t *
1466                                            mp)
1467 {
1468   snat_main_t *sm = &snat_main;
1469   vl_api_nat_ipfix_enable_disable_reply_t *rmp;
1470   int rv = 0;
1471
1472   rv = snat_ipfix_logging_enable_disable (mp->enable,
1473                                           clib_host_to_net_u32
1474                                           (mp->domain_id),
1475                                           clib_host_to_net_u16
1476                                           (mp->src_port));
1477
1478   REPLY_MACRO (VL_API_NAT_IPFIX_ENABLE_DISABLE_REPLY);
1479 }
1480
1481 static void *
1482 vl_api_nat_ipfix_enable_disable_t_print (vl_api_nat_ipfix_enable_disable_t *
1483                                          mp, void *handle)
1484 {
1485   u8 *s;
1486
1487   s = format (0, "SCRIPT: nat_ipfix_enable_disable ");
1488   if (mp->domain_id)
1489     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
1490   if (mp->src_port)
1491     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
1492   if (!mp->enable)
1493     s = format (s, "disable ");
1494
1495   FINISH;
1496 }
1497
1498 /*************/
1499 /*** NAT44 ***/
1500 /*************/
1501 static void
1502   vl_api_nat44_add_del_address_range_t_handler
1503   (vl_api_nat44_add_del_address_range_t * mp)
1504 {
1505   snat_main_t *sm = &snat_main;
1506   vl_api_nat44_add_del_address_range_reply_t *rmp;
1507   ip4_address_t this_addr;
1508   u32 start_host_order, end_host_order;
1509   u32 vrf_id;
1510   int i, count;
1511   int rv = 0;
1512   u32 *tmp;
1513
1514   if (sm->static_mapping_only)
1515     {
1516       rv = VNET_API_ERROR_FEATURE_DISABLED;
1517       goto send_reply;
1518     }
1519
1520   tmp = (u32 *) mp->first_ip_address;
1521   start_host_order = clib_host_to_net_u32 (tmp[0]);
1522   tmp = (u32 *) mp->last_ip_address;
1523   end_host_order = clib_host_to_net_u32 (tmp[0]);
1524
1525   count = (end_host_order - start_host_order) + 1;
1526
1527   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
1528
1529   if (count > 1024)
1530     clib_warning ("%U - %U, %d addresses...",
1531                   format_ip4_address, mp->first_ip_address,
1532                   format_ip4_address, mp->last_ip_address, count);
1533
1534   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
1535
1536   for (i = 0; i < count; i++)
1537     {
1538       if (mp->is_add)
1539         snat_add_address (sm, &this_addr, vrf_id);
1540       else
1541         rv = snat_del_address (sm, this_addr, 0);
1542
1543       if (rv)
1544         goto send_reply;
1545
1546       increment_v4_address (&this_addr);
1547     }
1548
1549 send_reply:
1550   REPLY_MACRO (VL_API_NAT44_ADD_DEL_ADDRESS_RANGE_REPLY);
1551 }
1552
1553 static void *vl_api_nat44_add_del_address_range_t_print
1554   (vl_api_nat44_add_del_address_range_t * mp, void *handle)
1555 {
1556   u8 *s;
1557
1558   s = format (0, "SCRIPT: nat44_add_address_range ");
1559   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
1560   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
1561     {
1562       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
1563     }
1564   FINISH;
1565 }
1566
1567 static void
1568 send_nat44_address_details (snat_address_t * a,
1569                             unix_shared_memory_queue_t * q, u32 context)
1570 {
1571   vl_api_nat44_address_details_t *rmp;
1572   snat_main_t *sm = &snat_main;
1573
1574   rmp = vl_msg_api_alloc (sizeof (*rmp));
1575   memset (rmp, 0, sizeof (*rmp));
1576   rmp->_vl_msg_id = ntohs (VL_API_NAT44_ADDRESS_DETAILS + sm->msg_id_base);
1577   clib_memcpy (rmp->ip_address, &(a->addr), 4);
1578   if (a->fib_index != ~0)
1579     {
1580       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
1581       rmp->vrf_id = ntohl (fib->ft_table_id);
1582     }
1583   else
1584     rmp->vrf_id = ~0;
1585   rmp->context = context;
1586
1587   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1588 }
1589
1590 static void
1591 vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp)
1592 {
1593   unix_shared_memory_queue_t *q;
1594   snat_main_t *sm = &snat_main;
1595   snat_address_t *a;
1596
1597   q = vl_api_client_index_to_input_queue (mp->client_index);
1598   if (q == 0)
1599     return;
1600
1601   /* *INDENT-OFF* */
1602   vec_foreach (a, sm->addresses)
1603     send_nat44_address_details (a, q, mp->context);
1604   /* *INDENT-ON* */
1605 }
1606
1607 static void *
1608 vl_api_nat44_address_dump_t_print (vl_api_nat44_address_dump_t * mp,
1609                                    void *handle)
1610 {
1611   u8 *s;
1612
1613   s = format (0, "SCRIPT: nat44_address_dump ");
1614
1615   FINISH;
1616 }
1617
1618 static void
1619   vl_api_nat44_interface_add_del_feature_t_handler
1620   (vl_api_nat44_interface_add_del_feature_t * mp)
1621 {
1622   snat_main_t *sm = &snat_main;
1623   vl_api_nat44_interface_add_del_feature_reply_t *rmp;
1624   u8 is_del = mp->is_add == 0;
1625   u32 sw_if_index = ntohl (mp->sw_if_index);
1626   int rv = 0;
1627
1628   VALIDATE_SW_IF_INDEX (mp);
1629
1630   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
1631
1632   BAD_SW_IF_INDEX_LABEL;
1633
1634   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY);
1635 }
1636
1637 static void *vl_api_nat44_interface_add_del_feature_t_print
1638   (vl_api_nat44_interface_add_del_feature_t * mp, void *handle)
1639 {
1640   u8 *s;
1641
1642   s = format (0, "SCRIPT: nat44_interface_add_del_feature ");
1643   s = format (s, "sw_if_index %d %s %s",
1644               clib_host_to_net_u32 (mp->sw_if_index),
1645               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1646
1647   FINISH;
1648 }
1649
1650 static void
1651 send_nat44_interface_details (snat_interface_t * i,
1652                               unix_shared_memory_queue_t * q, u32 context)
1653 {
1654   vl_api_nat44_interface_details_t *rmp;
1655   snat_main_t *sm = &snat_main;
1656
1657   rmp = vl_msg_api_alloc (sizeof (*rmp));
1658   memset (rmp, 0, sizeof (*rmp));
1659   rmp->_vl_msg_id = ntohs (VL_API_NAT44_INTERFACE_DETAILS + sm->msg_id_base);
1660   rmp->sw_if_index = ntohl (i->sw_if_index);
1661   rmp->is_inside = i->is_inside;
1662   rmp->context = context;
1663
1664   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1665 }
1666
1667 static void
1668 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
1669 {
1670   unix_shared_memory_queue_t *q;
1671   snat_main_t *sm = &snat_main;
1672   snat_interface_t *i;
1673
1674   q = vl_api_client_index_to_input_queue (mp->client_index);
1675   if (q == 0)
1676     return;
1677
1678   /* *INDENT-OFF* */
1679   pool_foreach (i, sm->interfaces,
1680   ({
1681     send_nat44_interface_details(i, q, mp->context);
1682   }));
1683   /* *INDENT-ON* */
1684 }
1685
1686 static void *
1687 vl_api_nat44_interface_dump_t_print (vl_api_nat44_interface_dump_t * mp,
1688                                      void *handle)
1689 {
1690   u8 *s;
1691
1692   s = format (0, "SCRIPT: nat44_interface_dump ");
1693
1694   FINISH;
1695 }
1696
1697 static void
1698   vl_api_nat44_interface_add_del_output_feature_t_handler
1699   (vl_api_nat44_interface_add_del_output_feature_t * mp)
1700 {
1701   snat_main_t *sm = &snat_main;
1702   vl_api_nat44_interface_add_del_output_feature_reply_t *rmp;
1703   u8 is_del = mp->is_add == 0;
1704   u32 sw_if_index = ntohl (mp->sw_if_index);
1705   int rv = 0;
1706
1707   VALIDATE_SW_IF_INDEX (mp);
1708
1709   rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
1710                                               is_del);
1711
1712   BAD_SW_IF_INDEX_LABEL;
1713
1714   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
1715 }
1716
1717 static void *vl_api_nat44_interface_add_del_output_feature_t_print
1718   (vl_api_nat44_interface_add_del_output_feature_t * mp, void *handle)
1719 {
1720   u8 *s;
1721
1722   s = format (0, "SCRIPT: nat44_interface_add_del_output_feature ");
1723   s = format (s, "sw_if_index %d %s %s",
1724               clib_host_to_net_u32 (mp->sw_if_index),
1725               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1726
1727   FINISH;
1728 }
1729
1730 static void
1731 send_nat44_interface_output_feature_details (snat_interface_t * i,
1732                                              unix_shared_memory_queue_t * q,
1733                                              u32 context)
1734 {
1735   vl_api_nat44_interface_output_feature_details_t *rmp;
1736   snat_main_t *sm = &snat_main;
1737
1738   rmp = vl_msg_api_alloc (sizeof (*rmp));
1739   memset (rmp, 0, sizeof (*rmp));
1740   rmp->_vl_msg_id =
1741     ntohs (VL_API_NAT44_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
1742   rmp->sw_if_index = ntohl (i->sw_if_index);
1743   rmp->context = context;
1744   rmp->is_inside = i->is_inside;
1745
1746   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1747 }
1748
1749 static void
1750   vl_api_nat44_interface_output_feature_dump_t_handler
1751   (vl_api_nat44_interface_output_feature_dump_t * mp)
1752 {
1753   unix_shared_memory_queue_t *q;
1754   snat_main_t *sm = &snat_main;
1755   snat_interface_t *i;
1756
1757   q = vl_api_client_index_to_input_queue (mp->client_index);
1758   if (q == 0)
1759     return;
1760
1761   /* *INDENT-OFF* */
1762   pool_foreach (i, sm->output_feature_interfaces,
1763   ({
1764     send_nat44_interface_output_feature_details(i, q, mp->context);
1765   }));
1766   /* *INDENT-ON* */
1767 }
1768
1769 static void *vl_api_nat44_interface_output_feature_dump_t_print
1770   (vl_api_nat44_interface_output_feature_dump_t * mp, void *handle)
1771 {
1772   u8 *s;
1773
1774   s = format (0, "SCRIPT: nat44_interface_output_feature_dump ");
1775
1776   FINISH;
1777 }
1778
1779 static void
1780   vl_api_nat44_add_del_static_mapping_t_handler
1781   (vl_api_nat44_add_del_static_mapping_t * mp)
1782 {
1783   snat_main_t *sm = &snat_main;
1784   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
1785   ip4_address_t local_addr, external_addr;
1786   u16 local_port = 0, external_port = 0;
1787   u32 vrf_id, external_sw_if_index;
1788   int rv = 0;
1789   snat_protocol_t proto;
1790
1791   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
1792   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
1793   if (mp->addr_only == 0)
1794     {
1795       local_port = clib_net_to_host_u16 (mp->local_port);
1796       external_port = clib_net_to_host_u16 (mp->external_port);
1797     }
1798   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1799   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
1800   proto = ip_proto_to_snat_proto (mp->protocol);
1801
1802   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
1803                                 external_port, vrf_id, mp->addr_only,
1804                                 external_sw_if_index, proto, mp->is_add);
1805
1806   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
1807 }
1808
1809 static void *vl_api_nat44_add_del_static_mapping_t_print
1810   (vl_api_nat44_add_del_static_mapping_t * mp, void *handle)
1811 {
1812   u8 *s;
1813
1814   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1815   s = format (s, "protocol %d local_addr %U external_addr %U ",
1816               mp->protocol,
1817               format_ip4_address, mp->local_ip_address,
1818               format_ip4_address, mp->external_ip_address);
1819
1820   if (mp->addr_only == 0)
1821     s = format (s, "local_port %d external_port %d ",
1822                 clib_net_to_host_u16 (mp->local_port),
1823                 clib_net_to_host_u16 (mp->external_port));
1824
1825   if (mp->vrf_id != ~0)
1826     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1827
1828   if (mp->external_sw_if_index != ~0)
1829     s = format (s, "external_sw_if_index %d",
1830                 clib_net_to_host_u32 (mp->external_sw_if_index));
1831   FINISH;
1832 }
1833
1834 static void
1835 send_nat44_static_mapping_details (snat_static_mapping_t * m,
1836                                    unix_shared_memory_queue_t * q,
1837                                    u32 context)
1838 {
1839   vl_api_nat44_static_mapping_details_t *rmp;
1840   snat_main_t *sm = &snat_main;
1841
1842   rmp = vl_msg_api_alloc (sizeof (*rmp));
1843   memset (rmp, 0, sizeof (*rmp));
1844   rmp->_vl_msg_id =
1845     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1846   rmp->addr_only = m->addr_only;
1847   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
1848   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
1849   rmp->local_port = htons (m->local_port);
1850   rmp->external_port = htons (m->external_port);
1851   rmp->external_sw_if_index = ~0;
1852   rmp->vrf_id = htonl (m->vrf_id);
1853   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1854   rmp->context = context;
1855
1856   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1857 }
1858
1859 static void
1860 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
1861                                        unix_shared_memory_queue_t * q,
1862                                        u32 context)
1863 {
1864   vl_api_nat44_static_mapping_details_t *rmp;
1865   snat_main_t *sm = &snat_main;
1866
1867   rmp = vl_msg_api_alloc (sizeof (*rmp));
1868   memset (rmp, 0, sizeof (*rmp));
1869   rmp->_vl_msg_id =
1870     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1871   rmp->addr_only = m->addr_only;
1872   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
1873   rmp->local_port = htons (m->l_port);
1874   rmp->external_port = htons (m->e_port);
1875   rmp->external_sw_if_index = htonl (m->sw_if_index);
1876   rmp->vrf_id = htonl (m->vrf_id);
1877   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1878   rmp->context = context;
1879
1880   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1881 }
1882
1883 static void
1884 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
1885                                             * mp)
1886 {
1887   unix_shared_memory_queue_t *q;
1888   snat_main_t *sm = &snat_main;
1889   snat_static_mapping_t *m;
1890   snat_static_map_resolve_t *rp;
1891   int j;
1892
1893   q = vl_api_client_index_to_input_queue (mp->client_index);
1894   if (q == 0)
1895     return;
1896
1897   /* *INDENT-OFF* */
1898   pool_foreach (m, sm->static_mappings,
1899   ({
1900       if (!vec_len(m->locals))
1901         send_nat44_static_mapping_details (m, q, mp->context);
1902   }));
1903   /* *INDENT-ON* */
1904
1905   for (j = 0; j < vec_len (sm->to_resolve); j++)
1906     {
1907       rp = sm->to_resolve + j;
1908       send_nat44_static_map_resolve_details (rp, q, mp->context);
1909     }
1910 }
1911
1912 static void *
1913 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
1914                                           mp, void *handle)
1915 {
1916   u8 *s;
1917
1918   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
1919
1920   FINISH;
1921 }
1922
1923 static void
1924   vl_api_nat44_add_del_interface_addr_t_handler
1925   (vl_api_nat44_add_del_interface_addr_t * mp)
1926 {
1927   snat_main_t *sm = &snat_main;
1928   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1929   u8 is_del = mp->is_add == 0;
1930   u32 sw_if_index = ntohl (mp->sw_if_index);
1931   int rv = 0;
1932
1933   VALIDATE_SW_IF_INDEX (mp);
1934
1935   rv = snat_add_interface_address (sm, sw_if_index, is_del);
1936
1937   BAD_SW_IF_INDEX_LABEL;
1938
1939   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1940 }
1941
1942 static void *vl_api_nat44_add_del_interface_addr_t_print
1943   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
1944 {
1945   u8 *s;
1946
1947   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
1948   s = format (s, "sw_if_index %d %s",
1949               clib_host_to_net_u32 (mp->sw_if_index),
1950               mp->is_add ? "" : "del");
1951
1952   FINISH;
1953 }
1954
1955 static void
1956 send_nat44_interface_addr_details (u32 sw_if_index,
1957                                    unix_shared_memory_queue_t * q,
1958                                    u32 context)
1959 {
1960   vl_api_nat44_interface_addr_details_t *rmp;
1961   snat_main_t *sm = &snat_main;
1962
1963   rmp = vl_msg_api_alloc (sizeof (*rmp));
1964   memset (rmp, 0, sizeof (*rmp));
1965   rmp->_vl_msg_id =
1966     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1967   rmp->sw_if_index = ntohl (sw_if_index);
1968   rmp->context = context;
1969
1970   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1971 }
1972
1973 static void
1974 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1975                                             * mp)
1976 {
1977   unix_shared_memory_queue_t *q;
1978   snat_main_t *sm = &snat_main;
1979   u32 *i;
1980
1981   q = vl_api_client_index_to_input_queue (mp->client_index);
1982   if (q == 0)
1983     return;
1984
1985   /* *INDENT-OFF* */
1986   vec_foreach (i, sm->auto_add_sw_if_indices)
1987     send_nat44_interface_addr_details(*i, q, mp->context);
1988   /* *INDENT-ON* */
1989 }
1990
1991 static void *
1992 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1993                                           mp, void *handle)
1994 {
1995   u8 *s;
1996
1997   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
1998
1999   FINISH;
2000 }
2001
2002 static void
2003 send_nat44_user_details (snat_user_t * u, unix_shared_memory_queue_t * q,
2004                          u32 context)
2005 {
2006   vl_api_nat44_user_details_t *rmp;
2007   snat_main_t *sm = &snat_main;
2008   fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
2009
2010   rmp = vl_msg_api_alloc (sizeof (*rmp));
2011   memset (rmp, 0, sizeof (*rmp));
2012   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
2013
2014   rmp->vrf_id = ntohl (fib->ft_table_id);
2015
2016   clib_memcpy (rmp->ip_address, &(u->addr), 4);
2017   rmp->nsessions = ntohl (u->nsessions);
2018   rmp->nstaticsessions = ntohl (u->nstaticsessions);
2019   rmp->context = context;
2020
2021   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2022 }
2023
2024 static void
2025 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
2026 {
2027   unix_shared_memory_queue_t *q;
2028   snat_main_t *sm = &snat_main;
2029   snat_main_per_thread_data_t *tsm;
2030   snat_user_t *u;
2031
2032   q = vl_api_client_index_to_input_queue (mp->client_index);
2033   if (q == 0)
2034     return;
2035
2036   /* *INDENT-OFF* */
2037   vec_foreach (tsm, sm->per_thread_data)
2038     vec_foreach (u, tsm->users)
2039       send_nat44_user_details (u, q, mp->context);
2040   /* *INDENT-ON* */
2041 }
2042
2043 static void *
2044 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
2045 {
2046   u8 *s;
2047
2048   s = format (0, "SCRIPT: nat44_user_dump ");
2049
2050   FINISH;
2051 }
2052
2053 static void
2054 send_nat44_user_session_details (snat_session_t * s,
2055                                  unix_shared_memory_queue_t * q, u32 context)
2056 {
2057   vl_api_nat44_user_session_details_t *rmp;
2058   snat_main_t *sm = &snat_main;
2059
2060   rmp = vl_msg_api_alloc (sizeof (*rmp));
2061   memset (rmp, 0, sizeof (*rmp));
2062   rmp->_vl_msg_id =
2063     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
2064   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
2065   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
2066   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
2067   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
2068   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
2069   rmp->total_pkts = ntohl (s->total_pkts);
2070   rmp->context = context;
2071   if (snat_is_unk_proto_session (s))
2072     {
2073       rmp->outside_port = 0;
2074       rmp->inside_port = 0;
2075       rmp->protocol = ntohs (s->in2out.port);
2076     }
2077   else
2078     {
2079       rmp->outside_port = s->out2in.port;
2080       rmp->inside_port = s->in2out.port;
2081       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
2082     }
2083
2084   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2085 }
2086
2087 static void
2088 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
2089                                           mp)
2090 {
2091   unix_shared_memory_queue_t *q;
2092   snat_main_t *sm = &snat_main;
2093   snat_main_per_thread_data_t *tsm;
2094   snat_session_t *s;
2095   clib_bihash_kv_8_8_t key, value;
2096   snat_user_key_t ukey;
2097   snat_user_t *u;
2098   u32 session_index, head_index, elt_index;
2099   dlist_elt_t *head, *elt;
2100   ip4_header_t ip;
2101
2102   q = vl_api_client_index_to_input_queue (mp->client_index);
2103   if (q == 0)
2104     return;
2105
2106   clib_memcpy (&ukey.addr, mp->ip_address, 4);
2107   ip.src_address.as_u32 = ukey.addr.as_u32;
2108   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
2109   key.key = ukey.as_u64;
2110   if (sm->num_workers)
2111     tsm =
2112       vec_elt_at_index (sm->per_thread_data,
2113                         sm->worker_in2out_cb (&ip, ukey.fib_index));
2114   else
2115     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
2116   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
2117     return;
2118   u = pool_elt_at_index (tsm->users, value.value);
2119   if (!u->nsessions && !u->nstaticsessions)
2120     return;
2121
2122   head_index = u->sessions_per_user_list_head_index;
2123   head = pool_elt_at_index (tsm->list_pool, head_index);
2124   elt_index = head->next;
2125   elt = pool_elt_at_index (tsm->list_pool, elt_index);
2126   session_index = elt->value;
2127   while (session_index != ~0)
2128     {
2129       s = pool_elt_at_index (tsm->sessions, session_index);
2130
2131       send_nat44_user_session_details (s, q, mp->context);
2132
2133       elt_index = elt->next;
2134       elt = pool_elt_at_index (tsm->list_pool, elt_index);
2135       session_index = elt->value;
2136     }
2137 }
2138
2139 static void *
2140 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
2141                                         void *handle)
2142 {
2143   u8 *s;
2144
2145   s = format (0, "SCRIPT: nat44_user_session_dump ");
2146   s = format (s, "ip_address %U vrf_id %d\n",
2147               format_ip4_address, mp->ip_address,
2148               clib_net_to_host_u32 (mp->vrf_id));
2149
2150   FINISH;
2151 }
2152
2153 static nat44_lb_addr_port_t *
2154 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
2155                              u8 addr_port_pair_num)
2156 {
2157   u8 i;
2158   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
2159   vl_api_nat44_lb_addr_port_t *ap;
2160
2161   for (i = 0; i < addr_port_pair_num; i++)
2162     {
2163       ap = &addr_port_pairs[i];
2164       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
2165       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
2166       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
2167       lb_addr_port.probability = ap->probability;
2168       vec_add1 (lb_addr_port_pairs, lb_addr_port);
2169     }
2170
2171   return lb_addr_port_pairs;
2172 }
2173
2174 static void
2175   vl_api_nat44_add_del_lb_static_mapping_t_handler
2176   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
2177 {
2178   snat_main_t *sm = &snat_main;
2179   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
2180   int rv = 0;
2181   nat44_lb_addr_port_t *locals = 0;
2182   ip4_address_t e_addr;
2183   snat_protocol_t proto;
2184
2185   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
2186   clib_memcpy (&e_addr, mp->external_addr, 4);
2187   proto = ip_proto_to_snat_proto (mp->protocol);
2188
2189   rv =
2190     nat44_add_del_lb_static_mapping (e_addr,
2191                                      clib_net_to_host_u16 (mp->external_port),
2192                                      proto, clib_net_to_host_u32 (mp->vrf_id),
2193                                      locals, mp->is_add);
2194
2195   vec_free (locals);
2196
2197   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
2198 }
2199
2200 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
2201   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
2202 {
2203   u8 *s;
2204
2205   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
2206   s = format (s, "is_add %d\n", mp->is_add);
2207
2208   FINISH;
2209 }
2210
2211 static void
2212 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
2213                                       unix_shared_memory_queue_t * q,
2214                                       u32 context)
2215 {
2216   vl_api_nat44_lb_static_mapping_details_t *rmp;
2217   snat_main_t *sm = &snat_main;
2218   nat44_lb_addr_port_t *ap;
2219   vl_api_nat44_lb_addr_port_t *locals;
2220
2221   rmp =
2222     vl_msg_api_alloc (sizeof (*rmp) +
2223                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
2224   memset (rmp, 0, sizeof (*rmp));
2225   rmp->_vl_msg_id =
2226     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
2227
2228   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
2229   rmp->external_port = ntohs (m->external_port);
2230   rmp->protocol = snat_proto_to_ip_proto (m->proto);
2231   rmp->vrf_id = ntohl (m->vrf_id);
2232   rmp->context = context;
2233
2234   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
2235   vec_foreach (ap, m->locals)
2236   {
2237     clib_memcpy (locals->addr, &(ap->addr), 4);
2238     locals->port = htons (ap->port);
2239     locals->probability = ap->probability;
2240     locals++;
2241     rmp->local_num++;
2242   }
2243
2244   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2245 }
2246
2247 static void
2248   vl_api_nat44_lb_static_mapping_dump_t_handler
2249   (vl_api_nat44_lb_static_mapping_dump_t * mp)
2250 {
2251   unix_shared_memory_queue_t *q;
2252   snat_main_t *sm = &snat_main;
2253   snat_static_mapping_t *m;
2254
2255   q = vl_api_client_index_to_input_queue (mp->client_index);
2256   if (q == 0)
2257     return;
2258
2259   /* *INDENT-OFF* */
2260   pool_foreach (m, sm->static_mappings,
2261   ({
2262       if (vec_len(m->locals))
2263         send_nat44_lb_static_mapping_details (m, q, mp->context);
2264   }));
2265   /* *INDENT-ON* */
2266 }
2267
2268 static void *vl_api_nat44_lb_static_mapping_dump_t_print
2269   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
2270 {
2271   u8 *s;
2272
2273   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
2274
2275   FINISH;
2276 }
2277
2278 /*******************************/
2279 /*** Deterministic NAT (CGN) ***/
2280 /*******************************/
2281
2282 static void
2283 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
2284 {
2285   snat_main_t *sm = &snat_main;
2286   vl_api_nat_det_add_del_map_reply_t *rmp;
2287   int rv = 0;
2288   ip4_address_t in_addr, out_addr;
2289
2290   if (!mp->is_nat44)
2291     {
2292       rv = VNET_API_ERROR_UNIMPLEMENTED;
2293       goto send_reply;
2294     }
2295
2296   clib_memcpy (&in_addr, mp->in_addr, 4);
2297   clib_memcpy (&out_addr, mp->out_addr, 4);
2298   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
2299                          mp->out_plen, mp->is_add);
2300
2301 send_reply:
2302   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
2303 }
2304
2305 static void *
2306 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
2307                                     void *handle)
2308 {
2309   u8 *s;
2310
2311   s = format (0, "SCRIPT: nat_det_add_del_map ");
2312   s = format (s, "inside address %U/%d outside address %U/%d\n",
2313               format_ip4_address, mp->in_addr, mp->in_plen,
2314               format_ip4_address, mp->out_addr, mp->out_plen);
2315
2316   FINISH;
2317 }
2318
2319 static void
2320 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
2321 {
2322   snat_main_t *sm = &snat_main;
2323   vl_api_nat_det_forward_reply_t *rmp;
2324   int rv = 0;
2325   u16 lo_port = 0, hi_port = 0;
2326   snat_det_map_t *dm;
2327   ip4_address_t in_addr, out_addr;
2328
2329   if (!mp->is_nat44)
2330     {
2331       out_addr.as_u32 = 0;
2332       rv = VNET_API_ERROR_UNIMPLEMENTED;
2333       goto send_reply;
2334     }
2335
2336   out_addr.as_u32 = 0;
2337   clib_memcpy (&in_addr, mp->in_addr, 4);
2338   dm = snat_det_map_by_user (sm, &in_addr);
2339   if (!dm)
2340     {
2341       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2342       goto send_reply;
2343     }
2344
2345   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
2346   hi_port = lo_port + dm->ports_per_host - 1;
2347
2348 send_reply:
2349   /* *INDENT-OFF* */
2350   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
2351   ({
2352     rmp->out_port_lo = ntohs (lo_port);
2353     rmp->out_port_hi = ntohs (hi_port);
2354     clib_memcpy (rmp->out_addr, &out_addr, 4);
2355   }))
2356   /* *INDENT-ON* */
2357 }
2358
2359 static void *
2360 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
2361 {
2362   u8 *s;
2363
2364   s = format (0, "SCRIPT: nat_det_forward");
2365   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
2366
2367   FINISH;
2368 }
2369
2370 static void
2371 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
2372 {
2373   snat_main_t *sm = &snat_main;
2374   vl_api_nat_det_reverse_reply_t *rmp;
2375   int rv = 0;
2376   ip4_address_t out_addr, in_addr;
2377   snat_det_map_t *dm;
2378
2379   in_addr.as_u32 = 0;
2380   clib_memcpy (&out_addr, mp->out_addr, 4);
2381   dm = snat_det_map_by_out (sm, &out_addr);
2382   if (!dm)
2383     {
2384       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2385       goto send_reply;
2386     }
2387
2388   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
2389
2390 send_reply:
2391   /* *INDENT-OFF* */
2392   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
2393   ({
2394     rmp->is_nat44 = 1;
2395     memset (rmp->in_addr, 0, 16);
2396     clib_memcpy (rmp->in_addr, &in_addr, 4);
2397   }))
2398   /* *INDENT-ON* */
2399 }
2400
2401 static void *
2402 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
2403 {
2404   u8 *s;
2405
2406   s = format (0, "SCRIPT: nat_det_reverse");
2407   s = format (s, "outside ip address %U outside port %d",
2408               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
2409
2410   FINISH;
2411 }
2412
2413 static void
2414 sent_nat_det_map_details (snat_det_map_t * m, unix_shared_memory_queue_t * q,
2415                           u32 context)
2416 {
2417   vl_api_nat_det_map_details_t *rmp;
2418   snat_main_t *sm = &snat_main;
2419
2420   rmp = vl_msg_api_alloc (sizeof (*rmp));
2421   memset (rmp, 0, sizeof (*rmp));
2422   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
2423   rmp->is_nat44 = 1;
2424   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
2425   rmp->in_plen = m->in_plen;
2426   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
2427   rmp->out_plen = m->out_plen;
2428   rmp->sharing_ratio = htonl (m->sharing_ratio);
2429   rmp->ports_per_host = htons (m->ports_per_host);
2430   rmp->ses_num = htonl (m->ses_num);
2431   rmp->context = context;
2432
2433   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2434 }
2435
2436 static void
2437 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
2438 {
2439   unix_shared_memory_queue_t *q;
2440   snat_main_t *sm = &snat_main;
2441   snat_det_map_t *m;
2442
2443   q = vl_api_client_index_to_input_queue (mp->client_index);
2444   if (q == 0)
2445     return;
2446
2447   /* *INDENT-OFF* */
2448   vec_foreach(m, sm->det_maps)
2449     sent_nat_det_map_details(m, q, mp->context);
2450   /* *INDENT-ON* */
2451 }
2452
2453 static void *
2454 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
2455 {
2456   u8 *s;
2457
2458   s = format (0, "SCRIPT: nat_det_map_dump ");
2459
2460   FINISH;
2461 }
2462
2463 static void
2464 vl_api_nat_det_set_timeouts_t_handler (vl_api_nat_det_set_timeouts_t * mp)
2465 {
2466   snat_main_t *sm = &snat_main;
2467   vl_api_nat_det_set_timeouts_reply_t *rmp;
2468   int rv = 0;
2469
2470   sm->udp_timeout = ntohl (mp->udp);
2471   sm->tcp_established_timeout = ntohl (mp->tcp_established);
2472   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
2473   sm->icmp_timeout = ntohl (mp->icmp);
2474
2475   REPLY_MACRO (VL_API_NAT_DET_SET_TIMEOUTS_REPLY);
2476 }
2477
2478 static void *
2479 vl_api_nat_det_set_timeouts_t_print (vl_api_nat_det_set_timeouts_t * mp,
2480                                      void *handle)
2481 {
2482   u8 *s;
2483
2484   s = format (0, "SCRIPT: nat_det_set_timeouts ");
2485   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
2486               ntohl (mp->udp),
2487               ntohl (mp->tcp_established),
2488               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
2489
2490   FINISH;
2491 }
2492
2493 static void
2494 vl_api_nat_det_get_timeouts_t_handler (vl_api_nat_det_get_timeouts_t * mp)
2495 {
2496   snat_main_t *sm = &snat_main;
2497   vl_api_nat_det_get_timeouts_reply_t *rmp;
2498   int rv = 0;
2499
2500   /* *INDENT-OFF* */
2501   REPLY_MACRO2 (VL_API_NAT_DET_GET_TIMEOUTS_REPLY,
2502   ({
2503     rmp->udp = htonl (sm->udp_timeout);
2504     rmp->tcp_established = htonl (sm->tcp_established_timeout);
2505     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
2506     rmp->icmp = htonl (sm->icmp_timeout);
2507   }))
2508   /* *INDENT-ON* */
2509 }
2510
2511 static void *
2512 vl_api_nat_det_get_timeouts_t_print (vl_api_nat_det_get_timeouts_t * mp,
2513                                      void *handle)
2514 {
2515   u8 *s;
2516
2517   s = format (0, "SCRIPT: nat_det_get_timeouts");
2518
2519   FINISH;
2520 }
2521
2522 static void
2523 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
2524                                             * mp)
2525 {
2526   snat_main_t *sm = &snat_main;
2527   vl_api_nat_det_close_session_out_reply_t *rmp;
2528   ip4_address_t out_addr, ext_addr, in_addr;
2529   snat_det_out_key_t key;
2530   snat_det_map_t *dm;
2531   snat_det_session_t *ses;
2532   int rv = 0;
2533
2534   clib_memcpy (&out_addr, mp->out_addr, 4);
2535   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2536
2537   dm = snat_det_map_by_out (sm, &out_addr);
2538   if (!dm)
2539     {
2540       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2541       goto send_reply;
2542     }
2543   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
2544   key.ext_host_addr = ext_addr;
2545   key.ext_host_port = mp->ext_port;
2546   key.out_port = mp->out_port;
2547   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
2548   if (!ses)
2549     {
2550       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2551       goto send_reply;
2552     }
2553   snat_det_ses_close (dm, ses);
2554
2555 send_reply:
2556   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2557 }
2558
2559 static void *
2560 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
2561                                           mp, void *handle)
2562 {
2563   u8 *s;
2564
2565   s = format (0, "SCRIPT: nat_det_close_session_out ");
2566   s = format (s, "out_addr %U out_port %d "
2567               "ext_addr %U ext_port %d\n",
2568               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
2569               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2570
2571   FINISH;
2572 }
2573
2574 static void
2575 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
2576                                            mp)
2577 {
2578   snat_main_t *sm = &snat_main;
2579   vl_api_nat_det_close_session_in_reply_t *rmp;
2580   ip4_address_t in_addr, ext_addr;
2581   snat_det_out_key_t key;
2582   snat_det_map_t *dm;
2583   snat_det_session_t *ses;
2584   int rv = 0;
2585
2586   if (!mp->is_nat44)
2587     {
2588       rv = VNET_API_ERROR_UNIMPLEMENTED;
2589       goto send_reply;
2590     }
2591
2592   clib_memcpy (&in_addr, mp->in_addr, 4);
2593   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2594
2595   dm = snat_det_map_by_user (sm, &in_addr);
2596   if (!dm)
2597     {
2598       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2599       goto send_reply;
2600     }
2601   key.ext_host_addr = ext_addr;
2602   key.ext_host_port = mp->ext_port;
2603   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
2604   if (!ses)
2605     {
2606       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2607       goto send_reply;
2608     }
2609   snat_det_ses_close (dm, ses);
2610
2611 send_reply:
2612   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2613 }
2614
2615 static void *
2616 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2617                                          mp, void *handle)
2618 {
2619   u8 *s;
2620   s = format (0, "SCRIPT: nat_det_close_session_in ");
2621   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2622               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2623               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2624
2625   FINISH;
2626 }
2627
2628 static void
2629 send_nat_det_session_details (snat_det_session_t * s,
2630                               unix_shared_memory_queue_t * q, u32 context)
2631 {
2632   vl_api_nat_det_session_details_t *rmp;
2633   snat_main_t *sm = &snat_main;
2634
2635   rmp = vl_msg_api_alloc (sizeof (*rmp));
2636   memset (rmp, 0, sizeof (*rmp));
2637   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2638   rmp->in_port = s->in_port;
2639   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2640   rmp->ext_port = s->out.ext_host_port;
2641   rmp->out_port = s->out.out_port;
2642   rmp->state = s->state;
2643   rmp->expire = ntohl (s->expire);
2644   rmp->context = context;
2645
2646   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2647 }
2648
2649 static void
2650 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2651 {
2652   unix_shared_memory_queue_t *q;
2653   snat_main_t *sm = &snat_main;
2654   ip4_address_t user_addr;
2655   snat_det_map_t *dm;
2656   snat_det_session_t *s, empty_ses;
2657   u16 i;
2658
2659   q = vl_api_client_index_to_input_queue (mp->client_index);
2660   if (q == 0)
2661     return;
2662   if (!mp->is_nat44)
2663     return;
2664
2665   memset (&empty_ses, 0, sizeof (empty_ses));
2666   clib_memcpy (&user_addr, mp->user_addr, 4);
2667   dm = snat_det_map_by_user (sm, &user_addr);
2668   if (!dm)
2669     return;
2670
2671   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2672   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2673     {
2674       if (s->out.as_u64)
2675         send_nat_det_session_details (s, q, mp->context);
2676       s++;
2677     }
2678 }
2679
2680 static void *
2681 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2682                                      void *handle)
2683 {
2684   u8 *s;
2685
2686   s = format (0, "SCRIPT: nat_det_session_dump ");
2687   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2688
2689   FINISH;
2690 }
2691
2692 /*************/
2693 /*** NAT64 ***/
2694 /*************/
2695
2696 static void
2697   vl_api_nat64_add_del_pool_addr_range_t_handler
2698   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2699 {
2700   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2701   snat_main_t *sm = &snat_main;
2702   nat64_main_t *nm = &nat64_main;
2703   int rv = 0;
2704   ip4_address_t this_addr;
2705   u32 start_host_order, end_host_order;
2706   u32 vrf_id;
2707   int i, count;
2708   u32 *tmp;
2709
2710   if (nm->is_disabled)
2711     {
2712       rv = VNET_API_ERROR_FEATURE_DISABLED;
2713       goto send_reply;
2714     }
2715
2716   tmp = (u32 *) mp->start_addr;
2717   start_host_order = clib_host_to_net_u32 (tmp[0]);
2718   tmp = (u32 *) mp->end_addr;
2719   end_host_order = clib_host_to_net_u32 (tmp[0]);
2720
2721   count = (end_host_order - start_host_order) + 1;
2722
2723   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2724
2725   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2726
2727   for (i = 0; i < count; i++)
2728     {
2729       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
2730         goto send_reply;
2731
2732       increment_v4_address (&this_addr);
2733     }
2734
2735 send_reply:
2736   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2737 }
2738
2739 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2740   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2741 {
2742   u8 *s;
2743
2744   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2745   s = format (s, "%U - %U vrf_id %u %s\n",
2746               format_ip4_address, mp->start_addr,
2747               format_ip4_address, mp->end_addr,
2748               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2749
2750   FINISH;
2751 }
2752
2753 typedef struct nat64_api_walk_ctx_t_
2754 {
2755   unix_shared_memory_queue_t *q;
2756   u32 context;
2757 } nat64_api_walk_ctx_t;
2758
2759 static int
2760 nat64_api_pool_walk (snat_address_t * a, void *arg)
2761 {
2762   vl_api_nat64_pool_addr_details_t *rmp;
2763   snat_main_t *sm = &snat_main;
2764   nat64_api_walk_ctx_t *ctx = arg;
2765
2766   rmp = vl_msg_api_alloc (sizeof (*rmp));
2767   memset (rmp, 0, sizeof (*rmp));
2768   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2769   clib_memcpy (rmp->address, &(a->addr), 4);
2770   if (a->fib_index != ~0)
2771     {
2772       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2773       if (!fib)
2774         return -1;
2775       rmp->vrf_id = ntohl (fib->ft_table_id);
2776     }
2777   else
2778     rmp->vrf_id = ~0;
2779   rmp->context = ctx->context;
2780
2781   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2782
2783   return 0;
2784 }
2785
2786 static void
2787 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2788 {
2789   unix_shared_memory_queue_t *q;
2790   nat64_main_t *nm = &nat64_main;
2791
2792   if (nm->is_disabled)
2793     return;
2794
2795   q = vl_api_client_index_to_input_queue (mp->client_index);
2796   if (q == 0)
2797     return;
2798
2799   nat64_api_walk_ctx_t ctx = {
2800     .q = q,
2801     .context = mp->context,
2802   };
2803
2804   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2805 }
2806
2807 static void *
2808 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2809                                      void *handle)
2810 {
2811   u8 *s;
2812
2813   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2814
2815   FINISH;
2816 }
2817
2818 static void
2819 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2820                                           mp)
2821 {
2822   snat_main_t *sm = &snat_main;
2823   nat64_main_t *nm = &nat64_main;
2824   vl_api_nat64_add_del_interface_reply_t *rmp;
2825   int rv = 0;
2826
2827   if (nm->is_disabled)
2828     {
2829       rv = VNET_API_ERROR_FEATURE_DISABLED;
2830       goto send_reply;
2831     }
2832
2833   VALIDATE_SW_IF_INDEX (mp);
2834
2835   rv =
2836     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
2837                              mp->is_add);
2838
2839   BAD_SW_IF_INDEX_LABEL;
2840
2841 send_reply:
2842   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2843 }
2844
2845 static void *
2846 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2847                                         void *handle)
2848 {
2849   u8 *s;
2850
2851   s = format (0, "SCRIPT: nat64_add_del_interface ");
2852   s = format (s, "sw_if_index %d %s %s",
2853               clib_host_to_net_u32 (mp->sw_if_index),
2854               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2855
2856   FINISH;
2857 }
2858
2859 static int
2860 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2861 {
2862   vl_api_nat64_interface_details_t *rmp;
2863   snat_main_t *sm = &snat_main;
2864   nat64_api_walk_ctx_t *ctx = arg;
2865
2866   rmp = vl_msg_api_alloc (sizeof (*rmp));
2867   memset (rmp, 0, sizeof (*rmp));
2868   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2869   rmp->sw_if_index = ntohl (i->sw_if_index);
2870   rmp->is_inside = i->is_inside;
2871   rmp->context = ctx->context;
2872
2873   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2874
2875   return 0;
2876 }
2877
2878 static void
2879 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2880 {
2881   unix_shared_memory_queue_t *q;
2882   nat64_main_t *nm = &nat64_main;
2883
2884   if (nm->is_disabled)
2885     return;
2886
2887   q = vl_api_client_index_to_input_queue (mp->client_index);
2888   if (q == 0)
2889     return;
2890
2891   nat64_api_walk_ctx_t ctx = {
2892     .q = q,
2893     .context = mp->context,
2894   };
2895
2896   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2897 }
2898
2899 static void *
2900 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2901                                      void *handle)
2902 {
2903   u8 *s;
2904
2905   s = format (0, "SCRIPT: snat_interface_dump ");
2906
2907   FINISH;
2908 }
2909
2910 static void
2911   vl_api_nat64_add_del_static_bib_t_handler
2912   (vl_api_nat64_add_del_static_bib_t * mp)
2913 {
2914   snat_main_t *sm = &snat_main;
2915   nat64_main_t *nm = &nat64_main;
2916   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2917   ip6_address_t in_addr;
2918   ip4_address_t out_addr;
2919   int rv = 0;
2920
2921   if (nm->is_disabled)
2922     {
2923       rv = VNET_API_ERROR_FEATURE_DISABLED;
2924       goto send_reply;
2925     }
2926
2927   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2928   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2929
2930   rv =
2931     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2932                                     clib_net_to_host_u16 (mp->i_port),
2933                                     clib_net_to_host_u16 (mp->o_port),
2934                                     mp->proto,
2935                                     clib_net_to_host_u32 (mp->vrf_id),
2936                                     mp->is_add);
2937
2938 send_reply:
2939   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2940 }
2941
2942 static void *vl_api_nat64_add_del_static_bib_t_print
2943   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2944 {
2945   u8 *s;
2946
2947   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2948   s = format (s, "protocol %d i_addr %U o_addr %U ",
2949               mp->proto,
2950               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2951
2952   if (mp->vrf_id != ~0)
2953     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2954
2955   FINISH;
2956 }
2957
2958 static int
2959 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2960 {
2961   vl_api_nat64_bib_details_t *rmp;
2962   snat_main_t *sm = &snat_main;
2963   nat64_api_walk_ctx_t *ctx = arg;
2964   fib_table_t *fib;
2965
2966   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2967   if (!fib)
2968     return -1;
2969
2970   rmp = vl_msg_api_alloc (sizeof (*rmp));
2971   memset (rmp, 0, sizeof (*rmp));
2972   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2973   rmp->context = ctx->context;
2974   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2975   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2976   rmp->i_port = bibe->in_port;
2977   rmp->o_port = bibe->out_port;
2978   rmp->vrf_id = ntohl (fib->ft_table_id);
2979   rmp->proto = bibe->proto;
2980   rmp->is_static = bibe->is_static;
2981   rmp->ses_num = ntohl (bibe->ses_num);
2982
2983   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2984
2985   return 0;
2986 }
2987
2988 static void
2989 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2990 {
2991   unix_shared_memory_queue_t *q;
2992   nat64_main_t *nm = &nat64_main;
2993
2994   if (nm->is_disabled)
2995     return;
2996
2997   q = vl_api_client_index_to_input_queue (mp->client_index);
2998   if (q == 0)
2999     return;
3000
3001   nat64_api_walk_ctx_t ctx = {
3002     .q = q,
3003     .context = mp->context,
3004   };
3005
3006   nat64_db_bib_walk (&nm->db, mp->proto, nat64_api_bib_walk, &ctx);
3007 }
3008
3009 static void *
3010 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
3011 {
3012   u8 *s;
3013
3014   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
3015
3016   FINISH;
3017 }
3018
3019 static void
3020 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
3021 {
3022   snat_main_t *sm = &snat_main;
3023   nat64_main_t *nm = &nat64_main;
3024   vl_api_nat64_set_timeouts_reply_t *rmp;
3025   int rv = 0;
3026
3027   if (nm->is_disabled)
3028     {
3029       rv = VNET_API_ERROR_FEATURE_DISABLED;
3030       goto send_reply;
3031     }
3032
3033   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
3034   if (rv)
3035     goto send_reply;
3036   rv = nat64_set_udp_timeout (ntohl (mp->udp));
3037   if (rv)
3038     goto send_reply;
3039   rv =
3040     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
3041                             ntohl (mp->tcp_incoming_syn));
3042
3043 send_reply:
3044   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
3045 }
3046
3047 static void *vl_api_nat64_set_timeouts_t_print
3048   (vl_api_nat64_set_timeouts_t * mp, void *handle)
3049 {
3050   u8 *s;
3051
3052   s = format (0, "SCRIPT: nat64_set_timeouts ");
3053   s =
3054     format (s,
3055             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
3056             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
3057             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
3058
3059   FINISH;
3060 }
3061
3062 static void
3063 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
3064 {
3065   snat_main_t *sm = &snat_main;
3066   nat64_main_t *nm = &nat64_main;
3067   vl_api_nat64_get_timeouts_reply_t *rmp;
3068   int rv = 0;
3069
3070   if (nm->is_disabled)
3071     return;
3072
3073   /* *INDENT-OFF* */
3074   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
3075   ({
3076     rmp->udp = htonl (nat64_get_udp_timeout());
3077     rmp->icmp = htonl (nat64_get_icmp_timeout());
3078     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
3079     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
3080     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
3081   }))
3082   /* *INDENT-ON* */
3083 }
3084
3085 static void *vl_api_nat64_get_timeouts_t_print
3086   (vl_api_nat64_get_timeouts_t * mp, void *handle)
3087 {
3088   u8 *s;
3089
3090   s = format (0, "SCRIPT: nat64_get_timeouts");
3091
3092   FINISH;
3093 }
3094
3095 static int
3096 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
3097 {
3098   vl_api_nat64_st_details_t *rmp;
3099   snat_main_t *sm = &snat_main;
3100   nat64_api_walk_ctx_t *ctx = arg;
3101   nat64_main_t *nm = &nat64_main;
3102   nat64_db_bib_entry_t *bibe;
3103   fib_table_t *fib;
3104
3105   bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
3106   if (!bibe)
3107     return -1;
3108
3109   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
3110   if (!fib)
3111     return -1;
3112
3113   rmp = vl_msg_api_alloc (sizeof (*rmp));
3114   memset (rmp, 0, sizeof (*rmp));
3115   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
3116   rmp->context = ctx->context;
3117   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
3118   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
3119   rmp->il_port = bibe->in_port;
3120   rmp->ol_port = bibe->out_port;
3121   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
3122   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
3123   rmp->il_port = ste->r_port;
3124   rmp->vrf_id = ntohl (fib->ft_table_id);
3125   rmp->proto = ste->proto;
3126
3127   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3128
3129   return 0;
3130 }
3131
3132 static void
3133 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
3134 {
3135   unix_shared_memory_queue_t *q;
3136   nat64_main_t *nm = &nat64_main;
3137
3138   if (nm->is_disabled)
3139     return;
3140
3141   q = vl_api_client_index_to_input_queue (mp->client_index);
3142   if (q == 0)
3143     return;
3144
3145   nat64_api_walk_ctx_t ctx = {
3146     .q = q,
3147     .context = mp->context,
3148   };
3149
3150   nat64_db_st_walk (&nm->db, mp->proto, nat64_api_st_walk, &ctx);
3151 }
3152
3153 static void *
3154 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
3155 {
3156   u8 *s;
3157
3158   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
3159
3160   FINISH;
3161 }
3162
3163 static void
3164 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
3165 {
3166   vl_api_nat64_add_del_prefix_reply_t *rmp;
3167   snat_main_t *sm = &snat_main;
3168   nat64_main_t *nm = &nat64_main;
3169   ip6_address_t prefix;
3170   int rv = 0;
3171
3172   if (nm->is_disabled)
3173     {
3174       rv = VNET_API_ERROR_FEATURE_DISABLED;
3175       goto send_reply;
3176     }
3177
3178   memcpy (&prefix.as_u8, mp->prefix, 16);
3179
3180   rv =
3181     nat64_add_del_prefix (&prefix, mp->prefix_len,
3182                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
3183 send_reply:
3184   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
3185 }
3186
3187 static void *
3188 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
3189                                      void *handle)
3190 {
3191   u8 *s;
3192
3193   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
3194               format_ip6_address, mp->prefix, mp->prefix_len,
3195               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
3196
3197   FINISH;
3198 }
3199
3200 static int
3201 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
3202 {
3203   vl_api_nat64_prefix_details_t *rmp;
3204   snat_main_t *sm = &snat_main;
3205   nat64_api_walk_ctx_t *ctx = arg;
3206
3207   rmp = vl_msg_api_alloc (sizeof (*rmp));
3208   memset (rmp, 0, sizeof (*rmp));
3209   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
3210   clib_memcpy (rmp->prefix, &(p->prefix), 16);
3211   rmp->prefix_len = p->plen;
3212   rmp->vrf_id = ntohl (p->vrf_id);
3213   rmp->context = ctx->context;
3214
3215   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3216
3217   return 0;
3218 }
3219
3220 static void
3221 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
3222 {
3223   unix_shared_memory_queue_t *q;
3224   nat64_main_t *nm = &nat64_main;
3225
3226   if (nm->is_disabled)
3227     return;
3228
3229   q = vl_api_client_index_to_input_queue (mp->client_index);
3230   if (q == 0)
3231     return;
3232
3233   nat64_api_walk_ctx_t ctx = {
3234     .q = q,
3235     .context = mp->context,
3236   };
3237
3238   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
3239 }
3240
3241 static void *
3242 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
3243                                   void *handle)
3244 {
3245   u8 *s;
3246
3247   s = format (0, "SCRIPT: nat64_prefix_dump\n");
3248
3249   FINISH;
3250 }
3251
3252 /* List of message types that this plugin understands */
3253 #define foreach_snat_plugin_api_msg                                     \
3254 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range)                       \
3255 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature)       \
3256 _(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping)                     \
3257 _(SNAT_CONTROL_PING, snat_control_ping)                                 \
3258 _(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump)                   \
3259 _(SNAT_SHOW_CONFIG, snat_show_config)                                   \
3260 _(SNAT_ADDRESS_DUMP, snat_address_dump)                                 \
3261 _(SNAT_INTERFACE_DUMP, snat_interface_dump)                             \
3262 _(SNAT_SET_WORKERS, snat_set_workers)                                   \
3263 _(SNAT_WORKER_DUMP, snat_worker_dump)                                   \
3264 _(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr)             \
3265 _(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump)                   \
3266 _(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable)                 \
3267 _(SNAT_USER_DUMP, snat_user_dump)                                       \
3268 _(SNAT_USER_SESSION_DUMP, snat_user_session_dump)                       \
3269 _(SNAT_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                                \
3270   snat_interface_add_del_output_feature)                                \
3271 _(SNAT_INTERFACE_OUTPUT_FEATURE_DUMP,                                   \
3272   snat_interface_output_feature_dump)                                   \
3273 _(SNAT_ADD_DET_MAP, snat_add_det_map)                                   \
3274 _(SNAT_DET_FORWARD, snat_det_forward)                                   \
3275 _(SNAT_DET_REVERSE, snat_det_reverse)                                   \
3276 _(SNAT_DET_MAP_DUMP, snat_det_map_dump)                                 \
3277 _(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts)                         \
3278 _(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts)                         \
3279 _(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out)               \
3280 _(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in)                 \
3281 _(SNAT_DET_SESSION_DUMP, snat_det_session_dump)                         \
3282 _(NAT_CONTROL_PING, nat_control_ping)                                   \
3283 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
3284 _(NAT_SET_WORKERS, nat_set_workers)                                     \
3285 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
3286 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
3287 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
3288 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
3289 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
3290 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3291 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3292 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3293 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3294 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3295 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3296 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3297 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3298   nat44_interface_add_del_output_feature)                               \
3299 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3300   nat44_interface_output_feature_dump)                                  \
3301 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3302 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3303 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3304 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3305 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3306 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3307 _(NAT_DET_SET_TIMEOUTS, nat_det_set_timeouts)                           \
3308 _(NAT_DET_GET_TIMEOUTS, nat_det_get_timeouts)                           \
3309 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3310 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3311 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3312 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3313 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3314 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3315 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3316 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3317 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3318 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
3319 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
3320 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3321 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3322 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)
3323
3324 /* Set up the API message handling tables */
3325 static clib_error_t *
3326 snat_plugin_api_hookup (vlib_main_t * vm)
3327 {
3328   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3329 #define _(N,n)                                                  \
3330     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3331                            #n,                                  \
3332                            vl_api_##n##_t_handler,              \
3333                            vl_noop_handler,                     \
3334                            vl_api_##n##_t_endian,               \
3335                            vl_api_##n##_t_print,                \
3336                            sizeof(vl_api_##n##_t), 1);
3337   foreach_snat_plugin_api_msg;
3338 #undef _
3339
3340   return 0;
3341 }
3342
3343 #define vl_msg_name_crc_list
3344 #include <nat/nat_all_api_h.h>
3345 #undef vl_msg_name_crc_list
3346
3347 static void
3348 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3349 {
3350 #define _(id,n,crc) \
3351   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3352   foreach_vl_msg_name_crc_nat;
3353 #undef _
3354 }
3355
3356 static void
3357 plugin_custom_dump_configure (snat_main_t * sm)
3358 {
3359 #define _(n,f) sm->api_main->msg_print_handlers \
3360   [VL_API_##n + sm->msg_id_base]                \
3361     = (void *) vl_api_##f##_t_print;
3362   foreach_snat_plugin_api_msg;
3363 #undef _
3364 }
3365
3366 clib_error_t *
3367 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3368 {
3369   u8 *name;
3370   clib_error_t *error = 0;
3371
3372   name = format (0, "snat_%08x%c", api_version, 0);
3373
3374   /* Ask for a correctly-sized block of API message decode slots */
3375   sm->msg_id_base =
3376     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3377
3378   error = snat_plugin_api_hookup (vm);
3379
3380   /* Add our API messages to the global name_crc hash table */
3381   setup_message_id_table (sm, sm->api_main);
3382
3383   plugin_custom_dump_configure (sm);
3384
3385   vec_free (name);
3386
3387   return error;
3388 }
3389
3390 /*
3391  * fd.io coding-style-patch-verification: ON
3392  *
3393  * Local Variables:
3394  * eval: (c-set-style "gnu")
3395  * End:
3396  */