NAT: delete session API/CLI (VPP-1041)
[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
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 = nat_interface_is_inside (i);
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 = nat_interface_is_inside (i);
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 = (nat_interface_is_inside (i)
1662                     && nat_interface_is_outside (i)) ? 2 :
1663     nat_interface_is_inside (i);
1664   rmp->context = context;
1665
1666   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1667 }
1668
1669 static void
1670 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
1671 {
1672   unix_shared_memory_queue_t *q;
1673   snat_main_t *sm = &snat_main;
1674   snat_interface_t *i;
1675
1676   q = vl_api_client_index_to_input_queue (mp->client_index);
1677   if (q == 0)
1678     return;
1679
1680   /* *INDENT-OFF* */
1681   pool_foreach (i, sm->interfaces,
1682   ({
1683     send_nat44_interface_details(i, q, mp->context);
1684   }));
1685   /* *INDENT-ON* */
1686 }
1687
1688 static void *
1689 vl_api_nat44_interface_dump_t_print (vl_api_nat44_interface_dump_t * mp,
1690                                      void *handle)
1691 {
1692   u8 *s;
1693
1694   s = format (0, "SCRIPT: nat44_interface_dump ");
1695
1696   FINISH;
1697 }
1698
1699 static void
1700   vl_api_nat44_interface_add_del_output_feature_t_handler
1701   (vl_api_nat44_interface_add_del_output_feature_t * mp)
1702 {
1703   snat_main_t *sm = &snat_main;
1704   vl_api_nat44_interface_add_del_output_feature_reply_t *rmp;
1705   u8 is_del = mp->is_add == 0;
1706   u32 sw_if_index = ntohl (mp->sw_if_index);
1707   int rv = 0;
1708
1709   VALIDATE_SW_IF_INDEX (mp);
1710
1711   rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
1712                                               is_del);
1713
1714   BAD_SW_IF_INDEX_LABEL;
1715
1716   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
1717 }
1718
1719 static void *vl_api_nat44_interface_add_del_output_feature_t_print
1720   (vl_api_nat44_interface_add_del_output_feature_t * mp, void *handle)
1721 {
1722   u8 *s;
1723
1724   s = format (0, "SCRIPT: nat44_interface_add_del_output_feature ");
1725   s = format (s, "sw_if_index %d %s %s",
1726               clib_host_to_net_u32 (mp->sw_if_index),
1727               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1728
1729   FINISH;
1730 }
1731
1732 static void
1733 send_nat44_interface_output_feature_details (snat_interface_t * i,
1734                                              unix_shared_memory_queue_t * q,
1735                                              u32 context)
1736 {
1737   vl_api_nat44_interface_output_feature_details_t *rmp;
1738   snat_main_t *sm = &snat_main;
1739
1740   rmp = vl_msg_api_alloc (sizeof (*rmp));
1741   memset (rmp, 0, sizeof (*rmp));
1742   rmp->_vl_msg_id =
1743     ntohs (VL_API_NAT44_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
1744   rmp->sw_if_index = ntohl (i->sw_if_index);
1745   rmp->context = context;
1746   rmp->is_inside = nat_interface_is_inside (i);
1747
1748   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1749 }
1750
1751 static void
1752   vl_api_nat44_interface_output_feature_dump_t_handler
1753   (vl_api_nat44_interface_output_feature_dump_t * mp)
1754 {
1755   unix_shared_memory_queue_t *q;
1756   snat_main_t *sm = &snat_main;
1757   snat_interface_t *i;
1758
1759   q = vl_api_client_index_to_input_queue (mp->client_index);
1760   if (q == 0)
1761     return;
1762
1763   /* *INDENT-OFF* */
1764   pool_foreach (i, sm->output_feature_interfaces,
1765   ({
1766     send_nat44_interface_output_feature_details(i, q, mp->context);
1767   }));
1768   /* *INDENT-ON* */
1769 }
1770
1771 static void *vl_api_nat44_interface_output_feature_dump_t_print
1772   (vl_api_nat44_interface_output_feature_dump_t * mp, void *handle)
1773 {
1774   u8 *s;
1775
1776   s = format (0, "SCRIPT: nat44_interface_output_feature_dump ");
1777
1778   FINISH;
1779 }
1780
1781 static void
1782   vl_api_nat44_add_del_static_mapping_t_handler
1783   (vl_api_nat44_add_del_static_mapping_t * mp)
1784 {
1785   snat_main_t *sm = &snat_main;
1786   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
1787   ip4_address_t local_addr, external_addr;
1788   u16 local_port = 0, external_port = 0;
1789   u32 vrf_id, external_sw_if_index;
1790   int rv = 0;
1791   snat_protocol_t proto;
1792
1793   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
1794   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
1795   if (mp->addr_only == 0)
1796     {
1797       local_port = clib_net_to_host_u16 (mp->local_port);
1798       external_port = clib_net_to_host_u16 (mp->external_port);
1799     }
1800   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1801   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
1802   proto = ip_proto_to_snat_proto (mp->protocol);
1803
1804   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
1805                                 external_port, vrf_id, mp->addr_only,
1806                                 external_sw_if_index, proto, mp->is_add);
1807
1808   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
1809 }
1810
1811 static void *vl_api_nat44_add_del_static_mapping_t_print
1812   (vl_api_nat44_add_del_static_mapping_t * mp, void *handle)
1813 {
1814   u8 *s;
1815
1816   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1817   s = format (s, "protocol %d local_addr %U external_addr %U ",
1818               mp->protocol,
1819               format_ip4_address, mp->local_ip_address,
1820               format_ip4_address, mp->external_ip_address);
1821
1822   if (mp->addr_only == 0)
1823     s = format (s, "local_port %d external_port %d ",
1824                 clib_net_to_host_u16 (mp->local_port),
1825                 clib_net_to_host_u16 (mp->external_port));
1826
1827   if (mp->vrf_id != ~0)
1828     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1829
1830   if (mp->external_sw_if_index != ~0)
1831     s = format (s, "external_sw_if_index %d",
1832                 clib_net_to_host_u32 (mp->external_sw_if_index));
1833   FINISH;
1834 }
1835
1836 static void
1837 send_nat44_static_mapping_details (snat_static_mapping_t * m,
1838                                    unix_shared_memory_queue_t * q,
1839                                    u32 context)
1840 {
1841   vl_api_nat44_static_mapping_details_t *rmp;
1842   snat_main_t *sm = &snat_main;
1843
1844   rmp = vl_msg_api_alloc (sizeof (*rmp));
1845   memset (rmp, 0, sizeof (*rmp));
1846   rmp->_vl_msg_id =
1847     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1848   rmp->addr_only = m->addr_only;
1849   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
1850   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
1851   rmp->local_port = htons (m->local_port);
1852   rmp->external_port = htons (m->external_port);
1853   rmp->external_sw_if_index = ~0;
1854   rmp->vrf_id = htonl (m->vrf_id);
1855   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1856   rmp->context = context;
1857
1858   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1859 }
1860
1861 static void
1862 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
1863                                        unix_shared_memory_queue_t * q,
1864                                        u32 context)
1865 {
1866   vl_api_nat44_static_mapping_details_t *rmp;
1867   snat_main_t *sm = &snat_main;
1868
1869   rmp = vl_msg_api_alloc (sizeof (*rmp));
1870   memset (rmp, 0, sizeof (*rmp));
1871   rmp->_vl_msg_id =
1872     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1873   rmp->addr_only = m->addr_only;
1874   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
1875   rmp->local_port = htons (m->l_port);
1876   rmp->external_port = htons (m->e_port);
1877   rmp->external_sw_if_index = htonl (m->sw_if_index);
1878   rmp->vrf_id = htonl (m->vrf_id);
1879   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1880   rmp->context = context;
1881
1882   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1883 }
1884
1885 static void
1886 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
1887                                             * mp)
1888 {
1889   unix_shared_memory_queue_t *q;
1890   snat_main_t *sm = &snat_main;
1891   snat_static_mapping_t *m;
1892   snat_static_map_resolve_t *rp;
1893   int j;
1894
1895   q = vl_api_client_index_to_input_queue (mp->client_index);
1896   if (q == 0)
1897     return;
1898
1899   /* *INDENT-OFF* */
1900   pool_foreach (m, sm->static_mappings,
1901   ({
1902       if (!vec_len(m->locals))
1903         send_nat44_static_mapping_details (m, q, mp->context);
1904   }));
1905   /* *INDENT-ON* */
1906
1907   for (j = 0; j < vec_len (sm->to_resolve); j++)
1908     {
1909       rp = sm->to_resolve + j;
1910       send_nat44_static_map_resolve_details (rp, q, mp->context);
1911     }
1912 }
1913
1914 static void *
1915 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
1916                                           mp, void *handle)
1917 {
1918   u8 *s;
1919
1920   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
1921
1922   FINISH;
1923 }
1924
1925 static void
1926   vl_api_nat44_add_del_interface_addr_t_handler
1927   (vl_api_nat44_add_del_interface_addr_t * mp)
1928 {
1929   snat_main_t *sm = &snat_main;
1930   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1931   u8 is_del = mp->is_add == 0;
1932   u32 sw_if_index = ntohl (mp->sw_if_index);
1933   int rv = 0;
1934
1935   VALIDATE_SW_IF_INDEX (mp);
1936
1937   rv = snat_add_interface_address (sm, sw_if_index, is_del);
1938
1939   BAD_SW_IF_INDEX_LABEL;
1940
1941   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1942 }
1943
1944 static void *vl_api_nat44_add_del_interface_addr_t_print
1945   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
1946 {
1947   u8 *s;
1948
1949   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
1950   s = format (s, "sw_if_index %d %s",
1951               clib_host_to_net_u32 (mp->sw_if_index),
1952               mp->is_add ? "" : "del");
1953
1954   FINISH;
1955 }
1956
1957 static void
1958 send_nat44_interface_addr_details (u32 sw_if_index,
1959                                    unix_shared_memory_queue_t * q,
1960                                    u32 context)
1961 {
1962   vl_api_nat44_interface_addr_details_t *rmp;
1963   snat_main_t *sm = &snat_main;
1964
1965   rmp = vl_msg_api_alloc (sizeof (*rmp));
1966   memset (rmp, 0, sizeof (*rmp));
1967   rmp->_vl_msg_id =
1968     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1969   rmp->sw_if_index = ntohl (sw_if_index);
1970   rmp->context = context;
1971
1972   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1973 }
1974
1975 static void
1976 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1977                                             * mp)
1978 {
1979   unix_shared_memory_queue_t *q;
1980   snat_main_t *sm = &snat_main;
1981   u32 *i;
1982
1983   q = vl_api_client_index_to_input_queue (mp->client_index);
1984   if (q == 0)
1985     return;
1986
1987   /* *INDENT-OFF* */
1988   vec_foreach (i, sm->auto_add_sw_if_indices)
1989     send_nat44_interface_addr_details(*i, q, mp->context);
1990   /* *INDENT-ON* */
1991 }
1992
1993 static void *
1994 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1995                                           mp, void *handle)
1996 {
1997   u8 *s;
1998
1999   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
2000
2001   FINISH;
2002 }
2003
2004 static void
2005 send_nat44_user_details (snat_user_t * u, unix_shared_memory_queue_t * q,
2006                          u32 context)
2007 {
2008   vl_api_nat44_user_details_t *rmp;
2009   snat_main_t *sm = &snat_main;
2010   fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
2011
2012   rmp = vl_msg_api_alloc (sizeof (*rmp));
2013   memset (rmp, 0, sizeof (*rmp));
2014   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
2015
2016   rmp->vrf_id = ntohl (fib->ft_table_id);
2017
2018   clib_memcpy (rmp->ip_address, &(u->addr), 4);
2019   rmp->nsessions = ntohl (u->nsessions);
2020   rmp->nstaticsessions = ntohl (u->nstaticsessions);
2021   rmp->context = context;
2022
2023   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2024 }
2025
2026 static void
2027 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
2028 {
2029   unix_shared_memory_queue_t *q;
2030   snat_main_t *sm = &snat_main;
2031   snat_main_per_thread_data_t *tsm;
2032   snat_user_t *u;
2033
2034   q = vl_api_client_index_to_input_queue (mp->client_index);
2035   if (q == 0)
2036     return;
2037
2038   /* *INDENT-OFF* */
2039   vec_foreach (tsm, sm->per_thread_data)
2040     vec_foreach (u, tsm->users)
2041       send_nat44_user_details (u, q, mp->context);
2042   /* *INDENT-ON* */
2043 }
2044
2045 static void *
2046 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
2047 {
2048   u8 *s;
2049
2050   s = format (0, "SCRIPT: nat44_user_dump ");
2051
2052   FINISH;
2053 }
2054
2055 static void
2056 send_nat44_user_session_details (snat_session_t * s,
2057                                  unix_shared_memory_queue_t * q, u32 context)
2058 {
2059   vl_api_nat44_user_session_details_t *rmp;
2060   snat_main_t *sm = &snat_main;
2061
2062   rmp = vl_msg_api_alloc (sizeof (*rmp));
2063   memset (rmp, 0, sizeof (*rmp));
2064   rmp->_vl_msg_id =
2065     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
2066   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
2067   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
2068   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
2069   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
2070   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
2071   rmp->total_pkts = ntohl (s->total_pkts);
2072   rmp->context = context;
2073   if (snat_is_unk_proto_session (s))
2074     {
2075       rmp->outside_port = 0;
2076       rmp->inside_port = 0;
2077       rmp->protocol = ntohs (s->in2out.port);
2078     }
2079   else
2080     {
2081       rmp->outside_port = s->out2in.port;
2082       rmp->inside_port = s->in2out.port;
2083       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
2084     }
2085
2086   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2087 }
2088
2089 static void
2090 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
2091                                           mp)
2092 {
2093   unix_shared_memory_queue_t *q;
2094   snat_main_t *sm = &snat_main;
2095   snat_main_per_thread_data_t *tsm;
2096   snat_session_t *s;
2097   clib_bihash_kv_8_8_t key, value;
2098   snat_user_key_t ukey;
2099   snat_user_t *u;
2100   u32 session_index, head_index, elt_index;
2101   dlist_elt_t *head, *elt;
2102   ip4_header_t ip;
2103
2104   q = vl_api_client_index_to_input_queue (mp->client_index);
2105   if (q == 0)
2106     return;
2107
2108   clib_memcpy (&ukey.addr, mp->ip_address, 4);
2109   ip.src_address.as_u32 = ukey.addr.as_u32;
2110   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
2111   key.key = ukey.as_u64;
2112   if (sm->num_workers)
2113     tsm =
2114       vec_elt_at_index (sm->per_thread_data,
2115                         sm->worker_in2out_cb (&ip, ukey.fib_index));
2116   else
2117     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
2118   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
2119     return;
2120   u = pool_elt_at_index (tsm->users, value.value);
2121   if (!u->nsessions && !u->nstaticsessions)
2122     return;
2123
2124   head_index = u->sessions_per_user_list_head_index;
2125   head = pool_elt_at_index (tsm->list_pool, head_index);
2126   elt_index = head->next;
2127   elt = pool_elt_at_index (tsm->list_pool, elt_index);
2128   session_index = elt->value;
2129   while (session_index != ~0)
2130     {
2131       s = pool_elt_at_index (tsm->sessions, session_index);
2132
2133       send_nat44_user_session_details (s, q, mp->context);
2134
2135       elt_index = elt->next;
2136       elt = pool_elt_at_index (tsm->list_pool, elt_index);
2137       session_index = elt->value;
2138     }
2139 }
2140
2141 static void *
2142 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
2143                                         void *handle)
2144 {
2145   u8 *s;
2146
2147   s = format (0, "SCRIPT: nat44_user_session_dump ");
2148   s = format (s, "ip_address %U vrf_id %d\n",
2149               format_ip4_address, mp->ip_address,
2150               clib_net_to_host_u32 (mp->vrf_id));
2151
2152   FINISH;
2153 }
2154
2155 static nat44_lb_addr_port_t *
2156 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
2157                              u8 addr_port_pair_num)
2158 {
2159   u8 i;
2160   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
2161   vl_api_nat44_lb_addr_port_t *ap;
2162
2163   for (i = 0; i < addr_port_pair_num; i++)
2164     {
2165       ap = &addr_port_pairs[i];
2166       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
2167       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
2168       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
2169       lb_addr_port.probability = ap->probability;
2170       vec_add1 (lb_addr_port_pairs, lb_addr_port);
2171     }
2172
2173   return lb_addr_port_pairs;
2174 }
2175
2176 static void
2177   vl_api_nat44_add_del_lb_static_mapping_t_handler
2178   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
2179 {
2180   snat_main_t *sm = &snat_main;
2181   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
2182   int rv = 0;
2183   nat44_lb_addr_port_t *locals = 0;
2184   ip4_address_t e_addr;
2185   snat_protocol_t proto;
2186
2187   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
2188   clib_memcpy (&e_addr, mp->external_addr, 4);
2189   proto = ip_proto_to_snat_proto (mp->protocol);
2190
2191   rv =
2192     nat44_add_del_lb_static_mapping (e_addr,
2193                                      clib_net_to_host_u16 (mp->external_port),
2194                                      proto, clib_net_to_host_u32 (mp->vrf_id),
2195                                      locals, mp->is_add);
2196
2197   vec_free (locals);
2198
2199   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
2200 }
2201
2202 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
2203   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
2204 {
2205   u8 *s;
2206
2207   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
2208   s = format (s, "is_add %d\n", mp->is_add);
2209
2210   FINISH;
2211 }
2212
2213 static void
2214 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
2215                                       unix_shared_memory_queue_t * q,
2216                                       u32 context)
2217 {
2218   vl_api_nat44_lb_static_mapping_details_t *rmp;
2219   snat_main_t *sm = &snat_main;
2220   nat44_lb_addr_port_t *ap;
2221   vl_api_nat44_lb_addr_port_t *locals;
2222
2223   rmp =
2224     vl_msg_api_alloc (sizeof (*rmp) +
2225                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
2226   memset (rmp, 0, sizeof (*rmp));
2227   rmp->_vl_msg_id =
2228     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
2229
2230   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
2231   rmp->external_port = ntohs (m->external_port);
2232   rmp->protocol = snat_proto_to_ip_proto (m->proto);
2233   rmp->vrf_id = ntohl (m->vrf_id);
2234   rmp->context = context;
2235
2236   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
2237   vec_foreach (ap, m->locals)
2238   {
2239     clib_memcpy (locals->addr, &(ap->addr), 4);
2240     locals->port = htons (ap->port);
2241     locals->probability = ap->probability;
2242     locals++;
2243     rmp->local_num++;
2244   }
2245
2246   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2247 }
2248
2249 static void
2250   vl_api_nat44_lb_static_mapping_dump_t_handler
2251   (vl_api_nat44_lb_static_mapping_dump_t * mp)
2252 {
2253   unix_shared_memory_queue_t *q;
2254   snat_main_t *sm = &snat_main;
2255   snat_static_mapping_t *m;
2256
2257   q = vl_api_client_index_to_input_queue (mp->client_index);
2258   if (q == 0)
2259     return;
2260
2261   /* *INDENT-OFF* */
2262   pool_foreach (m, sm->static_mappings,
2263   ({
2264       if (vec_len(m->locals))
2265         send_nat44_lb_static_mapping_details (m, q, mp->context);
2266   }));
2267   /* *INDENT-ON* */
2268 }
2269
2270 static void *vl_api_nat44_lb_static_mapping_dump_t_print
2271   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
2272 {
2273   u8 *s;
2274
2275   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
2276
2277   FINISH;
2278 }
2279
2280 static void
2281 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
2282 {
2283   snat_main_t *sm = &snat_main;
2284   vl_api_nat44_del_session_reply_t *rmp;
2285   ip4_address_t addr;
2286   u16 port;
2287   u32 vrf_id;
2288   int rv = 0;
2289   snat_protocol_t proto;
2290
2291   memcpy (&addr.as_u8, mp->address, 4);
2292   port = clib_net_to_host_u16 (mp->port);
2293   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
2294   proto = ip_proto_to_snat_proto (mp->protocol);
2295
2296   rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
2297
2298   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
2299 }
2300
2301 static void *
2302 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
2303                                   void *handle)
2304 {
2305   u8 *s;
2306
2307   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
2308   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
2309               format_ip4_address, mp->address,
2310               clib_net_to_host_u16 (mp->port),
2311               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
2312
2313   FINISH;
2314 }
2315
2316 /*******************************/
2317 /*** Deterministic NAT (CGN) ***/
2318 /*******************************/
2319
2320 static void
2321 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
2322 {
2323   snat_main_t *sm = &snat_main;
2324   vl_api_nat_det_add_del_map_reply_t *rmp;
2325   int rv = 0;
2326   ip4_address_t in_addr, out_addr;
2327
2328   if (!mp->is_nat44)
2329     {
2330       rv = VNET_API_ERROR_UNIMPLEMENTED;
2331       goto send_reply;
2332     }
2333
2334   clib_memcpy (&in_addr, mp->in_addr, 4);
2335   clib_memcpy (&out_addr, mp->out_addr, 4);
2336   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
2337                          mp->out_plen, mp->is_add);
2338
2339 send_reply:
2340   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
2341 }
2342
2343 static void *
2344 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
2345                                     void *handle)
2346 {
2347   u8 *s;
2348
2349   s = format (0, "SCRIPT: nat_det_add_del_map ");
2350   s = format (s, "inside address %U/%d outside address %U/%d\n",
2351               format_ip4_address, mp->in_addr, mp->in_plen,
2352               format_ip4_address, mp->out_addr, mp->out_plen);
2353
2354   FINISH;
2355 }
2356
2357 static void
2358 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
2359 {
2360   snat_main_t *sm = &snat_main;
2361   vl_api_nat_det_forward_reply_t *rmp;
2362   int rv = 0;
2363   u16 lo_port = 0, hi_port = 0;
2364   snat_det_map_t *dm;
2365   ip4_address_t in_addr, out_addr;
2366
2367   if (!mp->is_nat44)
2368     {
2369       out_addr.as_u32 = 0;
2370       rv = VNET_API_ERROR_UNIMPLEMENTED;
2371       goto send_reply;
2372     }
2373
2374   out_addr.as_u32 = 0;
2375   clib_memcpy (&in_addr, mp->in_addr, 4);
2376   dm = snat_det_map_by_user (sm, &in_addr);
2377   if (!dm)
2378     {
2379       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2380       goto send_reply;
2381     }
2382
2383   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
2384   hi_port = lo_port + dm->ports_per_host - 1;
2385
2386 send_reply:
2387   /* *INDENT-OFF* */
2388   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
2389   ({
2390     rmp->out_port_lo = ntohs (lo_port);
2391     rmp->out_port_hi = ntohs (hi_port);
2392     clib_memcpy (rmp->out_addr, &out_addr, 4);
2393   }))
2394   /* *INDENT-ON* */
2395 }
2396
2397 static void *
2398 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
2399 {
2400   u8 *s;
2401
2402   s = format (0, "SCRIPT: nat_det_forward");
2403   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
2404
2405   FINISH;
2406 }
2407
2408 static void
2409 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
2410 {
2411   snat_main_t *sm = &snat_main;
2412   vl_api_nat_det_reverse_reply_t *rmp;
2413   int rv = 0;
2414   ip4_address_t out_addr, in_addr;
2415   snat_det_map_t *dm;
2416
2417   in_addr.as_u32 = 0;
2418   clib_memcpy (&out_addr, mp->out_addr, 4);
2419   dm = snat_det_map_by_out (sm, &out_addr);
2420   if (!dm)
2421     {
2422       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2423       goto send_reply;
2424     }
2425
2426   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
2427
2428 send_reply:
2429   /* *INDENT-OFF* */
2430   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
2431   ({
2432     rmp->is_nat44 = 1;
2433     memset (rmp->in_addr, 0, 16);
2434     clib_memcpy (rmp->in_addr, &in_addr, 4);
2435   }))
2436   /* *INDENT-ON* */
2437 }
2438
2439 static void *
2440 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
2441 {
2442   u8 *s;
2443
2444   s = format (0, "SCRIPT: nat_det_reverse");
2445   s = format (s, "outside ip address %U outside port %d",
2446               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
2447
2448   FINISH;
2449 }
2450
2451 static void
2452 sent_nat_det_map_details (snat_det_map_t * m, unix_shared_memory_queue_t * q,
2453                           u32 context)
2454 {
2455   vl_api_nat_det_map_details_t *rmp;
2456   snat_main_t *sm = &snat_main;
2457
2458   rmp = vl_msg_api_alloc (sizeof (*rmp));
2459   memset (rmp, 0, sizeof (*rmp));
2460   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
2461   rmp->is_nat44 = 1;
2462   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
2463   rmp->in_plen = m->in_plen;
2464   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
2465   rmp->out_plen = m->out_plen;
2466   rmp->sharing_ratio = htonl (m->sharing_ratio);
2467   rmp->ports_per_host = htons (m->ports_per_host);
2468   rmp->ses_num = htonl (m->ses_num);
2469   rmp->context = context;
2470
2471   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2472 }
2473
2474 static void
2475 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
2476 {
2477   unix_shared_memory_queue_t *q;
2478   snat_main_t *sm = &snat_main;
2479   snat_det_map_t *m;
2480
2481   q = vl_api_client_index_to_input_queue (mp->client_index);
2482   if (q == 0)
2483     return;
2484
2485   /* *INDENT-OFF* */
2486   vec_foreach(m, sm->det_maps)
2487     sent_nat_det_map_details(m, q, mp->context);
2488   /* *INDENT-ON* */
2489 }
2490
2491 static void *
2492 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
2493 {
2494   u8 *s;
2495
2496   s = format (0, "SCRIPT: nat_det_map_dump ");
2497
2498   FINISH;
2499 }
2500
2501 static void
2502 vl_api_nat_det_set_timeouts_t_handler (vl_api_nat_det_set_timeouts_t * mp)
2503 {
2504   snat_main_t *sm = &snat_main;
2505   vl_api_nat_det_set_timeouts_reply_t *rmp;
2506   int rv = 0;
2507
2508   sm->udp_timeout = ntohl (mp->udp);
2509   sm->tcp_established_timeout = ntohl (mp->tcp_established);
2510   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
2511   sm->icmp_timeout = ntohl (mp->icmp);
2512
2513   REPLY_MACRO (VL_API_NAT_DET_SET_TIMEOUTS_REPLY);
2514 }
2515
2516 static void *
2517 vl_api_nat_det_set_timeouts_t_print (vl_api_nat_det_set_timeouts_t * mp,
2518                                      void *handle)
2519 {
2520   u8 *s;
2521
2522   s = format (0, "SCRIPT: nat_det_set_timeouts ");
2523   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
2524               ntohl (mp->udp),
2525               ntohl (mp->tcp_established),
2526               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
2527
2528   FINISH;
2529 }
2530
2531 static void
2532 vl_api_nat_det_get_timeouts_t_handler (vl_api_nat_det_get_timeouts_t * mp)
2533 {
2534   snat_main_t *sm = &snat_main;
2535   vl_api_nat_det_get_timeouts_reply_t *rmp;
2536   int rv = 0;
2537
2538   /* *INDENT-OFF* */
2539   REPLY_MACRO2 (VL_API_NAT_DET_GET_TIMEOUTS_REPLY,
2540   ({
2541     rmp->udp = htonl (sm->udp_timeout);
2542     rmp->tcp_established = htonl (sm->tcp_established_timeout);
2543     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
2544     rmp->icmp = htonl (sm->icmp_timeout);
2545   }))
2546   /* *INDENT-ON* */
2547 }
2548
2549 static void *
2550 vl_api_nat_det_get_timeouts_t_print (vl_api_nat_det_get_timeouts_t * mp,
2551                                      void *handle)
2552 {
2553   u8 *s;
2554
2555   s = format (0, "SCRIPT: nat_det_get_timeouts");
2556
2557   FINISH;
2558 }
2559
2560 static void
2561 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
2562                                             * mp)
2563 {
2564   snat_main_t *sm = &snat_main;
2565   vl_api_nat_det_close_session_out_reply_t *rmp;
2566   ip4_address_t out_addr, ext_addr, in_addr;
2567   snat_det_out_key_t key;
2568   snat_det_map_t *dm;
2569   snat_det_session_t *ses;
2570   int rv = 0;
2571
2572   clib_memcpy (&out_addr, mp->out_addr, 4);
2573   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2574
2575   dm = snat_det_map_by_out (sm, &out_addr);
2576   if (!dm)
2577     {
2578       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2579       goto send_reply;
2580     }
2581   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
2582   key.ext_host_addr = ext_addr;
2583   key.ext_host_port = mp->ext_port;
2584   key.out_port = mp->out_port;
2585   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
2586   if (!ses)
2587     {
2588       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2589       goto send_reply;
2590     }
2591   snat_det_ses_close (dm, ses);
2592
2593 send_reply:
2594   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2595 }
2596
2597 static void *
2598 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
2599                                           mp, void *handle)
2600 {
2601   u8 *s;
2602
2603   s = format (0, "SCRIPT: nat_det_close_session_out ");
2604   s = format (s, "out_addr %U out_port %d "
2605               "ext_addr %U ext_port %d\n",
2606               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
2607               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2608
2609   FINISH;
2610 }
2611
2612 static void
2613 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
2614                                            mp)
2615 {
2616   snat_main_t *sm = &snat_main;
2617   vl_api_nat_det_close_session_in_reply_t *rmp;
2618   ip4_address_t in_addr, ext_addr;
2619   snat_det_out_key_t key;
2620   snat_det_map_t *dm;
2621   snat_det_session_t *ses;
2622   int rv = 0;
2623
2624   if (!mp->is_nat44)
2625     {
2626       rv = VNET_API_ERROR_UNIMPLEMENTED;
2627       goto send_reply;
2628     }
2629
2630   clib_memcpy (&in_addr, mp->in_addr, 4);
2631   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2632
2633   dm = snat_det_map_by_user (sm, &in_addr);
2634   if (!dm)
2635     {
2636       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2637       goto send_reply;
2638     }
2639   key.ext_host_addr = ext_addr;
2640   key.ext_host_port = mp->ext_port;
2641   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
2642   if (!ses)
2643     {
2644       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2645       goto send_reply;
2646     }
2647   snat_det_ses_close (dm, ses);
2648
2649 send_reply:
2650   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2651 }
2652
2653 static void *
2654 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2655                                          mp, void *handle)
2656 {
2657   u8 *s;
2658   s = format (0, "SCRIPT: nat_det_close_session_in ");
2659   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2660               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2661               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2662
2663   FINISH;
2664 }
2665
2666 static void
2667 send_nat_det_session_details (snat_det_session_t * s,
2668                               unix_shared_memory_queue_t * q, u32 context)
2669 {
2670   vl_api_nat_det_session_details_t *rmp;
2671   snat_main_t *sm = &snat_main;
2672
2673   rmp = vl_msg_api_alloc (sizeof (*rmp));
2674   memset (rmp, 0, sizeof (*rmp));
2675   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2676   rmp->in_port = s->in_port;
2677   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2678   rmp->ext_port = s->out.ext_host_port;
2679   rmp->out_port = s->out.out_port;
2680   rmp->state = s->state;
2681   rmp->expire = ntohl (s->expire);
2682   rmp->context = context;
2683
2684   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2685 }
2686
2687 static void
2688 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2689 {
2690   unix_shared_memory_queue_t *q;
2691   snat_main_t *sm = &snat_main;
2692   ip4_address_t user_addr;
2693   snat_det_map_t *dm;
2694   snat_det_session_t *s, empty_ses;
2695   u16 i;
2696
2697   q = vl_api_client_index_to_input_queue (mp->client_index);
2698   if (q == 0)
2699     return;
2700   if (!mp->is_nat44)
2701     return;
2702
2703   memset (&empty_ses, 0, sizeof (empty_ses));
2704   clib_memcpy (&user_addr, mp->user_addr, 4);
2705   dm = snat_det_map_by_user (sm, &user_addr);
2706   if (!dm)
2707     return;
2708
2709   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2710   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2711     {
2712       if (s->out.as_u64)
2713         send_nat_det_session_details (s, q, mp->context);
2714       s++;
2715     }
2716 }
2717
2718 static void *
2719 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2720                                      void *handle)
2721 {
2722   u8 *s;
2723
2724   s = format (0, "SCRIPT: nat_det_session_dump ");
2725   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2726
2727   FINISH;
2728 }
2729
2730 /*************/
2731 /*** NAT64 ***/
2732 /*************/
2733
2734 static void
2735   vl_api_nat64_add_del_pool_addr_range_t_handler
2736   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2737 {
2738   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2739   snat_main_t *sm = &snat_main;
2740   nat64_main_t *nm = &nat64_main;
2741   int rv = 0;
2742   ip4_address_t this_addr;
2743   u32 start_host_order, end_host_order;
2744   u32 vrf_id;
2745   int i, count;
2746   u32 *tmp;
2747
2748   if (nm->is_disabled)
2749     {
2750       rv = VNET_API_ERROR_FEATURE_DISABLED;
2751       goto send_reply;
2752     }
2753
2754   tmp = (u32 *) mp->start_addr;
2755   start_host_order = clib_host_to_net_u32 (tmp[0]);
2756   tmp = (u32 *) mp->end_addr;
2757   end_host_order = clib_host_to_net_u32 (tmp[0]);
2758
2759   count = (end_host_order - start_host_order) + 1;
2760
2761   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2762
2763   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2764
2765   for (i = 0; i < count; i++)
2766     {
2767       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
2768         goto send_reply;
2769
2770       increment_v4_address (&this_addr);
2771     }
2772
2773 send_reply:
2774   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2775 }
2776
2777 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2778   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2779 {
2780   u8 *s;
2781
2782   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2783   s = format (s, "%U - %U vrf_id %u %s\n",
2784               format_ip4_address, mp->start_addr,
2785               format_ip4_address, mp->end_addr,
2786               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2787
2788   FINISH;
2789 }
2790
2791 typedef struct nat64_api_walk_ctx_t_
2792 {
2793   unix_shared_memory_queue_t *q;
2794   u32 context;
2795 } nat64_api_walk_ctx_t;
2796
2797 static int
2798 nat64_api_pool_walk (snat_address_t * a, void *arg)
2799 {
2800   vl_api_nat64_pool_addr_details_t *rmp;
2801   snat_main_t *sm = &snat_main;
2802   nat64_api_walk_ctx_t *ctx = arg;
2803
2804   rmp = vl_msg_api_alloc (sizeof (*rmp));
2805   memset (rmp, 0, sizeof (*rmp));
2806   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2807   clib_memcpy (rmp->address, &(a->addr), 4);
2808   if (a->fib_index != ~0)
2809     {
2810       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2811       if (!fib)
2812         return -1;
2813       rmp->vrf_id = ntohl (fib->ft_table_id);
2814     }
2815   else
2816     rmp->vrf_id = ~0;
2817   rmp->context = ctx->context;
2818
2819   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2820
2821   return 0;
2822 }
2823
2824 static void
2825 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2826 {
2827   unix_shared_memory_queue_t *q;
2828   nat64_main_t *nm = &nat64_main;
2829
2830   if (nm->is_disabled)
2831     return;
2832
2833   q = vl_api_client_index_to_input_queue (mp->client_index);
2834   if (q == 0)
2835     return;
2836
2837   nat64_api_walk_ctx_t ctx = {
2838     .q = q,
2839     .context = mp->context,
2840   };
2841
2842   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2843 }
2844
2845 static void *
2846 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2847                                      void *handle)
2848 {
2849   u8 *s;
2850
2851   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2852
2853   FINISH;
2854 }
2855
2856 static void
2857 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2858                                           mp)
2859 {
2860   snat_main_t *sm = &snat_main;
2861   nat64_main_t *nm = &nat64_main;
2862   vl_api_nat64_add_del_interface_reply_t *rmp;
2863   int rv = 0;
2864
2865   if (nm->is_disabled)
2866     {
2867       rv = VNET_API_ERROR_FEATURE_DISABLED;
2868       goto send_reply;
2869     }
2870
2871   VALIDATE_SW_IF_INDEX (mp);
2872
2873   rv =
2874     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
2875                              mp->is_add);
2876
2877   BAD_SW_IF_INDEX_LABEL;
2878
2879 send_reply:
2880   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2881 }
2882
2883 static void *
2884 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2885                                         void *handle)
2886 {
2887   u8 *s;
2888
2889   s = format (0, "SCRIPT: nat64_add_del_interface ");
2890   s = format (s, "sw_if_index %d %s %s",
2891               clib_host_to_net_u32 (mp->sw_if_index),
2892               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2893
2894   FINISH;
2895 }
2896
2897 static int
2898 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2899 {
2900   vl_api_nat64_interface_details_t *rmp;
2901   snat_main_t *sm = &snat_main;
2902   nat64_api_walk_ctx_t *ctx = arg;
2903
2904   rmp = vl_msg_api_alloc (sizeof (*rmp));
2905   memset (rmp, 0, sizeof (*rmp));
2906   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2907   rmp->sw_if_index = ntohl (i->sw_if_index);
2908   rmp->is_inside = (nat_interface_is_inside (i)
2909                     && nat_interface_is_outside (i)) ? 2 :
2910     nat_interface_is_inside (i);
2911   rmp->context = ctx->context;
2912
2913   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2914
2915   return 0;
2916 }
2917
2918 static void
2919 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2920 {
2921   unix_shared_memory_queue_t *q;
2922   nat64_main_t *nm = &nat64_main;
2923
2924   if (nm->is_disabled)
2925     return;
2926
2927   q = vl_api_client_index_to_input_queue (mp->client_index);
2928   if (q == 0)
2929     return;
2930
2931   nat64_api_walk_ctx_t ctx = {
2932     .q = q,
2933     .context = mp->context,
2934   };
2935
2936   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2937 }
2938
2939 static void *
2940 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2941                                      void *handle)
2942 {
2943   u8 *s;
2944
2945   s = format (0, "SCRIPT: snat_interface_dump ");
2946
2947   FINISH;
2948 }
2949
2950 static void
2951   vl_api_nat64_add_del_static_bib_t_handler
2952   (vl_api_nat64_add_del_static_bib_t * mp)
2953 {
2954   snat_main_t *sm = &snat_main;
2955   nat64_main_t *nm = &nat64_main;
2956   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2957   ip6_address_t in_addr;
2958   ip4_address_t out_addr;
2959   int rv = 0;
2960
2961   if (nm->is_disabled)
2962     {
2963       rv = VNET_API_ERROR_FEATURE_DISABLED;
2964       goto send_reply;
2965     }
2966
2967   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2968   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2969
2970   rv =
2971     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2972                                     clib_net_to_host_u16 (mp->i_port),
2973                                     clib_net_to_host_u16 (mp->o_port),
2974                                     mp->proto,
2975                                     clib_net_to_host_u32 (mp->vrf_id),
2976                                     mp->is_add);
2977
2978 send_reply:
2979   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2980 }
2981
2982 static void *vl_api_nat64_add_del_static_bib_t_print
2983   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2984 {
2985   u8 *s;
2986
2987   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2988   s = format (s, "protocol %d i_addr %U o_addr %U ",
2989               mp->proto,
2990               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2991
2992   if (mp->vrf_id != ~0)
2993     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2994
2995   FINISH;
2996 }
2997
2998 static int
2999 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
3000 {
3001   vl_api_nat64_bib_details_t *rmp;
3002   snat_main_t *sm = &snat_main;
3003   nat64_api_walk_ctx_t *ctx = arg;
3004   fib_table_t *fib;
3005
3006   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
3007   if (!fib)
3008     return -1;
3009
3010   rmp = vl_msg_api_alloc (sizeof (*rmp));
3011   memset (rmp, 0, sizeof (*rmp));
3012   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
3013   rmp->context = ctx->context;
3014   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
3015   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
3016   rmp->i_port = bibe->in_port;
3017   rmp->o_port = bibe->out_port;
3018   rmp->vrf_id = ntohl (fib->ft_table_id);
3019   rmp->proto = bibe->proto;
3020   rmp->is_static = bibe->is_static;
3021   rmp->ses_num = ntohl (bibe->ses_num);
3022
3023   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3024
3025   return 0;
3026 }
3027
3028 static void
3029 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
3030 {
3031   unix_shared_memory_queue_t *q;
3032   nat64_main_t *nm = &nat64_main;
3033
3034   if (nm->is_disabled)
3035     return;
3036
3037   q = vl_api_client_index_to_input_queue (mp->client_index);
3038   if (q == 0)
3039     return;
3040
3041   nat64_api_walk_ctx_t ctx = {
3042     .q = q,
3043     .context = mp->context,
3044   };
3045
3046   nat64_db_bib_walk (&nm->db, mp->proto, nat64_api_bib_walk, &ctx);
3047 }
3048
3049 static void *
3050 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
3051 {
3052   u8 *s;
3053
3054   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
3055
3056   FINISH;
3057 }
3058
3059 static void
3060 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
3061 {
3062   snat_main_t *sm = &snat_main;
3063   nat64_main_t *nm = &nat64_main;
3064   vl_api_nat64_set_timeouts_reply_t *rmp;
3065   int rv = 0;
3066
3067   if (nm->is_disabled)
3068     {
3069       rv = VNET_API_ERROR_FEATURE_DISABLED;
3070       goto send_reply;
3071     }
3072
3073   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
3074   if (rv)
3075     goto send_reply;
3076   rv = nat64_set_udp_timeout (ntohl (mp->udp));
3077   if (rv)
3078     goto send_reply;
3079   rv =
3080     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
3081                             ntohl (mp->tcp_incoming_syn));
3082
3083 send_reply:
3084   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
3085 }
3086
3087 static void *vl_api_nat64_set_timeouts_t_print
3088   (vl_api_nat64_set_timeouts_t * mp, void *handle)
3089 {
3090   u8 *s;
3091
3092   s = format (0, "SCRIPT: nat64_set_timeouts ");
3093   s =
3094     format (s,
3095             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
3096             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
3097             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
3098
3099   FINISH;
3100 }
3101
3102 static void
3103 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
3104 {
3105   snat_main_t *sm = &snat_main;
3106   nat64_main_t *nm = &nat64_main;
3107   vl_api_nat64_get_timeouts_reply_t *rmp;
3108   int rv = 0;
3109
3110   if (nm->is_disabled)
3111     return;
3112
3113   /* *INDENT-OFF* */
3114   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
3115   ({
3116     rmp->udp = htonl (nat64_get_udp_timeout());
3117     rmp->icmp = htonl (nat64_get_icmp_timeout());
3118     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
3119     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
3120     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
3121   }))
3122   /* *INDENT-ON* */
3123 }
3124
3125 static void *vl_api_nat64_get_timeouts_t_print
3126   (vl_api_nat64_get_timeouts_t * mp, void *handle)
3127 {
3128   u8 *s;
3129
3130   s = format (0, "SCRIPT: nat64_get_timeouts");
3131
3132   FINISH;
3133 }
3134
3135 static int
3136 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
3137 {
3138   vl_api_nat64_st_details_t *rmp;
3139   snat_main_t *sm = &snat_main;
3140   nat64_api_walk_ctx_t *ctx = arg;
3141   nat64_main_t *nm = &nat64_main;
3142   nat64_db_bib_entry_t *bibe;
3143   fib_table_t *fib;
3144
3145   bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
3146   if (!bibe)
3147     return -1;
3148
3149   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
3150   if (!fib)
3151     return -1;
3152
3153   rmp = vl_msg_api_alloc (sizeof (*rmp));
3154   memset (rmp, 0, sizeof (*rmp));
3155   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
3156   rmp->context = ctx->context;
3157   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
3158   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
3159   rmp->il_port = bibe->in_port;
3160   rmp->ol_port = bibe->out_port;
3161   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
3162   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
3163   rmp->il_port = ste->r_port;
3164   rmp->vrf_id = ntohl (fib->ft_table_id);
3165   rmp->proto = ste->proto;
3166
3167   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3168
3169   return 0;
3170 }
3171
3172 static void
3173 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
3174 {
3175   unix_shared_memory_queue_t *q;
3176   nat64_main_t *nm = &nat64_main;
3177
3178   if (nm->is_disabled)
3179     return;
3180
3181   q = vl_api_client_index_to_input_queue (mp->client_index);
3182   if (q == 0)
3183     return;
3184
3185   nat64_api_walk_ctx_t ctx = {
3186     .q = q,
3187     .context = mp->context,
3188   };
3189
3190   nat64_db_st_walk (&nm->db, mp->proto, nat64_api_st_walk, &ctx);
3191 }
3192
3193 static void *
3194 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
3195 {
3196   u8 *s;
3197
3198   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
3199
3200   FINISH;
3201 }
3202
3203 static void
3204 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
3205 {
3206   vl_api_nat64_add_del_prefix_reply_t *rmp;
3207   snat_main_t *sm = &snat_main;
3208   nat64_main_t *nm = &nat64_main;
3209   ip6_address_t prefix;
3210   int rv = 0;
3211
3212   if (nm->is_disabled)
3213     {
3214       rv = VNET_API_ERROR_FEATURE_DISABLED;
3215       goto send_reply;
3216     }
3217
3218   memcpy (&prefix.as_u8, mp->prefix, 16);
3219
3220   rv =
3221     nat64_add_del_prefix (&prefix, mp->prefix_len,
3222                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
3223 send_reply:
3224   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
3225 }
3226
3227 static void *
3228 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
3229                                      void *handle)
3230 {
3231   u8 *s;
3232
3233   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
3234               format_ip6_address, mp->prefix, mp->prefix_len,
3235               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
3236
3237   FINISH;
3238 }
3239
3240 static int
3241 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
3242 {
3243   vl_api_nat64_prefix_details_t *rmp;
3244   snat_main_t *sm = &snat_main;
3245   nat64_api_walk_ctx_t *ctx = arg;
3246
3247   rmp = vl_msg_api_alloc (sizeof (*rmp));
3248   memset (rmp, 0, sizeof (*rmp));
3249   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
3250   clib_memcpy (rmp->prefix, &(p->prefix), 16);
3251   rmp->prefix_len = p->plen;
3252   rmp->vrf_id = ntohl (p->vrf_id);
3253   rmp->context = ctx->context;
3254
3255   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3256
3257   return 0;
3258 }
3259
3260 static void
3261 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
3262 {
3263   unix_shared_memory_queue_t *q;
3264   nat64_main_t *nm = &nat64_main;
3265
3266   if (nm->is_disabled)
3267     return;
3268
3269   q = vl_api_client_index_to_input_queue (mp->client_index);
3270   if (q == 0)
3271     return;
3272
3273   nat64_api_walk_ctx_t ctx = {
3274     .q = q,
3275     .context = mp->context,
3276   };
3277
3278   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
3279 }
3280
3281 static void *
3282 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
3283                                   void *handle)
3284 {
3285   u8 *s;
3286
3287   s = format (0, "SCRIPT: nat64_prefix_dump\n");
3288
3289   FINISH;
3290 }
3291
3292 /* List of message types that this plugin understands */
3293 #define foreach_snat_plugin_api_msg                                     \
3294 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range)                       \
3295 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature)       \
3296 _(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping)                     \
3297 _(SNAT_CONTROL_PING, snat_control_ping)                                 \
3298 _(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump)                   \
3299 _(SNAT_SHOW_CONFIG, snat_show_config)                                   \
3300 _(SNAT_ADDRESS_DUMP, snat_address_dump)                                 \
3301 _(SNAT_INTERFACE_DUMP, snat_interface_dump)                             \
3302 _(SNAT_SET_WORKERS, snat_set_workers)                                   \
3303 _(SNAT_WORKER_DUMP, snat_worker_dump)                                   \
3304 _(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr)             \
3305 _(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump)                   \
3306 _(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable)                 \
3307 _(SNAT_USER_DUMP, snat_user_dump)                                       \
3308 _(SNAT_USER_SESSION_DUMP, snat_user_session_dump)                       \
3309 _(SNAT_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                                \
3310   snat_interface_add_del_output_feature)                                \
3311 _(SNAT_INTERFACE_OUTPUT_FEATURE_DUMP,                                   \
3312   snat_interface_output_feature_dump)                                   \
3313 _(SNAT_ADD_DET_MAP, snat_add_det_map)                                   \
3314 _(SNAT_DET_FORWARD, snat_det_forward)                                   \
3315 _(SNAT_DET_REVERSE, snat_det_reverse)                                   \
3316 _(SNAT_DET_MAP_DUMP, snat_det_map_dump)                                 \
3317 _(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts)                         \
3318 _(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts)                         \
3319 _(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out)               \
3320 _(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in)                 \
3321 _(SNAT_DET_SESSION_DUMP, snat_det_session_dump)                         \
3322 _(NAT_CONTROL_PING, nat_control_ping)                                   \
3323 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
3324 _(NAT_SET_WORKERS, nat_set_workers)                                     \
3325 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
3326 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
3327 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
3328 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
3329 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
3330 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3331 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3332 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3333 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3334 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3335 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3336 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3337 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3338   nat44_interface_add_del_output_feature)                               \
3339 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3340   nat44_interface_output_feature_dump)                                  \
3341 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3342 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3343 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
3344 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3345 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3346 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3347 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3348 _(NAT_DET_SET_TIMEOUTS, nat_det_set_timeouts)                           \
3349 _(NAT_DET_GET_TIMEOUTS, nat_det_get_timeouts)                           \
3350 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3351 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3352 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3353 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3354 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3355 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3356 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3357 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3358 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3359 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
3360 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
3361 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3362 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3363 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)
3364
3365 /* Set up the API message handling tables */
3366 static clib_error_t *
3367 snat_plugin_api_hookup (vlib_main_t * vm)
3368 {
3369   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3370 #define _(N,n)                                                  \
3371     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3372                            #n,                                  \
3373                            vl_api_##n##_t_handler,              \
3374                            vl_noop_handler,                     \
3375                            vl_api_##n##_t_endian,               \
3376                            vl_api_##n##_t_print,                \
3377                            sizeof(vl_api_##n##_t), 1);
3378   foreach_snat_plugin_api_msg;
3379 #undef _
3380
3381   return 0;
3382 }
3383
3384 #define vl_msg_name_crc_list
3385 #include <nat/nat_all_api_h.h>
3386 #undef vl_msg_name_crc_list
3387
3388 static void
3389 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3390 {
3391 #define _(id,n,crc) \
3392   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3393   foreach_vl_msg_name_crc_nat;
3394 #undef _
3395 }
3396
3397 static void
3398 plugin_custom_dump_configure (snat_main_t * sm)
3399 {
3400 #define _(n,f) sm->api_main->msg_print_handlers \
3401   [VL_API_##n + sm->msg_id_base]                \
3402     = (void *) vl_api_##f##_t_print;
3403   foreach_snat_plugin_api_msg;
3404 #undef _
3405 }
3406
3407 clib_error_t *
3408 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3409 {
3410   u8 *name;
3411   clib_error_t *error = 0;
3412
3413   name = format (0, "snat_%08x%c", api_version, 0);
3414
3415   /* Ask for a correctly-sized block of API message decode slots */
3416   sm->msg_id_base =
3417     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3418
3419   error = snat_plugin_api_hookup (vm);
3420
3421   /* Add our API messages to the global name_crc hash table */
3422   setup_message_id_table (sm, sm->api_main);
3423
3424   plugin_custom_dump_configure (sm);
3425
3426   vec_free (name);
3427
3428   return error;
3429 }
3430
3431 /*
3432  * fd.io coding-style-patch-verification: ON
3433  *
3434  * Local Variables:
3435  * eval: (c-set-style "gnu")
3436  * End:
3437  */