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