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