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