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