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