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