NAT44: client-IP based session affinity for load-balancing (VPP-1297)
[vpp.git] / src / plugins / nat / nat_api.c
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @file
18  * @brief NAT plugin API implementation
19  */
20
21 #include <nat/nat.h>
22 #include <nat/nat_det.h>
23 #include <nat/nat64.h>
24 #include <nat/nat66.h>
25 #include <nat/dslite.h>
26 #include <nat/nat_reass.h>
27 #include <nat/nat_inlines.h>
28 #include <vlibapi/api.h>
29 #include <vlibmemory/api.h>
30
31 #include <nat/nat_msg_enum.h>
32 #include <vnet/fib/fib_table.h>
33
34 #define vl_api_nat44_lb_addr_port_t_endian vl_noop_handler
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 /******************************/
67 /*** Common NAT plugin APIs ***/
68 /******************************/
69
70 static void
71 vl_api_nat_control_ping_t_handler (vl_api_nat_control_ping_t * mp)
72 {
73   vl_api_nat_control_ping_reply_t *rmp;
74   snat_main_t *sm = &snat_main;
75   int rv = 0;
76
77   /* *INDENT-OFF* */
78   REPLY_MACRO2 (VL_API_NAT_CONTROL_PING_REPLY,
79   ({
80     rmp->vpe_pid = ntohl (getpid ());
81   }));
82   /* *INDENT-ON* */
83 }
84
85 static void *
86 vl_api_nat_control_ping_t_print (vl_api_nat_control_ping_t * mp, void *handle)
87 {
88   u8 *s;
89
90   s = format (0, "SCRIPT: nat_control_ping ");
91
92   FINISH;
93 }
94
95 static void
96 vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t * mp)
97 {
98   vl_api_nat_show_config_reply_t *rmp;
99   snat_main_t *sm = &snat_main;
100   dslite_main_t *dm = &dslite_main;
101   nat64_main_t *n64m = &nat64_main;
102   int rv = 0;
103
104   /* *INDENT-OFF* */
105   REPLY_MACRO2 (VL_API_NAT_SHOW_CONFIG_REPLY,
106   ({
107     rmp->translation_buckets = htonl (sm->translation_buckets);
108     rmp->translation_memory_size = htonl (sm->translation_memory_size);
109     rmp->user_buckets = htonl (sm->user_buckets);
110     rmp->user_memory_size = htonl (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->deterministic = sm->deterministic;
118     rmp->endpoint_dependent = sm->endpoint_dependent;
119     rmp->out2in_dpo = sm->out2in_dpo;
120     rmp->dslite_ce = dm->is_ce;
121     rmp->nat64_bib_buckets = n64m->bib_buckets;
122     rmp->nat64_bib_memory_size = n64m->bib_memory_size;
123     rmp->nat64_st_buckets = n64m->st_buckets;
124     rmp->nat64_st_memory_size = n64m->st_memory_size;
125   }));
126   /* *INDENT-ON* */
127 }
128
129 static void *
130 vl_api_nat_show_config_t_print (vl_api_nat_show_config_t * mp, void *handle)
131 {
132   u8 *s;
133
134   s = format (0, "SCRIPT: nat_show_config ");
135
136   FINISH;
137 }
138
139 static void
140 vl_api_nat_set_workers_t_handler (vl_api_nat_set_workers_t * mp)
141 {
142   snat_main_t *sm = &snat_main;
143   vl_api_nat_set_workers_reply_t *rmp;
144   int rv = 0;
145   uword *bitmap = 0;
146   u64 mask;
147
148   if (sm->deterministic)
149     {
150       rv = VNET_API_ERROR_UNSUPPORTED;
151       goto send_reply;
152     }
153
154   mask = clib_net_to_host_u64 (mp->worker_mask);
155
156   if (sm->num_workers < 2)
157     {
158       rv = VNET_API_ERROR_FEATURE_DISABLED;
159       goto send_reply;
160     }
161
162   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
163   rv = snat_set_workers (bitmap);
164   clib_bitmap_free (bitmap);
165
166 send_reply:
167   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
168 }
169
170 static void *
171 vl_api_nat_set_workers_t_print (vl_api_nat_set_workers_t * mp, void *handle)
172 {
173   u8 *s;
174   uword *bitmap = 0;
175   u8 first = 1;
176   int i;
177   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
178
179   s = format (0, "SCRIPT: nat_set_workers ");
180   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
181   /* *INDENT-OFF* */
182   clib_bitmap_foreach (i, bitmap,
183     ({
184       if (first)
185         s = format (s, "%d", i);
186       else
187         s = format (s, ",%d", i);
188       first = 0;
189     }));
190   /* *INDENT-ON* */
191   clib_bitmap_free (bitmap);
192   FINISH;
193 }
194
195 static void
196 send_nat_worker_details (u32 worker_index, vl_api_registration_t * reg,
197                          u32 context)
198 {
199   vl_api_nat_worker_details_t *rmp;
200   snat_main_t *sm = &snat_main;
201   vlib_worker_thread_t *w =
202     vlib_worker_threads + worker_index + sm->first_worker_index;
203
204   rmp = vl_msg_api_alloc (sizeof (*rmp));
205   memset (rmp, 0, sizeof (*rmp));
206   rmp->_vl_msg_id = ntohs (VL_API_NAT_WORKER_DETAILS + sm->msg_id_base);
207   rmp->context = context;
208   rmp->worker_index = htonl (worker_index);
209   rmp->lcore_id = htonl (w->lcore_id);
210   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
211
212   vl_api_send_msg (reg, (u8 *) rmp);
213 }
214
215 static void
216 vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp)
217 {
218   vl_api_registration_t *reg;
219   snat_main_t *sm = &snat_main;
220   u32 *worker_index;
221
222   if (sm->deterministic)
223     return;
224
225   reg = vl_api_client_index_to_registration (mp->client_index);
226   if (!reg)
227     return;
228
229   /* *INDENT-OFF* */
230   vec_foreach (worker_index, sm->workers)
231     send_nat_worker_details(*worker_index, reg, mp->context);
232   /* *INDENT-ON* */
233 }
234
235 static void *
236 vl_api_nat_worker_dump_t_print (vl_api_nat_worker_dump_t * mp, void *handle)
237 {
238   u8 *s;
239
240   s = format (0, "SCRIPT: nat_worker_dump ");
241
242   FINISH;
243 }
244
245 static void
246 vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t *
247                                            mp)
248 {
249   snat_main_t *sm = &snat_main;
250   vl_api_nat_ipfix_enable_disable_reply_t *rmp;
251   int rv = 0;
252
253   rv = snat_ipfix_logging_enable_disable (mp->enable,
254                                           clib_host_to_net_u32
255                                           (mp->domain_id),
256                                           clib_host_to_net_u16
257                                           (mp->src_port));
258
259   REPLY_MACRO (VL_API_NAT_IPFIX_ENABLE_DISABLE_REPLY);
260 }
261
262 static void *
263 vl_api_nat_ipfix_enable_disable_t_print (vl_api_nat_ipfix_enable_disable_t *
264                                          mp, void *handle)
265 {
266   u8 *s;
267
268   s = format (0, "SCRIPT: nat_ipfix_enable_disable ");
269   if (mp->domain_id)
270     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
271   if (mp->src_port)
272     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
273   if (!mp->enable)
274     s = format (s, "disable ");
275
276   FINISH;
277 }
278
279 static void
280 vl_api_nat_set_reass_t_handler (vl_api_nat_set_reass_t * mp)
281 {
282   snat_main_t *sm = &snat_main;
283   vl_api_nat_set_reass_reply_t *rmp;
284   int rv = 0;
285
286   rv =
287     nat_reass_set (ntohl (mp->timeout), ntohs (mp->max_reass), mp->max_frag,
288                    mp->drop_frag, mp->is_ip6);
289
290   REPLY_MACRO (VL_API_NAT_SET_REASS_REPLY);
291 }
292
293 static void *
294 vl_api_nat_set_reass_t_print (vl_api_nat_set_reass_t * mp, void *handle)
295 {
296   u8 *s;
297
298   s = format (0, "SCRIPT: nat_set_reass ");
299   s = format (s, "timeout %d max_reass %d max_frag %d drop_frag %d is_ip6 %d",
300               clib_host_to_net_u32 (mp->timeout),
301               clib_host_to_net_u16 (mp->max_reass),
302               mp->max_frag, mp->drop_frag, mp->is_ip6);
303
304   FINISH;
305 }
306
307 static void
308 vl_api_nat_get_reass_t_handler (vl_api_nat_get_reass_t * mp)
309 {
310   snat_main_t *sm = &snat_main;
311   vl_api_nat_get_reass_reply_t *rmp;
312   int rv = 0;
313
314   /* *INDENT-OFF* */
315   REPLY_MACRO2 (VL_API_NAT_GET_REASS_REPLY,
316   ({
317     rmp->ip4_timeout = htonl (nat_reass_get_timeout(0));
318     rmp->ip4_max_reass = htons (nat_reass_get_max_reass(0));
319     rmp->ip4_max_frag = nat_reass_get_max_frag(0);
320     rmp->ip4_drop_frag = nat_reass_is_drop_frag(0);
321     rmp->ip6_timeout = htonl (nat_reass_get_timeout(1));
322     rmp->ip6_max_reass = htons (nat_reass_get_max_reass(1));
323     rmp->ip6_max_frag = nat_reass_get_max_frag(1);
324     rmp->ip6_drop_frag = nat_reass_is_drop_frag(1);
325   }))
326   /* *INDENT-ON* */
327 }
328
329 static void *
330 vl_api_nat_get_reass_t_print (vl_api_nat_get_reass_t * mp, void *handle)
331 {
332   u8 *s;
333
334   s = format (0, "SCRIPT: nat_get_reass");
335
336   FINISH;
337 }
338
339 typedef struct nat_api_walk_ctx_t_
340 {
341   vl_api_registration_t *reg;
342   u32 context;
343 } nat_api_walk_ctx_t;
344
345 static int
346 nat_ip4_reass_walk_api (nat_reass_ip4_t * reass, void *arg)
347 {
348   vl_api_nat_reass_details_t *rmp;
349   snat_main_t *sm = &snat_main;
350   nat_api_walk_ctx_t *ctx = arg;
351
352   rmp = vl_msg_api_alloc (sizeof (*rmp));
353   memset (rmp, 0, sizeof (*rmp));
354   rmp->_vl_msg_id = ntohs (VL_API_NAT_REASS_DETAILS + sm->msg_id_base);
355   rmp->context = ctx->context;
356   clib_memcpy (rmp->src_addr, &(reass->key.src), 4);
357   clib_memcpy (rmp->dst_addr, &(reass->key.dst), 4);
358   rmp->proto = reass->key.proto;
359   rmp->frag_id = ntohl (reass->key.frag_id);
360   rmp->frag_n = reass->frag_n;
361   rmp->is_ip4 = 1;
362
363   vl_api_send_msg (ctx->reg, (u8 *) rmp);
364
365   return 0;
366 }
367
368 static int
369 nat_ip6_reass_walk_api (nat_reass_ip6_t * reass, void *arg)
370 {
371   vl_api_nat_reass_details_t *rmp;
372   snat_main_t *sm = &snat_main;
373   nat_api_walk_ctx_t *ctx = arg;
374
375   rmp = vl_msg_api_alloc (sizeof (*rmp));
376   memset (rmp, 0, sizeof (*rmp));
377   rmp->_vl_msg_id = ntohs (VL_API_NAT_REASS_DETAILS + sm->msg_id_base);
378   rmp->context = ctx->context;
379   clib_memcpy (rmp->src_addr, &(reass->key.src), 16);
380   clib_memcpy (rmp->dst_addr, &(reass->key.dst), 16);
381   rmp->proto = reass->key.proto;
382   rmp->frag_id = ntohl (reass->key.frag_id);
383   rmp->frag_n = reass->frag_n;
384   rmp->is_ip4 = 0;
385
386   vl_api_send_msg (ctx->reg, (u8 *) rmp);
387
388   return 0;
389 }
390
391 static void
392 vl_api_nat_reass_dump_t_handler (vl_api_nat_reass_dump_t * mp)
393 {
394   vl_api_registration_t *reg;
395
396   reg = vl_api_client_index_to_registration (mp->client_index);
397   if (!reg)
398     return;
399
400   nat_api_walk_ctx_t ctx = {
401     .reg = reg,
402     .context = mp->context,
403   };
404
405   nat_ip4_reass_walk (nat_ip4_reass_walk_api, &ctx);
406   nat_ip6_reass_walk (nat_ip6_reass_walk_api, &ctx);
407 }
408
409 static void *
410 vl_api_nat_reass_dump_t_print (vl_api_nat_reass_dump_t * mp, void *handle)
411 {
412   u8 *s;
413
414   s = format (0, "SCRIPT: nat_reass_dump");
415
416   FINISH;
417 }
418
419 static void
420 vl_api_nat_set_timeouts_t_handler (vl_api_nat_set_timeouts_t * mp)
421 {
422   snat_main_t *sm = &snat_main;
423   vl_api_nat_set_timeouts_reply_t *rmp;
424   int rv = 0;
425
426   sm->udp_timeout = ntohl (mp->udp);
427   sm->tcp_established_timeout = ntohl (mp->tcp_established);
428   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
429   sm->icmp_timeout = ntohl (mp->icmp);
430
431   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
432   if (rv)
433     goto send_reply;
434   rv = nat64_set_udp_timeout (ntohl (mp->udp));
435   if (rv)
436     goto send_reply;
437   rv =
438     nat64_set_tcp_timeouts (ntohl (mp->tcp_transitory),
439                             ntohl (mp->tcp_established));
440
441 send_reply:
442   REPLY_MACRO (VL_API_NAT_SET_TIMEOUTS_REPLY);
443 }
444
445 static void *
446 vl_api_nat_set_timeouts_t_print (vl_api_nat_set_timeouts_t * mp, void *handle)
447 {
448   u8 *s;
449
450   s = format (0, "SCRIPT: nat_set_timeouts ");
451   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
452               ntohl (mp->udp),
453               ntohl (mp->tcp_established),
454               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
455
456   FINISH;
457 }
458
459 static void
460 vl_api_nat_get_timeouts_t_handler (vl_api_nat_get_timeouts_t * mp)
461 {
462   snat_main_t *sm = &snat_main;
463   vl_api_nat_get_timeouts_reply_t *rmp;
464   int rv = 0;
465
466   /* *INDENT-OFF* */
467   REPLY_MACRO2 (VL_API_NAT_GET_TIMEOUTS_REPLY,
468   ({
469     rmp->udp = htonl (sm->udp_timeout);
470     rmp->tcp_established = htonl (sm->tcp_established_timeout);
471     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
472     rmp->icmp = htonl (sm->icmp_timeout);
473   }))
474   /* *INDENT-ON* */
475 }
476
477 static void *
478 vl_api_nat_get_timeouts_t_print (vl_api_nat_get_timeouts_t * mp, void *handle)
479 {
480   u8 *s;
481
482   s = format (0, "SCRIPT: nat_get_timeouts");
483
484   FINISH;
485 }
486
487 /*************/
488 /*** NAT44 ***/
489 /*************/
490 static void
491   vl_api_nat44_add_del_address_range_t_handler
492   (vl_api_nat44_add_del_address_range_t * mp)
493 {
494   snat_main_t *sm = &snat_main;
495   vl_api_nat44_add_del_address_range_reply_t *rmp;
496   ip4_address_t this_addr;
497   u32 start_host_order, end_host_order;
498   u32 vrf_id;
499   int i, count;
500   int rv = 0;
501   u32 *tmp;
502
503   if (sm->deterministic)
504     {
505       rv = VNET_API_ERROR_UNSUPPORTED;
506       goto send_reply;
507     }
508
509   if (sm->static_mapping_only)
510     {
511       rv = VNET_API_ERROR_FEATURE_DISABLED;
512       goto send_reply;
513     }
514
515   tmp = (u32 *) mp->first_ip_address;
516   start_host_order = clib_host_to_net_u32 (tmp[0]);
517   tmp = (u32 *) mp->last_ip_address;
518   end_host_order = clib_host_to_net_u32 (tmp[0]);
519
520   count = (end_host_order - start_host_order) + 1;
521
522   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
523
524   if (count > 1024)
525     nat_log_info ("%U - %U, %d addresses...",
526                   format_ip4_address, mp->first_ip_address,
527                   format_ip4_address, mp->last_ip_address, count);
528
529   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
530
531   for (i = 0; i < count; i++)
532     {
533       if (mp->is_add)
534         rv = snat_add_address (sm, &this_addr, vrf_id, mp->twice_nat);
535       else
536         rv = snat_del_address (sm, this_addr, 0, mp->twice_nat);
537
538       if (rv)
539         goto send_reply;
540
541       if (sm->out2in_dpo)
542         nat44_add_del_address_dpo (this_addr, mp->is_add);
543
544       increment_v4_address (&this_addr);
545     }
546
547 send_reply:
548   REPLY_MACRO (VL_API_NAT44_ADD_DEL_ADDRESS_RANGE_REPLY);
549 }
550
551 static void *vl_api_nat44_add_del_address_range_t_print
552   (vl_api_nat44_add_del_address_range_t * mp, void *handle)
553 {
554   u8 *s;
555
556   s = format (0, "SCRIPT: nat44_add_address_range ");
557   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
558   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
559     {
560       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
561     }
562   s = format (s, "twice_nat %d ", mp->twice_nat);
563   FINISH;
564 }
565
566 static void
567 send_nat44_address_details (snat_address_t * a,
568                             vl_api_registration_t * reg, u32 context,
569                             u8 twice_nat)
570 {
571   vl_api_nat44_address_details_t *rmp;
572   snat_main_t *sm = &snat_main;
573
574   rmp = vl_msg_api_alloc (sizeof (*rmp));
575   memset (rmp, 0, sizeof (*rmp));
576   rmp->_vl_msg_id = ntohs (VL_API_NAT44_ADDRESS_DETAILS + sm->msg_id_base);
577   clib_memcpy (rmp->ip_address, &(a->addr), 4);
578   if (a->fib_index != ~0)
579     {
580       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
581       rmp->vrf_id = ntohl (fib->ft_table_id);
582     }
583   else
584     rmp->vrf_id = ~0;
585   rmp->twice_nat = twice_nat;
586   rmp->context = context;
587
588   vl_api_send_msg (reg, (u8 *) rmp);
589 }
590
591 static void
592 vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp)
593 {
594   vl_api_registration_t *reg;
595   snat_main_t *sm = &snat_main;
596   snat_address_t *a;
597
598   if (sm->deterministic)
599     return;
600
601   reg = vl_api_client_index_to_registration (mp->client_index);
602   if (!reg)
603     return;
604
605   /* *INDENT-OFF* */
606   vec_foreach (a, sm->addresses)
607     send_nat44_address_details (a, reg, mp->context, 0);
608   vec_foreach (a, sm->twice_nat_addresses)
609     send_nat44_address_details (a, reg, mp->context, 1);
610   /* *INDENT-ON* */
611 }
612
613 static void *
614 vl_api_nat44_address_dump_t_print (vl_api_nat44_address_dump_t * mp,
615                                    void *handle)
616 {
617   u8 *s;
618
619   s = format (0, "SCRIPT: nat44_address_dump ");
620
621   FINISH;
622 }
623
624 static void
625   vl_api_nat44_interface_add_del_feature_t_handler
626   (vl_api_nat44_interface_add_del_feature_t * mp)
627 {
628   snat_main_t *sm = &snat_main;
629   vl_api_nat44_interface_add_del_feature_reply_t *rmp;
630   u8 is_del = mp->is_add == 0;
631   u32 sw_if_index = ntohl (mp->sw_if_index);
632   int rv = 0;
633
634   VALIDATE_SW_IF_INDEX (mp);
635
636   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
637
638   BAD_SW_IF_INDEX_LABEL;
639
640   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY);
641 }
642
643 static void *vl_api_nat44_interface_add_del_feature_t_print
644   (vl_api_nat44_interface_add_del_feature_t * mp, void *handle)
645 {
646   u8 *s;
647
648   s = format (0, "SCRIPT: nat44_interface_add_del_feature ");
649   s = format (s, "sw_if_index %d %s %s",
650               clib_host_to_net_u32 (mp->sw_if_index),
651               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
652
653   FINISH;
654 }
655
656 static void
657 send_nat44_interface_details (snat_interface_t * i,
658                               vl_api_registration_t * reg, u32 context)
659 {
660   vl_api_nat44_interface_details_t *rmp;
661   snat_main_t *sm = &snat_main;
662
663   rmp = vl_msg_api_alloc (sizeof (*rmp));
664   memset (rmp, 0, sizeof (*rmp));
665   rmp->_vl_msg_id = ntohs (VL_API_NAT44_INTERFACE_DETAILS + sm->msg_id_base);
666   rmp->sw_if_index = ntohl (i->sw_if_index);
667   rmp->is_inside = (nat_interface_is_inside (i)
668                     && nat_interface_is_outside (i)) ? 2 :
669     nat_interface_is_inside (i);
670   rmp->context = context;
671
672   vl_api_send_msg (reg, (u8 *) rmp);
673 }
674
675 static void
676 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
677 {
678   vl_api_registration_t *reg;
679   snat_main_t *sm = &snat_main;
680   snat_interface_t *i;
681
682   reg = vl_api_client_index_to_registration (mp->client_index);
683   if (!reg)
684     return;
685
686   /* *INDENT-OFF* */
687   pool_foreach (i, sm->interfaces,
688   ({
689     send_nat44_interface_details(i, reg, mp->context);
690   }));
691   /* *INDENT-ON* */
692 }
693
694 static void *
695 vl_api_nat44_interface_dump_t_print (vl_api_nat44_interface_dump_t * mp,
696                                      void *handle)
697 {
698   u8 *s;
699
700   s = format (0, "SCRIPT: nat44_interface_dump ");
701
702   FINISH;
703 }
704
705 static void
706   vl_api_nat44_interface_add_del_output_feature_t_handler
707   (vl_api_nat44_interface_add_del_output_feature_t * mp)
708 {
709   snat_main_t *sm = &snat_main;
710   vl_api_nat44_interface_add_del_output_feature_reply_t *rmp;
711   u8 is_del = mp->is_add == 0;
712   u32 sw_if_index = ntohl (mp->sw_if_index);
713   int rv = 0;
714
715   if (sm->deterministic)
716     {
717       rv = VNET_API_ERROR_UNSUPPORTED;
718       goto send_reply;
719     }
720
721   VALIDATE_SW_IF_INDEX (mp);
722
723   rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
724                                               is_del);
725
726   BAD_SW_IF_INDEX_LABEL;
727 send_reply:
728   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
729 }
730
731 static void *vl_api_nat44_interface_add_del_output_feature_t_print
732   (vl_api_nat44_interface_add_del_output_feature_t * mp, void *handle)
733 {
734   u8 *s;
735
736   s = format (0, "SCRIPT: nat44_interface_add_del_output_feature ");
737   s = format (s, "sw_if_index %d %s %s",
738               clib_host_to_net_u32 (mp->sw_if_index),
739               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
740
741   FINISH;
742 }
743
744 static void
745 send_nat44_interface_output_feature_details (snat_interface_t * i,
746                                              vl_api_registration_t * reg,
747                                              u32 context)
748 {
749   vl_api_nat44_interface_output_feature_details_t *rmp;
750   snat_main_t *sm = &snat_main;
751
752   rmp = vl_msg_api_alloc (sizeof (*rmp));
753   memset (rmp, 0, sizeof (*rmp));
754   rmp->_vl_msg_id =
755     ntohs (VL_API_NAT44_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
756   rmp->sw_if_index = ntohl (i->sw_if_index);
757   rmp->context = context;
758   rmp->is_inside = nat_interface_is_inside (i);
759
760   vl_api_send_msg (reg, (u8 *) rmp);
761 }
762
763 static void
764   vl_api_nat44_interface_output_feature_dump_t_handler
765   (vl_api_nat44_interface_output_feature_dump_t * mp)
766 {
767   vl_api_registration_t *reg;
768   snat_main_t *sm = &snat_main;
769   snat_interface_t *i;
770
771   if (sm->deterministic)
772     return;
773
774   reg = vl_api_client_index_to_registration (mp->client_index);
775   if (!reg)
776     return;
777
778   /* *INDENT-OFF* */
779   pool_foreach (i, sm->output_feature_interfaces,
780   ({
781     send_nat44_interface_output_feature_details(i, reg, mp->context);
782   }));
783   /* *INDENT-ON* */
784 }
785
786 static void *vl_api_nat44_interface_output_feature_dump_t_print
787   (vl_api_nat44_interface_output_feature_dump_t * mp, void *handle)
788 {
789   u8 *s;
790
791   s = format (0, "SCRIPT: nat44_interface_output_feature_dump ");
792
793   FINISH;
794 }
795
796 static void
797   vl_api_nat44_add_del_static_mapping_t_handler
798   (vl_api_nat44_add_del_static_mapping_t * mp)
799 {
800   snat_main_t *sm = &snat_main;
801   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
802   ip4_address_t local_addr, external_addr;
803   u16 local_port = 0, external_port = 0;
804   u32 vrf_id, external_sw_if_index;
805   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
806   int rv = 0;
807   snat_protocol_t proto;
808   u8 *tag = 0;
809
810   if (sm->deterministic)
811     {
812       rv = VNET_API_ERROR_UNSUPPORTED;
813       goto send_reply;
814     }
815
816   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
817   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
818   if (mp->addr_only == 0)
819     {
820       local_port = clib_net_to_host_u16 (mp->local_port);
821       external_port = clib_net_to_host_u16 (mp->external_port);
822     }
823   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
824   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
825   proto = ip_proto_to_snat_proto (mp->protocol);
826   if (mp->twice_nat)
827     twice_nat = TWICE_NAT;
828   else if (mp->self_twice_nat)
829     twice_nat = TWICE_NAT_SELF;
830   mp->tag[sizeof (mp->tag) - 1] = 0;
831   tag = format (0, "%s", mp->tag);
832   vec_terminate_c_string (tag);
833
834   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
835                                 external_port, vrf_id, mp->addr_only,
836                                 external_sw_if_index, proto, mp->is_add,
837                                 twice_nat, mp->out2in_only, tag);
838
839   vec_free (tag);
840
841 send_reply:
842   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
843 }
844
845 static void *vl_api_nat44_add_del_static_mapping_t_print
846   (vl_api_nat44_add_del_static_mapping_t * mp, void *handle)
847 {
848   u8 *s;
849
850   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
851   s = format (s, "protocol %d local_addr %U external_addr %U ",
852               mp->protocol,
853               format_ip4_address, mp->local_ip_address,
854               format_ip4_address, mp->external_ip_address);
855
856   if (mp->addr_only == 0)
857     s = format (s, "local_port %d external_port %d ",
858                 clib_net_to_host_u16 (mp->local_port),
859                 clib_net_to_host_u16 (mp->external_port));
860
861   s = format (s, "twice_nat %d out2in_only %d ",
862               mp->twice_nat, mp->out2in_only);
863
864   if (mp->vrf_id != ~0)
865     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
866
867   if (mp->external_sw_if_index != ~0)
868     s = format (s, "external_sw_if_index %d",
869                 clib_net_to_host_u32 (mp->external_sw_if_index));
870   FINISH;
871 }
872
873 static void
874 send_nat44_static_mapping_details (snat_static_mapping_t * m,
875                                    vl_api_registration_t * reg, u32 context)
876 {
877   vl_api_nat44_static_mapping_details_t *rmp;
878   snat_main_t *sm = &snat_main;
879
880   rmp = vl_msg_api_alloc (sizeof (*rmp));
881   memset (rmp, 0, sizeof (*rmp));
882   rmp->_vl_msg_id =
883     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
884   rmp->addr_only = m->addr_only;
885   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
886   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
887   rmp->external_sw_if_index = ~0;
888   rmp->vrf_id = htonl (m->vrf_id);
889   rmp->context = context;
890   if (m->twice_nat == TWICE_NAT)
891     rmp->twice_nat = 1;
892   else if (m->twice_nat == TWICE_NAT_SELF)
893     rmp->self_twice_nat = 1;
894   rmp->out2in_only = m->out2in_only;
895   if (m->addr_only == 0)
896     {
897       rmp->protocol = snat_proto_to_ip_proto (m->proto);
898       rmp->external_port = htons (m->external_port);
899       rmp->local_port = htons (m->local_port);
900     }
901   if (m->tag)
902     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
903
904   vl_api_send_msg (reg, (u8 *) rmp);
905 }
906
907 static void
908 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
909                                        vl_api_registration_t * reg,
910                                        u32 context)
911 {
912   vl_api_nat44_static_mapping_details_t *rmp;
913   snat_main_t *sm = &snat_main;
914
915   rmp = vl_msg_api_alloc (sizeof (*rmp));
916   memset (rmp, 0, sizeof (*rmp));
917   rmp->_vl_msg_id =
918     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
919   rmp->addr_only = m->addr_only;
920   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
921   rmp->external_sw_if_index = htonl (m->sw_if_index);
922   rmp->vrf_id = htonl (m->vrf_id);
923   rmp->context = context;
924   rmp->twice_nat = m->twice_nat;
925   if (m->addr_only == 0)
926     {
927       rmp->protocol = snat_proto_to_ip_proto (m->proto);
928       rmp->external_port = htons (m->e_port);
929       rmp->local_port = htons (m->l_port);
930     }
931   if (m->tag)
932     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
933
934   vl_api_send_msg (reg, (u8 *) rmp);
935 }
936
937 static void
938 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
939                                             * mp)
940 {
941   vl_api_registration_t *reg;
942   snat_main_t *sm = &snat_main;
943   snat_static_mapping_t *m;
944   snat_static_map_resolve_t *rp;
945   int j;
946
947   if (sm->deterministic)
948     return;
949
950   reg = vl_api_client_index_to_registration (mp->client_index);
951   if (!reg)
952     return;
953
954   /* *INDENT-OFF* */
955   pool_foreach (m, sm->static_mappings,
956   ({
957       if (!vec_len (m->locals) &&
958           ((m->local_port != m->external_port)
959            || (m->local_addr.as_u32 != m->external_addr.as_u32)))
960         send_nat44_static_mapping_details (m, reg, mp->context);
961   }));
962   /* *INDENT-ON* */
963
964   for (j = 0; j < vec_len (sm->to_resolve); j++)
965     {
966       rp = sm->to_resolve + j;
967       if (rp->l_addr.as_u32 != 0)
968         send_nat44_static_map_resolve_details (rp, reg, mp->context);
969     }
970 }
971
972 static void *
973 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
974                                           mp, void *handle)
975 {
976   u8 *s;
977
978   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
979
980   FINISH;
981 }
982
983 static void
984   vl_api_nat44_add_del_identity_mapping_t_handler
985   (vl_api_nat44_add_del_identity_mapping_t * mp)
986 {
987   snat_main_t *sm = &snat_main;
988   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
989   ip4_address_t addr;
990   u16 port = 0;
991   u32 vrf_id, sw_if_index;
992   int rv = 0;
993   snat_protocol_t proto = ~0;
994   u8 *tag = 0;
995
996   if (sm->deterministic)
997     {
998       rv = VNET_API_ERROR_UNSUPPORTED;
999       goto send_reply;
1000     }
1001
1002   if (mp->addr_only == 0)
1003     {
1004       port = clib_net_to_host_u16 (mp->port);
1005       proto = ip_proto_to_snat_proto (mp->protocol);
1006     }
1007   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1008   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1009   if (sw_if_index != ~0)
1010     addr.as_u32 = 0;
1011   else
1012     memcpy (&addr.as_u8, mp->ip_address, 4);
1013   mp->tag[sizeof (mp->tag) - 1] = 0;
1014   tag = format (0, "%s", mp->tag);
1015   vec_terminate_c_string (tag);
1016
1017   rv =
1018     snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only,
1019                              sw_if_index, proto, mp->is_add, 0, 0, tag);
1020
1021   vec_free (tag);
1022
1023 send_reply:
1024   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
1025 }
1026
1027 static void *vl_api_nat44_add_del_identity_mapping_t_print
1028   (vl_api_nat44_add_del_identity_mapping_t * mp, void *handle)
1029 {
1030   u8 *s;
1031
1032   s = format (0, "SCRIPT: nat44_add_del_identity_mapping ");
1033   if (mp->sw_if_index != ~0)
1034     s = format (s, "sw_if_index %d", clib_net_to_host_u32 (mp->sw_if_index));
1035   else
1036     s = format (s, "addr %U", format_ip4_address, mp->ip_address);
1037
1038   if (mp->addr_only == 0)
1039     s =
1040       format (s, "protocol %d port %d", mp->protocol,
1041               clib_net_to_host_u16 (mp->port));
1042
1043   if (mp->vrf_id != ~0)
1044     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1045
1046   FINISH;
1047 }
1048
1049 static void
1050 send_nat44_identity_mapping_details (snat_static_mapping_t * m,
1051                                      vl_api_registration_t * reg, u32 context)
1052 {
1053   vl_api_nat44_identity_mapping_details_t *rmp;
1054   snat_main_t *sm = &snat_main;
1055
1056   rmp = vl_msg_api_alloc (sizeof (*rmp));
1057   memset (rmp, 0, sizeof (*rmp));
1058   rmp->_vl_msg_id =
1059     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1060   rmp->addr_only = m->addr_only;
1061   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
1062   rmp->port = htons (m->local_port);
1063   rmp->sw_if_index = ~0;
1064   rmp->vrf_id = htonl (m->vrf_id);
1065   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1066   rmp->context = context;
1067   if (m->tag)
1068     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1069
1070   vl_api_send_msg (reg, (u8 *) rmp);
1071 }
1072
1073 static void
1074 send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
1075                                          vl_api_registration_t * reg,
1076                                          u32 context)
1077 {
1078   vl_api_nat44_identity_mapping_details_t *rmp;
1079   snat_main_t *sm = &snat_main;
1080
1081   rmp = vl_msg_api_alloc (sizeof (*rmp));
1082   memset (rmp, 0, sizeof (*rmp));
1083   rmp->_vl_msg_id =
1084     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1085   rmp->addr_only = m->addr_only;
1086   rmp->port = htons (m->l_port);
1087   rmp->sw_if_index = htonl (m->sw_if_index);
1088   rmp->vrf_id = htonl (m->vrf_id);
1089   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1090   rmp->context = context;
1091   if (m->tag)
1092     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1093
1094   vl_api_send_msg (reg, (u8 *) rmp);
1095 }
1096
1097 static void
1098   vl_api_nat44_identity_mapping_dump_t_handler
1099   (vl_api_nat44_identity_mapping_dump_t * mp)
1100 {
1101   vl_api_registration_t *reg;
1102   snat_main_t *sm = &snat_main;
1103   snat_static_mapping_t *m;
1104   snat_static_map_resolve_t *rp;
1105   int j;
1106
1107   if (sm->deterministic)
1108     return;
1109
1110   reg = vl_api_client_index_to_registration (mp->client_index);
1111   if (!reg)
1112     return;
1113
1114   /* *INDENT-OFF* */
1115   pool_foreach (m, sm->static_mappings,
1116   ({
1117       if (!vec_len (m->locals) && (m->local_port == m->external_port)
1118           && (m->local_addr.as_u32 == m->external_addr.as_u32))
1119         send_nat44_identity_mapping_details (m, reg, mp->context);
1120   }));
1121   /* *INDENT-ON* */
1122
1123   for (j = 0; j < vec_len (sm->to_resolve); j++)
1124     {
1125       rp = sm->to_resolve + j;
1126       if (rp->l_addr.as_u32 == 0)
1127         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
1128     }
1129 }
1130
1131 static void *vl_api_nat44_identity_mapping_dump_t_print
1132   (vl_api_nat44_identity_mapping_dump_t * mp, void *handle)
1133 {
1134   u8 *s;
1135
1136   s = format (0, "SCRIPT: nat44_identity_mapping_dump ");
1137
1138   FINISH;
1139 }
1140
1141 static void
1142   vl_api_nat44_add_del_interface_addr_t_handler
1143   (vl_api_nat44_add_del_interface_addr_t * mp)
1144 {
1145   snat_main_t *sm = &snat_main;
1146   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1147   u8 is_del = mp->is_add == 0;
1148   u32 sw_if_index = ntohl (mp->sw_if_index);
1149   int rv = 0;
1150
1151   if (sm->deterministic)
1152     {
1153       rv = VNET_API_ERROR_UNSUPPORTED;
1154       goto send_reply;
1155     }
1156
1157   VALIDATE_SW_IF_INDEX (mp);
1158
1159   rv = snat_add_interface_address (sm, sw_if_index, is_del, mp->twice_nat);
1160
1161   BAD_SW_IF_INDEX_LABEL;
1162 send_reply:
1163   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1164 }
1165
1166 static void *vl_api_nat44_add_del_interface_addr_t_print
1167   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
1168 {
1169   u8 *s;
1170
1171   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
1172   s = format (s, "sw_if_index %d twice_nat %d %s",
1173               clib_host_to_net_u32 (mp->sw_if_index),
1174               mp->twice_nat, mp->is_add ? "" : "del");
1175
1176   FINISH;
1177 }
1178
1179 static void
1180 send_nat44_interface_addr_details (u32 sw_if_index,
1181                                    vl_api_registration_t * reg, u32 context,
1182                                    u8 twice_nat)
1183 {
1184   vl_api_nat44_interface_addr_details_t *rmp;
1185   snat_main_t *sm = &snat_main;
1186
1187   rmp = vl_msg_api_alloc (sizeof (*rmp));
1188   memset (rmp, 0, sizeof (*rmp));
1189   rmp->_vl_msg_id =
1190     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1191   rmp->sw_if_index = ntohl (sw_if_index);
1192   rmp->twice_nat = twice_nat;
1193   rmp->context = context;
1194
1195   vl_api_send_msg (reg, (u8 *) rmp);
1196 }
1197
1198 static void
1199 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1200                                             * mp)
1201 {
1202   vl_api_registration_t *reg;
1203   snat_main_t *sm = &snat_main;
1204   u32 *i;
1205
1206   if (sm->deterministic)
1207     return;
1208
1209   reg = vl_api_client_index_to_registration (mp->client_index);
1210   if (!reg)
1211     return;
1212
1213   /* *INDENT-OFF* */
1214   vec_foreach (i, sm->auto_add_sw_if_indices)
1215     send_nat44_interface_addr_details(*i, reg, mp->context, 0);
1216   vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
1217     send_nat44_interface_addr_details(*i, reg, mp->context, 1);
1218   /* *INDENT-ON* */
1219 }
1220
1221 static void *
1222 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1223                                           mp, void *handle)
1224 {
1225   u8 *s;
1226
1227   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
1228
1229   FINISH;
1230 }
1231
1232 static void
1233 send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg,
1234                          u32 context)
1235 {
1236   vl_api_nat44_user_details_t *rmp;
1237   snat_main_t *sm = &snat_main;
1238   ip4_main_t *im = &ip4_main;
1239
1240   rmp = vl_msg_api_alloc (sizeof (*rmp));
1241   memset (rmp, 0, sizeof (*rmp));
1242   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1243
1244   if (!pool_is_free_index (im->fibs, u->fib_index))
1245     {
1246       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1247       rmp->vrf_id = ntohl (fib->ft_table_id);
1248     }
1249
1250   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1251   rmp->nsessions = ntohl (u->nsessions);
1252   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1253   rmp->context = context;
1254
1255   vl_api_send_msg (reg, (u8 *) rmp);
1256 }
1257
1258 static void
1259 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1260 {
1261   vl_api_registration_t *reg;
1262   snat_main_t *sm = &snat_main;
1263   snat_main_per_thread_data_t *tsm;
1264   snat_user_t *u;
1265
1266   if (sm->deterministic)
1267     return;
1268
1269   reg = vl_api_client_index_to_registration (mp->client_index);
1270   if (!reg)
1271     return;
1272
1273   /* *INDENT-OFF* */
1274   vec_foreach (tsm, sm->per_thread_data)
1275     {
1276       pool_foreach (u, tsm->users,
1277       ({
1278         send_nat44_user_details (u, reg, mp->context);
1279       }));
1280     }
1281   /* *INDENT-ON* */
1282 }
1283
1284 static void *
1285 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
1286 {
1287   u8 *s;
1288
1289   s = format (0, "SCRIPT: nat44_user_dump ");
1290
1291   FINISH;
1292 }
1293
1294 static void
1295 send_nat44_user_session_details (snat_session_t * s,
1296                                  vl_api_registration_t * reg, u32 context)
1297 {
1298   vl_api_nat44_user_session_details_t *rmp;
1299   snat_main_t *sm = &snat_main;
1300
1301   rmp = vl_msg_api_alloc (sizeof (*rmp));
1302   memset (rmp, 0, sizeof (*rmp));
1303   rmp->_vl_msg_id =
1304     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1305   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1306   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1307   rmp->is_static = snat_is_session_static (s) ? 1 : 0;
1308   rmp->is_twicenat = is_twice_nat_session (s) ? 1 : 0;
1309   rmp->ext_host_valid = is_ed_session (s)
1310     || is_fwd_bypass_session (s) ? 1 : 0;
1311   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1312   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1313   rmp->total_pkts = ntohl (s->total_pkts);
1314   rmp->context = context;
1315   if (snat_is_unk_proto_session (s))
1316     {
1317       rmp->outside_port = 0;
1318       rmp->inside_port = 0;
1319       rmp->protocol = ntohs (s->in2out.port);
1320     }
1321   else
1322     {
1323       rmp->outside_port = s->out2in.port;
1324       rmp->inside_port = s->in2out.port;
1325       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
1326     }
1327   if (is_ed_session (s) || is_fwd_bypass_session (s))
1328     {
1329       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1330       rmp->ext_host_port = s->ext_host_port;
1331       if (is_twice_nat_session (s))
1332         {
1333           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1334           rmp->ext_host_nat_port = s->ext_host_nat_port;
1335         }
1336     }
1337
1338   vl_api_send_msg (reg, (u8 *) rmp);
1339 }
1340
1341 static void
1342 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1343                                           mp)
1344 {
1345   vl_api_registration_t *reg;
1346   snat_main_t *sm = &snat_main;
1347   snat_main_per_thread_data_t *tsm;
1348   snat_session_t *s;
1349   clib_bihash_kv_8_8_t key, value;
1350   snat_user_key_t ukey;
1351   snat_user_t *u;
1352   u32 session_index, head_index, elt_index;
1353   dlist_elt_t *head, *elt;
1354   ip4_header_t ip;
1355
1356   if (sm->deterministic)
1357     return;
1358
1359   reg = vl_api_client_index_to_registration (mp->client_index);
1360   if (!reg)
1361     return;
1362
1363   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1364   ip.src_address.as_u32 = ukey.addr.as_u32;
1365   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1366   key.key = ukey.as_u64;
1367   if (sm->num_workers > 1)
1368     tsm =
1369       vec_elt_at_index (sm->per_thread_data,
1370                         sm->worker_in2out_cb (&ip, ukey.fib_index));
1371   else
1372     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1373   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1374     return;
1375   u = pool_elt_at_index (tsm->users, value.value);
1376   if (!u->nsessions && !u->nstaticsessions)
1377     return;
1378
1379   head_index = u->sessions_per_user_list_head_index;
1380   head = pool_elt_at_index (tsm->list_pool, head_index);
1381   elt_index = head->next;
1382   elt = pool_elt_at_index (tsm->list_pool, elt_index);
1383   session_index = elt->value;
1384   while (session_index != ~0)
1385     {
1386       s = pool_elt_at_index (tsm->sessions, session_index);
1387
1388       send_nat44_user_session_details (s, reg, mp->context);
1389
1390       elt_index = elt->next;
1391       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1392       session_index = elt->value;
1393     }
1394 }
1395
1396 static void *
1397 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
1398                                         void *handle)
1399 {
1400   u8 *s;
1401
1402   s = format (0, "SCRIPT: nat44_user_session_dump ");
1403   s = format (s, "ip_address %U vrf_id %d\n",
1404               format_ip4_address, mp->ip_address,
1405               clib_net_to_host_u32 (mp->vrf_id));
1406
1407   FINISH;
1408 }
1409
1410 static nat44_lb_addr_port_t *
1411 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1412                              u8 addr_port_pair_num)
1413 {
1414   u8 i;
1415   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1416   vl_api_nat44_lb_addr_port_t *ap;
1417
1418   for (i = 0; i < addr_port_pair_num; i++)
1419     {
1420       ap = &addr_port_pairs[i];
1421       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1422       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1423       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
1424       lb_addr_port.probability = ap->probability;
1425       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1426       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1427     }
1428
1429   return lb_addr_port_pairs;
1430 }
1431
1432 static void
1433   vl_api_nat44_add_del_lb_static_mapping_t_handler
1434   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1435 {
1436   snat_main_t *sm = &snat_main;
1437   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1438   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1439   int rv = 0;
1440   nat44_lb_addr_port_t *locals = 0;
1441   ip4_address_t e_addr;
1442   snat_protocol_t proto;
1443   u8 *tag = 0;
1444
1445   if (!sm->endpoint_dependent)
1446     {
1447       rv = VNET_API_ERROR_UNSUPPORTED;
1448       goto send_reply;
1449     }
1450
1451   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
1452   clib_memcpy (&e_addr, mp->external_addr, 4);
1453   proto = ip_proto_to_snat_proto (mp->protocol);
1454   if (mp->twice_nat)
1455     twice_nat = TWICE_NAT;
1456   else if (mp->self_twice_nat)
1457     twice_nat = TWICE_NAT_SELF;
1458   mp->tag[sizeof (mp->tag) - 1] = 0;
1459   tag = format (0, "%s", mp->tag);
1460   vec_terminate_c_string (tag);
1461
1462   rv =
1463     nat44_add_del_lb_static_mapping (e_addr,
1464                                      clib_net_to_host_u16 (mp->external_port),
1465                                      proto, locals, mp->is_add, twice_nat,
1466                                      mp->out2in_only, tag,
1467                                      clib_net_to_host_u32 (mp->affinity));
1468
1469   vec_free (locals);
1470   vec_free (tag);
1471
1472 send_reply:
1473   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1474 }
1475
1476 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1477   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1478 {
1479   u8 *s;
1480
1481   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1482   s = format (s, "is_add %d twice_nat %d out2in_only %d ",
1483               mp->is_add, mp->twice_nat, mp->out2in_only);
1484
1485   FINISH;
1486 }
1487
1488 static void
1489 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1490                                       vl_api_registration_t * reg,
1491                                       u32 context)
1492 {
1493   vl_api_nat44_lb_static_mapping_details_t *rmp;
1494   snat_main_t *sm = &snat_main;
1495   nat44_lb_addr_port_t *ap;
1496   vl_api_nat44_lb_addr_port_t *locals;
1497
1498   rmp =
1499     vl_msg_api_alloc (sizeof (*rmp) +
1500                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
1501   memset (rmp, 0, sizeof (*rmp));
1502   rmp->_vl_msg_id =
1503     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1504
1505   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1506   rmp->external_port = ntohs (m->external_port);
1507   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1508   rmp->context = context;
1509   if (m->twice_nat == TWICE_NAT)
1510     rmp->twice_nat = 1;
1511   else if (m->twice_nat == TWICE_NAT_SELF)
1512     rmp->self_twice_nat = 1;
1513   rmp->out2in_only = m->out2in_only;
1514   if (m->tag)
1515     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1516
1517   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1518   vec_foreach (ap, m->locals)
1519   {
1520     clib_memcpy (locals->addr, &(ap->addr), 4);
1521     locals->port = htons (ap->port);
1522     locals->probability = ap->probability;
1523     locals->vrf_id = ntohl (ap->vrf_id);
1524     locals++;
1525     rmp->local_num++;
1526   }
1527
1528   vl_api_send_msg (reg, (u8 *) rmp);
1529 }
1530
1531 static void
1532   vl_api_nat44_lb_static_mapping_dump_t_handler
1533   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1534 {
1535   vl_api_registration_t *reg;
1536   snat_main_t *sm = &snat_main;
1537   snat_static_mapping_t *m;
1538
1539   if (!sm->endpoint_dependent)
1540     return;
1541
1542   reg = vl_api_client_index_to_registration (mp->client_index);
1543   if (!reg)
1544     return;
1545
1546   /* *INDENT-OFF* */
1547   pool_foreach (m, sm->static_mappings,
1548   ({
1549       if (vec_len(m->locals))
1550         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1551   }));
1552   /* *INDENT-ON* */
1553 }
1554
1555 static void *vl_api_nat44_lb_static_mapping_dump_t_print
1556   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
1557 {
1558   u8 *s;
1559
1560   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
1561
1562   FINISH;
1563 }
1564
1565 static void
1566 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1567 {
1568   snat_main_t *sm = &snat_main;
1569   vl_api_nat44_del_session_reply_t *rmp;
1570   ip4_address_t addr, eh_addr;
1571   u16 port, eh_port;
1572   u32 vrf_id;
1573   int rv = 0;
1574   snat_protocol_t proto;
1575
1576   if (sm->deterministic)
1577     {
1578       rv = VNET_API_ERROR_UNSUPPORTED;
1579       goto send_reply;
1580     }
1581
1582   memcpy (&addr.as_u8, mp->address, 4);
1583   port = clib_net_to_host_u16 (mp->port);
1584   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1585   proto = ip_proto_to_snat_proto (mp->protocol);
1586   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1587   eh_port = clib_net_to_host_u16 (mp->ext_host_port);
1588
1589   if (mp->ext_host_valid)
1590     rv =
1591       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1592                             vrf_id, mp->is_in);
1593   else
1594     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
1595
1596 send_reply:
1597   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1598 }
1599
1600 static void *
1601 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
1602                                   void *handle)
1603 {
1604   u8 *s;
1605
1606   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1607   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
1608               format_ip4_address, mp->address,
1609               clib_net_to_host_u16 (mp->port),
1610               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
1611   if (mp->ext_host_valid)
1612     s = format (s, "ext_host_address %U ext_host_port %d",
1613                 format_ip4_address, mp->ext_host_address,
1614                 clib_net_to_host_u16 (mp->ext_host_port));
1615
1616   FINISH;
1617 }
1618
1619 static void
1620   vl_api_nat44_forwarding_enable_disable_t_handler
1621   (vl_api_nat44_forwarding_enable_disable_t * mp)
1622 {
1623   snat_main_t *sm = &snat_main;
1624   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1625   int rv = 0;
1626   u32 *ses_to_be_removed = 0, *ses_index;
1627   snat_main_per_thread_data_t *tsm;
1628   snat_session_t *s;
1629
1630   sm->forwarding_enabled = mp->enable != 0;
1631
1632   if (mp->enable == 0)
1633     {
1634       /* *INDENT-OFF* */
1635       vec_foreach (tsm, sm->per_thread_data)
1636       {
1637         pool_foreach (s, tsm->sessions,
1638         ({
1639           if (is_fwd_bypass_session(s))
1640             {
1641               vec_add1 (ses_to_be_removed, s - tsm->sessions);
1642             }
1643         }));
1644         vec_foreach (ses_index, ses_to_be_removed)
1645         {
1646           s = pool_elt_at_index(tsm->sessions, ses_index[0]);
1647           nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1648           nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1649         }
1650         vec_free (ses_to_be_removed);
1651       }
1652       /* *INDENT-ON* */
1653     }
1654
1655   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1656 }
1657
1658 static void *vl_api_nat44_forwarding_enable_disable_t_print
1659   (vl_api_nat44_forwarding_enable_disable_t * mp, void *handle)
1660 {
1661   u8 *s;
1662
1663   s = format (0, "SCRIPT: nat44_forwarding_enable_disable ");
1664   s = format (s, "enable %d", mp->enable != 0);
1665
1666   FINISH;
1667 }
1668
1669 static void
1670   vl_api_nat44_forwarding_is_enabled_t_handler
1671   (vl_api_nat44_forwarding_is_enabled_t * mp)
1672 {
1673   vl_api_registration_t *reg;
1674   snat_main_t *sm = &snat_main;
1675   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1676
1677   reg = vl_api_client_index_to_registration (mp->client_index);
1678   if (!reg)
1679     return;
1680
1681   rmp = vl_msg_api_alloc (sizeof (*rmp));
1682   memset (rmp, 0, sizeof (*rmp));
1683   rmp->_vl_msg_id =
1684     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1685   rmp->context = mp->context;
1686
1687   rmp->enabled = sm->forwarding_enabled;
1688
1689   vl_api_send_msg (reg, (u8 *) rmp);
1690 }
1691
1692 static void *vl_api_nat44_forwarding_is_enabled_t_print
1693   (vl_api_nat44_forwarding_is_enabled_t * mp, void *handle)
1694 {
1695   u8 *s;
1696
1697   s = format (0, "SCRIPT: nat44_forwarding_is_enabled ");
1698
1699   FINISH;
1700 }
1701
1702 /*******************************/
1703 /*** Deterministic NAT (CGN) ***/
1704 /*******************************/
1705
1706 static void
1707 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
1708 {
1709   snat_main_t *sm = &snat_main;
1710   vl_api_nat_det_add_del_map_reply_t *rmp;
1711   int rv = 0;
1712   ip4_address_t in_addr, out_addr;
1713
1714   if (!sm->deterministic)
1715     {
1716       rv = VNET_API_ERROR_UNSUPPORTED;
1717       goto send_reply;
1718     }
1719
1720   if (!mp->is_nat44)
1721     {
1722       rv = VNET_API_ERROR_UNIMPLEMENTED;
1723       goto send_reply;
1724     }
1725
1726   clib_memcpy (&in_addr, mp->in_addr, 4);
1727   clib_memcpy (&out_addr, mp->out_addr, 4);
1728   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
1729                          mp->out_plen, mp->is_add);
1730
1731 send_reply:
1732   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
1733 }
1734
1735 static void *
1736 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
1737                                     void *handle)
1738 {
1739   u8 *s;
1740
1741   s = format (0, "SCRIPT: nat_det_add_del_map ");
1742   s = format (s, "inside address %U/%d outside address %U/%d\n",
1743               format_ip4_address, mp->in_addr, mp->in_plen,
1744               format_ip4_address, mp->out_addr, mp->out_plen);
1745
1746   FINISH;
1747 }
1748
1749 static void
1750 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
1751 {
1752   snat_main_t *sm = &snat_main;
1753   vl_api_nat_det_forward_reply_t *rmp;
1754   int rv = 0;
1755   u16 lo_port = 0, hi_port = 0;
1756   snat_det_map_t *dm;
1757   ip4_address_t in_addr, out_addr;
1758
1759   if (!sm->deterministic)
1760     {
1761       rv = VNET_API_ERROR_UNSUPPORTED;
1762       REPLY_MACRO (VL_API_NAT_DET_FORWARD_REPLY);
1763       return;
1764     }
1765
1766   if (!mp->is_nat44)
1767     {
1768       out_addr.as_u32 = 0;
1769       rv = VNET_API_ERROR_UNIMPLEMENTED;
1770       goto send_reply;
1771     }
1772
1773   out_addr.as_u32 = 0;
1774   clib_memcpy (&in_addr, mp->in_addr, 4);
1775   dm = snat_det_map_by_user (sm, &in_addr);
1776   if (!dm)
1777     {
1778       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1779       goto send_reply;
1780     }
1781
1782   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1783   hi_port = lo_port + dm->ports_per_host - 1;
1784
1785 send_reply:
1786   /* *INDENT-OFF* */
1787   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
1788   ({
1789     rmp->out_port_lo = ntohs (lo_port);
1790     rmp->out_port_hi = ntohs (hi_port);
1791     clib_memcpy (rmp->out_addr, &out_addr, 4);
1792   }))
1793   /* *INDENT-ON* */
1794 }
1795
1796 static void *
1797 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
1798 {
1799   u8 *s;
1800
1801   s = format (0, "SCRIPT: nat_det_forward");
1802   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
1803
1804   FINISH;
1805 }
1806
1807 static void
1808 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
1809 {
1810   snat_main_t *sm = &snat_main;
1811   vl_api_nat_det_reverse_reply_t *rmp;
1812   int rv = 0;
1813   ip4_address_t out_addr, in_addr;
1814   snat_det_map_t *dm;
1815
1816   if (!sm->deterministic)
1817     {
1818       rv = VNET_API_ERROR_UNSUPPORTED;
1819       REPLY_MACRO (VL_API_NAT_DET_REVERSE_REPLY);
1820       return;
1821     }
1822
1823   in_addr.as_u32 = 0;
1824   clib_memcpy (&out_addr, mp->out_addr, 4);
1825   dm = snat_det_map_by_out (sm, &out_addr);
1826   if (!dm)
1827     {
1828       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1829       goto send_reply;
1830     }
1831
1832   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1833
1834 send_reply:
1835   /* *INDENT-OFF* */
1836   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
1837   ({
1838     rmp->is_nat44 = 1;
1839     memset (rmp->in_addr, 0, 16);
1840     clib_memcpy (rmp->in_addr, &in_addr, 4);
1841   }))
1842   /* *INDENT-ON* */
1843 }
1844
1845 static void *
1846 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
1847 {
1848   u8 *s;
1849
1850   s = format (0, "SCRIPT: nat_det_reverse");
1851   s = format (s, "outside ip address %U outside port %d",
1852               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1853
1854   FINISH;
1855 }
1856
1857 static void
1858 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
1859                           u32 context)
1860 {
1861   vl_api_nat_det_map_details_t *rmp;
1862   snat_main_t *sm = &snat_main;
1863
1864   rmp = vl_msg_api_alloc (sizeof (*rmp));
1865   memset (rmp, 0, sizeof (*rmp));
1866   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
1867   rmp->is_nat44 = 1;
1868   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
1869   rmp->in_plen = m->in_plen;
1870   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
1871   rmp->out_plen = m->out_plen;
1872   rmp->sharing_ratio = htonl (m->sharing_ratio);
1873   rmp->ports_per_host = htons (m->ports_per_host);
1874   rmp->ses_num = htonl (m->ses_num);
1875   rmp->context = context;
1876
1877   vl_api_send_msg (reg, (u8 *) rmp);
1878 }
1879
1880 static void
1881 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
1882 {
1883   vl_api_registration_t *reg;
1884   snat_main_t *sm = &snat_main;
1885   snat_det_map_t *m;
1886
1887   if (!sm->deterministic)
1888     return;
1889
1890   reg = vl_api_client_index_to_registration (mp->client_index);
1891   if (!reg)
1892     return;
1893
1894   /* *INDENT-OFF* */
1895   vec_foreach(m, sm->det_maps)
1896     sent_nat_det_map_details(m, reg, mp->context);
1897   /* *INDENT-ON* */
1898 }
1899
1900 static void *
1901 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
1902 {
1903   u8 *s;
1904
1905   s = format (0, "SCRIPT: nat_det_map_dump ");
1906
1907   FINISH;
1908 }
1909
1910 static void
1911 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
1912                                             * mp)
1913 {
1914   snat_main_t *sm = &snat_main;
1915   vl_api_nat_det_close_session_out_reply_t *rmp;
1916   ip4_address_t out_addr, ext_addr, in_addr;
1917   snat_det_out_key_t key;
1918   snat_det_map_t *dm;
1919   snat_det_session_t *ses;
1920   int rv = 0;
1921
1922   if (!sm->deterministic)
1923     {
1924       rv = VNET_API_ERROR_UNSUPPORTED;
1925       goto send_reply;
1926     }
1927
1928   clib_memcpy (&out_addr, mp->out_addr, 4);
1929   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1930
1931   dm = snat_det_map_by_out (sm, &out_addr);
1932   if (!dm)
1933     {
1934       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1935       goto send_reply;
1936     }
1937   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
1938   key.ext_host_addr = ext_addr;
1939   key.ext_host_port = mp->ext_port;
1940   key.out_port = mp->out_port;
1941   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
1942   if (!ses)
1943     {
1944       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1945       goto send_reply;
1946     }
1947   snat_det_ses_close (dm, ses);
1948
1949 send_reply:
1950   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
1951 }
1952
1953 static void *
1954 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
1955                                           mp, void *handle)
1956 {
1957   u8 *s;
1958
1959   s = format (0, "SCRIPT: nat_det_close_session_out ");
1960   s = format (s, "out_addr %U out_port %d "
1961               "ext_addr %U ext_port %d\n",
1962               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
1963               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
1964
1965   FINISH;
1966 }
1967
1968 static void
1969 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
1970                                            mp)
1971 {
1972   snat_main_t *sm = &snat_main;
1973   vl_api_nat_det_close_session_in_reply_t *rmp;
1974   ip4_address_t in_addr, ext_addr;
1975   snat_det_out_key_t key;
1976   snat_det_map_t *dm;
1977   snat_det_session_t *ses;
1978   int rv = 0;
1979
1980   if (!sm->deterministic)
1981     {
1982       rv = VNET_API_ERROR_UNSUPPORTED;
1983       goto send_reply;
1984     }
1985
1986   if (!mp->is_nat44)
1987     {
1988       rv = VNET_API_ERROR_UNIMPLEMENTED;
1989       goto send_reply;
1990     }
1991
1992   clib_memcpy (&in_addr, mp->in_addr, 4);
1993   clib_memcpy (&ext_addr, mp->ext_addr, 4);
1994
1995   dm = snat_det_map_by_user (sm, &in_addr);
1996   if (!dm)
1997     {
1998       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1999       goto send_reply;
2000     }
2001   key.ext_host_addr = ext_addr;
2002   key.ext_host_port = mp->ext_port;
2003   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
2004   if (!ses)
2005     {
2006       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2007       goto send_reply;
2008     }
2009   snat_det_ses_close (dm, ses);
2010
2011 send_reply:
2012   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2013 }
2014
2015 static void *
2016 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2017                                          mp, void *handle)
2018 {
2019   u8 *s;
2020   s = format (0, "SCRIPT: nat_det_close_session_in ");
2021   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2022               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2023               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2024
2025   FINISH;
2026 }
2027
2028 static void
2029 send_nat_det_session_details (snat_det_session_t * s,
2030                               vl_api_registration_t * reg, u32 context)
2031 {
2032   vl_api_nat_det_session_details_t *rmp;
2033   snat_main_t *sm = &snat_main;
2034
2035   rmp = vl_msg_api_alloc (sizeof (*rmp));
2036   memset (rmp, 0, sizeof (*rmp));
2037   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2038   rmp->in_port = s->in_port;
2039   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2040   rmp->ext_port = s->out.ext_host_port;
2041   rmp->out_port = s->out.out_port;
2042   rmp->state = s->state;
2043   rmp->expire = ntohl (s->expire);
2044   rmp->context = context;
2045
2046   vl_api_send_msg (reg, (u8 *) rmp);
2047 }
2048
2049 static void
2050 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2051 {
2052   vl_api_registration_t *reg;
2053   snat_main_t *sm = &snat_main;
2054   ip4_address_t user_addr;
2055   snat_det_map_t *dm;
2056   snat_det_session_t *s, empty_ses;
2057   u16 i;
2058
2059   if (!sm->deterministic)
2060     return;
2061
2062   reg = vl_api_client_index_to_registration (mp->client_index);
2063   if (!reg)
2064     return;
2065   if (!mp->is_nat44)
2066     return;
2067
2068   memset (&empty_ses, 0, sizeof (empty_ses));
2069   clib_memcpy (&user_addr, mp->user_addr, 4);
2070   dm = snat_det_map_by_user (sm, &user_addr);
2071   if (!dm)
2072     return;
2073
2074   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2075   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2076     {
2077       if (s->out.as_u64)
2078         send_nat_det_session_details (s, reg, mp->context);
2079       s++;
2080     }
2081 }
2082
2083 static void *
2084 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2085                                      void *handle)
2086 {
2087   u8 *s;
2088
2089   s = format (0, "SCRIPT: nat_det_session_dump ");
2090   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2091
2092   FINISH;
2093 }
2094
2095 /*************/
2096 /*** NAT64 ***/
2097 /*************/
2098
2099 static void
2100   vl_api_nat64_add_del_pool_addr_range_t_handler
2101   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2102 {
2103   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2104   snat_main_t *sm = &snat_main;
2105   int rv = 0;
2106   ip4_address_t this_addr;
2107   u32 start_host_order, end_host_order;
2108   u32 vrf_id;
2109   int i, count;
2110   u32 *tmp;
2111
2112   tmp = (u32 *) mp->start_addr;
2113   start_host_order = clib_host_to_net_u32 (tmp[0]);
2114   tmp = (u32 *) mp->end_addr;
2115   end_host_order = clib_host_to_net_u32 (tmp[0]);
2116
2117   count = (end_host_order - start_host_order) + 1;
2118
2119   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2120
2121   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2122
2123   for (i = 0; i < count; i++)
2124     {
2125       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
2126         goto send_reply;
2127
2128       increment_v4_address (&this_addr);
2129     }
2130
2131 send_reply:
2132   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2133 }
2134
2135 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2136   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2137 {
2138   u8 *s;
2139
2140   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2141   s = format (s, "%U - %U vrf_id %u %s\n",
2142               format_ip4_address, mp->start_addr,
2143               format_ip4_address, mp->end_addr,
2144               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2145
2146   FINISH;
2147 }
2148
2149 typedef struct nat64_api_walk_ctx_t_
2150 {
2151   vl_api_registration_t *reg;
2152   u32 context;
2153   nat64_db_t *db;
2154 } nat64_api_walk_ctx_t;
2155
2156 static int
2157 nat64_api_pool_walk (snat_address_t * a, void *arg)
2158 {
2159   vl_api_nat64_pool_addr_details_t *rmp;
2160   snat_main_t *sm = &snat_main;
2161   nat64_api_walk_ctx_t *ctx = arg;
2162
2163   rmp = vl_msg_api_alloc (sizeof (*rmp));
2164   memset (rmp, 0, sizeof (*rmp));
2165   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2166   clib_memcpy (rmp->address, &(a->addr), 4);
2167   if (a->fib_index != ~0)
2168     {
2169       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2170       if (!fib)
2171         return -1;
2172       rmp->vrf_id = ntohl (fib->ft_table_id);
2173     }
2174   else
2175     rmp->vrf_id = ~0;
2176   rmp->context = ctx->context;
2177
2178   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2179
2180   return 0;
2181 }
2182
2183 static void
2184 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2185 {
2186   vl_api_registration_t *reg;
2187
2188   reg = vl_api_client_index_to_registration (mp->client_index);
2189   if (!reg)
2190     return;
2191
2192   nat64_api_walk_ctx_t ctx = {
2193     .reg = reg,
2194     .context = mp->context,
2195   };
2196
2197   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2198 }
2199
2200 static void *
2201 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2202                                      void *handle)
2203 {
2204   u8 *s;
2205
2206   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2207
2208   FINISH;
2209 }
2210
2211 static void
2212 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2213                                           mp)
2214 {
2215   snat_main_t *sm = &snat_main;
2216   vl_api_nat64_add_del_interface_reply_t *rmp;
2217   int rv = 0;
2218
2219   VALIDATE_SW_IF_INDEX (mp);
2220
2221   rv =
2222     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
2223                              mp->is_add);
2224
2225   BAD_SW_IF_INDEX_LABEL;
2226
2227   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2228 }
2229
2230 static void *
2231 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2232                                         void *handle)
2233 {
2234   u8 *s;
2235
2236   s = format (0, "SCRIPT: nat64_add_del_interface ");
2237   s = format (s, "sw_if_index %d %s %s",
2238               clib_host_to_net_u32 (mp->sw_if_index),
2239               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2240
2241   FINISH;
2242 }
2243
2244 static int
2245 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2246 {
2247   vl_api_nat64_interface_details_t *rmp;
2248   snat_main_t *sm = &snat_main;
2249   nat64_api_walk_ctx_t *ctx = arg;
2250
2251   rmp = vl_msg_api_alloc (sizeof (*rmp));
2252   memset (rmp, 0, sizeof (*rmp));
2253   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2254   rmp->sw_if_index = ntohl (i->sw_if_index);
2255   rmp->is_inside = (nat_interface_is_inside (i)
2256                     && nat_interface_is_outside (i)) ? 2 :
2257     nat_interface_is_inside (i);
2258   rmp->context = ctx->context;
2259
2260   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2261
2262   return 0;
2263 }
2264
2265 static void
2266 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2267 {
2268   vl_api_registration_t *reg;
2269
2270   reg = vl_api_client_index_to_registration (mp->client_index);
2271   if (!reg)
2272     return;
2273
2274   nat64_api_walk_ctx_t ctx = {
2275     .reg = reg,
2276     .context = mp->context,
2277   };
2278
2279   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2280 }
2281
2282 static void *
2283 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2284                                      void *handle)
2285 {
2286   u8 *s;
2287
2288   s = format (0, "SCRIPT: snat_interface_dump ");
2289
2290   FINISH;
2291 }
2292
2293 static void
2294   vl_api_nat64_add_del_static_bib_t_handler
2295   (vl_api_nat64_add_del_static_bib_t * mp)
2296 {
2297   snat_main_t *sm = &snat_main;
2298   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2299   ip6_address_t in_addr;
2300   ip4_address_t out_addr;
2301   int rv = 0;
2302
2303   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2304   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2305
2306   rv =
2307     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2308                                     clib_net_to_host_u16 (mp->i_port),
2309                                     clib_net_to_host_u16 (mp->o_port),
2310                                     mp->proto,
2311                                     clib_net_to_host_u32 (mp->vrf_id),
2312                                     mp->is_add);
2313
2314   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2315 }
2316
2317 static void *vl_api_nat64_add_del_static_bib_t_print
2318   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2319 {
2320   u8 *s;
2321
2322   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2323   s = format (s, "protocol %d i_addr %U o_addr %U ",
2324               mp->proto,
2325               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2326
2327   if (mp->vrf_id != ~0)
2328     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2329
2330   FINISH;
2331 }
2332
2333 static int
2334 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2335 {
2336   vl_api_nat64_bib_details_t *rmp;
2337   snat_main_t *sm = &snat_main;
2338   nat64_api_walk_ctx_t *ctx = arg;
2339   fib_table_t *fib;
2340
2341   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2342   if (!fib)
2343     return -1;
2344
2345   rmp = vl_msg_api_alloc (sizeof (*rmp));
2346   memset (rmp, 0, sizeof (*rmp));
2347   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2348   rmp->context = ctx->context;
2349   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2350   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2351   rmp->i_port = bibe->in_port;
2352   rmp->o_port = bibe->out_port;
2353   rmp->vrf_id = ntohl (fib->ft_table_id);
2354   rmp->proto = bibe->proto;
2355   rmp->is_static = bibe->is_static;
2356   rmp->ses_num = ntohl (bibe->ses_num);
2357
2358   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2359
2360   return 0;
2361 }
2362
2363 static void
2364 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2365 {
2366   vl_api_registration_t *reg;
2367   nat64_main_t *nm = &nat64_main;
2368   nat64_db_t *db;
2369
2370   reg = vl_api_client_index_to_registration (mp->client_index);
2371   if (!reg)
2372     return;
2373
2374   nat64_api_walk_ctx_t ctx = {
2375     .reg = reg,
2376     .context = mp->context,
2377   };
2378
2379   /* *INDENT-OFF* */
2380   vec_foreach (db, nm->db)
2381     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2382   /* *INDENT-ON* */
2383 }
2384
2385 static void *
2386 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2387 {
2388   u8 *s;
2389
2390   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2391
2392   FINISH;
2393 }
2394
2395 static int
2396 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2397 {
2398   vl_api_nat64_st_details_t *rmp;
2399   snat_main_t *sm = &snat_main;
2400   nat64_api_walk_ctx_t *ctx = arg;
2401   nat64_db_bib_entry_t *bibe;
2402   fib_table_t *fib;
2403
2404   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2405   if (!bibe)
2406     return -1;
2407
2408   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2409   if (!fib)
2410     return -1;
2411
2412   rmp = vl_msg_api_alloc (sizeof (*rmp));
2413   memset (rmp, 0, sizeof (*rmp));
2414   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2415   rmp->context = ctx->context;
2416   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2417   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2418   rmp->il_port = bibe->in_port;
2419   rmp->ol_port = bibe->out_port;
2420   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2421   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2422   rmp->il_port = ste->r_port;
2423   rmp->vrf_id = ntohl (fib->ft_table_id);
2424   rmp->proto = ste->proto;
2425
2426   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2427
2428   return 0;
2429 }
2430
2431 static void
2432 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2433 {
2434   vl_api_registration_t *reg;
2435   nat64_main_t *nm = &nat64_main;
2436   nat64_db_t *db;
2437
2438   reg = vl_api_client_index_to_registration (mp->client_index);
2439   if (!reg)
2440     return;
2441
2442   nat64_api_walk_ctx_t ctx = {
2443     .reg = reg,
2444     .context = mp->context,
2445   };
2446
2447   /* *INDENT-OFF* */
2448   vec_foreach (db, nm->db)
2449     {
2450       ctx.db = db;
2451       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2452     }
2453   /* *INDENT-ON* */
2454 }
2455
2456 static void *
2457 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2458 {
2459   u8 *s;
2460
2461   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2462
2463   FINISH;
2464 }
2465
2466 static void
2467 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2468 {
2469   vl_api_nat64_add_del_prefix_reply_t *rmp;
2470   snat_main_t *sm = &snat_main;
2471   ip6_address_t prefix;
2472   int rv = 0;
2473
2474   memcpy (&prefix.as_u8, mp->prefix, 16);
2475
2476   rv =
2477     nat64_add_del_prefix (&prefix, mp->prefix_len,
2478                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2479   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2480 }
2481
2482 static void *
2483 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2484                                      void *handle)
2485 {
2486   u8 *s;
2487
2488   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2489               format_ip6_address, mp->prefix, mp->prefix_len,
2490               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2491
2492   FINISH;
2493 }
2494
2495 static int
2496 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2497 {
2498   vl_api_nat64_prefix_details_t *rmp;
2499   snat_main_t *sm = &snat_main;
2500   nat64_api_walk_ctx_t *ctx = arg;
2501
2502   rmp = vl_msg_api_alloc (sizeof (*rmp));
2503   memset (rmp, 0, sizeof (*rmp));
2504   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2505   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2506   rmp->prefix_len = p->plen;
2507   rmp->vrf_id = ntohl (p->vrf_id);
2508   rmp->context = ctx->context;
2509
2510   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2511
2512   return 0;
2513 }
2514
2515 static void
2516 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2517 {
2518   vl_api_registration_t *reg;
2519
2520   reg = vl_api_client_index_to_registration (mp->client_index);
2521   if (!reg)
2522     return;
2523
2524   nat64_api_walk_ctx_t ctx = {
2525     .reg = reg,
2526     .context = mp->context,
2527   };
2528
2529   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2530 }
2531
2532 static void *
2533 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2534                                   void *handle)
2535 {
2536   u8 *s;
2537
2538   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2539
2540   FINISH;
2541 }
2542
2543 static void
2544   vl_api_nat64_add_del_interface_addr_t_handler
2545   (vl_api_nat64_add_del_interface_addr_t * mp)
2546 {
2547   snat_main_t *sm = &snat_main;
2548   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2549   u32 sw_if_index = ntohl (mp->sw_if_index);
2550   int rv = 0;
2551
2552   VALIDATE_SW_IF_INDEX (mp);
2553
2554   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2555
2556   BAD_SW_IF_INDEX_LABEL;
2557
2558   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2559 }
2560
2561 static void *vl_api_nat64_add_del_interface_addr_t_print
2562   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2563 {
2564   u8 *s;
2565
2566   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2567   s = format (s, "sw_if_index %d %s",
2568               clib_host_to_net_u32 (mp->sw_if_index),
2569               mp->is_add ? "" : "del");
2570
2571   FINISH;
2572 }
2573
2574 /***************/
2575 /*** DS-Lite ***/
2576 /***************/
2577
2578 static void
2579 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2580 {
2581   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2582   snat_main_t *sm = &snat_main;
2583   dslite_main_t *dm = &dslite_main;
2584   int rv = 0;
2585   ip6_address_t ip6_addr;
2586   ip4_address_t ip4_addr;
2587
2588   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2589   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2590
2591   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2592   if (rv == 0)
2593     rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr);
2594
2595   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2596 }
2597
2598 static void *
2599 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2600                                      void *handle)
2601 {
2602   u8 *s;
2603
2604   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2605   s = format (s, "ip6_addr %U ip4_addr %U\n",
2606               format_ip6_address, mp->ip6_addr,
2607               format_ip4_address, mp->ip4_addr);
2608
2609   FINISH;
2610 }
2611
2612 static void
2613 vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp)
2614 {
2615   snat_main_t *sm = &snat_main;
2616   vl_api_dslite_get_aftr_addr_reply_t *rmp;
2617   dslite_main_t *dm = &dslite_main;
2618   int rv = 0;
2619
2620   /* *INDENT-OFF* */
2621   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2622   ({
2623     memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4);
2624     memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16);
2625   }))
2626   /* *INDENT-ON* */
2627 }
2628
2629 static void *
2630 vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp,
2631                                      void *handle)
2632 {
2633   u8 *s;
2634
2635   s = format (0, "SCRIPT: dslite_get_aftr_addr");
2636
2637   FINISH;
2638 }
2639
2640 static void
2641 vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp)
2642 {
2643   vl_api_dslite_set_b4_addr_reply_t *rmp;
2644   snat_main_t *sm = &snat_main;
2645   dslite_main_t *dm = &dslite_main;
2646   int rv = 0;
2647   ip6_address_t ip6_addr;
2648   ip4_address_t ip4_addr;
2649
2650   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2651   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2652
2653   rv = dslite_set_b4_ip6_addr (dm, &ip6_addr);
2654   if (rv == 0)
2655     rv = dslite_set_b4_ip4_addr (dm, &ip4_addr);
2656
2657   REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY);
2658 }
2659
2660 static void *
2661 vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp,
2662                                    void *handle)
2663 {
2664   u8 *s;
2665
2666   s = format (0, "SCRIPT: dslite_set_b4_addr ");
2667   s = format (s, "ip6_addr %U ip4_addr %U\n",
2668               format_ip6_address, mp->ip6_addr,
2669               format_ip6_address, mp->ip4_addr);
2670
2671   FINISH;
2672 }
2673
2674 static void
2675 vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp)
2676 {
2677   snat_main_t *sm = &snat_main;
2678   vl_api_dslite_get_b4_addr_reply_t *rmp;
2679   dslite_main_t *dm = &dslite_main;
2680   int rv = 0;
2681
2682   /* *INDENT-OFF* */
2683   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2684   ({
2685     memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4);
2686     memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16);
2687   }))
2688   /* *INDENT-ON* */
2689 }
2690
2691 static void *
2692 vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp,
2693                                    void *handle)
2694 {
2695   u8 *s;
2696
2697   s = format (0, "SCRIPT: dslite_get_b4_addr");
2698
2699   FINISH;
2700 }
2701
2702 static void
2703   vl_api_dslite_add_del_pool_addr_range_t_handler
2704   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2705 {
2706   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2707   snat_main_t *sm = &snat_main;
2708   dslite_main_t *dm = &dslite_main;
2709   int rv = 0;
2710   ip4_address_t this_addr;
2711   u32 start_host_order, end_host_order;
2712   int i, count;
2713   u32 *tmp;
2714
2715   tmp = (u32 *) mp->start_addr;
2716   start_host_order = clib_host_to_net_u32 (tmp[0]);
2717   tmp = (u32 *) mp->end_addr;
2718   end_host_order = clib_host_to_net_u32 (tmp[0]);
2719
2720   count = (end_host_order - start_host_order) + 1;
2721   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2722
2723   for (i = 0; i < count; i++)
2724     {
2725       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2726         goto send_reply;
2727
2728       increment_v4_address (&this_addr);
2729     }
2730
2731 send_reply:
2732   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2733 }
2734
2735 static void
2736 send_dslite_address_details (snat_address_t * ap,
2737                              vl_api_registration_t * reg, u32 context)
2738 {
2739   vl_api_dslite_address_details_t *rmp;
2740   snat_main_t *sm = &snat_main;
2741
2742   rmp = vl_msg_api_alloc (sizeof (*rmp));
2743
2744   memset (rmp, 0, sizeof (*rmp));
2745
2746   rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + sm->msg_id_base);
2747   clib_memcpy (rmp->ip_address, &(ap->addr), 4);
2748   rmp->context = context;
2749
2750   vl_api_send_msg (reg, (u8 *) rmp);
2751 }
2752
2753 static void
2754 vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp)
2755 {
2756   vl_api_registration_t *reg;
2757   dslite_main_t *dm = &dslite_main;
2758   snat_address_t *ap;
2759
2760   reg = vl_api_client_index_to_registration (mp->client_index);
2761   if (!reg)
2762     return;
2763
2764   /* *INDENT-OFF* */
2765   vec_foreach (ap, dm->addr_pool)
2766     {
2767       send_dslite_address_details (ap, reg, mp->context);
2768     }
2769   /* *INDENT-ON* */
2770 }
2771
2772 static void *
2773 vl_api_dslite_address_dump_t_print (vl_api_dslite_address_dump_t * mp,
2774                                     void *handle)
2775 {
2776   u8 *s;
2777
2778   s = format (0, "SCRIPT: dslite_address_dump ");
2779
2780   FINISH;
2781 }
2782
2783 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2784   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2785 {
2786   u8 *s;
2787
2788   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2789   s = format (s, "%U - %U\n",
2790               format_ip4_address, mp->start_addr,
2791               format_ip4_address, mp->end_addr);
2792
2793   FINISH;
2794 }
2795
2796
2797 /*************/
2798 /*** NAT66 ***/
2799 /*************/
2800
2801 static void
2802 vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
2803                                           mp)
2804 {
2805   snat_main_t *sm = &snat_main;
2806   vl_api_nat66_add_del_interface_reply_t *rmp;
2807   int rv = 0;
2808
2809   VALIDATE_SW_IF_INDEX (mp);
2810
2811   rv =
2812     nat66_interface_add_del (ntohl (mp->sw_if_index), mp->is_inside,
2813                              mp->is_add);
2814
2815   BAD_SW_IF_INDEX_LABEL;
2816
2817   REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
2818 }
2819
2820 static void *
2821 vl_api_nat66_add_del_interface_t_print (vl_api_nat66_add_del_interface_t * mp,
2822                                         void *handle)
2823 {
2824   u8 *s;
2825
2826   s = format (0, "SCRIPT: nat66_add_del_interface ");
2827   s = format (s, "sw_if_index %d %s %s",
2828               clib_host_to_net_u32 (mp->sw_if_index),
2829               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2830
2831   FINISH;
2832 }
2833
2834 static void
2835   vl_api_nat66_add_del_static_mapping_t_handler
2836   (vl_api_nat66_add_del_static_mapping_t * mp)
2837 {
2838   snat_main_t *sm = &snat_main;
2839   vl_api_nat66_add_del_static_mapping_reply_t *rmp;
2840   ip6_address_t l_addr, e_addr;
2841   int rv = 0;
2842
2843   memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
2844   memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
2845
2846   rv =
2847     nat66_static_mapping_add_del (&l_addr, &e_addr,
2848                                   clib_net_to_host_u32 (mp->vrf_id),
2849                                   mp->is_add);
2850
2851   REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
2852 }
2853
2854 static void *vl_api_nat66_add_del_static_mapping_t_print
2855   (vl_api_nat66_add_del_static_mapping_t * mp, void *handle)
2856 {
2857   u8 *s;
2858
2859   s = format (0, "SCRIPT: nat66_add_del_static_mapping ");
2860   s = format (s, "local_ip_address %U external_ip_address %U vrf_id %d %s",
2861               format_ip6_address, mp->local_ip_address,
2862               format_ip6_address, mp->external_ip_address,
2863               clib_net_to_host_u32 (mp->vrf_id), mp->is_add ? "" : "del");
2864
2865   FINISH;
2866 }
2867
2868 typedef struct nat66_api_walk_ctx_t_
2869 {
2870   svm_queue_t *q;
2871   u32 context;
2872 } nat66_api_walk_ctx_t;
2873
2874 static int
2875 nat66_api_interface_walk (snat_interface_t * i, void *arg)
2876 {
2877   vl_api_nat66_interface_details_t *rmp;
2878   snat_main_t *sm = &snat_main;
2879   nat66_api_walk_ctx_t *ctx = arg;
2880
2881   rmp = vl_msg_api_alloc (sizeof (*rmp));
2882   memset (rmp, 0, sizeof (*rmp));
2883   rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + sm->msg_id_base);
2884   rmp->sw_if_index = ntohl (i->sw_if_index);
2885   rmp->is_inside = nat_interface_is_inside (i);
2886   rmp->context = ctx->context;
2887
2888   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2889
2890   return 0;
2891 }
2892
2893 static void
2894 vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
2895 {
2896   svm_queue_t *q;
2897
2898   q = vl_api_client_index_to_input_queue (mp->client_index);
2899   if (q == 0)
2900     return;
2901
2902   nat66_api_walk_ctx_t ctx = {
2903     .q = q,
2904     .context = mp->context,
2905   };
2906
2907   nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
2908 }
2909
2910 static void *
2911 vl_api_nat66_interface_dump_t_print (vl_api_nat66_interface_dump_t * mp,
2912                                      void *handle)
2913 {
2914   u8 *s;
2915
2916   s = format (0, "SCRIPT: nat66_interface_dump ");
2917
2918   FINISH;
2919 }
2920
2921 static int
2922 nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
2923 {
2924   vl_api_nat66_static_mapping_details_t *rmp;
2925   nat66_main_t *nm = &nat66_main;
2926   snat_main_t *sm = &snat_main;
2927   nat66_api_walk_ctx_t *ctx = arg;
2928   fib_table_t *fib;
2929   vlib_counter_t vc;
2930
2931   fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
2932   if (!fib)
2933     return -1;
2934
2935   vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
2936
2937   rmp = vl_msg_api_alloc (sizeof (*rmp));
2938   memset (rmp, 0, sizeof (*rmp));
2939   rmp->_vl_msg_id =
2940     ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + sm->msg_id_base);
2941   clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
2942   clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
2943   rmp->vrf_id = ntohl (fib->ft_table_id);
2944   rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
2945   rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
2946   rmp->context = ctx->context;
2947
2948   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
2949
2950   return 0;
2951 }
2952
2953 static void
2954 vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
2955                                             * mp)
2956 {
2957   svm_queue_t *q;
2958
2959   q = vl_api_client_index_to_input_queue (mp->client_index);
2960   if (q == 0)
2961     return;
2962
2963   nat66_api_walk_ctx_t ctx = {
2964     .q = q,
2965     .context = mp->context,
2966   };
2967
2968   nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
2969 }
2970
2971 static void *
2972 vl_api_nat66_static_mapping_dump_t_print (vl_api_nat66_static_mapping_dump_t *
2973                                           mp, void *handle)
2974 {
2975   u8 *s;
2976
2977   s = format (0, "SCRIPT: nat66_static_mapping_dump ");
2978
2979   FINISH;
2980 }
2981
2982
2983 /* List of message types that this plugin understands */
2984 #define foreach_snat_plugin_api_msg                                     \
2985 _(NAT_CONTROL_PING, nat_control_ping)                                   \
2986 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
2987 _(NAT_SET_WORKERS, nat_set_workers)                                     \
2988 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
2989 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
2990 _(NAT_SET_REASS, nat_set_reass)                                         \
2991 _(NAT_GET_REASS, nat_get_reass)                                         \
2992 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
2993 _(NAT_SET_TIMEOUTS, nat_set_timeouts)                           \
2994 _(NAT_GET_TIMEOUTS, nat_get_timeouts)                           \
2995 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
2996 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
2997 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
2998 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
2999 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3000 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
3001 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3002 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3003 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3004 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3005 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3006 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3007 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3008   nat44_interface_add_del_output_feature)                               \
3009 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3010   nat44_interface_output_feature_dump)                                  \
3011 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3012 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3013 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
3014 _(NAT44_FORWARDING_ENABLE_DISABLE, nat44_forwarding_enable_disable)     \
3015 _(NAT44_FORWARDING_IS_ENABLED, nat44_forwarding_is_enabled)             \
3016 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3017 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3018 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3019 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3020 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3021 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3022 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3023 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3024 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3025 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3026 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3027 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3028 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3029 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3030 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3031 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
3032 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
3033 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
3034 _(DSLITE_ADDRESS_DUMP, dslite_address_dump)                             \
3035 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)                           \
3036 _(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr)                           \
3037 _(DSLITE_SET_B4_ADDR, dslite_set_b4_addr)                               \
3038 _(DSLITE_GET_B4_ADDR, dslite_get_b4_addr)                               \
3039 _(NAT66_ADD_DEL_INTERFACE, nat66_add_del_interface)                     \
3040 _(NAT66_INTERFACE_DUMP, nat66_interface_dump)                           \
3041 _(NAT66_ADD_DEL_STATIC_MAPPING, nat66_add_del_static_mapping)           \
3042 _(NAT66_STATIC_MAPPING_DUMP, nat66_static_mapping_dump)
3043
3044 /* Set up the API message handling tables */
3045 static clib_error_t *
3046 snat_plugin_api_hookup (vlib_main_t * vm)
3047 {
3048   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3049 #define _(N,n)                                                  \
3050     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3051                            #n,                                  \
3052                            vl_api_##n##_t_handler,              \
3053                            vl_noop_handler,                     \
3054                            vl_api_##n##_t_endian,               \
3055                            vl_api_##n##_t_print,                \
3056                            sizeof(vl_api_##n##_t), 1);
3057   foreach_snat_plugin_api_msg;
3058 #undef _
3059
3060   return 0;
3061 }
3062
3063 #define vl_msg_name_crc_list
3064 #include <nat/nat_all_api_h.h>
3065 #undef vl_msg_name_crc_list
3066
3067 static void
3068 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3069 {
3070 #define _(id,n,crc) \
3071   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3072   foreach_vl_msg_name_crc_nat;
3073 #undef _
3074 }
3075
3076 static void
3077 plugin_custom_dump_configure (snat_main_t * sm)
3078 {
3079 #define _(n,f) sm->api_main->msg_print_handlers \
3080   [VL_API_##n + sm->msg_id_base]                \
3081     = (void *) vl_api_##f##_t_print;
3082   foreach_snat_plugin_api_msg;
3083 #undef _
3084 }
3085
3086 clib_error_t *
3087 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3088 {
3089   u8 *name;
3090   clib_error_t *error = 0;
3091
3092   name = format (0, "nat_%08x%c", api_version, 0);
3093
3094   /* Ask for a correctly-sized block of API message decode slots */
3095   sm->msg_id_base =
3096     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3097
3098   error = snat_plugin_api_hookup (vm);
3099
3100   /* Add our API messages to the global name_crc hash table */
3101   setup_message_id_table (sm, sm->api_main);
3102
3103   plugin_custom_dump_configure (sm);
3104
3105   vec_free (name);
3106
3107   return error;
3108 }
3109
3110 /*
3111  * fd.io coding-style-patch-verification: ON
3112  *
3113  * Local Variables:
3114  * eval: (c-set-style "gnu")
3115  * End:
3116  */