acl-plugin: bihash-based ACL lookup
[vpp.git] / src / plugins / snat / snat_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 SNAT plugin API implementation
19  */
20
21 #include <snat/snat.h>
22 #include <snat/snat_det.h>
23 #include <snat/nat64.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vlibsocket/api.h>
27 #include <snat/snat_msg_enum.h>
28 #include <vnet/fib/fib_table.h>
29
30 /* define message structures */
31 #define vl_typedefs
32 #include <snat/snat_all_api_h.h>
33 #undef vl_typedefs
34
35 /* define generated endian-swappers */
36 #define vl_endianfun
37 #include <snat/snat_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 <snat/snat_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 } static void
257   vl_api_snat_add_static_mapping_t_handler
258   (vl_api_snat_add_static_mapping_t * mp)
259 {
260   snat_main_t *sm = &snat_main;
261   vl_api_snat_add_static_mapping_reply_t *rmp;
262   ip4_address_t local_addr, external_addr;
263   u16 local_port = 0, external_port = 0;
264   u32 vrf_id, external_sw_if_index;
265   int rv = 0;
266   snat_protocol_t proto;
267
268   if (mp->is_ip4 != 1)
269     {
270       rv = VNET_API_ERROR_UNIMPLEMENTED;
271       goto send_reply;
272     }
273
274   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
275   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
276   if (mp->addr_only == 0)
277     {
278       local_port = clib_net_to_host_u16 (mp->local_port);
279       external_port = clib_net_to_host_u16 (mp->external_port);
280     }
281   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
282   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
283   proto = ip_proto_to_snat_proto (mp->protocol);
284
285   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
286                                 external_port, vrf_id, mp->addr_only,
287                                 external_sw_if_index, proto, mp->is_add);
288
289 send_reply:
290   REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
291 }
292
293 static void *vl_api_snat_add_static_mapping_t_print
294   (vl_api_snat_add_static_mapping_t * mp, void *handle)
295 {
296   u8 *s;
297
298   s = format (0, "SCRIPT: snat_add_static_mapping ");
299   s = format (s, "protocol %d local_addr %U external_addr %U ",
300               mp->protocol,
301               format_ip4_address, mp->local_ip_address,
302               format_ip4_address, mp->external_ip_address);
303
304   if (mp->addr_only == 0)
305     s = format (s, "local_port %d external_port %d ",
306                 clib_net_to_host_u16 (mp->local_port),
307                 clib_net_to_host_u16 (mp->external_port));
308
309   if (mp->vrf_id != ~0)
310     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
311
312   if (mp->external_sw_if_index != ~0)
313     s = format (s, "external_sw_if_index %d",
314                 clib_net_to_host_u32 (mp->external_sw_if_index));
315   FINISH;
316 }
317
318 static void
319   send_snat_static_mapping_details
320   (snat_static_mapping_t * m, unix_shared_memory_queue_t * q, u32 context)
321 {
322   vl_api_snat_static_mapping_details_t *rmp;
323   snat_main_t *sm = &snat_main;
324
325   rmp = vl_msg_api_alloc (sizeof (*rmp));
326   memset (rmp, 0, sizeof (*rmp));
327   rmp->_vl_msg_id =
328     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
329   rmp->is_ip4 = 1;
330   rmp->addr_only = m->addr_only;
331   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
332   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
333   rmp->local_port = htons (m->local_port);
334   rmp->external_port = htons (m->external_port);
335   rmp->external_sw_if_index = ~0;
336   rmp->vrf_id = htonl (m->vrf_id);
337   rmp->protocol = snat_proto_to_ip_proto (m->proto);
338   rmp->context = context;
339
340   vl_msg_api_send_shmem (q, (u8 *) & rmp);
341 }
342
343 static void
344   send_snat_static_map_resolve_details
345   (snat_static_map_resolve_t * m, unix_shared_memory_queue_t * q, u32 context)
346 {
347   vl_api_snat_static_mapping_details_t *rmp;
348   snat_main_t *sm = &snat_main;
349
350   rmp = vl_msg_api_alloc (sizeof (*rmp));
351   memset (rmp, 0, sizeof (*rmp));
352   rmp->_vl_msg_id =
353     ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
354   rmp->is_ip4 = 1;
355   rmp->addr_only = m->addr_only;
356   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
357   rmp->local_port = htons (m->l_port);
358   rmp->external_port = htons (m->e_port);
359   rmp->external_sw_if_index = htonl (m->sw_if_index);
360   rmp->vrf_id = htonl (m->vrf_id);
361   rmp->protocol = snat_proto_to_ip_proto (m->proto);
362   rmp->context = context;
363
364   vl_msg_api_send_shmem (q, (u8 *) & rmp);
365 }
366
367 static void
368   vl_api_snat_static_mapping_dump_t_handler
369   (vl_api_snat_static_mapping_dump_t * mp)
370 {
371   unix_shared_memory_queue_t *q;
372   snat_main_t *sm = &snat_main;
373   snat_static_mapping_t *m;
374   snat_static_map_resolve_t *rp;
375   int j;
376
377   q = vl_api_client_index_to_input_queue (mp->client_index);
378   if (q == 0)
379     return;
380
381   /* *INDENT-OFF* */
382   pool_foreach (m, sm->static_mappings,
383   ({
384       send_snat_static_mapping_details (m, q, mp->context);
385   }));
386   /* *INDENT-ON* */
387
388   for (j = 0; j < vec_len (sm->to_resolve); j++)
389     {
390       rp = sm->to_resolve + j;
391       send_snat_static_map_resolve_details (rp, q, mp->context);
392     }
393 }
394
395 static void *vl_api_snat_static_mapping_dump_t_print
396   (vl_api_snat_static_mapping_dump_t * mp, void *handle)
397 {
398   u8 *s;
399
400   s = format (0, "SCRIPT: snat_static_mapping_dump ");
401
402   FINISH;
403 }
404
405 static void
406 vl_api_snat_control_ping_t_handler (vl_api_snat_control_ping_t * mp)
407 {
408   vl_api_snat_control_ping_reply_t *rmp;
409   snat_main_t *sm = &snat_main;
410   int rv = 0;
411
412   /* *INDENT-OFF* */
413   REPLY_MACRO2 (VL_API_SNAT_CONTROL_PING_REPLY,
414   ({
415     rmp->vpe_pid = ntohl (getpid ());
416   }));
417   /* *INDENT-ON* */
418 }
419
420 static void *vl_api_snat_control_ping_t_print
421   (vl_api_snat_control_ping_t * mp, void *handle)
422 {
423   u8 *s;
424
425   s = format (0, "SCRIPT: snat_control_ping ");
426
427   FINISH;
428 }
429
430 static void
431 vl_api_snat_show_config_t_handler (vl_api_snat_show_config_t * mp)
432 {
433   vl_api_snat_show_config_reply_t *rmp;
434   snat_main_t *sm = &snat_main;
435   int rv = 0;
436
437   /* *INDENT-OFF* */
438   REPLY_MACRO2 (VL_API_SNAT_SHOW_CONFIG_REPLY,
439   ({
440     rmp->translation_buckets = htonl (sm->translation_buckets);
441     rmp->translation_memory_size = htonl (sm->translation_memory_size);
442     rmp->user_buckets = htonl (sm->user_buckets);
443     rmp->user_memory_size = htonl (sm->user_memory_size);
444     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
445     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
446     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
447     rmp->static_mapping_only = sm->static_mapping_only;
448     rmp->static_mapping_connection_tracking =
449       sm->static_mapping_connection_tracking;
450     rmp->deterministic = sm->deterministic;
451   }));
452   /* *INDENT-ON* */
453 }
454
455 static void *vl_api_snat_show_config_t_print
456   (vl_api_snat_show_config_t * mp, void *handle)
457 {
458   u8 *s;
459
460   s = format (0, "SCRIPT: snat_show_config ");
461
462   FINISH;
463 }
464
465 static void
466 vl_api_snat_set_workers_t_handler (vl_api_snat_set_workers_t * mp)
467 {
468   snat_main_t *sm = &snat_main;
469   vl_api_snat_set_workers_reply_t *rmp;
470   int rv = 0;
471   uword *bitmap = 0;
472   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
473
474   if (sm->num_workers < 2)
475     {
476       rv = VNET_API_ERROR_FEATURE_DISABLED;
477       goto send_reply;
478     }
479
480   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
481   rv = snat_set_workers (bitmap);
482   clib_bitmap_free (bitmap);
483
484 send_reply:
485   REPLY_MACRO (VL_API_SNAT_SET_WORKERS_REPLY);
486 }
487
488 static void *vl_api_snat_set_workers_t_print
489   (vl_api_snat_set_workers_t * mp, void *handle)
490 {
491   u8 *s;
492   uword *bitmap = 0;
493   u8 first = 1;
494   int i;
495   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
496
497   s = format (0, "SCRIPT: snat_set_workers ");
498   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
499   /* *INDENT-OFF* */
500   clib_bitmap_foreach (i, bitmap,
501     ({
502       if (first)
503         s = format (s, "%d", i);
504       else
505         s = format (s, ",%d", i);
506       first = 0;
507     }));
508   /* *INDENT-ON* */
509   clib_bitmap_free (bitmap);
510   FINISH;
511 }
512
513 static void
514   send_snat_worker_details
515   (u32 worker_index, unix_shared_memory_queue_t * q, u32 context)
516 {
517   vl_api_snat_worker_details_t *rmp;
518   snat_main_t *sm = &snat_main;
519   vlib_worker_thread_t *w =
520     vlib_worker_threads + worker_index + sm->first_worker_index;
521
522   rmp = vl_msg_api_alloc (sizeof (*rmp));
523   memset (rmp, 0, sizeof (*rmp));
524   rmp->_vl_msg_id = ntohs (VL_API_SNAT_WORKER_DETAILS + sm->msg_id_base);
525   rmp->context = context;
526   rmp->worker_index = htonl (worker_index);
527   rmp->lcore_id = htonl (w->lcore_id);
528   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
529
530   vl_msg_api_send_shmem (q, (u8 *) & rmp);
531 }
532
533 static void
534 vl_api_snat_worker_dump_t_handler (vl_api_snat_worker_dump_t * mp)
535 {
536   unix_shared_memory_queue_t *q;
537   snat_main_t *sm = &snat_main;
538   u32 *worker_index;
539
540   q = vl_api_client_index_to_input_queue (mp->client_index);
541   if (q == 0)
542     return;
543
544   /* *INDENT-OFF* */
545   vec_foreach (worker_index, sm->workers)
546     send_snat_worker_details(*worker_index, q, mp->context);
547   /* *INDENT-ON* */
548 }
549
550 static void *vl_api_snat_worker_dump_t_print
551   (vl_api_snat_worker_dump_t * mp, void *handle)
552 {
553   u8 *s;
554
555   s = format (0, "SCRIPT: snat_worker_dump ");
556
557   FINISH;
558 }
559
560 static void
561   vl_api_snat_add_del_interface_addr_t_handler
562   (vl_api_snat_add_del_interface_addr_t * mp)
563 {
564   snat_main_t *sm = &snat_main;
565   vl_api_snat_add_del_interface_addr_reply_t *rmp;
566   u8 is_del = mp->is_add == 0;
567   u32 sw_if_index = ntohl (mp->sw_if_index);
568   int rv = 0;
569
570   VALIDATE_SW_IF_INDEX (mp);
571
572   rv = snat_add_interface_address (sm, sw_if_index, is_del);
573
574   BAD_SW_IF_INDEX_LABEL;
575
576   REPLY_MACRO (VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
577 }
578
579 static void *vl_api_snat_add_del_interface_addr_t_print
580   (vl_api_snat_add_del_interface_addr_t * mp, void *handle)
581 {
582   u8 *s;
583
584   s = format (0, "SCRIPT: snat_add_del_interface_addr ");
585   s = format (s, "sw_if_index %d %s",
586               clib_host_to_net_u32 (mp->sw_if_index),
587               mp->is_add ? "" : "del");
588
589   FINISH;
590 }
591
592 static void
593   send_snat_interface_addr_details
594   (u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
595 {
596   vl_api_snat_interface_addr_details_t *rmp;
597   snat_main_t *sm = &snat_main;
598
599   rmp = vl_msg_api_alloc (sizeof (*rmp));
600   memset (rmp, 0, sizeof (*rmp));
601   rmp->_vl_msg_id =
602     ntohs (VL_API_SNAT_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
603   rmp->sw_if_index = ntohl (sw_if_index);
604   rmp->context = context;
605
606   vl_msg_api_send_shmem (q, (u8 *) & rmp);
607 }
608
609 static void
610   vl_api_snat_interface_addr_dump_t_handler
611   (vl_api_snat_interface_addr_dump_t * mp)
612 {
613   unix_shared_memory_queue_t *q;
614   snat_main_t *sm = &snat_main;
615   u32 *i;
616
617   q = vl_api_client_index_to_input_queue (mp->client_index);
618   if (q == 0)
619     return;
620
621   /* *INDENT-OFF* */
622   vec_foreach (i, sm->auto_add_sw_if_indices)
623     send_snat_interface_addr_details(*i, q, mp->context);
624   /* *INDENT-ON* */
625 }
626
627 static void *vl_api_snat_interface_addr_dump_t_print
628   (vl_api_snat_interface_addr_dump_t * mp, void *handle)
629 {
630   u8 *s;
631
632   s = format (0, "SCRIPT: snat_interface_addr_dump ");
633
634   FINISH;
635 }
636
637 static void
638   vl_api_snat_ipfix_enable_disable_t_handler
639   (vl_api_snat_ipfix_enable_disable_t * mp)
640 {
641   snat_main_t *sm = &snat_main;
642   vl_api_snat_ipfix_enable_disable_reply_t *rmp;
643   int rv = 0;
644
645   rv = snat_ipfix_logging_enable_disable (mp->enable,
646                                           clib_host_to_net_u32
647                                           (mp->domain_id),
648                                           clib_host_to_net_u16
649                                           (mp->src_port));
650
651   REPLY_MACRO (VL_API_SNAT_IPFIX_ENABLE_DISABLE_REPLY);
652 }
653
654 static void *vl_api_snat_ipfix_enable_disable_t_print
655   (vl_api_snat_ipfix_enable_disable_t * mp, void *handle)
656 {
657   u8 *s;
658
659   s = format (0, "SCRIPT: snat_ipfix_enable_disable ");
660   if (mp->domain_id)
661     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
662   if (mp->src_port)
663     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
664   if (!mp->enable)
665     s = format (s, "disable ");
666
667   FINISH;
668 }
669
670 static void
671   send_snat_user_details
672   (snat_user_t * u, unix_shared_memory_queue_t * q, u32 context)
673 {
674   vl_api_snat_user_details_t *rmp;
675   snat_main_t *sm = &snat_main;
676   fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
677
678   rmp = vl_msg_api_alloc (sizeof (*rmp));
679   memset (rmp, 0, sizeof (*rmp));
680   rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS + sm->msg_id_base);
681
682   rmp->vrf_id = ntohl (fib->ft_table_id);
683
684   rmp->is_ip4 = 1;
685   clib_memcpy (rmp->ip_address, &(u->addr), 4);
686   rmp->nsessions = ntohl (u->nsessions);
687   rmp->nstaticsessions = ntohl (u->nstaticsessions);
688   rmp->context = context;
689
690   vl_msg_api_send_shmem (q, (u8 *) & rmp);
691 }
692
693 static void
694 vl_api_snat_user_dump_t_handler (vl_api_snat_user_dump_t * mp)
695 {
696   unix_shared_memory_queue_t *q;
697   snat_main_t *sm = &snat_main;
698   snat_main_per_thread_data_t *tsm;
699   snat_user_t *u;
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 (tsm, sm->per_thread_data)
707     vec_foreach (u, tsm->users)
708       send_snat_user_details (u, q, mp->context);
709   /* *INDENT-ON* */
710 }
711
712 static void *vl_api_snat_user_dump_t_print
713   (vl_api_snat_user_dump_t * mp, void *handle)
714 {
715   u8 *s;
716
717   s = format (0, "SCRIPT: snat_user_dump ");
718
719   FINISH;
720 }
721
722 static void
723   send_snat_user_session_details
724   (snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
725 {
726   vl_api_snat_user_session_details_t *rmp;
727   snat_main_t *sm = &snat_main;
728
729   rmp = vl_msg_api_alloc (sizeof (*rmp));
730   memset (rmp, 0, sizeof (*rmp));
731   rmp->_vl_msg_id =
732     ntohs (VL_API_SNAT_USER_SESSION_DETAILS + sm->msg_id_base);
733   rmp->is_ip4 = 1;
734   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
735   rmp->outside_port = s->out2in.port;
736   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
737   rmp->inside_port = s->in2out.port;
738   rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
739   rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
740   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
741   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
742   rmp->total_pkts = ntohl (s->total_pkts);
743   rmp->context = context;
744
745   vl_msg_api_send_shmem (q, (u8 *) & rmp);
746 }
747
748 static void
749   vl_api_snat_user_session_dump_t_handler
750   (vl_api_snat_user_session_dump_t * mp)
751 {
752   unix_shared_memory_queue_t *q;
753   snat_main_t *sm = &snat_main;
754   snat_main_per_thread_data_t *tsm;
755   snat_session_t *s;
756   clib_bihash_kv_8_8_t key, value;
757   snat_user_key_t ukey;
758   snat_user_t *u;
759   u32 session_index, head_index, elt_index;
760   dlist_elt_t *head, *elt;
761
762   q = vl_api_client_index_to_input_queue (mp->client_index);
763   if (q == 0)
764     return;
765   if (!mp->is_ip4)
766     return;
767
768   clib_memcpy (&ukey.addr, mp->ip_address, 4);
769   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
770   key.key = ukey.as_u64;
771   if (!clib_bihash_search_8_8 (&sm->worker_by_in, &key, &value))
772     tsm = vec_elt_at_index (sm->per_thread_data, value.value);
773   else
774     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
775   if (clib_bihash_search_8_8 (&sm->user_hash, &key, &value))
776     return;
777   u = pool_elt_at_index (tsm->users, value.value);
778   if (!u->nsessions && !u->nstaticsessions)
779     return;
780
781   head_index = u->sessions_per_user_list_head_index;
782   head = pool_elt_at_index (tsm->list_pool, head_index);
783   elt_index = head->next;
784   elt = pool_elt_at_index (tsm->list_pool, elt_index);
785   session_index = elt->value;
786   while (session_index != ~0)
787     {
788       s = pool_elt_at_index (tsm->sessions, session_index);
789
790       send_snat_user_session_details (s, q, mp->context);
791
792       elt_index = elt->next;
793       elt = pool_elt_at_index (tsm->list_pool, elt_index);
794       session_index = elt->value;
795     }
796 }
797
798 static void *vl_api_snat_user_session_dump_t_print
799   (vl_api_snat_user_session_dump_t * mp, void *handle)
800 {
801   u8 *s;
802
803   s = format (0, "SCRIPT: snat_user_session_dump ");
804   s = format (s, "ip_address %U vrf_id %d\n",
805               format_ip4_address, mp->ip_address,
806               clib_net_to_host_u32 (mp->vrf_id));
807
808   FINISH;
809 }
810
811 /****************************/
812 /*** detrministic NAT/CGN ***/
813 /****************************/
814
815 static void
816 vl_api_snat_add_det_map_t_handler (vl_api_snat_add_det_map_t * mp)
817 {
818   snat_main_t *sm = &snat_main;
819   vl_api_snat_add_det_map_reply_t *rmp;
820   int rv = 0;
821   ip4_address_t in_addr, out_addr;
822
823   clib_memcpy (&in_addr, mp->in_addr, 4);
824   clib_memcpy (&out_addr, mp->out_addr, 4);
825   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
826                          mp->out_plen, mp->is_add);
827
828   REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
829 }
830
831 static void *vl_api_snat_add_det_map_t_print
832   (vl_api_snat_add_det_map_t * mp, void *handle)
833 {
834   u8 *s;
835
836   s = format (0, "SCRIPT: snat_add_det_map ");
837   s = format (s, "inside address %U/%d outside address %U/%d\n",
838               format_ip4_address, mp->in_addr, mp->in_plen,
839               format_ip4_address, mp->out_addr, mp->out_plen);
840
841   FINISH;
842 }
843
844 static void
845 vl_api_snat_det_forward_t_handler (vl_api_snat_det_forward_t * mp)
846 {
847   snat_main_t *sm = &snat_main;
848   vl_api_snat_det_forward_reply_t *rmp;
849   int rv = 0;
850   u16 lo_port = 0, hi_port = 0;
851   snat_det_map_t *dm;
852   ip4_address_t in_addr, out_addr;
853
854   out_addr.as_u32 = 0;
855   clib_memcpy (&in_addr, mp->in_addr, 4);
856   dm = snat_det_map_by_user (sm, &in_addr);
857   if (!dm)
858     {
859       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
860       goto send_reply;
861     }
862
863   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
864   hi_port = lo_port + dm->ports_per_host - 1;
865
866 send_reply:
867   /* *INDENT-OFF* */
868   REPLY_MACRO2 (VL_API_SNAT_DET_FORWARD_REPLY,
869   ({
870     rmp->out_port_lo = ntohs (lo_port);
871     rmp->out_port_hi = ntohs (hi_port);
872     rmp->is_ip4 = 1;
873     memset (rmp->out_addr, 0, 16);
874     clib_memcpy (rmp->out_addr, &out_addr, 4);
875   }))
876   /* *INDENT-ON* */
877 }
878
879 static void *vl_api_snat_det_forward_t_print
880   (vl_api_snat_det_forward_t * mp, void *handle)
881 {
882   u8 *s;
883
884   s = format (0, "SCRIPT: smat_det_forward_t");
885   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
886
887   FINISH;
888 }
889
890 static void
891 vl_api_snat_det_reverse_t_handler (vl_api_snat_det_reverse_t * mp)
892 {
893   snat_main_t *sm = &snat_main;
894   vl_api_snat_det_reverse_reply_t *rmp;
895   int rv = 0;
896   ip4_address_t out_addr, in_addr;
897   snat_det_map_t *dm;
898
899   in_addr.as_u32 = 0;
900   clib_memcpy (&out_addr, mp->out_addr, 4);
901   dm = snat_det_map_by_out (sm, &out_addr);
902   if (!dm)
903     {
904       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
905       goto send_reply;
906     }
907
908   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
909
910 send_reply:
911   /* *INDENT-OFF* */
912   REPLY_MACRO2 (VL_API_SNAT_DET_REVERSE_REPLY,
913   ({
914     rmp->is_ip4 = 1;
915     memset (rmp->in_addr, 0, 16);
916     clib_memcpy (rmp->in_addr, &in_addr, 4);
917   }))
918   /* *INDENT-ON* */
919 }
920
921 static void *vl_api_snat_det_reverse_t_print
922   (vl_api_snat_det_reverse_t * mp, void *handle)
923 {
924   u8 *s;
925
926   s = format (0, "SCRIPT: smat_det_reverse_t");
927   s = format (s, "outside ip address %U outside port %d",
928               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
929
930   FINISH;
931 }
932
933 static void
934   sent_snat_det_map_details
935   (snat_det_map_t * m, unix_shared_memory_queue_t * q, u32 context)
936 {
937   vl_api_snat_det_map_details_t *rmp;
938   snat_main_t *sm = &snat_main;
939
940   rmp = vl_msg_api_alloc (sizeof (*rmp));
941   memset (rmp, 0, sizeof (*rmp));
942   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS + sm->msg_id_base);
943   rmp->is_ip4 = 1;
944   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
945   rmp->in_plen = m->in_plen;
946   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
947   rmp->out_plen = m->out_plen;
948   rmp->sharing_ratio = htonl (m->sharing_ratio);
949   rmp->ports_per_host = htons (m->ports_per_host);
950   rmp->ses_num = htonl (m->ses_num);
951   rmp->context = context;
952
953   vl_msg_api_send_shmem (q, (u8 *) & rmp);
954 }
955
956 static void
957 vl_api_snat_det_map_dump_t_handler (vl_api_snat_det_map_dump_t * mp)
958 {
959   unix_shared_memory_queue_t *q;
960   snat_main_t *sm = &snat_main;
961   snat_det_map_t *m;
962
963   q = vl_api_client_index_to_input_queue (mp->client_index);
964   if (q == 0)
965     return;
966
967   /* *INDENT-OFF* */
968   vec_foreach(m, sm->det_maps)
969     sent_snat_det_map_details(m, q, mp->context);
970   /* *INDENT-ON* */
971 }
972
973 static void *vl_api_snat_det_map_dump_t_print
974   (vl_api_snat_det_map_dump_t * mp, void *handle)
975 {
976   u8 *s;
977
978   s = format (0, "SCRIPT: snat_det_map_dump ");
979
980   FINISH;
981 }
982
983 static void
984 vl_api_snat_det_set_timeouts_t_handler (vl_api_snat_det_set_timeouts_t * mp)
985 {
986   snat_main_t *sm = &snat_main;
987   vl_api_snat_det_set_timeouts_reply_t *rmp;
988   int rv = 0;
989
990   sm->udp_timeout = ntohl (mp->udp);
991   sm->tcp_established_timeout = ntohl (mp->tcp_established);
992   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
993   sm->icmp_timeout = ntohl (mp->icmp);
994
995   REPLY_MACRO (VL_API_SNAT_DET_SET_TIMEOUTS_REPLY);
996 }
997
998 static void *vl_api_snat_det_set_timeouts_t_print
999   (vl_api_snat_det_set_timeouts_t * mp, void *handle)
1000 {
1001   u8 *s;
1002
1003   s = format (0, "SCRIPT: snat_det_set_timeouts ");
1004   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
1005               ntohl (mp->udp),
1006               ntohl (mp->tcp_established),
1007               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
1008
1009   FINISH;
1010 }
1011
1012 static void
1013 vl_api_snat_det_get_timeouts_t_handler (vl_api_snat_det_get_timeouts_t * mp)
1014 {
1015   snat_main_t *sm = &snat_main;
1016   vl_api_snat_det_get_timeouts_reply_t *rmp;
1017   int rv = 0;
1018
1019   /* *INDENT-OFF* */
1020   REPLY_MACRO2 (VL_API_SNAT_DET_GET_TIMEOUTS_REPLY,
1021   ({
1022     rmp->udp = htonl (sm->udp_timeout);
1023     rmp->tcp_established = htonl (sm->tcp_established_timeout);
1024     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
1025     rmp->icmp = htonl (sm->icmp_timeout);
1026   }))
1027   /* *INDENT-ON* */
1028 }
1029
1030 static void *vl_api_snat_det_get_timeouts_t_print
1031   (vl_api_snat_det_get_timeouts_t * mp, void *handle)
1032 {
1033   u8 *s;
1034
1035   s = format (0, "SCRIPT: snat_det_get_timeouts");
1036
1037   FINISH;
1038 }
1039
1040 static void
1041   vl_api_snat_det_close_session_out_t_handler
1042   (vl_api_snat_det_close_session_out_t * mp)
1043 {
1044   snat_main_t *sm = &snat_main;
1045   vl_api_snat_det_close_session_out_reply_t *rmp;
1046   ip4_address_t out_addr, ext_addr, in_addr;
1047   snat_det_out_key_t key;
1048   snat_det_map_t *dm;
1049   snat_det_session_t *ses;
1050   int rv = 0;
1051
1052   clib_memcpy (&out_addr, mp->out_addr, 4);
1053   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1054
1055   dm = snat_det_map_by_out (sm, &out_addr);
1056   if (!dm)
1057     {
1058       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1059       goto send_reply;
1060     }
1061   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1062   key.ext_host_addr = ext_addr;
1063   key.ext_host_port = mp->ext_port;
1064   key.out_port = mp->out_port;
1065   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1066   if (!ses)
1067     {
1068       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1069       goto send_reply;
1070     }
1071   snat_det_ses_close (dm, ses);
1072
1073 send_reply:
1074   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1075 }
1076
1077 static void *vl_api_snat_det_close_session_out_t_print
1078   (vl_api_snat_det_close_session_out_t * mp, void *handle)
1079 {
1080   u8 *s;
1081
1082   s = format (0, "SCRIPT: snat_det_close_session_out ");
1083   s = format (s, "out_addr %U out_port %d "
1084               "ext_addr %U ext_port %d\n",
1085               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1086               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1087
1088   FINISH;
1089 }
1090
1091 static void
1092   vl_api_snat_det_close_session_in_t_handler
1093   (vl_api_snat_det_close_session_in_t * mp)
1094 {
1095   snat_main_t *sm = &snat_main;
1096   vl_api_snat_det_close_session_in_reply_t *rmp;
1097   ip4_address_t in_addr, ext_addr;
1098   snat_det_out_key_t key;
1099   snat_det_map_t *dm;
1100   snat_det_session_t *ses;
1101   int rv = 0;
1102
1103   clib_memcpy (&in_addr, mp->in_addr, 4);
1104   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1105
1106   dm = snat_det_map_by_user (sm, &in_addr);
1107   if (!dm)
1108     {
1109       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1110       goto send_reply;
1111     }
1112   key.ext_host_addr = ext_addr;
1113   key.ext_host_port = mp->ext_port;
1114   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
1115   if (!ses)
1116     {
1117       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1118       goto send_reply;
1119     }
1120   snat_det_ses_close (dm, ses);
1121
1122 send_reply:
1123   REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
1124 }
1125
1126 static void *vl_api_snat_det_close_session_in_t_print
1127   (vl_api_snat_det_close_session_in_t * mp, void *handle)
1128 {
1129   u8 *s;
1130   s = format (0, "SCRIPT: snat_det_close_session_in ");
1131   s = format (s, "in_addr %U in_port %d "
1132               "ext_addr %U ext_port %d\n",
1133               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
1134               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1135
1136   FINISH;
1137 }
1138
1139 static void
1140   send_snat_det_session_details
1141   (snat_det_session_t * s, unix_shared_memory_queue_t * q, u32 context)
1142 {
1143   vl_api_snat_det_session_details_t *rmp;
1144   snat_main_t *sm = &snat_main;
1145
1146   rmp = vl_msg_api_alloc (sizeof (*rmp));
1147   memset (rmp, 0, sizeof (*rmp));
1148   rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_SESSION_DETAILS + sm->msg_id_base);
1149   rmp->is_ip4 = 1;
1150   rmp->in_port = s->in_port;
1151   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
1152   rmp->ext_port = s->out.ext_host_port;
1153   rmp->out_port = s->out.out_port;
1154   rmp->state = s->state;
1155   rmp->expire = ntohl (s->expire);
1156   rmp->context = context;
1157
1158   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1159 }
1160
1161 static void
1162 vl_api_snat_det_session_dump_t_handler (vl_api_snat_det_session_dump_t * mp)
1163 {
1164   unix_shared_memory_queue_t *q;
1165   snat_main_t *sm = &snat_main;
1166   ip4_address_t user_addr;
1167   snat_det_map_t *dm;
1168   snat_det_session_t *s, empty_ses;
1169   u16 i;
1170
1171   q = vl_api_client_index_to_input_queue (mp->client_index);
1172   if (q == 0)
1173     return;
1174   if (!mp->is_ip4)
1175     return;
1176
1177   memset (&empty_ses, 0, sizeof (empty_ses));
1178   clib_memcpy (&user_addr, mp->user_addr, 4);
1179   dm = snat_det_map_by_user (sm, &user_addr);
1180   if (!dm)
1181     return;
1182
1183   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
1184   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
1185     {
1186       if (s->out.as_u64)
1187         send_snat_det_session_details (s, q, mp->context);
1188       s++;
1189     }
1190 }
1191
1192 static void *vl_api_snat_det_session_dump_t_print
1193   (vl_api_snat_det_session_dump_t * mp, void *handle)
1194 {
1195   u8 *s;
1196
1197   s = format (0, "SCRIPT: snat_det_session_dump ");
1198   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
1199
1200   FINISH;
1201 }
1202
1203 /*************/
1204 /*** NAT64 ***/
1205 /*************/
1206
1207 static void
1208   vl_api_nat64_add_del_pool_addr_range_t_handler
1209   (vl_api_nat64_add_del_pool_addr_range_t * mp)
1210 {
1211   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
1212   snat_main_t *sm = &snat_main;
1213   int rv = 0;
1214   ip4_address_t this_addr;
1215   u32 start_host_order, end_host_order;
1216   u32 vrf_id;
1217   int i, count;
1218   u32 *tmp;
1219
1220   tmp = (u32 *) mp->start_addr;
1221   start_host_order = clib_host_to_net_u32 (tmp[0]);
1222   tmp = (u32 *) mp->end_addr;
1223   end_host_order = clib_host_to_net_u32 (tmp[0]);
1224
1225   count = (end_host_order - start_host_order) + 1;
1226
1227   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
1228
1229   memcpy (&this_addr.as_u8, mp->start_addr, 4);
1230
1231   for (i = 0; i < count; i++)
1232     {
1233       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
1234         goto send_reply;
1235
1236       increment_v4_address (&this_addr);
1237     }
1238
1239 send_reply:
1240   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
1241 }
1242
1243 static void *vl_api_nat64_add_del_pool_addr_range_t_print
1244   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
1245 {
1246   u8 *s;
1247
1248   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
1249   s = format (s, "%U - %U vrf_id %u %s\n",
1250               format_ip4_address, mp->start_addr,
1251               format_ip4_address, mp->end_addr,
1252               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
1253
1254   FINISH;
1255 }
1256
1257 typedef struct nat64_api_walk_ctx_t_
1258 {
1259   unix_shared_memory_queue_t *q;
1260   u32 context;
1261 } nat64_api_walk_ctx_t;
1262
1263 static int
1264 nat64_api_pool_walk (snat_address_t * a, void *arg)
1265 {
1266   vl_api_nat64_pool_addr_details_t *rmp;
1267   snat_main_t *sm = &snat_main;
1268   nat64_api_walk_ctx_t *ctx = arg;
1269
1270   rmp = vl_msg_api_alloc (sizeof (*rmp));
1271   memset (rmp, 0, sizeof (*rmp));
1272   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
1273   clib_memcpy (rmp->address, &(a->addr), 4);
1274   if (a->fib_index != ~0)
1275     {
1276       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
1277       if (!fib)
1278         return -1;
1279       rmp->vrf_id = ntohl (fib->ft_table_id);
1280     }
1281   else
1282     rmp->vrf_id = ~0;
1283   rmp->context = ctx->context;
1284
1285   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1286
1287   return 0;
1288 }
1289
1290 static void
1291 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
1292 {
1293   unix_shared_memory_queue_t *q;
1294
1295   q = vl_api_client_index_to_input_queue (mp->client_index);
1296   if (q == 0)
1297     return;
1298
1299   nat64_api_walk_ctx_t ctx = {
1300     .q = q,
1301     .context = mp->context,
1302   };
1303
1304   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
1305 }
1306
1307 static void *
1308 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
1309                                      void *handle)
1310 {
1311   u8 *s;
1312
1313   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
1314
1315   FINISH;
1316 }
1317
1318 static void
1319 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
1320                                           mp)
1321 {
1322   snat_main_t *sm = &snat_main;
1323   vl_api_nat64_add_del_interface_reply_t *rmp;
1324   int rv = 0;
1325
1326   VALIDATE_SW_IF_INDEX (mp);
1327
1328   rv =
1329     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
1330                              mp->is_add);
1331
1332   BAD_SW_IF_INDEX_LABEL;
1333
1334   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
1335 }
1336
1337 static void *
1338 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
1339                                         void *handle)
1340 {
1341   u8 *s;
1342
1343   s = format (0, "SCRIPT: nat64_add_del_interface ");
1344   s = format (s, "sw_if_index %d %s %s",
1345               clib_host_to_net_u32 (mp->sw_if_index),
1346               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
1347
1348   FINISH;
1349 }
1350
1351 static int
1352 nat64_api_interface_walk (snat_interface_t * i, void *arg)
1353 {
1354   vl_api_nat64_interface_details_t *rmp;
1355   snat_main_t *sm = &snat_main;
1356   nat64_api_walk_ctx_t *ctx = arg;
1357
1358   rmp = vl_msg_api_alloc (sizeof (*rmp));
1359   memset (rmp, 0, sizeof (*rmp));
1360   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
1361   rmp->sw_if_index = ntohl (i->sw_if_index);
1362   rmp->is_inside = i->is_inside;
1363   rmp->context = ctx->context;
1364
1365   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1366
1367   return 0;
1368 }
1369
1370 static void
1371 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
1372 {
1373   unix_shared_memory_queue_t *q;
1374
1375   q = vl_api_client_index_to_input_queue (mp->client_index);
1376   if (q == 0)
1377     return;
1378
1379   nat64_api_walk_ctx_t ctx = {
1380     .q = q,
1381     .context = mp->context,
1382   };
1383
1384   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
1385 }
1386
1387 static void *
1388 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
1389                                      void *handle)
1390 {
1391   u8 *s;
1392
1393   s = format (0, "SCRIPT: snat_interface_dump ");
1394
1395   FINISH;
1396 }
1397
1398 static void
1399   vl_api_nat64_add_del_static_bib_t_handler
1400   (vl_api_nat64_add_del_static_bib_t * mp)
1401 {
1402   snat_main_t *sm = &snat_main;
1403   vl_api_nat64_add_del_static_bib_reply_t *rmp;
1404   ip6_address_t in_addr;
1405   ip4_address_t out_addr;
1406   int rv = 0;
1407
1408   memcpy (&in_addr.as_u8, mp->i_addr, 16);
1409   memcpy (&out_addr.as_u8, mp->o_addr, 4);
1410
1411   rv =
1412     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
1413                                     clib_net_to_host_u16 (mp->i_port),
1414                                     clib_net_to_host_u16 (mp->o_port),
1415                                     mp->proto,
1416                                     clib_net_to_host_u32 (mp->vrf_id),
1417                                     mp->is_add);
1418
1419   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
1420 }
1421
1422 static void *vl_api_nat64_add_del_static_bib_t_print
1423   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
1424 {
1425   u8 *s;
1426
1427   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
1428   s = format (s, "protocol %d i_addr %U o_addr %U ",
1429               mp->proto,
1430               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
1431
1432   if (mp->vrf_id != ~0)
1433     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1434
1435   FINISH;
1436 }
1437
1438 static int
1439 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
1440 {
1441   vl_api_nat64_bib_details_t *rmp;
1442   snat_main_t *sm = &snat_main;
1443   nat64_api_walk_ctx_t *ctx = arg;
1444   fib_table_t *fib;
1445
1446   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
1447   if (!fib)
1448     return -1;
1449
1450   rmp = vl_msg_api_alloc (sizeof (*rmp));
1451   memset (rmp, 0, sizeof (*rmp));
1452   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
1453   rmp->context = ctx->context;
1454   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
1455   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
1456   rmp->i_port = bibe->in_port;
1457   rmp->o_port = bibe->out_port;
1458   rmp->vrf_id = ntohl (fib->ft_table_id);
1459   rmp->proto = snat_proto_to_ip_proto (bibe->proto);
1460   rmp->is_static = bibe->is_static;
1461   rmp->ses_num = ntohl (bibe->ses_num);
1462
1463   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1464
1465   return 0;
1466 }
1467
1468 static void
1469 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
1470 {
1471   unix_shared_memory_queue_t *q;
1472   nat64_main_t *nm = &nat64_main;
1473   snat_protocol_t proto;
1474
1475   q = vl_api_client_index_to_input_queue (mp->client_index);
1476   if (q == 0)
1477     return;
1478
1479   nat64_api_walk_ctx_t ctx = {
1480     .q = q,
1481     .context = mp->context,
1482   };
1483
1484   proto = ip_proto_to_snat_proto (mp->proto);
1485
1486   nat64_db_bib_walk (&nm->db, proto, nat64_api_bib_walk, &ctx);
1487 }
1488
1489 static void *
1490 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
1491 {
1492   u8 *s;
1493
1494   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
1495
1496   FINISH;
1497 }
1498
1499 static void
1500 vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
1501 {
1502   snat_main_t *sm = &snat_main;
1503   vl_api_nat64_set_timeouts_reply_t *rmp;
1504   int rv = 0;
1505
1506   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
1507   if (rv)
1508     goto send_reply;
1509   rv = nat64_set_udp_timeout (ntohl (mp->udp));
1510   if (rv)
1511     goto send_reply;
1512   rv =
1513     nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
1514                             ntohl (mp->tcp_incoming_syn));
1515
1516 send_reply:
1517   REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
1518 }
1519
1520 static void *vl_api_nat64_set_timeouts_t_print
1521   (vl_api_nat64_set_timeouts_t * mp, void *handle)
1522 {
1523   u8 *s;
1524
1525   s = format (0, "SCRIPT: nat64_set_timeouts ");
1526   s =
1527     format (s,
1528             "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
1529             ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
1530             ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
1531
1532   FINISH;
1533 }
1534
1535 static void
1536 vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
1537 {
1538   snat_main_t *sm = &snat_main;
1539   vl_api_nat64_get_timeouts_reply_t *rmp;
1540   int rv = 0;
1541
1542   /* *INDENT-OFF* */
1543   REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
1544   ({
1545     rmp->udp = htonl (nat64_get_udp_timeout());
1546     rmp->icmp = htonl (nat64_get_icmp_timeout());
1547     rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
1548     rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
1549     rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
1550   }))
1551   /* *INDENT-ON* */
1552 }
1553
1554 static void *vl_api_nat64_get_timeouts_t_print
1555   (vl_api_nat64_get_timeouts_t * mp, void *handle)
1556 {
1557   u8 *s;
1558
1559   s = format (0, "SCRIPT: nat64_get_timeouts");
1560
1561   FINISH;
1562 }
1563
1564 static int
1565 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
1566 {
1567   vl_api_nat64_st_details_t *rmp;
1568   snat_main_t *sm = &snat_main;
1569   nat64_api_walk_ctx_t *ctx = arg;
1570   nat64_main_t *nm = &nat64_main;
1571   nat64_db_bib_entry_t *bibe;
1572   fib_table_t *fib;
1573
1574   bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
1575   if (!bibe)
1576     return -1;
1577
1578   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
1579   if (!fib)
1580     return -1;
1581
1582   rmp = vl_msg_api_alloc (sizeof (*rmp));
1583   memset (rmp, 0, sizeof (*rmp));
1584   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
1585   rmp->context = ctx->context;
1586   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
1587   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
1588   rmp->il_port = bibe->in_port;
1589   rmp->ol_port = bibe->out_port;
1590   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
1591   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
1592   rmp->il_port = ste->r_port;
1593   rmp->vrf_id = ntohl (fib->ft_table_id);
1594   rmp->proto = snat_proto_to_ip_proto (ste->proto);
1595
1596   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
1597
1598   return 0;
1599 }
1600
1601 static void
1602 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
1603 {
1604   unix_shared_memory_queue_t *q;
1605   nat64_main_t *nm = &nat64_main;
1606   snat_protocol_t proto;
1607
1608   q = vl_api_client_index_to_input_queue (mp->client_index);
1609   if (q == 0)
1610     return;
1611
1612   nat64_api_walk_ctx_t ctx = {
1613     .q = q,
1614     .context = mp->context,
1615   };
1616
1617   proto = ip_proto_to_snat_proto (mp->proto);
1618
1619   nat64_db_st_walk (&nm->db, proto, nat64_api_st_walk, &ctx);
1620 }
1621
1622 static void *
1623 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
1624 {
1625   u8 *s;
1626
1627   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
1628
1629   FINISH;
1630 }
1631
1632 /* List of message types that this plugin understands */
1633 #define foreach_snat_plugin_api_msg                                     \
1634 _(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range)                       \
1635 _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature)       \
1636 _(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping)                     \
1637 _(SNAT_CONTROL_PING, snat_control_ping)                                 \
1638 _(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump)                   \
1639 _(SNAT_SHOW_CONFIG, snat_show_config)                                   \
1640 _(SNAT_ADDRESS_DUMP, snat_address_dump)                                 \
1641 _(SNAT_INTERFACE_DUMP, snat_interface_dump)                             \
1642 _(SNAT_SET_WORKERS, snat_set_workers)                                   \
1643 _(SNAT_WORKER_DUMP, snat_worker_dump)                                   \
1644 _(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr)             \
1645 _(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump)                   \
1646 _(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable)                 \
1647 _(SNAT_USER_DUMP, snat_user_dump)                                       \
1648 _(SNAT_USER_SESSION_DUMP, snat_user_session_dump)                       \
1649 _(SNAT_ADD_DET_MAP, snat_add_det_map)                                   \
1650 _(SNAT_DET_FORWARD, snat_det_forward)                                   \
1651 _(SNAT_DET_REVERSE, snat_det_reverse)                                   \
1652 _(SNAT_DET_MAP_DUMP, snat_det_map_dump)                                 \
1653 _(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts)                         \
1654 _(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts)                         \
1655 _(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out)               \
1656 _(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in)                 \
1657 _(SNAT_DET_SESSION_DUMP, snat_det_session_dump)                         \
1658 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
1659 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
1660 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
1661 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
1662 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
1663 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
1664 _(NAT64_SET_TIMEOUTS, nat64_set_timeouts)                               \
1665 _(NAT64_GET_TIMEOUTS, nat64_get_timeouts)                               \
1666 _(NAT64_ST_DUMP, nat64_st_dump)
1667
1668 /* Set up the API message handling tables */
1669 static clib_error_t *
1670 snat_plugin_api_hookup (vlib_main_t * vm)
1671 {
1672   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
1673 #define _(N,n)                                                  \
1674     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
1675                            #n,                                  \
1676                            vl_api_##n##_t_handler,              \
1677                            vl_noop_handler,                     \
1678                            vl_api_##n##_t_endian,               \
1679                            vl_api_##n##_t_print,                \
1680                            sizeof(vl_api_##n##_t), 1);
1681   foreach_snat_plugin_api_msg;
1682 #undef _
1683
1684   return 0;
1685 }
1686
1687 #define vl_msg_name_crc_list
1688 #include <snat/snat_all_api_h.h>
1689 #undef vl_msg_name_crc_list
1690
1691 static void
1692 setup_message_id_table (snat_main_t * sm, api_main_t * am)
1693 {
1694 #define _(id,n,crc) \
1695   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
1696   foreach_vl_msg_name_crc_snat;
1697 #undef _
1698 }
1699
1700 static void
1701 plugin_custom_dump_configure (snat_main_t * sm)
1702 {
1703 #define _(n,f) sm->api_main->msg_print_handlers \
1704   [VL_API_##n + sm->msg_id_base]                \
1705     = (void *) vl_api_##f##_t_print;
1706   foreach_snat_plugin_api_msg;
1707 #undef _
1708 }
1709
1710 clib_error_t *
1711 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
1712 {
1713   u8 *name;
1714   clib_error_t *error = 0;
1715
1716   name = format (0, "snat_%08x%c", api_version, 0);
1717
1718   /* Ask for a correctly-sized block of API message decode slots */
1719   sm->msg_id_base =
1720     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
1721
1722   error = snat_plugin_api_hookup (vm);
1723
1724   /* Add our API messages to the global name_crc hash table */
1725   setup_message_id_table (sm, sm->api_main);
1726
1727   plugin_custom_dump_configure (sm);
1728
1729   vec_free (name);
1730
1731   return error;
1732 }
1733
1734 /*
1735  * fd.io coding-style-patch-verification: ON
1736  *
1737  * Local Variables:
1738  * eval: (c-set-style "gnu")
1739  * End:
1740  */