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