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