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