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