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