NAT44: do not create session record for identity mapping (VPP-1439)
[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->cpu_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 static void
488   vl_api_nat_set_addr_and_port_alloc_alg_t_handler
489   (vl_api_nat_set_addr_and_port_alloc_alg_t * mp)
490 {
491   snat_main_t *sm = &snat_main;
492   vl_api_nat_set_addr_and_port_alloc_alg_reply_t *rmp;
493   int rv = 0;
494   u16 port_start, port_end;
495
496   if (sm->deterministic)
497     {
498       rv = VNET_API_ERROR_UNSUPPORTED;
499       goto send_reply;
500     }
501
502   switch (mp->alg)
503     {
504     case NAT_ADDR_AND_PORT_ALLOC_ALG_DEFAULT:
505       nat_set_alloc_addr_and_port_default ();
506       break;
507     case NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE:
508       nat_set_alloc_addr_and_port_mape (ntohs (mp->psid), mp->psid_offset,
509                                         mp->psid_length);
510       break;
511     case NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE:
512       port_start = ntohs (mp->start_port);
513       port_end = ntohs (mp->end_port);
514       if (port_end <= port_start)
515         {
516           rv = VNET_API_ERROR_INVALID_VALUE;
517           goto send_reply;
518         }
519       nat_set_alloc_addr_and_port_range (port_start, port_end);
520       break;
521     default:
522       rv = VNET_API_ERROR_INVALID_VALUE;
523       break;
524     }
525
526 send_reply:
527   REPLY_MACRO (VL_API_NAT_SET_ADDR_AND_PORT_ALLOC_ALG_REPLY);
528 }
529
530 static void *vl_api_nat_set_addr_and_port_alloc_alg_t_print
531   (vl_api_nat_set_addr_and_port_alloc_alg_t * mp, void *handle)
532 {
533   u8 *s;
534
535   s = format (0, "SCRIPT: nat_set_addr_and_port_alloc_alg ");
536   s = format (s, "alg %d psid_offset %d psid_length %d psid %d start_port %d "
537               "end_port %d\n",
538               ntohl (mp->alg), ntohl (mp->psid_offset),
539               ntohl (mp->psid_length), ntohs (mp->psid),
540               ntohs (mp->start_port), ntohs (mp->end_port));
541
542   FINISH;
543 }
544
545 static void
546   vl_api_nat_get_addr_and_port_alloc_alg_t_handler
547   (vl_api_nat_get_addr_and_port_alloc_alg_t * mp)
548 {
549   snat_main_t *sm = &snat_main;
550   vl_api_nat_get_addr_and_port_alloc_alg_reply_t *rmp;
551   int rv = 0;
552
553   /* *INDENT-OFF* */
554   REPLY_MACRO2 (VL_API_NAT_GET_ADDR_AND_PORT_ALLOC_ALG_REPLY,
555   ({
556     rmp->alg = sm->addr_and_port_alloc_alg;
557     rmp->psid_offset = sm->psid_offset;
558     rmp->psid_length = sm->psid_length;
559     rmp->psid = htons (sm->psid);
560     rmp->start_port = htons (sm->start_port);
561     rmp->end_port = htons (sm->end_port);
562   }))
563   /* *INDENT-ON* */
564 }
565
566 static void *vl_api_nat_get_addr_and_port_alloc_alg_t_print
567   (vl_api_nat_get_addr_and_port_alloc_alg_t * mp, void *handle)
568 {
569   u8 *s;
570
571   s = format (0, "SCRIPT: nat_get_addr_and_port_alloc_alg");
572
573   FINISH;
574 }
575
576 static void
577 vl_api_nat_set_mss_clamping_t_handler (vl_api_nat_set_mss_clamping_t * mp)
578 {
579   snat_main_t *sm = &snat_main;
580   vl_api_nat_set_mss_clamping_reply_t *rmp;
581   int rv = 0;
582
583   if (mp->enable)
584     {
585       sm->mss_clamping = ntohs (mp->mss_value);
586       sm->mss_value_net = mp->mss_value;
587     }
588   else
589     sm->mss_clamping = 0;
590
591   REPLY_MACRO (VL_API_NAT_SET_MSS_CLAMPING_REPLY);
592 }
593
594 static void *
595 vl_api_nat_set_mss_clamping_t_print (vl_api_nat_set_mss_clamping_t * mp,
596                                      void *handle)
597 {
598   u8 *s;
599
600   s = format (0, "SCRIPT: nat_set_mss_clamping enable %d mss_value %d\n",
601               mp->enable, ntohs (mp->mss_value));
602
603   FINISH;
604 }
605
606 static void
607 vl_api_nat_get_mss_clamping_t_handler (vl_api_nat_get_mss_clamping_t * mp)
608 {
609   snat_main_t *sm = &snat_main;
610   vl_api_nat_get_mss_clamping_reply_t *rmp;
611   int rv = 0;
612
613   /* *INDENT-OFF* */
614   REPLY_MACRO2 (VL_API_NAT_GET_MSS_CLAMPING_REPLY,
615   ({
616     rmp->enable = sm->mss_clamping ? 1 : 0;
617     rmp->mss_value = htons (sm->mss_clamping);
618   }))
619   /* *INDENT-ON* */
620 }
621
622 static void *
623 vl_api_nat_get_mss_clamping_t_print (vl_api_nat_get_mss_clamping_t * mp,
624                                      void *handle)
625 {
626   u8 *s;
627
628   s = format (0, "SCRIPT: nat_get_mss_clamping");
629
630   FINISH;
631 }
632
633 /*************/
634 /*** NAT44 ***/
635 /*************/
636 static void
637   vl_api_nat44_add_del_address_range_t_handler
638   (vl_api_nat44_add_del_address_range_t * mp)
639 {
640   snat_main_t *sm = &snat_main;
641   vl_api_nat44_add_del_address_range_reply_t *rmp;
642   ip4_address_t this_addr;
643   u32 start_host_order, end_host_order;
644   u32 vrf_id;
645   int i, count;
646   int rv = 0;
647   u32 *tmp;
648
649   if (sm->deterministic)
650     {
651       rv = VNET_API_ERROR_UNSUPPORTED;
652       goto send_reply;
653     }
654
655   if (sm->static_mapping_only)
656     {
657       rv = VNET_API_ERROR_FEATURE_DISABLED;
658       goto send_reply;
659     }
660
661   tmp = (u32 *) mp->first_ip_address;
662   start_host_order = clib_host_to_net_u32 (tmp[0]);
663   tmp = (u32 *) mp->last_ip_address;
664   end_host_order = clib_host_to_net_u32 (tmp[0]);
665
666   count = (end_host_order - start_host_order) + 1;
667
668   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
669
670   if (count > 1024)
671     nat_log_info ("%U - %U, %d addresses...",
672                   format_ip4_address, mp->first_ip_address,
673                   format_ip4_address, mp->last_ip_address, count);
674
675   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
676
677   for (i = 0; i < count; i++)
678     {
679       if (mp->is_add)
680         rv = snat_add_address (sm, &this_addr, vrf_id, mp->twice_nat);
681       else
682         rv = snat_del_address (sm, this_addr, 0, mp->twice_nat);
683
684       if (rv)
685         goto send_reply;
686
687       if (sm->out2in_dpo)
688         nat44_add_del_address_dpo (this_addr, mp->is_add);
689
690       increment_v4_address (&this_addr);
691     }
692
693 send_reply:
694   REPLY_MACRO (VL_API_NAT44_ADD_DEL_ADDRESS_RANGE_REPLY);
695 }
696
697 static void *vl_api_nat44_add_del_address_range_t_print
698   (vl_api_nat44_add_del_address_range_t * mp, void *handle)
699 {
700   u8 *s;
701
702   s = format (0, "SCRIPT: nat44_add_address_range ");
703   s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
704   if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
705     {
706       s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
707     }
708   s = format (s, "twice_nat %d ", mp->twice_nat);
709   FINISH;
710 }
711
712 static void
713 send_nat44_address_details (snat_address_t * a,
714                             vl_api_registration_t * reg, u32 context,
715                             u8 twice_nat)
716 {
717   vl_api_nat44_address_details_t *rmp;
718   snat_main_t *sm = &snat_main;
719
720   rmp = vl_msg_api_alloc (sizeof (*rmp));
721   memset (rmp, 0, sizeof (*rmp));
722   rmp->_vl_msg_id = ntohs (VL_API_NAT44_ADDRESS_DETAILS + sm->msg_id_base);
723   clib_memcpy (rmp->ip_address, &(a->addr), 4);
724   if (a->fib_index != ~0)
725     {
726       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
727       rmp->vrf_id = ntohl (fib->ft_table_id);
728     }
729   else
730     rmp->vrf_id = ~0;
731   rmp->twice_nat = twice_nat;
732   rmp->context = context;
733
734   vl_api_send_msg (reg, (u8 *) rmp);
735 }
736
737 static void
738 vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp)
739 {
740   vl_api_registration_t *reg;
741   snat_main_t *sm = &snat_main;
742   snat_address_t *a;
743
744   if (sm->deterministic)
745     return;
746
747   reg = vl_api_client_index_to_registration (mp->client_index);
748   if (!reg)
749     return;
750
751   /* *INDENT-OFF* */
752   vec_foreach (a, sm->addresses)
753     send_nat44_address_details (a, reg, mp->context, 0);
754   vec_foreach (a, sm->twice_nat_addresses)
755     send_nat44_address_details (a, reg, mp->context, 1);
756   /* *INDENT-ON* */
757 }
758
759 static void *
760 vl_api_nat44_address_dump_t_print (vl_api_nat44_address_dump_t * mp,
761                                    void *handle)
762 {
763   u8 *s;
764
765   s = format (0, "SCRIPT: nat44_address_dump ");
766
767   FINISH;
768 }
769
770 static void
771   vl_api_nat44_interface_add_del_feature_t_handler
772   (vl_api_nat44_interface_add_del_feature_t * mp)
773 {
774   snat_main_t *sm = &snat_main;
775   vl_api_nat44_interface_add_del_feature_reply_t *rmp;
776   u8 is_del = mp->is_add == 0;
777   u32 sw_if_index = ntohl (mp->sw_if_index);
778   int rv = 0;
779
780   VALIDATE_SW_IF_INDEX (mp);
781
782   rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
783
784   BAD_SW_IF_INDEX_LABEL;
785
786   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY);
787 }
788
789 static void *vl_api_nat44_interface_add_del_feature_t_print
790   (vl_api_nat44_interface_add_del_feature_t * mp, void *handle)
791 {
792   u8 *s;
793
794   s = format (0, "SCRIPT: nat44_interface_add_del_feature ");
795   s = format (s, "sw_if_index %d %s %s",
796               clib_host_to_net_u32 (mp->sw_if_index),
797               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
798
799   FINISH;
800 }
801
802 static void
803 send_nat44_interface_details (snat_interface_t * i,
804                               vl_api_registration_t * reg, u32 context)
805 {
806   vl_api_nat44_interface_details_t *rmp;
807   snat_main_t *sm = &snat_main;
808
809   rmp = vl_msg_api_alloc (sizeof (*rmp));
810   memset (rmp, 0, sizeof (*rmp));
811   rmp->_vl_msg_id = ntohs (VL_API_NAT44_INTERFACE_DETAILS + sm->msg_id_base);
812   rmp->sw_if_index = ntohl (i->sw_if_index);
813   rmp->is_inside = (nat_interface_is_inside (i)
814                     && nat_interface_is_outside (i)) ? 2 :
815     nat_interface_is_inside (i);
816   rmp->context = context;
817
818   vl_api_send_msg (reg, (u8 *) rmp);
819 }
820
821 static void
822 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
823 {
824   vl_api_registration_t *reg;
825   snat_main_t *sm = &snat_main;
826   snat_interface_t *i;
827
828   reg = vl_api_client_index_to_registration (mp->client_index);
829   if (!reg)
830     return;
831
832   /* *INDENT-OFF* */
833   pool_foreach (i, sm->interfaces,
834   ({
835     send_nat44_interface_details(i, reg, mp->context);
836   }));
837   /* *INDENT-ON* */
838 }
839
840 static void *
841 vl_api_nat44_interface_dump_t_print (vl_api_nat44_interface_dump_t * mp,
842                                      void *handle)
843 {
844   u8 *s;
845
846   s = format (0, "SCRIPT: nat44_interface_dump ");
847
848   FINISH;
849 }
850
851 static void
852   vl_api_nat44_interface_add_del_output_feature_t_handler
853   (vl_api_nat44_interface_add_del_output_feature_t * mp)
854 {
855   snat_main_t *sm = &snat_main;
856   vl_api_nat44_interface_add_del_output_feature_reply_t *rmp;
857   u8 is_del = mp->is_add == 0;
858   u32 sw_if_index = ntohl (mp->sw_if_index);
859   int rv = 0;
860
861   if (sm->deterministic)
862     {
863       rv = VNET_API_ERROR_UNSUPPORTED;
864       goto send_reply;
865     }
866
867   VALIDATE_SW_IF_INDEX (mp);
868
869   rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
870                                               is_del);
871
872   BAD_SW_IF_INDEX_LABEL;
873 send_reply:
874   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
875 }
876
877 static void *vl_api_nat44_interface_add_del_output_feature_t_print
878   (vl_api_nat44_interface_add_del_output_feature_t * mp, void *handle)
879 {
880   u8 *s;
881
882   s = format (0, "SCRIPT: nat44_interface_add_del_output_feature ");
883   s = format (s, "sw_if_index %d %s %s",
884               clib_host_to_net_u32 (mp->sw_if_index),
885               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
886
887   FINISH;
888 }
889
890 static void
891 send_nat44_interface_output_feature_details (snat_interface_t * i,
892                                              vl_api_registration_t * reg,
893                                              u32 context)
894 {
895   vl_api_nat44_interface_output_feature_details_t *rmp;
896   snat_main_t *sm = &snat_main;
897
898   rmp = vl_msg_api_alloc (sizeof (*rmp));
899   memset (rmp, 0, sizeof (*rmp));
900   rmp->_vl_msg_id =
901     ntohs (VL_API_NAT44_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
902   rmp->sw_if_index = ntohl (i->sw_if_index);
903   rmp->context = context;
904   rmp->is_inside = nat_interface_is_inside (i);
905
906   vl_api_send_msg (reg, (u8 *) rmp);
907 }
908
909 static void
910   vl_api_nat44_interface_output_feature_dump_t_handler
911   (vl_api_nat44_interface_output_feature_dump_t * mp)
912 {
913   vl_api_registration_t *reg;
914   snat_main_t *sm = &snat_main;
915   snat_interface_t *i;
916
917   if (sm->deterministic)
918     return;
919
920   reg = vl_api_client_index_to_registration (mp->client_index);
921   if (!reg)
922     return;
923
924   /* *INDENT-OFF* */
925   pool_foreach (i, sm->output_feature_interfaces,
926   ({
927     send_nat44_interface_output_feature_details(i, reg, mp->context);
928   }));
929   /* *INDENT-ON* */
930 }
931
932 static void *vl_api_nat44_interface_output_feature_dump_t_print
933   (vl_api_nat44_interface_output_feature_dump_t * mp, void *handle)
934 {
935   u8 *s;
936
937   s = format (0, "SCRIPT: nat44_interface_output_feature_dump ");
938
939   FINISH;
940 }
941
942 static void
943   vl_api_nat44_add_del_static_mapping_t_handler
944   (vl_api_nat44_add_del_static_mapping_t * mp)
945 {
946   snat_main_t *sm = &snat_main;
947   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
948   ip4_address_t local_addr, external_addr;
949   u16 local_port = 0, external_port = 0;
950   u32 vrf_id, external_sw_if_index;
951   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
952   int rv = 0;
953   snat_protocol_t proto;
954   u8 *tag = 0;
955
956   if (sm->deterministic)
957     {
958       rv = VNET_API_ERROR_UNSUPPORTED;
959       goto send_reply;
960     }
961
962   memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
963   memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
964   if (mp->addr_only == 0)
965     {
966       local_port = clib_net_to_host_u16 (mp->local_port);
967       external_port = clib_net_to_host_u16 (mp->external_port);
968     }
969   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
970   external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
971   proto = ip_proto_to_snat_proto (mp->protocol);
972   if (mp->twice_nat)
973     twice_nat = TWICE_NAT;
974   else if (mp->self_twice_nat)
975     twice_nat = TWICE_NAT_SELF;
976   mp->tag[sizeof (mp->tag) - 1] = 0;
977   tag = format (0, "%s", mp->tag);
978   vec_terminate_c_string (tag);
979
980   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
981                                 external_port, vrf_id, mp->addr_only,
982                                 external_sw_if_index, proto, mp->is_add,
983                                 twice_nat, mp->out2in_only, tag, 0);
984
985   vec_free (tag);
986
987 send_reply:
988   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
989 }
990
991 static void *vl_api_nat44_add_del_static_mapping_t_print
992   (vl_api_nat44_add_del_static_mapping_t * mp, void *handle)
993 {
994   u8 *s;
995
996   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
997   s = format (s, "protocol %d local_addr %U external_addr %U ",
998               mp->protocol,
999               format_ip4_address, mp->local_ip_address,
1000               format_ip4_address, mp->external_ip_address);
1001
1002   if (mp->addr_only == 0)
1003     s = format (s, "local_port %d external_port %d ",
1004                 clib_net_to_host_u16 (mp->local_port),
1005                 clib_net_to_host_u16 (mp->external_port));
1006
1007   s = format (s, "twice_nat %d out2in_only %d ",
1008               mp->twice_nat, mp->out2in_only);
1009
1010   if (mp->vrf_id != ~0)
1011     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1012
1013   if (mp->external_sw_if_index != ~0)
1014     s = format (s, "external_sw_if_index %d",
1015                 clib_net_to_host_u32 (mp->external_sw_if_index));
1016   FINISH;
1017 }
1018
1019 static void
1020 send_nat44_static_mapping_details (snat_static_mapping_t * m,
1021                                    vl_api_registration_t * reg, u32 context)
1022 {
1023   vl_api_nat44_static_mapping_details_t *rmp;
1024   snat_main_t *sm = &snat_main;
1025
1026   rmp = vl_msg_api_alloc (sizeof (*rmp));
1027   memset (rmp, 0, sizeof (*rmp));
1028   rmp->_vl_msg_id =
1029     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1030   rmp->addr_only = is_addr_only_static_mapping (m);
1031   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
1032   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
1033   rmp->external_sw_if_index = ~0;
1034   rmp->vrf_id = htonl (m->vrf_id);
1035   rmp->context = context;
1036   if (m->twice_nat == TWICE_NAT)
1037     rmp->twice_nat = 1;
1038   else if (m->twice_nat == TWICE_NAT_SELF)
1039     rmp->self_twice_nat = 1;
1040   rmp->out2in_only = is_out2in_only_static_mapping (m);
1041   if (rmp->addr_only == 0)
1042     {
1043       rmp->protocol = snat_proto_to_ip_proto (m->proto);
1044       rmp->external_port = htons (m->external_port);
1045       rmp->local_port = htons (m->local_port);
1046     }
1047   if (m->tag)
1048     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1049
1050   vl_api_send_msg (reg, (u8 *) rmp);
1051 }
1052
1053 static void
1054 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
1055                                        vl_api_registration_t * reg,
1056                                        u32 context)
1057 {
1058   vl_api_nat44_static_mapping_details_t *rmp;
1059   snat_main_t *sm = &snat_main;
1060
1061   rmp = vl_msg_api_alloc (sizeof (*rmp));
1062   memset (rmp, 0, sizeof (*rmp));
1063   rmp->_vl_msg_id =
1064     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1065   rmp->addr_only = m->addr_only;
1066   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
1067   rmp->external_sw_if_index = htonl (m->sw_if_index);
1068   rmp->vrf_id = htonl (m->vrf_id);
1069   rmp->context = context;
1070   rmp->twice_nat = m->twice_nat;
1071   if (m->addr_only == 0)
1072     {
1073       rmp->protocol = snat_proto_to_ip_proto (m->proto);
1074       rmp->external_port = htons (m->e_port);
1075       rmp->local_port = htons (m->l_port);
1076     }
1077   if (m->tag)
1078     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1079
1080   vl_api_send_msg (reg, (u8 *) rmp);
1081 }
1082
1083 static void
1084 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
1085                                             * mp)
1086 {
1087   vl_api_registration_t *reg;
1088   snat_main_t *sm = &snat_main;
1089   snat_static_mapping_t *m;
1090   snat_static_map_resolve_t *rp;
1091   int j;
1092
1093   if (sm->deterministic)
1094     return;
1095
1096   reg = vl_api_client_index_to_registration (mp->client_index);
1097   if (!reg)
1098     return;
1099
1100   /* *INDENT-OFF* */
1101   pool_foreach (m, sm->static_mappings,
1102   ({
1103       if (!is_identity_static_mapping(m) && !vec_len (m->locals))
1104         send_nat44_static_mapping_details (m, reg, mp->context);
1105   }));
1106   /* *INDENT-ON* */
1107
1108   for (j = 0; j < vec_len (sm->to_resolve); j++)
1109     {
1110       rp = sm->to_resolve + j;
1111       if (!rp->identity_nat)
1112         send_nat44_static_map_resolve_details (rp, reg, mp->context);
1113     }
1114 }
1115
1116 static void *
1117 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
1118                                           mp, void *handle)
1119 {
1120   u8 *s;
1121
1122   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
1123
1124   FINISH;
1125 }
1126
1127 static void
1128   vl_api_nat44_add_del_identity_mapping_t_handler
1129   (vl_api_nat44_add_del_identity_mapping_t * mp)
1130 {
1131   snat_main_t *sm = &snat_main;
1132   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
1133   ip4_address_t addr;
1134   u16 port = 0;
1135   u32 vrf_id, sw_if_index;
1136   int rv = 0;
1137   snat_protocol_t proto = ~0;
1138   u8 *tag = 0;
1139
1140   if (sm->deterministic)
1141     {
1142       rv = VNET_API_ERROR_UNSUPPORTED;
1143       goto send_reply;
1144     }
1145
1146   if (mp->addr_only == 0)
1147     {
1148       port = clib_net_to_host_u16 (mp->port);
1149       proto = ip_proto_to_snat_proto (mp->protocol);
1150     }
1151   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1152   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1153   if (sw_if_index != ~0)
1154     addr.as_u32 = 0;
1155   else
1156     memcpy (&addr.as_u8, mp->ip_address, 4);
1157   mp->tag[sizeof (mp->tag) - 1] = 0;
1158   tag = format (0, "%s", mp->tag);
1159   vec_terminate_c_string (tag);
1160
1161   rv =
1162     snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only,
1163                              sw_if_index, proto, mp->is_add, 0, 0, tag, 1);
1164
1165   vec_free (tag);
1166
1167 send_reply:
1168   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
1169 }
1170
1171 static void *vl_api_nat44_add_del_identity_mapping_t_print
1172   (vl_api_nat44_add_del_identity_mapping_t * mp, void *handle)
1173 {
1174   u8 *s;
1175
1176   s = format (0, "SCRIPT: nat44_add_del_identity_mapping ");
1177   if (mp->sw_if_index != ~0)
1178     s = format (s, "sw_if_index %d", clib_net_to_host_u32 (mp->sw_if_index));
1179   else
1180     s = format (s, "addr %U", format_ip4_address, mp->ip_address);
1181
1182   if (mp->addr_only == 0)
1183     s =
1184       format (s, "protocol %d port %d", mp->protocol,
1185               clib_net_to_host_u16 (mp->port));
1186
1187   if (mp->vrf_id != ~0)
1188     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1189
1190   FINISH;
1191 }
1192
1193 static void
1194 send_nat44_identity_mapping_details (snat_static_mapping_t * m,
1195                                      vl_api_registration_t * reg, u32 context)
1196 {
1197   vl_api_nat44_identity_mapping_details_t *rmp;
1198   snat_main_t *sm = &snat_main;
1199
1200   rmp = vl_msg_api_alloc (sizeof (*rmp));
1201   memset (rmp, 0, sizeof (*rmp));
1202   rmp->_vl_msg_id =
1203     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1204   rmp->addr_only = is_addr_only_static_mapping (m);
1205   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
1206   rmp->port = htons (m->local_port);
1207   rmp->sw_if_index = ~0;
1208   rmp->vrf_id = htonl (m->vrf_id);
1209   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1210   rmp->context = context;
1211   if (m->tag)
1212     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1213
1214   vl_api_send_msg (reg, (u8 *) rmp);
1215 }
1216
1217 static void
1218 send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
1219                                          vl_api_registration_t * reg,
1220                                          u32 context)
1221 {
1222   vl_api_nat44_identity_mapping_details_t *rmp;
1223   snat_main_t *sm = &snat_main;
1224
1225   rmp = vl_msg_api_alloc (sizeof (*rmp));
1226   memset (rmp, 0, sizeof (*rmp));
1227   rmp->_vl_msg_id =
1228     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1229   rmp->addr_only = m->addr_only;
1230   rmp->port = htons (m->l_port);
1231   rmp->sw_if_index = htonl (m->sw_if_index);
1232   rmp->vrf_id = htonl (m->vrf_id);
1233   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1234   rmp->context = context;
1235   if (m->tag)
1236     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1237
1238   vl_api_send_msg (reg, (u8 *) rmp);
1239 }
1240
1241 static void
1242   vl_api_nat44_identity_mapping_dump_t_handler
1243   (vl_api_nat44_identity_mapping_dump_t * mp)
1244 {
1245   vl_api_registration_t *reg;
1246   snat_main_t *sm = &snat_main;
1247   snat_static_mapping_t *m;
1248   snat_static_map_resolve_t *rp;
1249   int j;
1250
1251   if (sm->deterministic)
1252     return;
1253
1254   reg = vl_api_client_index_to_registration (mp->client_index);
1255   if (!reg)
1256     return;
1257
1258   /* *INDENT-OFF* */
1259   pool_foreach (m, sm->static_mappings,
1260   ({
1261       if (is_identity_static_mapping(m) && !vec_len (m->locals))
1262         send_nat44_identity_mapping_details (m, reg, mp->context);
1263   }));
1264   /* *INDENT-ON* */
1265
1266   for (j = 0; j < vec_len (sm->to_resolve); j++)
1267     {
1268       rp = sm->to_resolve + j;
1269       if (rp->identity_nat)
1270         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
1271     }
1272 }
1273
1274 static void *vl_api_nat44_identity_mapping_dump_t_print
1275   (vl_api_nat44_identity_mapping_dump_t * mp, void *handle)
1276 {
1277   u8 *s;
1278
1279   s = format (0, "SCRIPT: nat44_identity_mapping_dump ");
1280
1281   FINISH;
1282 }
1283
1284 static void
1285   vl_api_nat44_add_del_interface_addr_t_handler
1286   (vl_api_nat44_add_del_interface_addr_t * mp)
1287 {
1288   snat_main_t *sm = &snat_main;
1289   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1290   u8 is_del = mp->is_add == 0;
1291   u32 sw_if_index = ntohl (mp->sw_if_index);
1292   int rv = 0;
1293
1294   if (sm->deterministic)
1295     {
1296       rv = VNET_API_ERROR_UNSUPPORTED;
1297       goto send_reply;
1298     }
1299
1300   VALIDATE_SW_IF_INDEX (mp);
1301
1302   rv = snat_add_interface_address (sm, sw_if_index, is_del, mp->twice_nat);
1303
1304   BAD_SW_IF_INDEX_LABEL;
1305 send_reply:
1306   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1307 }
1308
1309 static void *vl_api_nat44_add_del_interface_addr_t_print
1310   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
1311 {
1312   u8 *s;
1313
1314   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
1315   s = format (s, "sw_if_index %d twice_nat %d %s",
1316               clib_host_to_net_u32 (mp->sw_if_index),
1317               mp->twice_nat, mp->is_add ? "" : "del");
1318
1319   FINISH;
1320 }
1321
1322 static void
1323 send_nat44_interface_addr_details (u32 sw_if_index,
1324                                    vl_api_registration_t * reg, u32 context,
1325                                    u8 twice_nat)
1326 {
1327   vl_api_nat44_interface_addr_details_t *rmp;
1328   snat_main_t *sm = &snat_main;
1329
1330   rmp = vl_msg_api_alloc (sizeof (*rmp));
1331   memset (rmp, 0, sizeof (*rmp));
1332   rmp->_vl_msg_id =
1333     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1334   rmp->sw_if_index = ntohl (sw_if_index);
1335   rmp->twice_nat = twice_nat;
1336   rmp->context = context;
1337
1338   vl_api_send_msg (reg, (u8 *) rmp);
1339 }
1340
1341 static void
1342 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1343                                             * mp)
1344 {
1345   vl_api_registration_t *reg;
1346   snat_main_t *sm = &snat_main;
1347   u32 *i;
1348
1349   if (sm->deterministic)
1350     return;
1351
1352   reg = vl_api_client_index_to_registration (mp->client_index);
1353   if (!reg)
1354     return;
1355
1356   /* *INDENT-OFF* */
1357   vec_foreach (i, sm->auto_add_sw_if_indices)
1358     send_nat44_interface_addr_details(*i, reg, mp->context, 0);
1359   vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
1360     send_nat44_interface_addr_details(*i, reg, mp->context, 1);
1361   /* *INDENT-ON* */
1362 }
1363
1364 static void *
1365 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1366                                           mp, void *handle)
1367 {
1368   u8 *s;
1369
1370   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
1371
1372   FINISH;
1373 }
1374
1375 static void
1376 send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg,
1377                          u32 context)
1378 {
1379   vl_api_nat44_user_details_t *rmp;
1380   snat_main_t *sm = &snat_main;
1381   ip4_main_t *im = &ip4_main;
1382
1383   rmp = vl_msg_api_alloc (sizeof (*rmp));
1384   memset (rmp, 0, sizeof (*rmp));
1385   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1386
1387   if (!pool_is_free_index (im->fibs, u->fib_index))
1388     {
1389       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1390       rmp->vrf_id = ntohl (fib->ft_table_id);
1391     }
1392
1393   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1394   rmp->nsessions = ntohl (u->nsessions);
1395   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1396   rmp->context = context;
1397
1398   vl_api_send_msg (reg, (u8 *) rmp);
1399 }
1400
1401 static void
1402 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1403 {
1404   vl_api_registration_t *reg;
1405   snat_main_t *sm = &snat_main;
1406   snat_main_per_thread_data_t *tsm;
1407   snat_user_t *u;
1408
1409   if (sm->deterministic)
1410     return;
1411
1412   reg = vl_api_client_index_to_registration (mp->client_index);
1413   if (!reg)
1414     return;
1415
1416   /* *INDENT-OFF* */
1417   vec_foreach (tsm, sm->per_thread_data)
1418     {
1419       pool_foreach (u, tsm->users,
1420       ({
1421         send_nat44_user_details (u, reg, mp->context);
1422       }));
1423     }
1424   /* *INDENT-ON* */
1425 }
1426
1427 static void *
1428 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
1429 {
1430   u8 *s;
1431
1432   s = format (0, "SCRIPT: nat44_user_dump ");
1433
1434   FINISH;
1435 }
1436
1437 static void
1438 send_nat44_user_session_details (snat_session_t * s,
1439                                  vl_api_registration_t * reg, u32 context)
1440 {
1441   vl_api_nat44_user_session_details_t *rmp;
1442   snat_main_t *sm = &snat_main;
1443
1444   rmp = vl_msg_api_alloc (sizeof (*rmp));
1445   memset (rmp, 0, sizeof (*rmp));
1446   rmp->_vl_msg_id =
1447     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1448   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1449   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1450   rmp->is_static = snat_is_session_static (s) ? 1 : 0;
1451   rmp->is_twicenat = is_twice_nat_session (s) ? 1 : 0;
1452   rmp->ext_host_valid = is_ed_session (s)
1453     || is_fwd_bypass_session (s) ? 1 : 0;
1454   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1455   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1456   rmp->total_pkts = ntohl (s->total_pkts);
1457   rmp->context = context;
1458   if (snat_is_unk_proto_session (s))
1459     {
1460       rmp->outside_port = 0;
1461       rmp->inside_port = 0;
1462       rmp->protocol = ntohs (s->in2out.port);
1463     }
1464   else
1465     {
1466       rmp->outside_port = s->out2in.port;
1467       rmp->inside_port = s->in2out.port;
1468       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
1469     }
1470   if (is_ed_session (s) || is_fwd_bypass_session (s))
1471     {
1472       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1473       rmp->ext_host_port = s->ext_host_port;
1474       if (is_twice_nat_session (s))
1475         {
1476           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1477           rmp->ext_host_nat_port = s->ext_host_nat_port;
1478         }
1479     }
1480
1481   vl_api_send_msg (reg, (u8 *) rmp);
1482 }
1483
1484 static void
1485 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1486                                           mp)
1487 {
1488   vl_api_registration_t *reg;
1489   snat_main_t *sm = &snat_main;
1490   snat_main_per_thread_data_t *tsm;
1491   snat_session_t *s;
1492   clib_bihash_kv_8_8_t key, value;
1493   snat_user_key_t ukey;
1494   snat_user_t *u;
1495   u32 session_index, head_index, elt_index;
1496   dlist_elt_t *head, *elt;
1497   ip4_header_t ip;
1498
1499   if (sm->deterministic)
1500     return;
1501
1502   reg = vl_api_client_index_to_registration (mp->client_index);
1503   if (!reg)
1504     return;
1505
1506   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1507   ip.src_address.as_u32 = ukey.addr.as_u32;
1508   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1509   key.key = ukey.as_u64;
1510   if (sm->num_workers > 1)
1511     tsm =
1512       vec_elt_at_index (sm->per_thread_data,
1513                         sm->worker_in2out_cb (&ip, ukey.fib_index));
1514   else
1515     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1516   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1517     return;
1518   u = pool_elt_at_index (tsm->users, value.value);
1519   if (!u->nsessions && !u->nstaticsessions)
1520     return;
1521
1522   head_index = u->sessions_per_user_list_head_index;
1523   head = pool_elt_at_index (tsm->list_pool, head_index);
1524   elt_index = head->next;
1525   elt = pool_elt_at_index (tsm->list_pool, elt_index);
1526   session_index = elt->value;
1527   while (session_index != ~0)
1528     {
1529       s = pool_elt_at_index (tsm->sessions, session_index);
1530
1531       send_nat44_user_session_details (s, reg, mp->context);
1532
1533       elt_index = elt->next;
1534       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1535       session_index = elt->value;
1536     }
1537 }
1538
1539 static void *
1540 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
1541                                         void *handle)
1542 {
1543   u8 *s;
1544
1545   s = format (0, "SCRIPT: nat44_user_session_dump ");
1546   s = format (s, "ip_address %U vrf_id %d\n",
1547               format_ip4_address, mp->ip_address,
1548               clib_net_to_host_u32 (mp->vrf_id));
1549
1550   FINISH;
1551 }
1552
1553 static nat44_lb_addr_port_t *
1554 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1555                              u8 addr_port_pair_num)
1556 {
1557   u8 i;
1558   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1559   vl_api_nat44_lb_addr_port_t *ap;
1560
1561   for (i = 0; i < addr_port_pair_num; i++)
1562     {
1563       ap = &addr_port_pairs[i];
1564       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1565       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1566       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
1567       lb_addr_port.probability = ap->probability;
1568       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1569       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1570     }
1571
1572   return lb_addr_port_pairs;
1573 }
1574
1575 static void
1576   vl_api_nat44_add_del_lb_static_mapping_t_handler
1577   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1578 {
1579   snat_main_t *sm = &snat_main;
1580   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1581   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1582   int rv = 0;
1583   nat44_lb_addr_port_t *locals = 0;
1584   ip4_address_t e_addr;
1585   snat_protocol_t proto;
1586   u8 *tag = 0;
1587
1588   if (!sm->endpoint_dependent)
1589     {
1590       rv = VNET_API_ERROR_UNSUPPORTED;
1591       goto send_reply;
1592     }
1593
1594   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
1595   clib_memcpy (&e_addr, mp->external_addr, 4);
1596   proto = ip_proto_to_snat_proto (mp->protocol);
1597   if (mp->twice_nat)
1598     twice_nat = TWICE_NAT;
1599   else if (mp->self_twice_nat)
1600     twice_nat = TWICE_NAT_SELF;
1601   mp->tag[sizeof (mp->tag) - 1] = 0;
1602   tag = format (0, "%s", mp->tag);
1603   vec_terminate_c_string (tag);
1604
1605   rv =
1606     nat44_add_del_lb_static_mapping (e_addr,
1607                                      clib_net_to_host_u16 (mp->external_port),
1608                                      proto, locals, mp->is_add, twice_nat,
1609                                      mp->out2in_only, tag,
1610                                      clib_net_to_host_u32 (mp->affinity));
1611
1612   vec_free (locals);
1613   vec_free (tag);
1614
1615 send_reply:
1616   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1617 }
1618
1619 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1620   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1621 {
1622   u8 *s;
1623
1624   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1625   s = format (s, "is_add %d twice_nat %d out2in_only %d ",
1626               mp->is_add, mp->twice_nat, mp->out2in_only);
1627
1628   FINISH;
1629 }
1630
1631 static void
1632 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1633                                       vl_api_registration_t * reg,
1634                                       u32 context)
1635 {
1636   vl_api_nat44_lb_static_mapping_details_t *rmp;
1637   snat_main_t *sm = &snat_main;
1638   nat44_lb_addr_port_t *ap;
1639   vl_api_nat44_lb_addr_port_t *locals;
1640
1641   rmp =
1642     vl_msg_api_alloc (sizeof (*rmp) +
1643                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
1644   memset (rmp, 0, sizeof (*rmp));
1645   rmp->_vl_msg_id =
1646     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1647
1648   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1649   rmp->external_port = ntohs (m->external_port);
1650   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1651   rmp->context = context;
1652   if (m->twice_nat == TWICE_NAT)
1653     rmp->twice_nat = 1;
1654   else if (m->twice_nat == TWICE_NAT_SELF)
1655     rmp->self_twice_nat = 1;
1656   rmp->out2in_only = is_out2in_only_static_mapping (m);
1657   if (m->tag)
1658     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1659
1660   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1661   vec_foreach (ap, m->locals)
1662   {
1663     clib_memcpy (locals->addr, &(ap->addr), 4);
1664     locals->port = htons (ap->port);
1665     locals->probability = ap->probability;
1666     locals->vrf_id = ntohl (ap->vrf_id);
1667     locals++;
1668     rmp->local_num++;
1669   }
1670
1671   vl_api_send_msg (reg, (u8 *) rmp);
1672 }
1673
1674 static void
1675   vl_api_nat44_lb_static_mapping_dump_t_handler
1676   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1677 {
1678   vl_api_registration_t *reg;
1679   snat_main_t *sm = &snat_main;
1680   snat_static_mapping_t *m;
1681
1682   if (!sm->endpoint_dependent)
1683     return;
1684
1685   reg = vl_api_client_index_to_registration (mp->client_index);
1686   if (!reg)
1687     return;
1688
1689   /* *INDENT-OFF* */
1690   pool_foreach (m, sm->static_mappings,
1691   ({
1692       if (vec_len(m->locals))
1693         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1694   }));
1695   /* *INDENT-ON* */
1696 }
1697
1698 static void *vl_api_nat44_lb_static_mapping_dump_t_print
1699   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
1700 {
1701   u8 *s;
1702
1703   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
1704
1705   FINISH;
1706 }
1707
1708 static void
1709 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1710 {
1711   snat_main_t *sm = &snat_main;
1712   vl_api_nat44_del_session_reply_t *rmp;
1713   ip4_address_t addr, eh_addr;
1714   u16 port, eh_port;
1715   u32 vrf_id;
1716   int rv = 0;
1717   snat_protocol_t proto;
1718
1719   if (sm->deterministic)
1720     {
1721       rv = VNET_API_ERROR_UNSUPPORTED;
1722       goto send_reply;
1723     }
1724
1725   memcpy (&addr.as_u8, mp->address, 4);
1726   port = clib_net_to_host_u16 (mp->port);
1727   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1728   proto = ip_proto_to_snat_proto (mp->protocol);
1729   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1730   eh_port = clib_net_to_host_u16 (mp->ext_host_port);
1731
1732   if (mp->ext_host_valid)
1733     rv =
1734       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1735                             vrf_id, mp->is_in);
1736   else
1737     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
1738
1739 send_reply:
1740   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1741 }
1742
1743 static void *
1744 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
1745                                   void *handle)
1746 {
1747   u8 *s;
1748
1749   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1750   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
1751               format_ip4_address, mp->address,
1752               clib_net_to_host_u16 (mp->port),
1753               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
1754   if (mp->ext_host_valid)
1755     s = format (s, "ext_host_address %U ext_host_port %d",
1756                 format_ip4_address, mp->ext_host_address,
1757                 clib_net_to_host_u16 (mp->ext_host_port));
1758
1759   FINISH;
1760 }
1761
1762 static void
1763   vl_api_nat44_forwarding_enable_disable_t_handler
1764   (vl_api_nat44_forwarding_enable_disable_t * mp)
1765 {
1766   snat_main_t *sm = &snat_main;
1767   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1768   int rv = 0;
1769   u32 *ses_to_be_removed = 0, *ses_index;
1770   snat_main_per_thread_data_t *tsm;
1771   snat_session_t *s;
1772
1773   sm->forwarding_enabled = mp->enable != 0;
1774
1775   if (mp->enable == 0)
1776     {
1777       /* *INDENT-OFF* */
1778       vec_foreach (tsm, sm->per_thread_data)
1779       {
1780         pool_foreach (s, tsm->sessions,
1781         ({
1782           if (is_fwd_bypass_session(s))
1783             {
1784               vec_add1 (ses_to_be_removed, s - tsm->sessions);
1785             }
1786         }));
1787         vec_foreach (ses_index, ses_to_be_removed)
1788         {
1789           s = pool_elt_at_index(tsm->sessions, ses_index[0]);
1790           nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1791           nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1792         }
1793         vec_free (ses_to_be_removed);
1794       }
1795       /* *INDENT-ON* */
1796     }
1797
1798   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1799 }
1800
1801 static void *vl_api_nat44_forwarding_enable_disable_t_print
1802   (vl_api_nat44_forwarding_enable_disable_t * mp, void *handle)
1803 {
1804   u8 *s;
1805
1806   s = format (0, "SCRIPT: nat44_forwarding_enable_disable ");
1807   s = format (s, "enable %d", mp->enable != 0);
1808
1809   FINISH;
1810 }
1811
1812 static void
1813   vl_api_nat44_forwarding_is_enabled_t_handler
1814   (vl_api_nat44_forwarding_is_enabled_t * mp)
1815 {
1816   vl_api_registration_t *reg;
1817   snat_main_t *sm = &snat_main;
1818   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1819
1820   reg = vl_api_client_index_to_registration (mp->client_index);
1821   if (!reg)
1822     return;
1823
1824   rmp = vl_msg_api_alloc (sizeof (*rmp));
1825   memset (rmp, 0, sizeof (*rmp));
1826   rmp->_vl_msg_id =
1827     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1828   rmp->context = mp->context;
1829
1830   rmp->enabled = sm->forwarding_enabled;
1831
1832   vl_api_send_msg (reg, (u8 *) rmp);
1833 }
1834
1835 static void *vl_api_nat44_forwarding_is_enabled_t_print
1836   (vl_api_nat44_forwarding_is_enabled_t * mp, void *handle)
1837 {
1838   u8 *s;
1839
1840   s = format (0, "SCRIPT: nat44_forwarding_is_enabled ");
1841
1842   FINISH;
1843 }
1844
1845 /*******************************/
1846 /*** Deterministic NAT (CGN) ***/
1847 /*******************************/
1848
1849 static void
1850 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
1851 {
1852   snat_main_t *sm = &snat_main;
1853   vl_api_nat_det_add_del_map_reply_t *rmp;
1854   int rv = 0;
1855   ip4_address_t in_addr, out_addr;
1856
1857   if (!sm->deterministic)
1858     {
1859       rv = VNET_API_ERROR_UNSUPPORTED;
1860       goto send_reply;
1861     }
1862
1863   if (!mp->is_nat44)
1864     {
1865       rv = VNET_API_ERROR_UNIMPLEMENTED;
1866       goto send_reply;
1867     }
1868
1869   clib_memcpy (&in_addr, mp->in_addr, 4);
1870   clib_memcpy (&out_addr, mp->out_addr, 4);
1871   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
1872                          mp->out_plen, mp->is_add);
1873
1874 send_reply:
1875   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
1876 }
1877
1878 static void *
1879 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
1880                                     void *handle)
1881 {
1882   u8 *s;
1883
1884   s = format (0, "SCRIPT: nat_det_add_del_map ");
1885   s = format (s, "inside address %U/%d outside address %U/%d\n",
1886               format_ip4_address, mp->in_addr, mp->in_plen,
1887               format_ip4_address, mp->out_addr, mp->out_plen);
1888
1889   FINISH;
1890 }
1891
1892 static void
1893 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
1894 {
1895   snat_main_t *sm = &snat_main;
1896   vl_api_nat_det_forward_reply_t *rmp;
1897   int rv = 0;
1898   u16 lo_port = 0, hi_port = 0;
1899   snat_det_map_t *dm;
1900   ip4_address_t in_addr, out_addr;
1901
1902   if (!sm->deterministic)
1903     {
1904       rv = VNET_API_ERROR_UNSUPPORTED;
1905       REPLY_MACRO (VL_API_NAT_DET_FORWARD_REPLY);
1906       return;
1907     }
1908
1909   if (!mp->is_nat44)
1910     {
1911       out_addr.as_u32 = 0;
1912       rv = VNET_API_ERROR_UNIMPLEMENTED;
1913       goto send_reply;
1914     }
1915
1916   out_addr.as_u32 = 0;
1917   clib_memcpy (&in_addr, mp->in_addr, 4);
1918   dm = snat_det_map_by_user (sm, &in_addr);
1919   if (!dm)
1920     {
1921       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1922       goto send_reply;
1923     }
1924
1925   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1926   hi_port = lo_port + dm->ports_per_host - 1;
1927
1928 send_reply:
1929   /* *INDENT-OFF* */
1930   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
1931   ({
1932     rmp->out_port_lo = ntohs (lo_port);
1933     rmp->out_port_hi = ntohs (hi_port);
1934     clib_memcpy (rmp->out_addr, &out_addr, 4);
1935   }))
1936   /* *INDENT-ON* */
1937 }
1938
1939 static void *
1940 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
1941 {
1942   u8 *s;
1943
1944   s = format (0, "SCRIPT: nat_det_forward");
1945   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
1946
1947   FINISH;
1948 }
1949
1950 static void
1951 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
1952 {
1953   snat_main_t *sm = &snat_main;
1954   vl_api_nat_det_reverse_reply_t *rmp;
1955   int rv = 0;
1956   ip4_address_t out_addr, in_addr;
1957   snat_det_map_t *dm;
1958
1959   if (!sm->deterministic)
1960     {
1961       rv = VNET_API_ERROR_UNSUPPORTED;
1962       REPLY_MACRO (VL_API_NAT_DET_REVERSE_REPLY);
1963       return;
1964     }
1965
1966   in_addr.as_u32 = 0;
1967   clib_memcpy (&out_addr, mp->out_addr, 4);
1968   dm = snat_det_map_by_out (sm, &out_addr);
1969   if (!dm)
1970     {
1971       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1972       goto send_reply;
1973     }
1974
1975   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1976
1977 send_reply:
1978   /* *INDENT-OFF* */
1979   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
1980   ({
1981     rmp->is_nat44 = 1;
1982     memset (rmp->in_addr, 0, 16);
1983     clib_memcpy (rmp->in_addr, &in_addr, 4);
1984   }))
1985   /* *INDENT-ON* */
1986 }
1987
1988 static void *
1989 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
1990 {
1991   u8 *s;
1992
1993   s = format (0, "SCRIPT: nat_det_reverse");
1994   s = format (s, "outside ip address %U outside port %d",
1995               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1996
1997   FINISH;
1998 }
1999
2000 static void
2001 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
2002                           u32 context)
2003 {
2004   vl_api_nat_det_map_details_t *rmp;
2005   snat_main_t *sm = &snat_main;
2006
2007   rmp = vl_msg_api_alloc (sizeof (*rmp));
2008   memset (rmp, 0, sizeof (*rmp));
2009   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
2010   rmp->is_nat44 = 1;
2011   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
2012   rmp->in_plen = m->in_plen;
2013   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
2014   rmp->out_plen = m->out_plen;
2015   rmp->sharing_ratio = htonl (m->sharing_ratio);
2016   rmp->ports_per_host = htons (m->ports_per_host);
2017   rmp->ses_num = htonl (m->ses_num);
2018   rmp->context = context;
2019
2020   vl_api_send_msg (reg, (u8 *) rmp);
2021 }
2022
2023 static void
2024 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
2025 {
2026   vl_api_registration_t *reg;
2027   snat_main_t *sm = &snat_main;
2028   snat_det_map_t *m;
2029
2030   if (!sm->deterministic)
2031     return;
2032
2033   reg = vl_api_client_index_to_registration (mp->client_index);
2034   if (!reg)
2035     return;
2036
2037   /* *INDENT-OFF* */
2038   vec_foreach(m, sm->det_maps)
2039     sent_nat_det_map_details(m, reg, mp->context);
2040   /* *INDENT-ON* */
2041 }
2042
2043 static void *
2044 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
2045 {
2046   u8 *s;
2047
2048   s = format (0, "SCRIPT: nat_det_map_dump ");
2049
2050   FINISH;
2051 }
2052
2053 static void
2054 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
2055                                             * mp)
2056 {
2057   snat_main_t *sm = &snat_main;
2058   vl_api_nat_det_close_session_out_reply_t *rmp;
2059   ip4_address_t out_addr, ext_addr, in_addr;
2060   snat_det_out_key_t key;
2061   snat_det_map_t *dm;
2062   snat_det_session_t *ses;
2063   int rv = 0;
2064
2065   if (!sm->deterministic)
2066     {
2067       rv = VNET_API_ERROR_UNSUPPORTED;
2068       goto send_reply;
2069     }
2070
2071   clib_memcpy (&out_addr, mp->out_addr, 4);
2072   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2073
2074   dm = snat_det_map_by_out (sm, &out_addr);
2075   if (!dm)
2076     {
2077       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2078       goto send_reply;
2079     }
2080   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
2081   key.ext_host_addr = ext_addr;
2082   key.ext_host_port = mp->ext_port;
2083   key.out_port = mp->out_port;
2084   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
2085   if (!ses)
2086     {
2087       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2088       goto send_reply;
2089     }
2090   snat_det_ses_close (dm, ses);
2091
2092 send_reply:
2093   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2094 }
2095
2096 static void *
2097 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
2098                                           mp, void *handle)
2099 {
2100   u8 *s;
2101
2102   s = format (0, "SCRIPT: nat_det_close_session_out ");
2103   s = format (s, "out_addr %U out_port %d "
2104               "ext_addr %U ext_port %d\n",
2105               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
2106               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2107
2108   FINISH;
2109 }
2110
2111 static void
2112 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
2113                                            mp)
2114 {
2115   snat_main_t *sm = &snat_main;
2116   vl_api_nat_det_close_session_in_reply_t *rmp;
2117   ip4_address_t in_addr, ext_addr;
2118   snat_det_out_key_t key;
2119   snat_det_map_t *dm;
2120   snat_det_session_t *ses;
2121   int rv = 0;
2122
2123   if (!sm->deterministic)
2124     {
2125       rv = VNET_API_ERROR_UNSUPPORTED;
2126       goto send_reply;
2127     }
2128
2129   if (!mp->is_nat44)
2130     {
2131       rv = VNET_API_ERROR_UNIMPLEMENTED;
2132       goto send_reply;
2133     }
2134
2135   clib_memcpy (&in_addr, mp->in_addr, 4);
2136   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2137
2138   dm = snat_det_map_by_user (sm, &in_addr);
2139   if (!dm)
2140     {
2141       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2142       goto send_reply;
2143     }
2144   key.ext_host_addr = ext_addr;
2145   key.ext_host_port = mp->ext_port;
2146   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
2147   if (!ses)
2148     {
2149       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2150       goto send_reply;
2151     }
2152   snat_det_ses_close (dm, ses);
2153
2154 send_reply:
2155   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2156 }
2157
2158 static void *
2159 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2160                                          mp, void *handle)
2161 {
2162   u8 *s;
2163   s = format (0, "SCRIPT: nat_det_close_session_in ");
2164   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2165               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2166               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2167
2168   FINISH;
2169 }
2170
2171 static void
2172 send_nat_det_session_details (snat_det_session_t * s,
2173                               vl_api_registration_t * reg, u32 context)
2174 {
2175   vl_api_nat_det_session_details_t *rmp;
2176   snat_main_t *sm = &snat_main;
2177
2178   rmp = vl_msg_api_alloc (sizeof (*rmp));
2179   memset (rmp, 0, sizeof (*rmp));
2180   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2181   rmp->in_port = s->in_port;
2182   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2183   rmp->ext_port = s->out.ext_host_port;
2184   rmp->out_port = s->out.out_port;
2185   rmp->state = s->state;
2186   rmp->expire = ntohl (s->expire);
2187   rmp->context = context;
2188
2189   vl_api_send_msg (reg, (u8 *) rmp);
2190 }
2191
2192 static void
2193 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2194 {
2195   vl_api_registration_t *reg;
2196   snat_main_t *sm = &snat_main;
2197   ip4_address_t user_addr;
2198   snat_det_map_t *dm;
2199   snat_det_session_t *s, empty_ses;
2200   u16 i;
2201
2202   if (!sm->deterministic)
2203     return;
2204
2205   reg = vl_api_client_index_to_registration (mp->client_index);
2206   if (!reg)
2207     return;
2208   if (!mp->is_nat44)
2209     return;
2210
2211   memset (&empty_ses, 0, sizeof (empty_ses));
2212   clib_memcpy (&user_addr, mp->user_addr, 4);
2213   dm = snat_det_map_by_user (sm, &user_addr);
2214   if (!dm)
2215     return;
2216
2217   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2218   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2219     {
2220       if (s->out.as_u64)
2221         send_nat_det_session_details (s, reg, mp->context);
2222       s++;
2223     }
2224 }
2225
2226 static void *
2227 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2228                                      void *handle)
2229 {
2230   u8 *s;
2231
2232   s = format (0, "SCRIPT: nat_det_session_dump ");
2233   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2234
2235   FINISH;
2236 }
2237
2238 /*************/
2239 /*** NAT64 ***/
2240 /*************/
2241
2242 static void
2243   vl_api_nat64_add_del_pool_addr_range_t_handler
2244   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2245 {
2246   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2247   snat_main_t *sm = &snat_main;
2248   int rv = 0;
2249   ip4_address_t this_addr;
2250   u32 start_host_order, end_host_order;
2251   u32 vrf_id;
2252   int i, count;
2253   u32 *tmp;
2254
2255   tmp = (u32 *) mp->start_addr;
2256   start_host_order = clib_host_to_net_u32 (tmp[0]);
2257   tmp = (u32 *) mp->end_addr;
2258   end_host_order = clib_host_to_net_u32 (tmp[0]);
2259
2260   count = (end_host_order - start_host_order) + 1;
2261
2262   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2263
2264   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2265
2266   for (i = 0; i < count; i++)
2267     {
2268       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
2269         goto send_reply;
2270
2271       increment_v4_address (&this_addr);
2272     }
2273
2274 send_reply:
2275   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2276 }
2277
2278 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2279   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2280 {
2281   u8 *s;
2282
2283   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2284   s = format (s, "%U - %U vrf_id %u %s\n",
2285               format_ip4_address, mp->start_addr,
2286               format_ip4_address, mp->end_addr,
2287               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2288
2289   FINISH;
2290 }
2291
2292 typedef struct nat64_api_walk_ctx_t_
2293 {
2294   vl_api_registration_t *reg;
2295   u32 context;
2296   nat64_db_t *db;
2297 } nat64_api_walk_ctx_t;
2298
2299 static int
2300 nat64_api_pool_walk (snat_address_t * a, void *arg)
2301 {
2302   vl_api_nat64_pool_addr_details_t *rmp;
2303   snat_main_t *sm = &snat_main;
2304   nat64_api_walk_ctx_t *ctx = arg;
2305
2306   rmp = vl_msg_api_alloc (sizeof (*rmp));
2307   memset (rmp, 0, sizeof (*rmp));
2308   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2309   clib_memcpy (rmp->address, &(a->addr), 4);
2310   if (a->fib_index != ~0)
2311     {
2312       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2313       if (!fib)
2314         return -1;
2315       rmp->vrf_id = ntohl (fib->ft_table_id);
2316     }
2317   else
2318     rmp->vrf_id = ~0;
2319   rmp->context = ctx->context;
2320
2321   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2322
2323   return 0;
2324 }
2325
2326 static void
2327 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2328 {
2329   vl_api_registration_t *reg;
2330
2331   reg = vl_api_client_index_to_registration (mp->client_index);
2332   if (!reg)
2333     return;
2334
2335   nat64_api_walk_ctx_t ctx = {
2336     .reg = reg,
2337     .context = mp->context,
2338   };
2339
2340   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2341 }
2342
2343 static void *
2344 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2345                                      void *handle)
2346 {
2347   u8 *s;
2348
2349   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2350
2351   FINISH;
2352 }
2353
2354 static void
2355 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2356                                           mp)
2357 {
2358   snat_main_t *sm = &snat_main;
2359   vl_api_nat64_add_del_interface_reply_t *rmp;
2360   int rv = 0;
2361
2362   VALIDATE_SW_IF_INDEX (mp);
2363
2364   rv =
2365     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
2366                              mp->is_add);
2367
2368   BAD_SW_IF_INDEX_LABEL;
2369
2370   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2371 }
2372
2373 static void *
2374 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2375                                         void *handle)
2376 {
2377   u8 *s;
2378
2379   s = format (0, "SCRIPT: nat64_add_del_interface ");
2380   s = format (s, "sw_if_index %d %s %s",
2381               clib_host_to_net_u32 (mp->sw_if_index),
2382               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2383
2384   FINISH;
2385 }
2386
2387 static int
2388 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2389 {
2390   vl_api_nat64_interface_details_t *rmp;
2391   snat_main_t *sm = &snat_main;
2392   nat64_api_walk_ctx_t *ctx = arg;
2393
2394   rmp = vl_msg_api_alloc (sizeof (*rmp));
2395   memset (rmp, 0, sizeof (*rmp));
2396   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2397   rmp->sw_if_index = ntohl (i->sw_if_index);
2398   rmp->is_inside = (nat_interface_is_inside (i)
2399                     && nat_interface_is_outside (i)) ? 2 :
2400     nat_interface_is_inside (i);
2401   rmp->context = ctx->context;
2402
2403   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2404
2405   return 0;
2406 }
2407
2408 static void
2409 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2410 {
2411   vl_api_registration_t *reg;
2412
2413   reg = vl_api_client_index_to_registration (mp->client_index);
2414   if (!reg)
2415     return;
2416
2417   nat64_api_walk_ctx_t ctx = {
2418     .reg = reg,
2419     .context = mp->context,
2420   };
2421
2422   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2423 }
2424
2425 static void *
2426 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2427                                      void *handle)
2428 {
2429   u8 *s;
2430
2431   s = format (0, "SCRIPT: snat_interface_dump ");
2432
2433   FINISH;
2434 }
2435
2436 static void
2437   vl_api_nat64_add_del_static_bib_t_handler
2438   (vl_api_nat64_add_del_static_bib_t * mp)
2439 {
2440   snat_main_t *sm = &snat_main;
2441   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2442   ip6_address_t in_addr;
2443   ip4_address_t out_addr;
2444   int rv = 0;
2445
2446   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2447   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2448
2449   rv =
2450     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2451                                     clib_net_to_host_u16 (mp->i_port),
2452                                     clib_net_to_host_u16 (mp->o_port),
2453                                     mp->proto,
2454                                     clib_net_to_host_u32 (mp->vrf_id),
2455                                     mp->is_add);
2456
2457   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2458 }
2459
2460 static void *vl_api_nat64_add_del_static_bib_t_print
2461   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2462 {
2463   u8 *s;
2464
2465   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2466   s = format (s, "protocol %d i_addr %U o_addr %U ",
2467               mp->proto,
2468               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2469
2470   if (mp->vrf_id != ~0)
2471     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2472
2473   FINISH;
2474 }
2475
2476 static int
2477 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2478 {
2479   vl_api_nat64_bib_details_t *rmp;
2480   snat_main_t *sm = &snat_main;
2481   nat64_api_walk_ctx_t *ctx = arg;
2482   fib_table_t *fib;
2483
2484   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2485   if (!fib)
2486     return -1;
2487
2488   rmp = vl_msg_api_alloc (sizeof (*rmp));
2489   memset (rmp, 0, sizeof (*rmp));
2490   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2491   rmp->context = ctx->context;
2492   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2493   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2494   rmp->i_port = bibe->in_port;
2495   rmp->o_port = bibe->out_port;
2496   rmp->vrf_id = ntohl (fib->ft_table_id);
2497   rmp->proto = bibe->proto;
2498   rmp->is_static = bibe->is_static;
2499   rmp->ses_num = ntohl (bibe->ses_num);
2500
2501   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2502
2503   return 0;
2504 }
2505
2506 static void
2507 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2508 {
2509   vl_api_registration_t *reg;
2510   nat64_main_t *nm = &nat64_main;
2511   nat64_db_t *db;
2512
2513   reg = vl_api_client_index_to_registration (mp->client_index);
2514   if (!reg)
2515     return;
2516
2517   nat64_api_walk_ctx_t ctx = {
2518     .reg = reg,
2519     .context = mp->context,
2520   };
2521
2522   /* *INDENT-OFF* */
2523   vec_foreach (db, nm->db)
2524     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2525   /* *INDENT-ON* */
2526 }
2527
2528 static void *
2529 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2530 {
2531   u8 *s;
2532
2533   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2534
2535   FINISH;
2536 }
2537
2538 static int
2539 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2540 {
2541   vl_api_nat64_st_details_t *rmp;
2542   snat_main_t *sm = &snat_main;
2543   nat64_api_walk_ctx_t *ctx = arg;
2544   nat64_db_bib_entry_t *bibe;
2545   fib_table_t *fib;
2546
2547   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2548   if (!bibe)
2549     return -1;
2550
2551   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2552   if (!fib)
2553     return -1;
2554
2555   rmp = vl_msg_api_alloc (sizeof (*rmp));
2556   memset (rmp, 0, sizeof (*rmp));
2557   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2558   rmp->context = ctx->context;
2559   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2560   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2561   rmp->il_port = bibe->in_port;
2562   rmp->ol_port = bibe->out_port;
2563   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2564   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2565   rmp->il_port = ste->r_port;
2566   rmp->vrf_id = ntohl (fib->ft_table_id);
2567   rmp->proto = ste->proto;
2568
2569   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2570
2571   return 0;
2572 }
2573
2574 static void
2575 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2576 {
2577   vl_api_registration_t *reg;
2578   nat64_main_t *nm = &nat64_main;
2579   nat64_db_t *db;
2580
2581   reg = vl_api_client_index_to_registration (mp->client_index);
2582   if (!reg)
2583     return;
2584
2585   nat64_api_walk_ctx_t ctx = {
2586     .reg = reg,
2587     .context = mp->context,
2588   };
2589
2590   /* *INDENT-OFF* */
2591   vec_foreach (db, nm->db)
2592     {
2593       ctx.db = db;
2594       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2595     }
2596   /* *INDENT-ON* */
2597 }
2598
2599 static void *
2600 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2601 {
2602   u8 *s;
2603
2604   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2605
2606   FINISH;
2607 }
2608
2609 static void
2610 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2611 {
2612   vl_api_nat64_add_del_prefix_reply_t *rmp;
2613   snat_main_t *sm = &snat_main;
2614   ip6_address_t prefix;
2615   int rv = 0;
2616
2617   memcpy (&prefix.as_u8, mp->prefix, 16);
2618
2619   rv =
2620     nat64_add_del_prefix (&prefix, mp->prefix_len,
2621                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2622   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2623 }
2624
2625 static void *
2626 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2627                                      void *handle)
2628 {
2629   u8 *s;
2630
2631   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2632               format_ip6_address, mp->prefix, mp->prefix_len,
2633               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2634
2635   FINISH;
2636 }
2637
2638 static int
2639 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2640 {
2641   vl_api_nat64_prefix_details_t *rmp;
2642   snat_main_t *sm = &snat_main;
2643   nat64_api_walk_ctx_t *ctx = arg;
2644
2645   rmp = vl_msg_api_alloc (sizeof (*rmp));
2646   memset (rmp, 0, sizeof (*rmp));
2647   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2648   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2649   rmp->prefix_len = p->plen;
2650   rmp->vrf_id = ntohl (p->vrf_id);
2651   rmp->context = ctx->context;
2652
2653   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2654
2655   return 0;
2656 }
2657
2658 static void
2659 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2660 {
2661   vl_api_registration_t *reg;
2662
2663   reg = vl_api_client_index_to_registration (mp->client_index);
2664   if (!reg)
2665     return;
2666
2667   nat64_api_walk_ctx_t ctx = {
2668     .reg = reg,
2669     .context = mp->context,
2670   };
2671
2672   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2673 }
2674
2675 static void *
2676 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2677                                   void *handle)
2678 {
2679   u8 *s;
2680
2681   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2682
2683   FINISH;
2684 }
2685
2686 static void
2687   vl_api_nat64_add_del_interface_addr_t_handler
2688   (vl_api_nat64_add_del_interface_addr_t * mp)
2689 {
2690   snat_main_t *sm = &snat_main;
2691   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2692   u32 sw_if_index = ntohl (mp->sw_if_index);
2693   int rv = 0;
2694
2695   VALIDATE_SW_IF_INDEX (mp);
2696
2697   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2698
2699   BAD_SW_IF_INDEX_LABEL;
2700
2701   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2702 }
2703
2704 static void *vl_api_nat64_add_del_interface_addr_t_print
2705   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2706 {
2707   u8 *s;
2708
2709   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2710   s = format (s, "sw_if_index %d %s",
2711               clib_host_to_net_u32 (mp->sw_if_index),
2712               mp->is_add ? "" : "del");
2713
2714   FINISH;
2715 }
2716
2717 /***************/
2718 /*** DS-Lite ***/
2719 /***************/
2720
2721 static void
2722 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2723 {
2724   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2725   snat_main_t *sm = &snat_main;
2726   dslite_main_t *dm = &dslite_main;
2727   int rv = 0;
2728   ip6_address_t ip6_addr;
2729   ip4_address_t ip4_addr;
2730
2731   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2732   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2733
2734   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2735   if (rv == 0)
2736     rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr);
2737
2738   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2739 }
2740
2741 static void *
2742 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2743                                      void *handle)
2744 {
2745   u8 *s;
2746
2747   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2748   s = format (s, "ip6_addr %U ip4_addr %U\n",
2749               format_ip6_address, mp->ip6_addr,
2750               format_ip4_address, mp->ip4_addr);
2751
2752   FINISH;
2753 }
2754
2755 static void
2756 vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp)
2757 {
2758   snat_main_t *sm = &snat_main;
2759   vl_api_dslite_get_aftr_addr_reply_t *rmp;
2760   dslite_main_t *dm = &dslite_main;
2761   int rv = 0;
2762
2763   /* *INDENT-OFF* */
2764   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2765   ({
2766     memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4);
2767     memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16);
2768   }))
2769   /* *INDENT-ON* */
2770 }
2771
2772 static void *
2773 vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp,
2774                                      void *handle)
2775 {
2776   u8 *s;
2777
2778   s = format (0, "SCRIPT: dslite_get_aftr_addr");
2779
2780   FINISH;
2781 }
2782
2783 static void
2784 vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp)
2785 {
2786   vl_api_dslite_set_b4_addr_reply_t *rmp;
2787   snat_main_t *sm = &snat_main;
2788   dslite_main_t *dm = &dslite_main;
2789   int rv = 0;
2790   ip6_address_t ip6_addr;
2791   ip4_address_t ip4_addr;
2792
2793   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2794   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2795
2796   rv = dslite_set_b4_ip6_addr (dm, &ip6_addr);
2797   if (rv == 0)
2798     rv = dslite_set_b4_ip4_addr (dm, &ip4_addr);
2799
2800   REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY);
2801 }
2802
2803 static void *
2804 vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp,
2805                                    void *handle)
2806 {
2807   u8 *s;
2808
2809   s = format (0, "SCRIPT: dslite_set_b4_addr ");
2810   s = format (s, "ip6_addr %U ip4_addr %U\n",
2811               format_ip6_address, mp->ip6_addr,
2812               format_ip6_address, mp->ip4_addr);
2813
2814   FINISH;
2815 }
2816
2817 static void
2818 vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp)
2819 {
2820   snat_main_t *sm = &snat_main;
2821   vl_api_dslite_get_b4_addr_reply_t *rmp;
2822   dslite_main_t *dm = &dslite_main;
2823   int rv = 0;
2824
2825   /* *INDENT-OFF* */
2826   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2827   ({
2828     memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4);
2829     memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16);
2830   }))
2831   /* *INDENT-ON* */
2832 }
2833
2834 static void *
2835 vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp,
2836                                    void *handle)
2837 {
2838   u8 *s;
2839
2840   s = format (0, "SCRIPT: dslite_get_b4_addr");
2841
2842   FINISH;
2843 }
2844
2845 static void
2846   vl_api_dslite_add_del_pool_addr_range_t_handler
2847   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2848 {
2849   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2850   snat_main_t *sm = &snat_main;
2851   dslite_main_t *dm = &dslite_main;
2852   int rv = 0;
2853   ip4_address_t this_addr;
2854   u32 start_host_order, end_host_order;
2855   int i, count;
2856   u32 *tmp;
2857
2858   tmp = (u32 *) mp->start_addr;
2859   start_host_order = clib_host_to_net_u32 (tmp[0]);
2860   tmp = (u32 *) mp->end_addr;
2861   end_host_order = clib_host_to_net_u32 (tmp[0]);
2862
2863   count = (end_host_order - start_host_order) + 1;
2864   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2865
2866   for (i = 0; i < count; i++)
2867     {
2868       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2869         goto send_reply;
2870
2871       increment_v4_address (&this_addr);
2872     }
2873
2874 send_reply:
2875   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2876 }
2877
2878 static void
2879 send_dslite_address_details (snat_address_t * ap,
2880                              vl_api_registration_t * reg, u32 context)
2881 {
2882   vl_api_dslite_address_details_t *rmp;
2883   snat_main_t *sm = &snat_main;
2884
2885   rmp = vl_msg_api_alloc (sizeof (*rmp));
2886
2887   memset (rmp, 0, sizeof (*rmp));
2888
2889   rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + sm->msg_id_base);
2890   clib_memcpy (rmp->ip_address, &(ap->addr), 4);
2891   rmp->context = context;
2892
2893   vl_api_send_msg (reg, (u8 *) rmp);
2894 }
2895
2896 static void
2897 vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp)
2898 {
2899   vl_api_registration_t *reg;
2900   dslite_main_t *dm = &dslite_main;
2901   snat_address_t *ap;
2902
2903   reg = vl_api_client_index_to_registration (mp->client_index);
2904   if (!reg)
2905     return;
2906
2907   /* *INDENT-OFF* */
2908   vec_foreach (ap, dm->addr_pool)
2909     {
2910       send_dslite_address_details (ap, reg, mp->context);
2911     }
2912   /* *INDENT-ON* */
2913 }
2914
2915 static void *
2916 vl_api_dslite_address_dump_t_print (vl_api_dslite_address_dump_t * mp,
2917                                     void *handle)
2918 {
2919   u8 *s;
2920
2921   s = format (0, "SCRIPT: dslite_address_dump ");
2922
2923   FINISH;
2924 }
2925
2926 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2927   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2928 {
2929   u8 *s;
2930
2931   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2932   s = format (s, "%U - %U\n",
2933               format_ip4_address, mp->start_addr,
2934               format_ip4_address, mp->end_addr);
2935
2936   FINISH;
2937 }
2938
2939
2940 /*************/
2941 /*** NAT66 ***/
2942 /*************/
2943
2944 static void
2945 vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
2946                                           mp)
2947 {
2948   snat_main_t *sm = &snat_main;
2949   vl_api_nat66_add_del_interface_reply_t *rmp;
2950   int rv = 0;
2951
2952   VALIDATE_SW_IF_INDEX (mp);
2953
2954   rv =
2955     nat66_interface_add_del (ntohl (mp->sw_if_index), mp->is_inside,
2956                              mp->is_add);
2957
2958   BAD_SW_IF_INDEX_LABEL;
2959
2960   REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
2961 }
2962
2963 static void *
2964 vl_api_nat66_add_del_interface_t_print (vl_api_nat66_add_del_interface_t * mp,
2965                                         void *handle)
2966 {
2967   u8 *s;
2968
2969   s = format (0, "SCRIPT: nat66_add_del_interface ");
2970   s = format (s, "sw_if_index %d %s %s",
2971               clib_host_to_net_u32 (mp->sw_if_index),
2972               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2973
2974   FINISH;
2975 }
2976
2977 static void
2978   vl_api_nat66_add_del_static_mapping_t_handler
2979   (vl_api_nat66_add_del_static_mapping_t * mp)
2980 {
2981   snat_main_t *sm = &snat_main;
2982   vl_api_nat66_add_del_static_mapping_reply_t *rmp;
2983   ip6_address_t l_addr, e_addr;
2984   int rv = 0;
2985
2986   memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
2987   memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
2988
2989   rv =
2990     nat66_static_mapping_add_del (&l_addr, &e_addr,
2991                                   clib_net_to_host_u32 (mp->vrf_id),
2992                                   mp->is_add);
2993
2994   REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
2995 }
2996
2997 static void *vl_api_nat66_add_del_static_mapping_t_print
2998   (vl_api_nat66_add_del_static_mapping_t * mp, void *handle)
2999 {
3000   u8 *s;
3001
3002   s = format (0, "SCRIPT: nat66_add_del_static_mapping ");
3003   s = format (s, "local_ip_address %U external_ip_address %U vrf_id %d %s",
3004               format_ip6_address, mp->local_ip_address,
3005               format_ip6_address, mp->external_ip_address,
3006               clib_net_to_host_u32 (mp->vrf_id), mp->is_add ? "" : "del");
3007
3008   FINISH;
3009 }
3010
3011 typedef struct nat66_api_walk_ctx_t_
3012 {
3013   svm_queue_t *q;
3014   u32 context;
3015 } nat66_api_walk_ctx_t;
3016
3017 static int
3018 nat66_api_interface_walk (snat_interface_t * i, void *arg)
3019 {
3020   vl_api_nat66_interface_details_t *rmp;
3021   snat_main_t *sm = &snat_main;
3022   nat66_api_walk_ctx_t *ctx = arg;
3023
3024   rmp = vl_msg_api_alloc (sizeof (*rmp));
3025   memset (rmp, 0, sizeof (*rmp));
3026   rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + sm->msg_id_base);
3027   rmp->sw_if_index = ntohl (i->sw_if_index);
3028   rmp->is_inside = nat_interface_is_inside (i);
3029   rmp->context = ctx->context;
3030
3031   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3032
3033   return 0;
3034 }
3035
3036 static void
3037 vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
3038 {
3039   svm_queue_t *q;
3040
3041   q = vl_api_client_index_to_input_queue (mp->client_index);
3042   if (q == 0)
3043     return;
3044
3045   nat66_api_walk_ctx_t ctx = {
3046     .q = q,
3047     .context = mp->context,
3048   };
3049
3050   nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
3051 }
3052
3053 static void *
3054 vl_api_nat66_interface_dump_t_print (vl_api_nat66_interface_dump_t * mp,
3055                                      void *handle)
3056 {
3057   u8 *s;
3058
3059   s = format (0, "SCRIPT: nat66_interface_dump ");
3060
3061   FINISH;
3062 }
3063
3064 static int
3065 nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
3066 {
3067   vl_api_nat66_static_mapping_details_t *rmp;
3068   nat66_main_t *nm = &nat66_main;
3069   snat_main_t *sm = &snat_main;
3070   nat66_api_walk_ctx_t *ctx = arg;
3071   fib_table_t *fib;
3072   vlib_counter_t vc;
3073
3074   fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
3075   if (!fib)
3076     return -1;
3077
3078   vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
3079
3080   rmp = vl_msg_api_alloc (sizeof (*rmp));
3081   memset (rmp, 0, sizeof (*rmp));
3082   rmp->_vl_msg_id =
3083     ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + sm->msg_id_base);
3084   clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
3085   clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
3086   rmp->vrf_id = ntohl (fib->ft_table_id);
3087   rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
3088   rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
3089   rmp->context = ctx->context;
3090
3091   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3092
3093   return 0;
3094 }
3095
3096 static void
3097 vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
3098                                             * mp)
3099 {
3100   svm_queue_t *q;
3101
3102   q = vl_api_client_index_to_input_queue (mp->client_index);
3103   if (q == 0)
3104     return;
3105
3106   nat66_api_walk_ctx_t ctx = {
3107     .q = q,
3108     .context = mp->context,
3109   };
3110
3111   nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
3112 }
3113
3114 static void *
3115 vl_api_nat66_static_mapping_dump_t_print (vl_api_nat66_static_mapping_dump_t *
3116                                           mp, void *handle)
3117 {
3118   u8 *s;
3119
3120   s = format (0, "SCRIPT: nat66_static_mapping_dump ");
3121
3122   FINISH;
3123 }
3124
3125
3126 /* List of message types that this plugin understands */
3127 #define foreach_snat_plugin_api_msg                                     \
3128 _(NAT_CONTROL_PING, nat_control_ping)                                   \
3129 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
3130 _(NAT_SET_WORKERS, nat_set_workers)                                     \
3131 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
3132 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
3133 _(NAT_SET_REASS, nat_set_reass)                                         \
3134 _(NAT_GET_REASS, nat_get_reass)                                         \
3135 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
3136 _(NAT_SET_TIMEOUTS, nat_set_timeouts)                                   \
3137 _(NAT_GET_TIMEOUTS, nat_get_timeouts)                                   \
3138 _(NAT_SET_ADDR_AND_PORT_ALLOC_ALG, nat_set_addr_and_port_alloc_alg)     \
3139 _(NAT_GET_ADDR_AND_PORT_ALLOC_ALG, nat_get_addr_and_port_alloc_alg)     \
3140 _(NAT_SET_MSS_CLAMPING, nat_set_mss_clamping)                           \
3141 _(NAT_GET_MSS_CLAMPING, nat_get_mss_clamping)                           \
3142 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
3143 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
3144 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
3145 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
3146 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3147 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
3148 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3149 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3150 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3151 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3152 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3153 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3154 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3155   nat44_interface_add_del_output_feature)                               \
3156 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3157   nat44_interface_output_feature_dump)                                  \
3158 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3159 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3160 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
3161 _(NAT44_FORWARDING_ENABLE_DISABLE, nat44_forwarding_enable_disable)     \
3162 _(NAT44_FORWARDING_IS_ENABLED, nat44_forwarding_is_enabled)             \
3163 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3164 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3165 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3166 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3167 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3168 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3169 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3170 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3171 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3172 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3173 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3174 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3175 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3176 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3177 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3178 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
3179 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
3180 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
3181 _(DSLITE_ADDRESS_DUMP, dslite_address_dump)                             \
3182 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)                           \
3183 _(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr)                           \
3184 _(DSLITE_SET_B4_ADDR, dslite_set_b4_addr)                               \
3185 _(DSLITE_GET_B4_ADDR, dslite_get_b4_addr)                               \
3186 _(NAT66_ADD_DEL_INTERFACE, nat66_add_del_interface)                     \
3187 _(NAT66_INTERFACE_DUMP, nat66_interface_dump)                           \
3188 _(NAT66_ADD_DEL_STATIC_MAPPING, nat66_add_del_static_mapping)           \
3189 _(NAT66_STATIC_MAPPING_DUMP, nat66_static_mapping_dump)
3190
3191 /* Set up the API message handling tables */
3192 static clib_error_t *
3193 snat_plugin_api_hookup (vlib_main_t * vm)
3194 {
3195   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3196 #define _(N,n)                                                  \
3197     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3198                            #n,                                  \
3199                            vl_api_##n##_t_handler,              \
3200                            vl_noop_handler,                     \
3201                            vl_api_##n##_t_endian,               \
3202                            vl_api_##n##_t_print,                \
3203                            sizeof(vl_api_##n##_t), 1);
3204   foreach_snat_plugin_api_msg;
3205 #undef _
3206
3207   return 0;
3208 }
3209
3210 #define vl_msg_name_crc_list
3211 #include <nat/nat_all_api_h.h>
3212 #undef vl_msg_name_crc_list
3213
3214 static void
3215 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3216 {
3217 #define _(id,n,crc) \
3218   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3219   foreach_vl_msg_name_crc_nat;
3220 #undef _
3221 }
3222
3223 static void
3224 plugin_custom_dump_configure (snat_main_t * sm)
3225 {
3226 #define _(n,f) sm->api_main->msg_print_handlers \
3227   [VL_API_##n + sm->msg_id_base]                \
3228     = (void *) vl_api_##f##_t_print;
3229   foreach_snat_plugin_api_msg;
3230 #undef _
3231 }
3232
3233 clib_error_t *
3234 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3235 {
3236   u8 *name;
3237   clib_error_t *error = 0;
3238
3239   name = format (0, "nat_%08x%c", api_version, 0);
3240
3241   /* Ask for a correctly-sized block of API message decode slots */
3242   sm->msg_id_base =
3243     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3244
3245   error = snat_plugin_api_hookup (vm);
3246
3247   /* Add our API messages to the global name_crc hash table */
3248   setup_message_id_table (sm, sm->api_main);
3249
3250   plugin_custom_dump_configure (sm);
3251
3252   vec_free (name);
3253
3254   return error;
3255 }
3256
3257 /*
3258  * fd.io coding-style-patch-verification: ON
3259  *
3260  * Local Variables:
3261  * eval: (c-set-style "gnu")
3262  * End:
3263  */