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