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