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