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