api: refactor format_vl_api_prefix_t return keys
[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   len = vl_api_string_len (&mp->tag);
1194
1195   if (len > 64)
1196     {
1197       rv = VNET_API_ERROR_INVALID_VALUE;
1198       goto send_reply;
1199     }
1200
1201   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
1202   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
1203
1204   if (!(mp->flags & NAT_API_IS_ADDR_ONLY))
1205     {
1206       local_port = clib_net_to_host_u16 (mp->local_port);
1207       external_port = clib_net_to_host_u16 (mp->external_port);
1208     }
1209
1210   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1211   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
1212   proto = ip_proto_to_snat_proto (mp->protocol);
1213
1214   if (mp->flags & NAT_API_IS_TWICE_NAT)
1215     twice_nat = TWICE_NAT;
1216   else if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
1217     twice_nat = TWICE_NAT_SELF;
1218
1219   tag = vec_new (u8, len);
1220
1221   memcpy (tag, mp->tag.buf, len);
1222   vec_terminate_c_string (tag);
1223
1224   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
1225                                 external_port, vrf_id,
1226                                 mp->flags & NAT_API_IS_ADDR_ONLY,
1227                                 external_sw_if_index, proto,
1228                                 mp->is_add, twice_nat,
1229                                 mp->flags & NAT_API_IS_OUT2IN_ONLY, tag, 0);
1230   vec_free (tag);
1231
1232 send_reply:
1233   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
1234 }
1235
1236 static void *vl_api_nat44_add_del_static_mapping_t_print
1237   (vl_api_nat44_add_del_static_mapping_t * mp, void *handle)
1238 {
1239   u8 *s;
1240
1241   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1242   s = format (s, "protocol %d local_addr %U external_addr %U ",
1243               mp->protocol,
1244               format_ip4_address, mp->local_ip_address,
1245               format_ip4_address, mp->external_ip_address);
1246
1247   if (!(mp->flags & NAT_API_IS_ADDR_ONLY))
1248     s = format (s, "local_port %d external_port %d ",
1249                 clib_net_to_host_u16 (mp->local_port),
1250                 clib_net_to_host_u16 (mp->external_port));
1251
1252   s = format (s, "twice_nat %d out2in_only %d ",
1253               mp->flags & NAT_API_IS_TWICE_NAT,
1254               mp->flags & NAT_API_IS_OUT2IN_ONLY);
1255
1256   if (mp->vrf_id != ~0)
1257     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1258
1259   if (mp->external_sw_if_index != ~0)
1260     s = format (s, "external_sw_if_index %d",
1261                 clib_net_to_host_u32 (mp->external_sw_if_index));
1262   FINISH;
1263 }
1264
1265 static void
1266 send_nat44_static_mapping_details (snat_static_mapping_t * m,
1267                                    vl_api_registration_t * reg, u32 context)
1268 {
1269   vl_api_nat44_static_mapping_details_t *rmp;
1270   snat_main_t *sm = &snat_main;
1271   u32 len = sizeof (*rmp);
1272
1273   if (m->tag)
1274     {
1275       len += vec_len (m->tag);
1276       rmp = vl_msg_api_alloc (len);
1277       clib_memset (rmp, 0, len);
1278       vl_api_to_api_string (vec_len (m->tag), (char *) m->tag, &rmp->tag);
1279     }
1280   else
1281     {
1282       rmp = vl_msg_api_alloc (len);
1283       clib_memset (rmp, 0, len);
1284     }
1285
1286   rmp->_vl_msg_id =
1287     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1288
1289   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
1290   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
1291   rmp->external_sw_if_index = ~0;
1292   rmp->vrf_id = htonl (m->vrf_id);
1293   rmp->context = context;
1294
1295   if (m->twice_nat == TWICE_NAT)
1296     rmp->flags |= NAT_API_IS_TWICE_NAT;
1297   else if (m->twice_nat == TWICE_NAT_SELF)
1298     rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
1299
1300   if (is_out2in_only_static_mapping (m))
1301     rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
1302
1303   if (is_addr_only_static_mapping (m))
1304     {
1305       rmp->flags |= NAT_API_IS_ADDR_ONLY;
1306     }
1307   else
1308     {
1309       rmp->protocol = snat_proto_to_ip_proto (m->proto);
1310       rmp->external_port = htons (m->external_port);
1311       rmp->local_port = htons (m->local_port);
1312     }
1313
1314   vl_api_send_msg (reg, (u8 *) rmp);
1315 }
1316
1317 static void
1318 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
1319                                        vl_api_registration_t * reg,
1320                                        u32 context)
1321 {
1322   vl_api_nat44_static_mapping_details_t *rmp;
1323   snat_main_t *sm = &snat_main;
1324   u32 len = sizeof (*rmp);
1325
1326   if (m->tag)
1327     {
1328       len += vec_len (m->tag);
1329       rmp = vl_msg_api_alloc (len);
1330       clib_memset (rmp, 0, len);
1331       vl_api_to_api_string (vec_len (m->tag), (char *) m->tag, &rmp->tag);
1332     }
1333   else
1334     {
1335       rmp = vl_msg_api_alloc (len);
1336       clib_memset (rmp, 0, len);
1337     }
1338
1339   rmp->_vl_msg_id =
1340     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1341   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
1342   rmp->external_sw_if_index = htonl (m->sw_if_index);
1343   rmp->vrf_id = htonl (m->vrf_id);
1344   rmp->context = context;
1345
1346   if (m->twice_nat)
1347     rmp->flags |= NAT_API_IS_TWICE_NAT;
1348
1349   if (m->addr_only)
1350     {
1351       rmp->flags |= NAT_API_IS_ADDR_ONLY;
1352     }
1353   else
1354     {
1355       rmp->protocol = snat_proto_to_ip_proto (m->proto);
1356       rmp->external_port = htons (m->e_port);
1357       rmp->local_port = htons (m->l_port);
1358     }
1359
1360   vl_api_send_msg (reg, (u8 *) rmp);
1361 }
1362
1363 static void
1364 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
1365                                             * mp)
1366 {
1367   vl_api_registration_t *reg;
1368   snat_main_t *sm = &snat_main;
1369   snat_static_mapping_t *m;
1370   snat_static_map_resolve_t *rp;
1371   int j;
1372
1373   if (sm->deterministic)
1374     return;
1375
1376   reg = vl_api_client_index_to_registration (mp->client_index);
1377   if (!reg)
1378     return;
1379
1380   /* *INDENT-OFF* */
1381   pool_foreach (m, sm->static_mappings,
1382   ({
1383       if (!is_identity_static_mapping(m) && !is_lb_static_mapping (m))
1384         send_nat44_static_mapping_details (m, reg, mp->context);
1385   }));
1386   /* *INDENT-ON* */
1387
1388   for (j = 0; j < vec_len (sm->to_resolve); j++)
1389     {
1390       rp = sm->to_resolve + j;
1391       if (!rp->identity_nat)
1392         send_nat44_static_map_resolve_details (rp, reg, mp->context);
1393     }
1394 }
1395
1396 static void *
1397 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
1398                                           mp, void *handle)
1399 {
1400   u8 *s;
1401
1402   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
1403
1404   FINISH;
1405 }
1406
1407 static void
1408   vl_api_nat44_add_del_identity_mapping_t_handler
1409   (vl_api_nat44_add_del_identity_mapping_t * mp)
1410 {
1411   snat_main_t *sm = &snat_main;
1412   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
1413   ip4_address_t addr;
1414   u16 port = 0;
1415   u32 vrf_id, sw_if_index;
1416   int rv = 0;
1417   snat_protocol_t proto = ~0;
1418   u8 *tag = 0;
1419   u32 len = 0;
1420
1421   if (sm->deterministic)
1422     {
1423       rv = VNET_API_ERROR_UNSUPPORTED;
1424       goto send_reply;
1425     }
1426
1427   if (!(mp->flags & NAT_API_IS_ADDR_ONLY))
1428     {
1429       port = clib_net_to_host_u16 (mp->port);
1430       proto = ip_proto_to_snat_proto (mp->protocol);
1431     }
1432   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1433   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1434   if (sw_if_index != ~0)
1435     addr.as_u32 = 0;
1436   else
1437     memcpy (&addr.as_u8, mp->ip_address, 4);
1438
1439   len = vl_api_string_len (&mp->tag);
1440
1441   tag = vec_new (u8, len);
1442   memcpy (tag, mp->tag.buf, len);
1443   vec_terminate_c_string (tag);
1444
1445   rv =
1446     snat_add_static_mapping (addr, addr, port, port, vrf_id,
1447                              mp->flags & NAT_API_IS_ADDR_ONLY, sw_if_index,
1448                              proto, mp->is_add, 0, 0, tag, 1);
1449   vec_free (tag);
1450
1451 send_reply:
1452   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
1453 }
1454
1455 static void *vl_api_nat44_add_del_identity_mapping_t_print
1456   (vl_api_nat44_add_del_identity_mapping_t * mp, void *handle)
1457 {
1458   u8 *s;
1459
1460   s = format (0, "SCRIPT: nat44_add_del_identity_mapping ");
1461   if (mp->sw_if_index != ~0)
1462     s = format (s, "sw_if_index %d", clib_net_to_host_u32 (mp->sw_if_index));
1463   else
1464     s = format (s, "addr %U", format_ip4_address, mp->ip_address);
1465
1466   if (!(mp->flags & NAT_API_IS_ADDR_ONLY))
1467     s =
1468       format (s, " protocol %d port %d", mp->protocol,
1469               clib_net_to_host_u16 (mp->port));
1470
1471   if (mp->vrf_id != ~0)
1472     s = format (s, " vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1473
1474   FINISH;
1475 }
1476
1477 static void
1478 send_nat44_identity_mapping_details (snat_static_mapping_t * m, int index,
1479                                      vl_api_registration_t * reg, u32 context)
1480 {
1481   vl_api_nat44_identity_mapping_details_t *rmp;
1482   snat_main_t *sm = &snat_main;
1483   nat44_lb_addr_port_t *local = pool_elt_at_index (m->locals, index);
1484   u32 len = sizeof (*rmp);
1485
1486   if (m->tag)
1487     {
1488       len += vec_len (m->tag);
1489       rmp = vl_msg_api_alloc (len);
1490       clib_memset (rmp, 0, len);
1491       vl_api_to_api_string (vec_len (m->tag), (char *) m->tag, &rmp->tag);
1492     }
1493   else
1494     {
1495       rmp = vl_msg_api_alloc (len);
1496       clib_memset (rmp, 0, len);
1497     }
1498
1499   rmp->_vl_msg_id =
1500     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1501
1502   if (is_addr_only_static_mapping (m))
1503     rmp->flags |= NAT_API_IS_ADDR_ONLY;
1504
1505   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
1506   rmp->port = htons (m->local_port);
1507   rmp->sw_if_index = ~0;
1508   rmp->vrf_id = htonl (local->vrf_id);
1509   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1510   rmp->context = context;
1511
1512   vl_api_send_msg (reg, (u8 *) rmp);
1513 }
1514
1515 static void
1516 send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
1517                                          vl_api_registration_t * reg,
1518                                          u32 context)
1519 {
1520   vl_api_nat44_identity_mapping_details_t *rmp;
1521   snat_main_t *sm = &snat_main;
1522   u32 len = sizeof (*rmp);
1523
1524   if (m->tag)
1525     {
1526       len += vec_len (m->tag);
1527       rmp = vl_msg_api_alloc (len);
1528       clib_memset (rmp, 0, len);
1529       vl_api_to_api_string (vec_len (m->tag), (char *) m->tag, &rmp->tag);
1530     }
1531   else
1532     {
1533       rmp = vl_msg_api_alloc (len);
1534       clib_memset (rmp, 0, len);
1535     }
1536
1537   rmp->_vl_msg_id =
1538     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1539
1540   if (m->addr_only)
1541     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_ADDR_ONLY;
1542
1543   rmp->port = htons (m->l_port);
1544   rmp->sw_if_index = htonl (m->sw_if_index);
1545   rmp->vrf_id = htonl (m->vrf_id);
1546   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1547   rmp->context = context;
1548
1549   vl_api_send_msg (reg, (u8 *) rmp);
1550 }
1551
1552 static void
1553   vl_api_nat44_identity_mapping_dump_t_handler
1554   (vl_api_nat44_identity_mapping_dump_t * mp)
1555 {
1556   vl_api_registration_t *reg;
1557   snat_main_t *sm = &snat_main;
1558   snat_static_mapping_t *m;
1559   snat_static_map_resolve_t *rp;
1560   int j;
1561
1562   if (sm->deterministic)
1563     return;
1564
1565   reg = vl_api_client_index_to_registration (mp->client_index);
1566   if (!reg)
1567     return;
1568
1569   /* *INDENT-OFF* */
1570   pool_foreach (m, sm->static_mappings,
1571   ({
1572       if (is_identity_static_mapping(m) && !is_lb_static_mapping (m))
1573         {
1574           pool_foreach_index (j, m->locals,
1575           ({
1576             send_nat44_identity_mapping_details (m, j, reg, mp->context);
1577           }));
1578         }
1579   }));
1580   /* *INDENT-ON* */
1581
1582   for (j = 0; j < vec_len (sm->to_resolve); j++)
1583     {
1584       rp = sm->to_resolve + j;
1585       if (rp->identity_nat)
1586         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
1587     }
1588 }
1589
1590 static void *vl_api_nat44_identity_mapping_dump_t_print
1591   (vl_api_nat44_identity_mapping_dump_t * mp, void *handle)
1592 {
1593   u8 *s;
1594
1595   s = format (0, "SCRIPT: nat44_identity_mapping_dump ");
1596
1597   FINISH;
1598 }
1599
1600 static void
1601   vl_api_nat44_add_del_interface_addr_t_handler
1602   (vl_api_nat44_add_del_interface_addr_t * mp)
1603 {
1604   snat_main_t *sm = &snat_main;
1605   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1606   u32 sw_if_index = ntohl (mp->sw_if_index);
1607   int rv = 0;
1608   u8 is_del;
1609
1610   if (sm->deterministic)
1611     {
1612       rv = VNET_API_ERROR_UNSUPPORTED;
1613       goto send_reply;
1614     }
1615
1616   is_del = !mp->is_add;
1617
1618   VALIDATE_SW_IF_INDEX (mp);
1619
1620   rv = snat_add_interface_address (sm, sw_if_index, is_del,
1621                                    mp->flags & NAT_API_IS_TWICE_NAT);
1622
1623   BAD_SW_IF_INDEX_LABEL;
1624 send_reply:
1625   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1626 }
1627
1628 static void *vl_api_nat44_add_del_interface_addr_t_print
1629   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
1630 {
1631   u8 *s;
1632
1633   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
1634   s = format (s, "sw_if_index %d twice_nat %d %s",
1635               clib_host_to_net_u32 (mp->sw_if_index),
1636               mp->flags & NAT_API_IS_TWICE_NAT, mp->is_add ? "" : "del");
1637
1638   FINISH;
1639 }
1640
1641 static void
1642 send_nat44_interface_addr_details (u32 sw_if_index,
1643                                    vl_api_registration_t * reg, u32 context,
1644                                    u8 twice_nat)
1645 {
1646   vl_api_nat44_interface_addr_details_t *rmp;
1647   snat_main_t *sm = &snat_main;
1648
1649   rmp = vl_msg_api_alloc (sizeof (*rmp));
1650   clib_memset (rmp, 0, sizeof (*rmp));
1651   rmp->_vl_msg_id =
1652     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1653   rmp->sw_if_index = ntohl (sw_if_index);
1654
1655   if (twice_nat)
1656     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_TWICE_NAT;
1657   rmp->context = context;
1658
1659   vl_api_send_msg (reg, (u8 *) rmp);
1660 }
1661
1662 static void
1663 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1664                                             * mp)
1665 {
1666   vl_api_registration_t *reg;
1667   snat_main_t *sm = &snat_main;
1668   u32 *i;
1669
1670   if (sm->deterministic)
1671     return;
1672
1673   reg = vl_api_client_index_to_registration (mp->client_index);
1674   if (!reg)
1675     return;
1676
1677   /* *INDENT-OFF* */
1678   vec_foreach (i, sm->auto_add_sw_if_indices)
1679     send_nat44_interface_addr_details(*i, reg, mp->context, 0);
1680   vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
1681     send_nat44_interface_addr_details(*i, reg, mp->context, 1);
1682   /* *INDENT-ON* */
1683 }
1684
1685 static void *
1686 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1687                                           mp, void *handle)
1688 {
1689   u8 *s;
1690
1691   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
1692
1693   FINISH;
1694 }
1695
1696 static void
1697 send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg,
1698                          u32 context)
1699 {
1700   vl_api_nat44_user_details_t *rmp;
1701   snat_main_t *sm = &snat_main;
1702   ip4_main_t *im = &ip4_main;
1703
1704   rmp = vl_msg_api_alloc (sizeof (*rmp));
1705   clib_memset (rmp, 0, sizeof (*rmp));
1706   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1707
1708   if (!pool_is_free_index (im->fibs, u->fib_index))
1709     {
1710       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1711       rmp->vrf_id = ntohl (fib->ft_table_id);
1712     }
1713
1714   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1715   rmp->nsessions = ntohl (u->nsessions);
1716   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1717   rmp->context = context;
1718
1719   vl_api_send_msg (reg, (u8 *) rmp);
1720 }
1721
1722 static void
1723 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1724 {
1725   vl_api_registration_t *reg;
1726   snat_main_t *sm = &snat_main;
1727   snat_main_per_thread_data_t *tsm;
1728   snat_user_t *u;
1729
1730   if (sm->deterministic)
1731     return;
1732
1733   reg = vl_api_client_index_to_registration (mp->client_index);
1734   if (!reg)
1735     return;
1736
1737   /* *INDENT-OFF* */
1738   vec_foreach (tsm, sm->per_thread_data)
1739     {
1740       pool_foreach (u, tsm->users,
1741       ({
1742         send_nat44_user_details (u, reg, mp->context);
1743       }));
1744     }
1745   /* *INDENT-ON* */
1746 }
1747
1748 static void *
1749 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
1750 {
1751   u8 *s;
1752
1753   s = format (0, "SCRIPT: nat44_user_dump ");
1754
1755   FINISH;
1756 }
1757
1758 static void
1759 send_nat44_user_session_details (snat_session_t * s,
1760                                  vl_api_registration_t * reg, u32 context)
1761 {
1762   vl_api_nat44_user_session_details_t *rmp;
1763   snat_main_t *sm = &snat_main;
1764
1765   rmp = vl_msg_api_alloc (sizeof (*rmp));
1766   clib_memset (rmp, 0, sizeof (*rmp));
1767   rmp->_vl_msg_id =
1768     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1769   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1770   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1771
1772   if (snat_is_session_static (s))
1773     rmp->flags |= NAT_API_IS_STATIC;
1774
1775   if (is_twice_nat_session (s))
1776     rmp->flags |= NAT_API_IS_TWICE_NAT;
1777
1778   if (is_ed_session (s) || is_fwd_bypass_session (s))
1779     rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1780
1781   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1782   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1783   rmp->total_pkts = ntohl (s->total_pkts);
1784   rmp->context = context;
1785   if (snat_is_unk_proto_session (s))
1786     {
1787       rmp->outside_port = 0;
1788       rmp->inside_port = 0;
1789       rmp->protocol = ntohs (s->in2out.port);
1790     }
1791   else
1792     {
1793       rmp->outside_port = s->out2in.port;
1794       rmp->inside_port = s->in2out.port;
1795       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
1796     }
1797   if (is_ed_session (s) || is_fwd_bypass_session (s))
1798     {
1799       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1800       rmp->ext_host_port = s->ext_host_port;
1801       if (is_twice_nat_session (s))
1802         {
1803           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1804           rmp->ext_host_nat_port = s->ext_host_nat_port;
1805         }
1806     }
1807
1808   vl_api_send_msg (reg, (u8 *) rmp);
1809 }
1810
1811 static void
1812 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1813                                           mp)
1814 {
1815   vl_api_registration_t *reg;
1816   snat_main_t *sm = &snat_main;
1817   snat_main_per_thread_data_t *tsm;
1818   snat_session_t *s;
1819   clib_bihash_kv_8_8_t key, value;
1820   snat_user_key_t ukey;
1821   snat_user_t *u;
1822   u32 session_index, head_index, elt_index;
1823   dlist_elt_t *head, *elt;
1824   ip4_header_t ip;
1825
1826   if (sm->deterministic)
1827     return;
1828
1829   reg = vl_api_client_index_to_registration (mp->client_index);
1830   if (!reg)
1831     return;
1832
1833   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1834   ip.src_address.as_u32 = ukey.addr.as_u32;
1835   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1836   key.key = ukey.as_u64;
1837   if (sm->num_workers > 1)
1838     tsm =
1839       vec_elt_at_index (sm->per_thread_data,
1840                         sm->worker_in2out_cb (&ip, ukey.fib_index));
1841   else
1842     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1843   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1844     return;
1845   u = pool_elt_at_index (tsm->users, value.value);
1846   if (!u->nsessions && !u->nstaticsessions)
1847     return;
1848
1849   head_index = u->sessions_per_user_list_head_index;
1850   head = pool_elt_at_index (tsm->list_pool, head_index);
1851   elt_index = head->next;
1852   elt = pool_elt_at_index (tsm->list_pool, elt_index);
1853   session_index = elt->value;
1854   while (session_index != ~0)
1855     {
1856       s = pool_elt_at_index (tsm->sessions, session_index);
1857
1858       send_nat44_user_session_details (s, reg, mp->context);
1859
1860       elt_index = elt->next;
1861       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1862       session_index = elt->value;
1863     }
1864 }
1865
1866 static void *
1867 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
1868                                         void *handle)
1869 {
1870   u8 *s;
1871
1872   s = format (0, "SCRIPT: nat44_user_session_dump ");
1873   s = format (s, "ip_address %U vrf_id %d\n",
1874               format_ip4_address, mp->ip_address,
1875               clib_net_to_host_u32 (mp->vrf_id));
1876
1877   FINISH;
1878 }
1879
1880 static nat44_lb_addr_port_t *
1881 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1882                              u32 addr_port_pair_num)
1883 {
1884   u8 i;
1885   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1886   vl_api_nat44_lb_addr_port_t *ap;
1887
1888   for (i = 0; i < addr_port_pair_num; i++)
1889     {
1890       ap = &addr_port_pairs[i];
1891       clib_memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1892       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1893       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
1894       lb_addr_port.probability = ap->probability;
1895       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1896       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1897     }
1898
1899   return lb_addr_port_pairs;
1900 }
1901
1902 static void
1903   vl_api_nat44_add_del_lb_static_mapping_t_handler
1904   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1905 {
1906   snat_main_t *sm = &snat_main;
1907   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1908   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1909   int rv = 0;
1910   nat44_lb_addr_port_t *locals = 0;
1911   ip4_address_t e_addr;
1912   snat_protocol_t proto;
1913   vl_api_string_t *sp;
1914   u8 *tag = 0;
1915   u32 len = 0;
1916
1917   if (!sm->endpoint_dependent)
1918     {
1919       rv = VNET_API_ERROR_UNSUPPORTED;
1920       goto send_reply;
1921     }
1922
1923   locals =
1924     unformat_nat44_lb_addr_port (mp->locals,
1925                                  clib_net_to_host_u32 (mp->local_num));
1926   clib_memcpy (&e_addr, mp->external_addr, 4);
1927   proto = ip_proto_to_snat_proto (mp->protocol);
1928
1929   if (mp->flags & NAT_API_IS_TWICE_NAT)
1930     twice_nat = TWICE_NAT;
1931   else if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
1932     twice_nat = TWICE_NAT_SELF;
1933
1934   sp = (void *) &mp->locals +
1935     sizeof (vl_api_nat44_lb_addr_port_t) *
1936     clib_net_to_host_u32 (mp->local_num);
1937
1938   len = vl_api_string_len (sp);
1939
1940   tag = vec_new (u8, len);
1941   memcpy (tag, sp->buf, len);
1942   vec_terminate_c_string (tag);
1943
1944   rv =
1945     nat44_add_del_lb_static_mapping (e_addr,
1946                                      clib_net_to_host_u16 (mp->external_port),
1947                                      proto, locals, mp->is_add,
1948                                      twice_nat,
1949                                      mp->flags & NAT_API_IS_OUT2IN_ONLY, tag,
1950                                      clib_net_to_host_u32 (mp->affinity));
1951
1952   vec_free (locals);
1953   vec_free (tag);
1954
1955 send_reply:
1956   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1957 }
1958
1959 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1960   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1961 {
1962   u8 *s;
1963
1964   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1965   s = format (s, "is_add %d twice_nat %d out2in_only %d ",
1966               mp->is_add,
1967               mp->flags & NAT_API_IS_TWICE_NAT,
1968               mp->flags & NAT_API_IS_OUT2IN_ONLY);
1969
1970   FINISH;
1971 }
1972
1973 static void
1974   vl_api_nat44_lb_static_mapping_add_del_local_t_handler
1975   (vl_api_nat44_lb_static_mapping_add_del_local_t * mp)
1976 {
1977   snat_main_t *sm = &snat_main;
1978   vl_api_nat44_lb_static_mapping_add_del_local_reply_t *rmp;
1979   int rv = 0;
1980   ip4_address_t e_addr, l_addr;
1981   snat_protocol_t proto;
1982
1983   if (!sm->endpoint_dependent)
1984     {
1985       rv = VNET_API_ERROR_UNSUPPORTED;
1986       goto send_reply;
1987     }
1988
1989   clib_memcpy (&e_addr, mp->external_addr, 4);
1990   clib_memcpy (&l_addr, mp->local.addr, 4);
1991   proto = ip_proto_to_snat_proto (mp->protocol);
1992
1993   rv =
1994     nat44_lb_static_mapping_add_del_local (e_addr,
1995                                            clib_net_to_host_u16
1996                                            (mp->external_port), l_addr,
1997                                            clib_net_to_host_u16 (mp->
1998                                                                  local.port),
1999                                            proto,
2000                                            clib_net_to_host_u32 (mp->
2001                                                                  local.vrf_id),
2002                                            mp->local.probability, mp->is_add);
2003
2004 send_reply:
2005   REPLY_MACRO (VL_API_NAT44_LB_STATIC_MAPPING_ADD_DEL_LOCAL_REPLY);
2006 }
2007
2008 static void *vl_api_nat44_lb_static_mapping_add_del_local_t_print
2009   (vl_api_nat44_lb_static_mapping_add_del_local_t * mp, void *handle)
2010 {
2011   u8 *s;
2012
2013   s = format (0, "SCRIPT: nat44_lb_static_mapping_add_del_local ");
2014   s = format (s, "is_add %d", mp->is_add);
2015
2016   FINISH;
2017 }
2018
2019 static void
2020 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
2021                                       vl_api_registration_t * reg,
2022                                       u32 context)
2023 {
2024   vl_api_nat44_lb_static_mapping_details_t *rmp;
2025   snat_main_t *sm = &snat_main;
2026   nat44_lb_addr_port_t *ap;
2027   vl_api_nat44_lb_addr_port_t *locals;
2028   vl_api_string_t *sp;
2029   u32 local_num = 0;
2030   u32 len = sizeof (*rmp);
2031
2032   if (m->tag)
2033     {
2034       len += pool_elts (m->locals) *
2035         sizeof (nat44_lb_addr_port_t) + vec_len (m->tag);
2036       rmp = vl_msg_api_alloc (len);
2037       clib_memset (rmp, 0, len);
2038
2039       sp = (void *) &m->locals +
2040         sizeof (vl_api_nat44_lb_addr_port_t) * pool_elts (m->locals);
2041       vl_api_to_api_string (vec_len (m->tag), (char *) m->tag, sp);
2042     }
2043   else
2044     {
2045       len += pool_elts (m->locals) * sizeof (nat44_lb_addr_port_t);
2046       rmp = vl_msg_api_alloc (len);
2047       clib_memset (rmp, 0, len);
2048     }
2049
2050   rmp->_vl_msg_id =
2051     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
2052
2053   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
2054   rmp->external_port = ntohs (m->external_port);
2055   rmp->protocol = snat_proto_to_ip_proto (m->proto);
2056   rmp->context = context;
2057
2058   if (m->twice_nat == TWICE_NAT)
2059     rmp->flags |= NAT_API_IS_TWICE_NAT;
2060   else if (m->twice_nat == TWICE_NAT_SELF)
2061     rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
2062   if (is_out2in_only_static_mapping (m))
2063     rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
2064
2065   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
2066   /* *INDENT-OFF* */
2067   pool_foreach (ap, m->locals,
2068   ({
2069     clib_memcpy (locals->addr, &(ap->addr), 4);
2070     locals->port = htons (ap->port);
2071     locals->probability = ap->probability;
2072     locals->vrf_id = ntohl (ap->vrf_id);
2073     locals++;
2074     local_num++;
2075   }));
2076   /* *INDENT-ON* */
2077   rmp->local_num = ntohl (local_num);
2078
2079   vl_api_send_msg (reg, (u8 *) rmp);
2080 }
2081
2082 static void
2083   vl_api_nat44_lb_static_mapping_dump_t_handler
2084   (vl_api_nat44_lb_static_mapping_dump_t * mp)
2085 {
2086   vl_api_registration_t *reg;
2087   snat_main_t *sm = &snat_main;
2088   snat_static_mapping_t *m;
2089
2090   if (!sm->endpoint_dependent)
2091     return;
2092
2093   reg = vl_api_client_index_to_registration (mp->client_index);
2094   if (!reg)
2095     return;
2096
2097   /* *INDENT-OFF* */
2098   pool_foreach (m, sm->static_mappings,
2099   ({
2100       if (is_lb_static_mapping(m))
2101         send_nat44_lb_static_mapping_details (m, reg, mp->context);
2102   }));
2103   /* *INDENT-ON* */
2104 }
2105
2106 static void *vl_api_nat44_lb_static_mapping_dump_t_print
2107   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
2108 {
2109   u8 *s;
2110
2111   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
2112
2113   FINISH;
2114 }
2115
2116 static void
2117 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
2118 {
2119   snat_main_t *sm = &snat_main;
2120   vl_api_nat44_del_session_reply_t *rmp;
2121   ip4_address_t addr, eh_addr;
2122   u16 port, eh_port;
2123   u32 vrf_id;
2124   int rv = 0;
2125   u8 is_in;
2126   snat_protocol_t proto;
2127
2128   if (sm->deterministic)
2129     {
2130       rv = VNET_API_ERROR_UNSUPPORTED;
2131       goto send_reply;
2132     }
2133
2134   memcpy (&addr.as_u8, mp->address, 4);
2135   port = clib_net_to_host_u16 (mp->port);
2136   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
2137   proto = ip_proto_to_snat_proto (mp->protocol);
2138   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
2139   eh_port = clib_net_to_host_u16 (mp->ext_host_port);
2140
2141   is_in = mp->flags & NAT_API_IS_INSIDE;
2142
2143   if (mp->flags & NAT_API_IS_EXT_HOST_VALID)
2144     rv =
2145       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
2146                             vrf_id, is_in);
2147   else
2148     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, is_in);
2149
2150 send_reply:
2151   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
2152 }
2153
2154 static void *
2155 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
2156                                   void *handle)
2157 {
2158   u8 *s;
2159
2160   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
2161   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
2162               format_ip4_address, mp->address,
2163               clib_net_to_host_u16 (mp->port),
2164               mp->protocol, clib_net_to_host_u32 (mp->vrf_id),
2165               mp->flags & NAT_API_IS_INSIDE);
2166   if (mp->flags & NAT_API_IS_EXT_HOST_VALID)
2167     s = format (s, "ext_host_address %U ext_host_port %d",
2168                 format_ip4_address, mp->ext_host_address,
2169                 clib_net_to_host_u16 (mp->ext_host_port));
2170
2171   FINISH;
2172 }
2173
2174 static void
2175   vl_api_nat44_forwarding_enable_disable_t_handler
2176   (vl_api_nat44_forwarding_enable_disable_t * mp)
2177 {
2178   snat_main_t *sm = &snat_main;
2179   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
2180   int rv = 0;
2181   u32 *ses_to_be_removed = 0, *ses_index;
2182   snat_main_per_thread_data_t *tsm;
2183   snat_session_t *s;
2184
2185   sm->forwarding_enabled = mp->enable != 0;
2186
2187   if (mp->enable == 0)
2188     {
2189       /* *INDENT-OFF* */
2190       vec_foreach (tsm, sm->per_thread_data)
2191       {
2192         pool_foreach (s, tsm->sessions,
2193         ({
2194           if (is_fwd_bypass_session(s))
2195             {
2196               vec_add1 (ses_to_be_removed, s - tsm->sessions);
2197             }
2198         }));
2199         vec_foreach (ses_index, ses_to_be_removed)
2200         {
2201           s = pool_elt_at_index(tsm->sessions, ses_index[0]);
2202           nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
2203           nat44_delete_session (sm, s, tsm - sm->per_thread_data);
2204         }
2205         vec_free (ses_to_be_removed);
2206       }
2207       /* *INDENT-ON* */
2208     }
2209
2210   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
2211 }
2212
2213 static void *vl_api_nat44_forwarding_enable_disable_t_print
2214   (vl_api_nat44_forwarding_enable_disable_t * mp, void *handle)
2215 {
2216   u8 *s;
2217
2218   s = format (0, "SCRIPT: nat44_forwarding_enable_disable ");
2219   s = format (s, "enable %d", mp->enable != 0);
2220
2221   FINISH;
2222 }
2223
2224 static void
2225   vl_api_nat44_forwarding_is_enabled_t_handler
2226   (vl_api_nat44_forwarding_is_enabled_t * mp)
2227 {
2228   vl_api_registration_t *reg;
2229   snat_main_t *sm = &snat_main;
2230   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
2231
2232   reg = vl_api_client_index_to_registration (mp->client_index);
2233   if (!reg)
2234     return;
2235
2236   rmp = vl_msg_api_alloc (sizeof (*rmp));
2237   clib_memset (rmp, 0, sizeof (*rmp));
2238   rmp->_vl_msg_id =
2239     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
2240   rmp->context = mp->context;
2241
2242   rmp->enabled = sm->forwarding_enabled;
2243
2244   vl_api_send_msg (reg, (u8 *) rmp);
2245 }
2246
2247 static void *vl_api_nat44_forwarding_is_enabled_t_print
2248   (vl_api_nat44_forwarding_is_enabled_t * mp, void *handle)
2249 {
2250   u8 *s;
2251
2252   s = format (0, "SCRIPT: nat44_forwarding_is_enabled ");
2253
2254   FINISH;
2255 }
2256
2257 /*******************************/
2258 /*** Deterministic NAT (CGN) ***/
2259 /*******************************/
2260
2261 static void
2262 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
2263 {
2264   snat_main_t *sm = &snat_main;
2265   vl_api_nat_det_add_del_map_reply_t *rmp;
2266   int rv = 0;
2267   ip4_address_t in_addr, out_addr;
2268
2269   if (!sm->deterministic)
2270     {
2271       rv = VNET_API_ERROR_UNSUPPORTED;
2272       goto send_reply;
2273     }
2274
2275   clib_memcpy (&in_addr, mp->in_addr, 4);
2276   clib_memcpy (&out_addr, mp->out_addr, 4);
2277   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
2278                          mp->out_plen, mp->is_add);
2279
2280 send_reply:
2281   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
2282 }
2283
2284 static void *
2285 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
2286                                     void *handle)
2287 {
2288   u8 *s;
2289
2290   s = format (0, "SCRIPT: nat_det_add_del_map ");
2291   s = format (s, "inside address %U/%d outside address %U/%d\n",
2292               format_ip4_address, mp->in_addr, mp->in_plen,
2293               format_ip4_address, mp->out_addr, mp->out_plen);
2294
2295   FINISH;
2296 }
2297
2298 static void
2299 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
2300 {
2301   snat_main_t *sm = &snat_main;
2302   vl_api_nat_det_forward_reply_t *rmp;
2303   int rv = 0;
2304   u16 lo_port = 0, hi_port = 0;
2305   snat_det_map_t *dm;
2306   ip4_address_t in_addr, out_addr;
2307
2308   if (!sm->deterministic)
2309     {
2310       rv = VNET_API_ERROR_UNSUPPORTED;
2311       REPLY_MACRO (VL_API_NAT_DET_FORWARD_REPLY);
2312       return;
2313     }
2314
2315   out_addr.as_u32 = 0;
2316   clib_memcpy (&in_addr, mp->in_addr, 4);
2317   dm = snat_det_map_by_user (sm, &in_addr);
2318   if (!dm)
2319     {
2320       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2321       goto send_reply;
2322     }
2323
2324   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
2325   hi_port = lo_port + dm->ports_per_host - 1;
2326
2327 send_reply:
2328   /* *INDENT-OFF* */
2329   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
2330   ({
2331     rmp->out_port_lo = ntohs (lo_port);
2332     rmp->out_port_hi = ntohs (hi_port);
2333     clib_memcpy (rmp->out_addr, &out_addr, 4);
2334   }))
2335   /* *INDENT-ON* */
2336 }
2337
2338 static void *
2339 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
2340 {
2341   u8 *s;
2342
2343   s = format (0, "SCRIPT: nat_det_forward");
2344   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
2345
2346   FINISH;
2347 }
2348
2349 static void
2350 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
2351 {
2352   snat_main_t *sm = &snat_main;
2353   vl_api_nat_det_reverse_reply_t *rmp;
2354   int rv = 0;
2355   ip4_address_t out_addr, in_addr;
2356   snat_det_map_t *dm;
2357
2358   if (!sm->deterministic)
2359     {
2360       rv = VNET_API_ERROR_UNSUPPORTED;
2361       REPLY_MACRO (VL_API_NAT_DET_REVERSE_REPLY);
2362       return;
2363     }
2364
2365   in_addr.as_u32 = 0;
2366   clib_memcpy (&out_addr, mp->out_addr, 4);
2367   dm = snat_det_map_by_out (sm, &out_addr);
2368   if (!dm)
2369     {
2370       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2371       goto send_reply;
2372     }
2373
2374   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
2375
2376 send_reply:
2377   /* *INDENT-OFF* */
2378   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
2379   ({
2380     clib_memcpy (rmp->in_addr, &in_addr, 4);
2381   }))
2382   /* *INDENT-ON* */
2383 }
2384
2385 static void *
2386 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
2387 {
2388   u8 *s;
2389
2390   s = format (0, "SCRIPT: nat_det_reverse");
2391   s = format (s, "outside ip address %U outside port %d",
2392               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
2393
2394   FINISH;
2395 }
2396
2397 static void
2398 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
2399                           u32 context)
2400 {
2401   vl_api_nat_det_map_details_t *rmp;
2402   snat_main_t *sm = &snat_main;
2403
2404   rmp = vl_msg_api_alloc (sizeof (*rmp));
2405   clib_memset (rmp, 0, sizeof (*rmp));
2406   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
2407   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
2408   rmp->in_plen = m->in_plen;
2409   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
2410   rmp->out_plen = m->out_plen;
2411   rmp->sharing_ratio = htonl (m->sharing_ratio);
2412   rmp->ports_per_host = htons (m->ports_per_host);
2413   rmp->ses_num = htonl (m->ses_num);
2414   rmp->context = context;
2415
2416   vl_api_send_msg (reg, (u8 *) rmp);
2417 }
2418
2419 static void
2420 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
2421 {
2422   vl_api_registration_t *reg;
2423   snat_main_t *sm = &snat_main;
2424   snat_det_map_t *m;
2425
2426   if (!sm->deterministic)
2427     return;
2428
2429   reg = vl_api_client_index_to_registration (mp->client_index);
2430   if (!reg)
2431     return;
2432
2433   /* *INDENT-OFF* */
2434   vec_foreach(m, sm->det_maps)
2435     sent_nat_det_map_details(m, reg, mp->context);
2436   /* *INDENT-ON* */
2437 }
2438
2439 static void *
2440 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
2441 {
2442   u8 *s;
2443
2444   s = format (0, "SCRIPT: nat_det_map_dump ");
2445
2446   FINISH;
2447 }
2448
2449 static void
2450 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
2451                                             * mp)
2452 {
2453   snat_main_t *sm = &snat_main;
2454   vl_api_nat_det_close_session_out_reply_t *rmp;
2455   ip4_address_t out_addr, ext_addr, in_addr;
2456   snat_det_out_key_t key;
2457   snat_det_map_t *dm;
2458   snat_det_session_t *ses;
2459   int rv = 0;
2460
2461   if (!sm->deterministic)
2462     {
2463       rv = VNET_API_ERROR_UNSUPPORTED;
2464       goto send_reply;
2465     }
2466
2467   clib_memcpy (&out_addr, mp->out_addr, 4);
2468   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2469
2470   dm = snat_det_map_by_out (sm, &out_addr);
2471   if (!dm)
2472     {
2473       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2474       goto send_reply;
2475     }
2476   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
2477   key.ext_host_addr = ext_addr;
2478   key.ext_host_port = mp->ext_port;
2479   key.out_port = mp->out_port;
2480   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
2481   if (!ses)
2482     {
2483       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2484       goto send_reply;
2485     }
2486   snat_det_ses_close (dm, ses);
2487
2488 send_reply:
2489   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2490 }
2491
2492 static void *
2493 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
2494                                           mp, void *handle)
2495 {
2496   u8 *s;
2497
2498   s = format (0, "SCRIPT: nat_det_close_session_out ");
2499   s = format (s, "out_addr %U out_port %d "
2500               "ext_addr %U ext_port %d\n",
2501               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
2502               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2503
2504   FINISH;
2505 }
2506
2507 static void
2508 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
2509                                            mp)
2510 {
2511   snat_main_t *sm = &snat_main;
2512   vl_api_nat_det_close_session_in_reply_t *rmp;
2513   ip4_address_t in_addr, ext_addr;
2514   snat_det_out_key_t key;
2515   snat_det_map_t *dm;
2516   snat_det_session_t *ses;
2517   int rv = 0;
2518
2519   if (!sm->deterministic)
2520     {
2521       rv = VNET_API_ERROR_UNSUPPORTED;
2522       goto send_reply;
2523     }
2524
2525   clib_memcpy (&in_addr, mp->in_addr, 4);
2526   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2527
2528   dm = snat_det_map_by_user (sm, &in_addr);
2529   if (!dm)
2530     {
2531       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2532       goto send_reply;
2533     }
2534   key.ext_host_addr = ext_addr;
2535   key.ext_host_port = mp->ext_port;
2536   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
2537   if (!ses)
2538     {
2539       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2540       goto send_reply;
2541     }
2542   snat_det_ses_close (dm, ses);
2543
2544 send_reply:
2545   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2546 }
2547
2548 static void *
2549 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2550                                          mp, void *handle)
2551 {
2552   u8 *s;
2553   s = format (0, "SCRIPT: nat_det_close_session_in ");
2554   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2555               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2556               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2557
2558   FINISH;
2559 }
2560
2561 static void
2562 send_nat_det_session_details (snat_det_session_t * s,
2563                               vl_api_registration_t * reg, u32 context)
2564 {
2565   vl_api_nat_det_session_details_t *rmp;
2566   snat_main_t *sm = &snat_main;
2567
2568   rmp = vl_msg_api_alloc (sizeof (*rmp));
2569   clib_memset (rmp, 0, sizeof (*rmp));
2570   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2571   rmp->in_port = s->in_port;
2572   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2573   rmp->ext_port = s->out.ext_host_port;
2574   rmp->out_port = s->out.out_port;
2575   rmp->state = s->state;
2576   rmp->expire = ntohl (s->expire);
2577   rmp->context = context;
2578
2579   vl_api_send_msg (reg, (u8 *) rmp);
2580 }
2581
2582 static void
2583 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2584 {
2585   vl_api_registration_t *reg;
2586   snat_main_t *sm = &snat_main;
2587   ip4_address_t user_addr;
2588   snat_det_map_t *dm;
2589   snat_det_session_t *s, empty_ses;
2590   u16 i;
2591
2592   if (!sm->deterministic)
2593     return;
2594
2595   reg = vl_api_client_index_to_registration (mp->client_index);
2596   if (!reg)
2597     return;
2598
2599   clib_memset (&empty_ses, 0, sizeof (empty_ses));
2600   clib_memcpy (&user_addr, mp->user_addr, 4);
2601   dm = snat_det_map_by_user (sm, &user_addr);
2602   if (!dm)
2603     return;
2604
2605   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2606   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2607     {
2608       if (s->out.as_u64)
2609         send_nat_det_session_details (s, reg, mp->context);
2610       s++;
2611     }
2612 }
2613
2614 static void *
2615 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2616                                      void *handle)
2617 {
2618   u8 *s;
2619
2620   s = format (0, "SCRIPT: nat_det_session_dump ");
2621   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2622
2623   FINISH;
2624 }
2625
2626 /*************/
2627 /*** NAT64 ***/
2628 /*************/
2629
2630 static void
2631   vl_api_nat64_add_del_pool_addr_range_t_handler
2632   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2633 {
2634   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2635   snat_main_t *sm = &snat_main;
2636   int rv = 0;
2637   ip4_address_t this_addr;
2638   u32 start_host_order, end_host_order;
2639   u32 vrf_id;
2640   int i, count;
2641   u32 *tmp;
2642
2643   tmp = (u32 *) mp->start_addr;
2644   start_host_order = clib_host_to_net_u32 (tmp[0]);
2645   tmp = (u32 *) mp->end_addr;
2646   end_host_order = clib_host_to_net_u32 (tmp[0]);
2647
2648   count = (end_host_order - start_host_order) + 1;
2649
2650   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2651
2652   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2653
2654   for (i = 0; i < count; i++)
2655     {
2656       if ((rv = nat64_add_del_pool_addr (0, &this_addr, vrf_id, mp->is_add)))
2657         goto send_reply;
2658
2659       increment_v4_address (&this_addr);
2660     }
2661
2662 send_reply:
2663   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2664 }
2665
2666 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2667   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2668 {
2669   u8 *s;
2670
2671   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2672   s = format (s, "%U - %U vrf_id %u %s\n",
2673               format_ip4_address, mp->start_addr,
2674               format_ip4_address, mp->end_addr,
2675               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2676
2677   FINISH;
2678 }
2679
2680 typedef struct nat64_api_walk_ctx_t_
2681 {
2682   vl_api_registration_t *reg;
2683   u32 context;
2684   nat64_db_t *db;
2685 } nat64_api_walk_ctx_t;
2686
2687 static int
2688 nat64_api_pool_walk (snat_address_t * a, void *arg)
2689 {
2690   vl_api_nat64_pool_addr_details_t *rmp;
2691   snat_main_t *sm = &snat_main;
2692   nat64_api_walk_ctx_t *ctx = arg;
2693
2694   rmp = vl_msg_api_alloc (sizeof (*rmp));
2695   clib_memset (rmp, 0, sizeof (*rmp));
2696   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2697   clib_memcpy (rmp->address, &(a->addr), 4);
2698   if (a->fib_index != ~0)
2699     {
2700       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2701       if (!fib)
2702         return -1;
2703       rmp->vrf_id = ntohl (fib->ft_table_id);
2704     }
2705   else
2706     rmp->vrf_id = ~0;
2707   rmp->context = ctx->context;
2708
2709   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2710
2711   return 0;
2712 }
2713
2714 static void
2715 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2716 {
2717   vl_api_registration_t *reg;
2718
2719   reg = vl_api_client_index_to_registration (mp->client_index);
2720   if (!reg)
2721     return;
2722
2723   nat64_api_walk_ctx_t ctx = {
2724     .reg = reg,
2725     .context = mp->context,
2726   };
2727
2728   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2729 }
2730
2731 static void *
2732 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2733                                      void *handle)
2734 {
2735   u8 *s;
2736
2737   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2738
2739   FINISH;
2740 }
2741
2742 static void
2743 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2744                                           mp)
2745 {
2746   snat_main_t *sm = &snat_main;
2747   vl_api_nat64_add_del_interface_reply_t *rmp;
2748   int rv = 0;
2749
2750   VALIDATE_SW_IF_INDEX (mp);
2751
2752   rv =
2753     nat64_add_del_interface (ntohl (mp->sw_if_index),
2754                              mp->flags & NAT_API_IS_INSIDE, mp->is_add);
2755
2756   BAD_SW_IF_INDEX_LABEL;
2757
2758   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2759 }
2760
2761 static void *
2762 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2763                                         void *handle)
2764 {
2765   u8 *s;
2766
2767   s = format (0, "SCRIPT: nat64_add_del_interface ");
2768   s = format (s, "sw_if_index %d %s %s",
2769               clib_host_to_net_u32 (mp->sw_if_index),
2770               mp->flags & NAT_API_IS_INSIDE ? "in" : "out",
2771               mp->is_add ? "" : "del");
2772
2773   FINISH;
2774 }
2775
2776 static int
2777 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2778 {
2779   vl_api_nat64_interface_details_t *rmp;
2780   snat_main_t *sm = &snat_main;
2781   nat64_api_walk_ctx_t *ctx = arg;
2782
2783   rmp = vl_msg_api_alloc (sizeof (*rmp));
2784   clib_memset (rmp, 0, sizeof (*rmp));
2785   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2786   rmp->sw_if_index = ntohl (i->sw_if_index);
2787
2788   if (nat_interface_is_inside (i))
2789     rmp->flags |= NAT_API_IS_INSIDE;
2790   if (nat_interface_is_outside (i))
2791     rmp->flags |= NAT_API_IS_OUTSIDE;
2792
2793   rmp->context = ctx->context;
2794
2795   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2796
2797   return 0;
2798 }
2799
2800 static void
2801 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2802 {
2803   vl_api_registration_t *reg;
2804
2805   reg = vl_api_client_index_to_registration (mp->client_index);
2806   if (!reg)
2807     return;
2808
2809   nat64_api_walk_ctx_t ctx = {
2810     .reg = reg,
2811     .context = mp->context,
2812   };
2813
2814   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2815 }
2816
2817 static void *
2818 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2819                                      void *handle)
2820 {
2821   u8 *s;
2822
2823   s = format (0, "SCRIPT: snat_interface_dump ");
2824
2825   FINISH;
2826 }
2827
2828 static void
2829   vl_api_nat64_add_del_static_bib_t_handler
2830   (vl_api_nat64_add_del_static_bib_t * mp)
2831 {
2832   snat_main_t *sm = &snat_main;
2833   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2834   ip6_address_t in_addr;
2835   ip4_address_t out_addr;
2836   int rv = 0;
2837
2838   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2839   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2840
2841   rv =
2842     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2843                                     clib_net_to_host_u16 (mp->i_port),
2844                                     clib_net_to_host_u16 (mp->o_port),
2845                                     mp->proto,
2846                                     clib_net_to_host_u32 (mp->vrf_id),
2847                                     mp->is_add);
2848
2849   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2850 }
2851
2852 static void *vl_api_nat64_add_del_static_bib_t_print
2853   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2854 {
2855   u8 *s;
2856
2857   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2858   s = format (s, "protocol %d i_addr %U o_addr %U ",
2859               mp->proto,
2860               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2861
2862   if (mp->vrf_id != ~0)
2863     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2864
2865   FINISH;
2866 }
2867
2868 static int
2869 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2870 {
2871   vl_api_nat64_bib_details_t *rmp;
2872   snat_main_t *sm = &snat_main;
2873   nat64_api_walk_ctx_t *ctx = arg;
2874   fib_table_t *fib;
2875
2876   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2877   if (!fib)
2878     return -1;
2879
2880   rmp = vl_msg_api_alloc (sizeof (*rmp));
2881   clib_memset (rmp, 0, sizeof (*rmp));
2882   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2883   rmp->context = ctx->context;
2884   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2885   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2886   rmp->i_port = bibe->in_port;
2887   rmp->o_port = bibe->out_port;
2888   rmp->vrf_id = ntohl (fib->ft_table_id);
2889   rmp->proto = bibe->proto;
2890   if (bibe->is_static)
2891     rmp->flags |= NAT_API_IS_STATIC;
2892   rmp->ses_num = ntohl (bibe->ses_num);
2893
2894   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2895
2896   return 0;
2897 }
2898
2899 static void
2900 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2901 {
2902   vl_api_registration_t *reg;
2903   nat64_main_t *nm = &nat64_main;
2904   nat64_db_t *db;
2905
2906   reg = vl_api_client_index_to_registration (mp->client_index);
2907   if (!reg)
2908     return;
2909
2910   nat64_api_walk_ctx_t ctx = {
2911     .reg = reg,
2912     .context = mp->context,
2913   };
2914
2915   /* *INDENT-OFF* */
2916   vec_foreach (db, nm->db)
2917     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2918   /* *INDENT-ON* */
2919 }
2920
2921 static void *
2922 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2923 {
2924   u8 *s;
2925
2926   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2927
2928   FINISH;
2929 }
2930
2931 static int
2932 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2933 {
2934   vl_api_nat64_st_details_t *rmp;
2935   snat_main_t *sm = &snat_main;
2936   nat64_api_walk_ctx_t *ctx = arg;
2937   nat64_db_bib_entry_t *bibe;
2938   fib_table_t *fib;
2939
2940   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2941   if (!bibe)
2942     return -1;
2943
2944   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2945   if (!fib)
2946     return -1;
2947
2948   rmp = vl_msg_api_alloc (sizeof (*rmp));
2949   clib_memset (rmp, 0, sizeof (*rmp));
2950   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2951   rmp->context = ctx->context;
2952   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2953   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2954   rmp->il_port = bibe->in_port;
2955   rmp->ol_port = bibe->out_port;
2956   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2957   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2958   rmp->il_port = ste->r_port;
2959   rmp->vrf_id = ntohl (fib->ft_table_id);
2960   rmp->proto = ste->proto;
2961
2962   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2963
2964   return 0;
2965 }
2966
2967 static void
2968 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2969 {
2970   vl_api_registration_t *reg;
2971   nat64_main_t *nm = &nat64_main;
2972   nat64_db_t *db;
2973
2974   reg = vl_api_client_index_to_registration (mp->client_index);
2975   if (!reg)
2976     return;
2977
2978   nat64_api_walk_ctx_t ctx = {
2979     .reg = reg,
2980     .context = mp->context,
2981   };
2982
2983   /* *INDENT-OFF* */
2984   vec_foreach (db, nm->db)
2985     {
2986       ctx.db = db;
2987       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2988     }
2989   /* *INDENT-ON* */
2990 }
2991
2992 static void *
2993 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2994 {
2995   u8 *s;
2996
2997   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2998
2999   FINISH;
3000 }
3001
3002 static void
3003 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
3004 {
3005   vl_api_nat64_add_del_prefix_reply_t *rmp;
3006   snat_main_t *sm = &snat_main;
3007   ip6_address_t prefix;
3008   int rv = 0;
3009
3010   memcpy (&prefix.as_u8, mp->prefix.address, 16);
3011
3012   rv =
3013     nat64_add_del_prefix (&prefix, mp->prefix.len,
3014                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
3015   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
3016 }
3017
3018 static void *
3019 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
3020                                      void *handle)
3021 {
3022   u8 *s;
3023
3024   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
3025               format_ip6_address, mp->prefix.address, mp->prefix.len,
3026               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
3027
3028   FINISH;
3029 }
3030
3031 static int
3032 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
3033 {
3034   vl_api_nat64_prefix_details_t *rmp;
3035   snat_main_t *sm = &snat_main;
3036   nat64_api_walk_ctx_t *ctx = arg;
3037
3038   rmp = vl_msg_api_alloc (sizeof (*rmp));
3039   clib_memset (rmp, 0, sizeof (*rmp));
3040   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
3041   clib_memcpy (rmp->prefix.address, &(p->prefix), 16);
3042   rmp->prefix.len = p->plen;
3043   rmp->vrf_id = ntohl (p->vrf_id);
3044   rmp->context = ctx->context;
3045
3046   vl_api_send_msg (ctx->reg, (u8 *) rmp);
3047
3048   return 0;
3049 }
3050
3051 static void
3052 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
3053 {
3054   vl_api_registration_t *reg;
3055
3056   reg = vl_api_client_index_to_registration (mp->client_index);
3057   if (!reg)
3058     return;
3059
3060   nat64_api_walk_ctx_t ctx = {
3061     .reg = reg,
3062     .context = mp->context,
3063   };
3064
3065   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
3066 }
3067
3068 static void *
3069 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
3070                                   void *handle)
3071 {
3072   u8 *s;
3073
3074   s = format (0, "SCRIPT: nat64_prefix_dump\n");
3075
3076   FINISH;
3077 }
3078
3079 static void
3080   vl_api_nat64_add_del_interface_addr_t_handler
3081   (vl_api_nat64_add_del_interface_addr_t * mp)
3082 {
3083   snat_main_t *sm = &snat_main;
3084   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
3085   u32 sw_if_index = ntohl (mp->sw_if_index);
3086   int rv = 0;
3087
3088   VALIDATE_SW_IF_INDEX (mp);
3089
3090   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
3091
3092   BAD_SW_IF_INDEX_LABEL;
3093
3094   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
3095 }
3096
3097 static void *vl_api_nat64_add_del_interface_addr_t_print
3098   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
3099 {
3100   u8 *s;
3101
3102   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
3103   s = format (s, "sw_if_index %d %s",
3104               clib_host_to_net_u32 (mp->sw_if_index),
3105               mp->is_add ? "" : "del");
3106
3107   FINISH;
3108 }
3109
3110 /***************/
3111 /*** DS-Lite ***/
3112 /***************/
3113
3114 static void
3115 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
3116 {
3117   vl_api_dslite_set_aftr_addr_reply_t *rmp;
3118   snat_main_t *sm = &snat_main;
3119   dslite_main_t *dm = &dslite_main;
3120   int rv = 0;
3121   ip6_address_t ip6_addr;
3122   ip4_address_t ip4_addr;
3123
3124   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
3125   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
3126
3127   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
3128   if (rv == 0)
3129     rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr);
3130
3131   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
3132 }
3133
3134 static void *
3135 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
3136                                      void *handle)
3137 {
3138   u8 *s;
3139
3140   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
3141   s = format (s, "ip6_addr %U ip4_addr %U\n",
3142               format_ip6_address, mp->ip6_addr,
3143               format_ip4_address, mp->ip4_addr);
3144
3145   FINISH;
3146 }
3147
3148 static void
3149 vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp)
3150 {
3151   snat_main_t *sm = &snat_main;
3152   vl_api_dslite_get_aftr_addr_reply_t *rmp;
3153   dslite_main_t *dm = &dslite_main;
3154   int rv = 0;
3155
3156   /* *INDENT-OFF* */
3157   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
3158   ({
3159     memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4);
3160     memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16);
3161   }))
3162   /* *INDENT-ON* */
3163 }
3164
3165 static void *
3166 vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp,
3167                                      void *handle)
3168 {
3169   u8 *s;
3170
3171   s = format (0, "SCRIPT: dslite_get_aftr_addr");
3172
3173   FINISH;
3174 }
3175
3176 static void
3177 vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp)
3178 {
3179   vl_api_dslite_set_b4_addr_reply_t *rmp;
3180   snat_main_t *sm = &snat_main;
3181   dslite_main_t *dm = &dslite_main;
3182   int rv = 0;
3183   ip6_address_t ip6_addr;
3184   ip4_address_t ip4_addr;
3185
3186   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
3187   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
3188
3189   rv = dslite_set_b4_ip6_addr (dm, &ip6_addr);
3190   if (rv == 0)
3191     rv = dslite_set_b4_ip4_addr (dm, &ip4_addr);
3192
3193   REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY);
3194 }
3195
3196 static void *
3197 vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp,
3198                                    void *handle)
3199 {
3200   u8 *s;
3201
3202   s = format (0, "SCRIPT: dslite_set_b4_addr ");
3203   s = format (s, "ip6_addr %U ip4_addr %U\n",
3204               format_ip6_address, mp->ip6_addr,
3205               format_ip6_address, mp->ip4_addr);
3206
3207   FINISH;
3208 }
3209
3210 static void
3211 vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp)
3212 {
3213   snat_main_t *sm = &snat_main;
3214   vl_api_dslite_get_b4_addr_reply_t *rmp;
3215   dslite_main_t *dm = &dslite_main;
3216   int rv = 0;
3217
3218   /* *INDENT-OFF* */
3219   REPLY_MACRO2 (VL_API_DSLITE_GET_B4_ADDR_REPLY,
3220   ({
3221     memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4);
3222     memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16);
3223   }))
3224   /* *INDENT-ON* */
3225 }
3226
3227 static void *
3228 vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp,
3229                                    void *handle)
3230 {
3231   u8 *s;
3232
3233   s = format (0, "SCRIPT: dslite_get_b4_addr");
3234
3235   FINISH;
3236 }
3237
3238 static void
3239   vl_api_dslite_add_del_pool_addr_range_t_handler
3240   (vl_api_dslite_add_del_pool_addr_range_t * mp)
3241 {
3242   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
3243   snat_main_t *sm = &snat_main;
3244   dslite_main_t *dm = &dslite_main;
3245   int rv = 0;
3246   ip4_address_t this_addr;
3247   u32 start_host_order, end_host_order;
3248   int i, count;
3249   u32 *tmp;
3250
3251   tmp = (u32 *) mp->start_addr;
3252   start_host_order = clib_host_to_net_u32 (tmp[0]);
3253   tmp = (u32 *) mp->end_addr;
3254   end_host_order = clib_host_to_net_u32 (tmp[0]);
3255
3256   count = (end_host_order - start_host_order) + 1;
3257   memcpy (&this_addr.as_u8, mp->start_addr, 4);
3258
3259   for (i = 0; i < count; i++)
3260     {
3261       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
3262         goto send_reply;
3263
3264       increment_v4_address (&this_addr);
3265     }
3266
3267 send_reply:
3268   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
3269 }
3270
3271 static void
3272 send_dslite_address_details (snat_address_t * ap,
3273                              vl_api_registration_t * reg, u32 context)
3274 {
3275   vl_api_dslite_address_details_t *rmp;
3276   snat_main_t *sm = &snat_main;
3277
3278   rmp = vl_msg_api_alloc (sizeof (*rmp));
3279
3280   clib_memset (rmp, 0, sizeof (*rmp));
3281
3282   rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + sm->msg_id_base);
3283   clib_memcpy (rmp->ip_address, &(ap->addr), 4);
3284   rmp->context = context;
3285
3286   vl_api_send_msg (reg, (u8 *) rmp);
3287 }
3288
3289 static void
3290 vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp)
3291 {
3292   vl_api_registration_t *reg;
3293   dslite_main_t *dm = &dslite_main;
3294   snat_address_t *ap;
3295
3296   reg = vl_api_client_index_to_registration (mp->client_index);
3297   if (!reg)
3298     return;
3299
3300   /* *INDENT-OFF* */
3301   vec_foreach (ap, dm->addr_pool)
3302     {
3303       send_dslite_address_details (ap, reg, mp->context);
3304     }
3305   /* *INDENT-ON* */
3306 }
3307
3308 static void *
3309 vl_api_dslite_address_dump_t_print (vl_api_dslite_address_dump_t * mp,
3310                                     void *handle)
3311 {
3312   u8 *s;
3313
3314   s = format (0, "SCRIPT: dslite_address_dump ");
3315
3316   FINISH;
3317 }
3318
3319 static void *vl_api_dslite_add_del_pool_addr_range_t_print
3320   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
3321 {
3322   u8 *s;
3323
3324   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
3325   s = format (s, "%U - %U\n",
3326               format_ip4_address, mp->start_addr,
3327               format_ip4_address, mp->end_addr);
3328
3329   FINISH;
3330 }
3331
3332
3333 /*************/
3334 /*** NAT66 ***/
3335 /*************/
3336
3337 static void
3338 vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
3339                                           mp)
3340 {
3341   snat_main_t *sm = &snat_main;
3342   vl_api_nat66_add_del_interface_reply_t *rmp;
3343   int rv = 0;
3344
3345   VALIDATE_SW_IF_INDEX (mp);
3346
3347   rv =
3348     nat66_interface_add_del (ntohl (mp->sw_if_index),
3349                              mp->flags & NAT_API_IS_INSIDE, mp->is_add);
3350
3351   BAD_SW_IF_INDEX_LABEL;
3352
3353   REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
3354 }
3355
3356 static void *
3357 vl_api_nat66_add_del_interface_t_print (vl_api_nat66_add_del_interface_t * mp,
3358                                         void *handle)
3359 {
3360   u8 *s;
3361
3362   s = format (0, "SCRIPT: nat66_add_del_interface ");
3363   s = format (s, "sw_if_index %d %s %s",
3364               clib_host_to_net_u32 (mp->sw_if_index),
3365               mp->flags & NAT_API_IS_INSIDE ? "in" : "out",
3366               mp->is_add ? "" : "del");
3367
3368   FINISH;
3369 }
3370
3371 static void
3372   vl_api_nat66_add_del_static_mapping_t_handler
3373   (vl_api_nat66_add_del_static_mapping_t * mp)
3374 {
3375   snat_main_t *sm = &snat_main;
3376   vl_api_nat66_add_del_static_mapping_reply_t *rmp;
3377   ip6_address_t l_addr, e_addr;
3378   int rv = 0;
3379
3380   memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
3381   memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
3382
3383   rv =
3384     nat66_static_mapping_add_del (&l_addr, &e_addr,
3385                                   clib_net_to_host_u32 (mp->vrf_id),
3386                                   mp->is_add);
3387
3388   REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
3389 }
3390
3391 static void *vl_api_nat66_add_del_static_mapping_t_print
3392   (vl_api_nat66_add_del_static_mapping_t * mp, void *handle)
3393 {
3394   u8 *s;
3395
3396   s = format (0, "SCRIPT: nat66_add_del_static_mapping ");
3397   s = format (s, "local_ip_address %U external_ip_address %U vrf_id %d %s",
3398               format_ip6_address, mp->local_ip_address,
3399               format_ip6_address, mp->external_ip_address,
3400               clib_net_to_host_u32 (mp->vrf_id), mp->is_add ? "" : "del");
3401
3402   FINISH;
3403 }
3404
3405 typedef struct nat66_api_walk_ctx_t_
3406 {
3407   vl_api_registration_t *rp;
3408   u32 context;
3409 } nat66_api_walk_ctx_t;
3410
3411 static int
3412 nat66_api_interface_walk (snat_interface_t * i, void *arg)
3413 {
3414   vl_api_nat66_interface_details_t *rmp;
3415   snat_main_t *sm = &snat_main;
3416   nat66_api_walk_ctx_t *ctx = arg;
3417
3418   rmp = vl_msg_api_alloc (sizeof (*rmp));
3419   clib_memset (rmp, 0, sizeof (*rmp));
3420   rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + sm->msg_id_base);
3421   rmp->sw_if_index = ntohl (i->sw_if_index);
3422   if (nat_interface_is_inside (i))
3423     rmp->flags |= NAT_API_IS_INSIDE;
3424   rmp->context = ctx->context;
3425
3426   vl_api_send_msg (ctx->rp, (u8 *) rmp);
3427
3428   return 0;
3429 }
3430
3431 static void
3432 vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
3433 {
3434   vl_api_registration_t *rp;
3435
3436   rp = vl_api_client_index_to_registration (mp->client_index);
3437   if (rp == 0)
3438     return;
3439
3440   nat66_api_walk_ctx_t ctx = {
3441     .rp = rp,
3442     .context = mp->context,
3443   };
3444
3445   nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
3446 }
3447
3448 static void *
3449 vl_api_nat66_interface_dump_t_print (vl_api_nat66_interface_dump_t * mp,
3450                                      void *handle)
3451 {
3452   u8 *s;
3453
3454   s = format (0, "SCRIPT: nat66_interface_dump ");
3455
3456   FINISH;
3457 }
3458
3459 static int
3460 nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
3461 {
3462   vl_api_nat66_static_mapping_details_t *rmp;
3463   nat66_main_t *nm = &nat66_main;
3464   snat_main_t *sm = &snat_main;
3465   nat66_api_walk_ctx_t *ctx = arg;
3466   fib_table_t *fib;
3467   vlib_counter_t vc;
3468
3469   fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
3470   if (!fib)
3471     return -1;
3472
3473   vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
3474
3475   rmp = vl_msg_api_alloc (sizeof (*rmp));
3476   clib_memset (rmp, 0, sizeof (*rmp));
3477   rmp->_vl_msg_id =
3478     ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + sm->msg_id_base);
3479   clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
3480   clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
3481   rmp->vrf_id = ntohl (fib->ft_table_id);
3482   rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
3483   rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
3484   rmp->context = ctx->context;
3485
3486   vl_api_send_msg (ctx->rp, (u8 *) rmp);
3487
3488   return 0;
3489 }
3490
3491 static void
3492 vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
3493                                             * mp)
3494 {
3495   vl_api_registration_t *rp;
3496
3497   rp = vl_api_client_index_to_registration (mp->client_index);
3498   if (rp == 0)
3499     return;
3500
3501   nat66_api_walk_ctx_t ctx = {
3502     .rp = rp,
3503     .context = mp->context,
3504   };
3505
3506   nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
3507 }
3508
3509 static void *
3510 vl_api_nat66_static_mapping_dump_t_print (vl_api_nat66_static_mapping_dump_t *
3511                                           mp, void *handle)
3512 {
3513   u8 *s;
3514
3515   s = format (0, "SCRIPT: nat66_static_mapping_dump ");
3516
3517   FINISH;
3518 }
3519
3520
3521 /* List of message types that this plugin understands */
3522 #define foreach_snat_plugin_api_msg                                     \
3523 _(NAT_CONTROL_PING, nat_control_ping)                                   \
3524 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
3525 _(NAT_SET_WORKERS, nat_set_workers)                                     \
3526 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
3527 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
3528 _(NAT_SET_REASS, nat_set_reass)                                         \
3529 _(NAT_GET_REASS, nat_get_reass)                                         \
3530 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
3531 _(NAT_SET_TIMEOUTS, nat_set_timeouts)                                   \
3532 _(NAT_GET_TIMEOUTS, nat_get_timeouts)                                   \
3533 _(NAT_SET_ADDR_AND_PORT_ALLOC_ALG, nat_set_addr_and_port_alloc_alg)     \
3534 _(NAT_GET_ADDR_AND_PORT_ALLOC_ALG, nat_get_addr_and_port_alloc_alg)     \
3535 _(NAT_SET_MSS_CLAMPING, nat_set_mss_clamping)                           \
3536 _(NAT_GET_MSS_CLAMPING, nat_get_mss_clamping)                           \
3537 _(NAT_HA_SET_LISTENER, nat_ha_set_listener)                             \
3538 _(NAT_HA_SET_FAILOVER, nat_ha_set_failover)                             \
3539 _(NAT_HA_GET_LISTENER, nat_ha_get_listener)                             \
3540 _(NAT_HA_GET_FAILOVER, nat_ha_get_failover)                             \
3541 _(NAT_HA_FLUSH, nat_ha_flush)                                           \
3542 _(NAT_HA_RESYNC, nat_ha_resync)                                         \
3543 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
3544 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
3545 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
3546 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
3547 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3548 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
3549 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3550 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3551 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3552 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3553 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3554 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3555 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3556   nat44_interface_add_del_output_feature)                               \
3557 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3558   nat44_interface_output_feature_dump)                                  \
3559 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3560 _(NAT44_LB_STATIC_MAPPING_ADD_DEL_LOCAL,                                \
3561   nat44_lb_static_mapping_add_del_local)                                \
3562 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3563 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
3564 _(NAT44_FORWARDING_ENABLE_DISABLE, nat44_forwarding_enable_disable)     \
3565 _(NAT44_FORWARDING_IS_ENABLED, nat44_forwarding_is_enabled)             \
3566 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3567 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3568 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3569 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3570 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3571 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3572 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3573 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3574 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3575 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3576 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3577 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3578 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3579 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3580 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3581 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
3582 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
3583 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
3584 _(DSLITE_ADDRESS_DUMP, dslite_address_dump)                             \
3585 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)                           \
3586 _(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr)                           \
3587 _(DSLITE_SET_B4_ADDR, dslite_set_b4_addr)                               \
3588 _(DSLITE_GET_B4_ADDR, dslite_get_b4_addr)                               \
3589 _(NAT66_ADD_DEL_INTERFACE, nat66_add_del_interface)                     \
3590 _(NAT66_INTERFACE_DUMP, nat66_interface_dump)                           \
3591 _(NAT66_ADD_DEL_STATIC_MAPPING, nat66_add_del_static_mapping)           \
3592 _(NAT66_STATIC_MAPPING_DUMP, nat66_static_mapping_dump)
3593
3594 /* Set up the API message handling tables */
3595 static clib_error_t *
3596 snat_plugin_api_hookup (vlib_main_t * vm)
3597 {
3598   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3599 #define _(N,n)                                                  \
3600     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3601                            #n,                                  \
3602                            vl_api_##n##_t_handler,              \
3603                            vl_noop_handler,                     \
3604                            vl_api_##n##_t_endian,               \
3605                            vl_api_##n##_t_print,                \
3606                            sizeof(vl_api_##n##_t), 1);
3607   foreach_snat_plugin_api_msg;
3608 #undef _
3609
3610   return 0;
3611 }
3612
3613 #define vl_msg_name_crc_list
3614 #include <nat/nat_all_api_h.h>
3615 #undef vl_msg_name_crc_list
3616
3617 static void
3618 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3619 {
3620 #define _(id,n,crc) \
3621   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3622   foreach_vl_msg_name_crc_nat;
3623 #undef _
3624 }
3625
3626 static void
3627 plugin_custom_dump_configure (snat_main_t * sm)
3628 {
3629 #define _(n,f) sm->api_main->msg_print_handlers \
3630   [VL_API_##n + sm->msg_id_base]                \
3631     = (void *) vl_api_##f##_t_print;
3632   foreach_snat_plugin_api_msg;
3633 #undef _
3634 }
3635
3636 clib_error_t *
3637 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3638 {
3639   u8 *name;
3640   clib_error_t *error = 0;
3641
3642   name = format (0, "nat_%08x%c", api_version, 0);
3643
3644   /* Ask for a correctly-sized block of API message decode slots */
3645   sm->msg_id_base =
3646     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3647
3648   error = snat_plugin_api_hookup (vm);
3649
3650   /* Add our API messages to the global name_crc hash table */
3651   setup_message_id_table (sm, sm->api_main);
3652
3653   plugin_custom_dump_configure (sm);
3654
3655   vec_free (name);
3656
3657   return error;
3658 }
3659
3660 /*
3661  * fd.io coding-style-patch-verification: ON
3662  *
3663  * Local Variables:
3664  * eval: (c-set-style "gnu")
3665  * End:
3666  */