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