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