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