NAT: TCP MSS clamping
[vpp.git] / src / plugins / nat / nat_api.c
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @file
18  * @brief NAT plugin API implementation
19  */
20
21 #include <nat/nat.h>
22 #include <nat/nat_det.h>
23 #include <nat/nat64.h>
24 #include <nat/nat66.h>
25 #include <nat/dslite.h>
26 #include <nat/nat_reass.h>
27 #include <nat/nat_inlines.h>
28 #include <vlibapi/api.h>
29 #include <vlibmemory/api.h>
30
31 #include <nat/nat_msg_enum.h>
32 #include <vnet/fib/fib_table.h>
33
34 #define vl_api_nat44_lb_addr_port_t_endian vl_noop_handler
35 #define vl_api_nat44_add_del_lb_static_mapping_t_endian vl_noop_handler
36 #define vl_api_nat44_nat44_lb_static_mapping_details_t_endian vl_noop_handler
37
38 /* define message structures */
39 #define vl_typedefs
40 #include <nat/nat_all_api_h.h>
41 #undef vl_typedefs
42
43 /* define generated endian-swappers */
44 #define vl_endianfun
45 #include <nat/nat_all_api_h.h>
46 #undef vl_endianfun
47
48 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
49
50 #define REPLY_MSG_ID_BASE sm->msg_id_base
51 #include <vlibapi/api_helper_macros.h>
52
53 /* Get the API version number */
54 #define vl_api_version(n,v) static u32 api_version=(v);
55 #include <nat/nat_all_api_h.h>
56 #undef vl_api_version
57
58 /* Macro to finish up custom dump fns */
59 #define FINISH                                  \
60     vec_add1 (s, 0);                            \
61     vl_print (handle, (char *)s);               \
62     vec_free (s);                               \
63     return handle;
64
65
66 /******************************/
67 /*** Common NAT plugin APIs ***/
68 /******************************/
69
70 static void
71 vl_api_nat_control_ping_t_handler (vl_api_nat_control_ping_t * mp)
72 {
73   vl_api_nat_control_ping_reply_t *rmp;
74   snat_main_t *sm = &snat_main;
75   int rv = 0;
76
77   /* *INDENT-OFF* */
78   REPLY_MACRO2 (VL_API_NAT_CONTROL_PING_REPLY,
79   ({
80     rmp->vpe_pid = ntohl (getpid ());
81   }));
82   /* *INDENT-ON* */
83 }
84
85 static void *
86 vl_api_nat_control_ping_t_print (vl_api_nat_control_ping_t * mp, void *handle)
87 {
88   u8 *s;
89
90   s = format (0, "SCRIPT: nat_control_ping ");
91
92   FINISH;
93 }
94
95 static void
96 vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t * mp)
97 {
98   vl_api_nat_show_config_reply_t *rmp;
99   snat_main_t *sm = &snat_main;
100   dslite_main_t *dm = &dslite_main;
101   nat64_main_t *n64m = &nat64_main;
102   int rv = 0;
103
104   /* *INDENT-OFF* */
105   REPLY_MACRO2 (VL_API_NAT_SHOW_CONFIG_REPLY,
106   ({
107     rmp->translation_buckets = htonl (sm->translation_buckets);
108     rmp->translation_memory_size = htonl (sm->translation_memory_size);
109     rmp->user_buckets = htonl (sm->user_buckets);
110     rmp->user_memory_size = htonl (sm->user_memory_size);
111     rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
112     rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
113     rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
114     rmp->static_mapping_only = sm->static_mapping_only;
115     rmp->static_mapping_connection_tracking =
116       sm->static_mapping_connection_tracking;
117     rmp->deterministic = sm->deterministic;
118     rmp->endpoint_dependent = sm->endpoint_dependent;
119     rmp->out2in_dpo = sm->out2in_dpo;
120     rmp->dslite_ce = dm->is_ce;
121     rmp->nat64_bib_buckets = n64m->bib_buckets;
122     rmp->nat64_bib_memory_size = n64m->bib_memory_size;
123     rmp->nat64_st_buckets = n64m->st_buckets;
124     rmp->nat64_st_memory_size = n64m->st_memory_size;
125   }));
126   /* *INDENT-ON* */
127 }
128
129 static void *
130 vl_api_nat_show_config_t_print (vl_api_nat_show_config_t * mp, void *handle)
131 {
132   u8 *s;
133
134   s = format (0, "SCRIPT: nat_show_config ");
135
136   FINISH;
137 }
138
139 static void
140 vl_api_nat_set_workers_t_handler (vl_api_nat_set_workers_t * mp)
141 {
142   snat_main_t *sm = &snat_main;
143   vl_api_nat_set_workers_reply_t *rmp;
144   int rv = 0;
145   uword *bitmap = 0;
146   u64 mask;
147
148   if (sm->deterministic)
149     {
150       rv = VNET_API_ERROR_UNSUPPORTED;
151       goto send_reply;
152     }
153
154   mask = clib_net_to_host_u64 (mp->worker_mask);
155
156   if (sm->num_workers < 2)
157     {
158       rv = VNET_API_ERROR_FEATURE_DISABLED;
159       goto send_reply;
160     }
161
162   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
163   rv = snat_set_workers (bitmap);
164   clib_bitmap_free (bitmap);
165
166 send_reply:
167   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
168 }
169
170 static void *
171 vl_api_nat_set_workers_t_print (vl_api_nat_set_workers_t * mp, void *handle)
172 {
173   u8 *s;
174   uword *bitmap = 0;
175   u8 first = 1;
176   int i;
177   u64 mask = clib_net_to_host_u64 (mp->worker_mask);
178
179   s = format (0, "SCRIPT: nat_set_workers ");
180   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
181   /* *INDENT-OFF* */
182   clib_bitmap_foreach (i, bitmap,
183     ({
184       if (first)
185         s = format (s, "%d", i);
186       else
187         s = format (s, ",%d", i);
188       first = 0;
189     }));
190   /* *INDENT-ON* */
191   clib_bitmap_free (bitmap);
192   FINISH;
193 }
194
195 static void
196 send_nat_worker_details (u32 worker_index, vl_api_registration_t * reg,
197                          u32 context)
198 {
199   vl_api_nat_worker_details_t *rmp;
200   snat_main_t *sm = &snat_main;
201   vlib_worker_thread_t *w =
202     vlib_worker_threads + worker_index + sm->first_worker_index;
203
204   rmp = vl_msg_api_alloc (sizeof (*rmp));
205   memset (rmp, 0, sizeof (*rmp));
206   rmp->_vl_msg_id = ntohs (VL_API_NAT_WORKER_DETAILS + sm->msg_id_base);
207   rmp->context = context;
208   rmp->worker_index = htonl (worker_index);
209   rmp->lcore_id = htonl (w->lcore_id);
210   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
211
212   vl_api_send_msg (reg, (u8 *) rmp);
213 }
214
215 static void
216 vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp)
217 {
218   vl_api_registration_t *reg;
219   snat_main_t *sm = &snat_main;
220   u32 *worker_index;
221
222   if (sm->deterministic)
223     return;
224
225   reg = vl_api_client_index_to_registration (mp->client_index);
226   if (!reg)
227     return;
228
229   /* *INDENT-OFF* */
230   vec_foreach (worker_index, sm->workers)
231     send_nat_worker_details(*worker_index, reg, mp->context);
232   /* *INDENT-ON* */
233 }
234
235 static void *
236 vl_api_nat_worker_dump_t_print (vl_api_nat_worker_dump_t * mp, void *handle)
237 {
238   u8 *s;
239
240   s = format (0, "SCRIPT: nat_worker_dump ");
241
242   FINISH;
243 }
244
245 static void
246 vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t *
247                                            mp)
248 {
249   snat_main_t *sm = &snat_main;
250   vl_api_nat_ipfix_enable_disable_reply_t *rmp;
251   int rv = 0;
252
253   rv = snat_ipfix_logging_enable_disable (mp->enable,
254                                           clib_host_to_net_u32
255                                           (mp->domain_id),
256                                           clib_host_to_net_u16
257                                           (mp->src_port));
258
259   REPLY_MACRO (VL_API_NAT_IPFIX_ENABLE_DISABLE_REPLY);
260 }
261
262 static void *
263 vl_api_nat_ipfix_enable_disable_t_print (vl_api_nat_ipfix_enable_disable_t *
264                                          mp, void *handle)
265 {
266   u8 *s;
267
268   s = format (0, "SCRIPT: nat_ipfix_enable_disable ");
269   if (mp->domain_id)
270     s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
271   if (mp->src_port)
272     s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
273   if (!mp->enable)
274     s = format (s, "disable ");
275
276   FINISH;
277 }
278
279 static void
280 vl_api_nat_set_reass_t_handler (vl_api_nat_set_reass_t * mp)
281 {
282   snat_main_t *sm = &snat_main;
283   vl_api_nat_set_reass_reply_t *rmp;
284   int rv = 0;
285
286   rv =
287     nat_reass_set (ntohl (mp->timeout), ntohs (mp->max_reass), mp->max_frag,
288                    mp->drop_frag, mp->is_ip6);
289
290   REPLY_MACRO (VL_API_NAT_SET_REASS_REPLY);
291 }
292
293 static void *
294 vl_api_nat_set_reass_t_print (vl_api_nat_set_reass_t * mp, void *handle)
295 {
296   u8 *s;
297
298   s = format (0, "SCRIPT: nat_set_reass ");
299   s = format (s, "timeout %d max_reass %d max_frag %d drop_frag %d is_ip6 %d",
300               clib_host_to_net_u32 (mp->timeout),
301               clib_host_to_net_u16 (mp->max_reass),
302               mp->max_frag, mp->drop_frag, mp->is_ip6);
303
304   FINISH;
305 }
306
307 static void
308 vl_api_nat_get_reass_t_handler (vl_api_nat_get_reass_t * mp)
309 {
310   snat_main_t *sm = &snat_main;
311   vl_api_nat_get_reass_reply_t *rmp;
312   int rv = 0;
313
314   /* *INDENT-OFF* */
315   REPLY_MACRO2 (VL_API_NAT_GET_REASS_REPLY,
316   ({
317     rmp->ip4_timeout = htonl (nat_reass_get_timeout(0));
318     rmp->ip4_max_reass = htons (nat_reass_get_max_reass(0));
319     rmp->ip4_max_frag = nat_reass_get_max_frag(0);
320     rmp->ip4_drop_frag = nat_reass_is_drop_frag(0);
321     rmp->ip6_timeout = htonl (nat_reass_get_timeout(1));
322     rmp->ip6_max_reass = htons (nat_reass_get_max_reass(1));
323     rmp->ip6_max_frag = nat_reass_get_max_frag(1);
324     rmp->ip6_drop_frag = nat_reass_is_drop_frag(1);
325   }))
326   /* *INDENT-ON* */
327 }
328
329 static void *
330 vl_api_nat_get_reass_t_print (vl_api_nat_get_reass_t * mp, void *handle)
331 {
332   u8 *s;
333
334   s = format (0, "SCRIPT: nat_get_reass");
335
336   FINISH;
337 }
338
339 typedef struct nat_api_walk_ctx_t_
340 {
341   vl_api_registration_t *reg;
342   u32 context;
343 } nat_api_walk_ctx_t;
344
345 static int
346 nat_ip4_reass_walk_api (nat_reass_ip4_t * reass, void *arg)
347 {
348   vl_api_nat_reass_details_t *rmp;
349   snat_main_t *sm = &snat_main;
350   nat_api_walk_ctx_t *ctx = arg;
351
352   rmp = vl_msg_api_alloc (sizeof (*rmp));
353   memset (rmp, 0, sizeof (*rmp));
354   rmp->_vl_msg_id = ntohs (VL_API_NAT_REASS_DETAILS + sm->msg_id_base);
355   rmp->context = ctx->context;
356   clib_memcpy (rmp->src_addr, &(reass->key.src), 4);
357   clib_memcpy (rmp->dst_addr, &(reass->key.dst), 4);
358   rmp->proto = reass->key.proto;
359   rmp->frag_id = ntohl (reass->key.frag_id);
360   rmp->frag_n = reass->frag_n;
361   rmp->is_ip4 = 1;
362
363   vl_api_send_msg (ctx->reg, (u8 *) rmp);
364
365   return 0;
366 }
367
368 static int
369 nat_ip6_reass_walk_api (nat_reass_ip6_t * reass, void *arg)
370 {
371   vl_api_nat_reass_details_t *rmp;
372   snat_main_t *sm = &snat_main;
373   nat_api_walk_ctx_t *ctx = arg;
374
375   rmp = vl_msg_api_alloc (sizeof (*rmp));
376   memset (rmp, 0, sizeof (*rmp));
377   rmp->_vl_msg_id = ntohs (VL_API_NAT_REASS_DETAILS + sm->msg_id_base);
378   rmp->context = ctx->context;
379   clib_memcpy (rmp->src_addr, &(reass->key.src), 16);
380   clib_memcpy (rmp->dst_addr, &(reass->key.dst), 16);
381   rmp->proto = reass->key.proto;
382   rmp->frag_id = ntohl (reass->key.frag_id);
383   rmp->frag_n = reass->frag_n;
384   rmp->is_ip4 = 0;
385
386   vl_api_send_msg (ctx->reg, (u8 *) rmp);
387
388   return 0;
389 }
390
391 static void
392 vl_api_nat_reass_dump_t_handler (vl_api_nat_reass_dump_t * mp)
393 {
394   vl_api_registration_t *reg;
395
396   reg = vl_api_client_index_to_registration (mp->client_index);
397   if (!reg)
398     return;
399
400   nat_api_walk_ctx_t ctx = {
401     .reg = reg,
402     .context = mp->context,
403   };
404
405   nat_ip4_reass_walk (nat_ip4_reass_walk_api, &ctx);
406   nat_ip6_reass_walk (nat_ip6_reass_walk_api, &ctx);
407 }
408
409 static void *
410 vl_api_nat_reass_dump_t_print (vl_api_nat_reass_dump_t * mp, void *handle)
411 {
412   u8 *s;
413
414   s = format (0, "SCRIPT: nat_reass_dump");
415
416   FINISH;
417 }
418
419 static void
420 vl_api_nat_set_timeouts_t_handler (vl_api_nat_set_timeouts_t * mp)
421 {
422   snat_main_t *sm = &snat_main;
423   vl_api_nat_set_timeouts_reply_t *rmp;
424   int rv = 0;
425
426   sm->udp_timeout = ntohl (mp->udp);
427   sm->tcp_established_timeout = ntohl (mp->tcp_established);
428   sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
429   sm->icmp_timeout = ntohl (mp->icmp);
430
431   rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
432   if (rv)
433     goto send_reply;
434   rv = nat64_set_udp_timeout (ntohl (mp->udp));
435   if (rv)
436     goto send_reply;
437   rv =
438     nat64_set_tcp_timeouts (ntohl (mp->tcp_transitory),
439                             ntohl (mp->tcp_established));
440
441 send_reply:
442   REPLY_MACRO (VL_API_NAT_SET_TIMEOUTS_REPLY);
443 }
444
445 static void *
446 vl_api_nat_set_timeouts_t_print (vl_api_nat_set_timeouts_t * mp, void *handle)
447 {
448   u8 *s;
449
450   s = format (0, "SCRIPT: nat_set_timeouts ");
451   s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
452               ntohl (mp->udp),
453               ntohl (mp->tcp_established),
454               ntohl (mp->tcp_transitory), ntohl (mp->icmp));
455
456   FINISH;
457 }
458
459 static void
460 vl_api_nat_get_timeouts_t_handler (vl_api_nat_get_timeouts_t * mp)
461 {
462   snat_main_t *sm = &snat_main;
463   vl_api_nat_get_timeouts_reply_t *rmp;
464   int rv = 0;
465
466   /* *INDENT-OFF* */
467   REPLY_MACRO2 (VL_API_NAT_GET_TIMEOUTS_REPLY,
468   ({
469     rmp->udp = htonl (sm->udp_timeout);
470     rmp->tcp_established = htonl (sm->tcp_established_timeout);
471     rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
472     rmp->icmp = htonl (sm->icmp_timeout);
473   }))
474   /* *INDENT-ON* */
475 }
476
477 static void *
478 vl_api_nat_get_timeouts_t_print (vl_api_nat_get_timeouts_t * mp, void *handle)
479 {
480   u8 *s;
481
482   s = format (0, "SCRIPT: nat_get_timeouts");
483
484   FINISH;
485 }
486
487 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);
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 = m->addr_only;
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 = m->out2in_only;
1041   if (m->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 (!vec_len (m->locals) &&
1104           ((m->local_port != m->external_port)
1105            || (m->local_addr.as_u32 != m->external_addr.as_u32)))
1106         send_nat44_static_mapping_details (m, reg, mp->context);
1107   }));
1108   /* *INDENT-ON* */
1109
1110   for (j = 0; j < vec_len (sm->to_resolve); j++)
1111     {
1112       rp = sm->to_resolve + j;
1113       if (rp->l_addr.as_u32 != 0)
1114         send_nat44_static_map_resolve_details (rp, reg, mp->context);
1115     }
1116 }
1117
1118 static void *
1119 vl_api_nat44_static_mapping_dump_t_print (vl_api_nat44_static_mapping_dump_t *
1120                                           mp, void *handle)
1121 {
1122   u8 *s;
1123
1124   s = format (0, "SCRIPT: nat44_static_mapping_dump ");
1125
1126   FINISH;
1127 }
1128
1129 static void
1130   vl_api_nat44_add_del_identity_mapping_t_handler
1131   (vl_api_nat44_add_del_identity_mapping_t * mp)
1132 {
1133   snat_main_t *sm = &snat_main;
1134   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
1135   ip4_address_t addr;
1136   u16 port = 0;
1137   u32 vrf_id, sw_if_index;
1138   int rv = 0;
1139   snat_protocol_t proto = ~0;
1140   u8 *tag = 0;
1141
1142   if (sm->deterministic)
1143     {
1144       rv = VNET_API_ERROR_UNSUPPORTED;
1145       goto send_reply;
1146     }
1147
1148   if (mp->addr_only == 0)
1149     {
1150       port = clib_net_to_host_u16 (mp->port);
1151       proto = ip_proto_to_snat_proto (mp->protocol);
1152     }
1153   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1154   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1155   if (sw_if_index != ~0)
1156     addr.as_u32 = 0;
1157   else
1158     memcpy (&addr.as_u8, mp->ip_address, 4);
1159   mp->tag[sizeof (mp->tag) - 1] = 0;
1160   tag = format (0, "%s", mp->tag);
1161   vec_terminate_c_string (tag);
1162
1163   rv =
1164     snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only,
1165                              sw_if_index, proto, mp->is_add, 0, 0, tag);
1166
1167   vec_free (tag);
1168
1169 send_reply:
1170   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
1171 }
1172
1173 static void *vl_api_nat44_add_del_identity_mapping_t_print
1174   (vl_api_nat44_add_del_identity_mapping_t * mp, void *handle)
1175 {
1176   u8 *s;
1177
1178   s = format (0, "SCRIPT: nat44_add_del_identity_mapping ");
1179   if (mp->sw_if_index != ~0)
1180     s = format (s, "sw_if_index %d", clib_net_to_host_u32 (mp->sw_if_index));
1181   else
1182     s = format (s, "addr %U", format_ip4_address, mp->ip_address);
1183
1184   if (mp->addr_only == 0)
1185     s =
1186       format (s, "protocol %d port %d", mp->protocol,
1187               clib_net_to_host_u16 (mp->port));
1188
1189   if (mp->vrf_id != ~0)
1190     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
1191
1192   FINISH;
1193 }
1194
1195 static void
1196 send_nat44_identity_mapping_details (snat_static_mapping_t * m,
1197                                      vl_api_registration_t * reg, u32 context)
1198 {
1199   vl_api_nat44_identity_mapping_details_t *rmp;
1200   snat_main_t *sm = &snat_main;
1201
1202   rmp = vl_msg_api_alloc (sizeof (*rmp));
1203   memset (rmp, 0, sizeof (*rmp));
1204   rmp->_vl_msg_id =
1205     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1206   rmp->addr_only = m->addr_only;
1207   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
1208   rmp->port = htons (m->local_port);
1209   rmp->sw_if_index = ~0;
1210   rmp->vrf_id = htonl (m->vrf_id);
1211   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1212   rmp->context = context;
1213   if (m->tag)
1214     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1215
1216   vl_api_send_msg (reg, (u8 *) rmp);
1217 }
1218
1219 static void
1220 send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
1221                                          vl_api_registration_t * reg,
1222                                          u32 context)
1223 {
1224   vl_api_nat44_identity_mapping_details_t *rmp;
1225   snat_main_t *sm = &snat_main;
1226
1227   rmp = vl_msg_api_alloc (sizeof (*rmp));
1228   memset (rmp, 0, sizeof (*rmp));
1229   rmp->_vl_msg_id =
1230     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
1231   rmp->addr_only = m->addr_only;
1232   rmp->port = htons (m->l_port);
1233   rmp->sw_if_index = htonl (m->sw_if_index);
1234   rmp->vrf_id = htonl (m->vrf_id);
1235   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1236   rmp->context = context;
1237   if (m->tag)
1238     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1239
1240   vl_api_send_msg (reg, (u8 *) rmp);
1241 }
1242
1243 static void
1244   vl_api_nat44_identity_mapping_dump_t_handler
1245   (vl_api_nat44_identity_mapping_dump_t * mp)
1246 {
1247   vl_api_registration_t *reg;
1248   snat_main_t *sm = &snat_main;
1249   snat_static_mapping_t *m;
1250   snat_static_map_resolve_t *rp;
1251   int j;
1252
1253   if (sm->deterministic)
1254     return;
1255
1256   reg = vl_api_client_index_to_registration (mp->client_index);
1257   if (!reg)
1258     return;
1259
1260   /* *INDENT-OFF* */
1261   pool_foreach (m, sm->static_mappings,
1262   ({
1263       if (!vec_len (m->locals) && (m->local_port == m->external_port)
1264           && (m->local_addr.as_u32 == m->external_addr.as_u32))
1265         send_nat44_identity_mapping_details (m, reg, mp->context);
1266   }));
1267   /* *INDENT-ON* */
1268
1269   for (j = 0; j < vec_len (sm->to_resolve); j++)
1270     {
1271       rp = sm->to_resolve + j;
1272       if (rp->l_addr.as_u32 == 0)
1273         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
1274     }
1275 }
1276
1277 static void *vl_api_nat44_identity_mapping_dump_t_print
1278   (vl_api_nat44_identity_mapping_dump_t * mp, void *handle)
1279 {
1280   u8 *s;
1281
1282   s = format (0, "SCRIPT: nat44_identity_mapping_dump ");
1283
1284   FINISH;
1285 }
1286
1287 static void
1288   vl_api_nat44_add_del_interface_addr_t_handler
1289   (vl_api_nat44_add_del_interface_addr_t * mp)
1290 {
1291   snat_main_t *sm = &snat_main;
1292   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1293   u8 is_del = mp->is_add == 0;
1294   u32 sw_if_index = ntohl (mp->sw_if_index);
1295   int rv = 0;
1296
1297   if (sm->deterministic)
1298     {
1299       rv = VNET_API_ERROR_UNSUPPORTED;
1300       goto send_reply;
1301     }
1302
1303   VALIDATE_SW_IF_INDEX (mp);
1304
1305   rv = snat_add_interface_address (sm, sw_if_index, is_del, mp->twice_nat);
1306
1307   BAD_SW_IF_INDEX_LABEL;
1308 send_reply:
1309   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1310 }
1311
1312 static void *vl_api_nat44_add_del_interface_addr_t_print
1313   (vl_api_nat44_add_del_interface_addr_t * mp, void *handle)
1314 {
1315   u8 *s;
1316
1317   s = format (0, "SCRIPT: nat44_add_del_interface_addr ");
1318   s = format (s, "sw_if_index %d twice_nat %d %s",
1319               clib_host_to_net_u32 (mp->sw_if_index),
1320               mp->twice_nat, mp->is_add ? "" : "del");
1321
1322   FINISH;
1323 }
1324
1325 static void
1326 send_nat44_interface_addr_details (u32 sw_if_index,
1327                                    vl_api_registration_t * reg, u32 context,
1328                                    u8 twice_nat)
1329 {
1330   vl_api_nat44_interface_addr_details_t *rmp;
1331   snat_main_t *sm = &snat_main;
1332
1333   rmp = vl_msg_api_alloc (sizeof (*rmp));
1334   memset (rmp, 0, sizeof (*rmp));
1335   rmp->_vl_msg_id =
1336     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1337   rmp->sw_if_index = ntohl (sw_if_index);
1338   rmp->twice_nat = twice_nat;
1339   rmp->context = context;
1340
1341   vl_api_send_msg (reg, (u8 *) rmp);
1342 }
1343
1344 static void
1345 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1346                                             * mp)
1347 {
1348   vl_api_registration_t *reg;
1349   snat_main_t *sm = &snat_main;
1350   u32 *i;
1351
1352   if (sm->deterministic)
1353     return;
1354
1355   reg = vl_api_client_index_to_registration (mp->client_index);
1356   if (!reg)
1357     return;
1358
1359   /* *INDENT-OFF* */
1360   vec_foreach (i, sm->auto_add_sw_if_indices)
1361     send_nat44_interface_addr_details(*i, reg, mp->context, 0);
1362   vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
1363     send_nat44_interface_addr_details(*i, reg, mp->context, 1);
1364   /* *INDENT-ON* */
1365 }
1366
1367 static void *
1368 vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t *
1369                                           mp, void *handle)
1370 {
1371   u8 *s;
1372
1373   s = format (0, "SCRIPT: nat44_interface_addr_dump ");
1374
1375   FINISH;
1376 }
1377
1378 static void
1379 send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg,
1380                          u32 context)
1381 {
1382   vl_api_nat44_user_details_t *rmp;
1383   snat_main_t *sm = &snat_main;
1384   ip4_main_t *im = &ip4_main;
1385
1386   rmp = vl_msg_api_alloc (sizeof (*rmp));
1387   memset (rmp, 0, sizeof (*rmp));
1388   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1389
1390   if (!pool_is_free_index (im->fibs, u->fib_index))
1391     {
1392       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1393       rmp->vrf_id = ntohl (fib->ft_table_id);
1394     }
1395
1396   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1397   rmp->nsessions = ntohl (u->nsessions);
1398   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1399   rmp->context = context;
1400
1401   vl_api_send_msg (reg, (u8 *) rmp);
1402 }
1403
1404 static void
1405 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1406 {
1407   vl_api_registration_t *reg;
1408   snat_main_t *sm = &snat_main;
1409   snat_main_per_thread_data_t *tsm;
1410   snat_user_t *u;
1411
1412   if (sm->deterministic)
1413     return;
1414
1415   reg = vl_api_client_index_to_registration (mp->client_index);
1416   if (!reg)
1417     return;
1418
1419   /* *INDENT-OFF* */
1420   vec_foreach (tsm, sm->per_thread_data)
1421     {
1422       pool_foreach (u, tsm->users,
1423       ({
1424         send_nat44_user_details (u, reg, mp->context);
1425       }));
1426     }
1427   /* *INDENT-ON* */
1428 }
1429
1430 static void *
1431 vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle)
1432 {
1433   u8 *s;
1434
1435   s = format (0, "SCRIPT: nat44_user_dump ");
1436
1437   FINISH;
1438 }
1439
1440 static void
1441 send_nat44_user_session_details (snat_session_t * s,
1442                                  vl_api_registration_t * reg, u32 context)
1443 {
1444   vl_api_nat44_user_session_details_t *rmp;
1445   snat_main_t *sm = &snat_main;
1446
1447   rmp = vl_msg_api_alloc (sizeof (*rmp));
1448   memset (rmp, 0, sizeof (*rmp));
1449   rmp->_vl_msg_id =
1450     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1451   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1452   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1453   rmp->is_static = snat_is_session_static (s) ? 1 : 0;
1454   rmp->is_twicenat = is_twice_nat_session (s) ? 1 : 0;
1455   rmp->ext_host_valid = is_ed_session (s)
1456     || is_fwd_bypass_session (s) ? 1 : 0;
1457   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1458   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1459   rmp->total_pkts = ntohl (s->total_pkts);
1460   rmp->context = context;
1461   if (snat_is_unk_proto_session (s))
1462     {
1463       rmp->outside_port = 0;
1464       rmp->inside_port = 0;
1465       rmp->protocol = ntohs (s->in2out.port);
1466     }
1467   else
1468     {
1469       rmp->outside_port = s->out2in.port;
1470       rmp->inside_port = s->in2out.port;
1471       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
1472     }
1473   if (is_ed_session (s) || is_fwd_bypass_session (s))
1474     {
1475       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1476       rmp->ext_host_port = s->ext_host_port;
1477       if (is_twice_nat_session (s))
1478         {
1479           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1480           rmp->ext_host_nat_port = s->ext_host_nat_port;
1481         }
1482     }
1483
1484   vl_api_send_msg (reg, (u8 *) rmp);
1485 }
1486
1487 static void
1488 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1489                                           mp)
1490 {
1491   vl_api_registration_t *reg;
1492   snat_main_t *sm = &snat_main;
1493   snat_main_per_thread_data_t *tsm;
1494   snat_session_t *s;
1495   clib_bihash_kv_8_8_t key, value;
1496   snat_user_key_t ukey;
1497   snat_user_t *u;
1498   u32 session_index, head_index, elt_index;
1499   dlist_elt_t *head, *elt;
1500   ip4_header_t ip;
1501
1502   if (sm->deterministic)
1503     return;
1504
1505   reg = vl_api_client_index_to_registration (mp->client_index);
1506   if (!reg)
1507     return;
1508
1509   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1510   ip.src_address.as_u32 = ukey.addr.as_u32;
1511   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1512   key.key = ukey.as_u64;
1513   if (sm->num_workers > 1)
1514     tsm =
1515       vec_elt_at_index (sm->per_thread_data,
1516                         sm->worker_in2out_cb (&ip, ukey.fib_index));
1517   else
1518     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1519   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1520     return;
1521   u = pool_elt_at_index (tsm->users, value.value);
1522   if (!u->nsessions && !u->nstaticsessions)
1523     return;
1524
1525   head_index = u->sessions_per_user_list_head_index;
1526   head = pool_elt_at_index (tsm->list_pool, head_index);
1527   elt_index = head->next;
1528   elt = pool_elt_at_index (tsm->list_pool, elt_index);
1529   session_index = elt->value;
1530   while (session_index != ~0)
1531     {
1532       s = pool_elt_at_index (tsm->sessions, session_index);
1533
1534       send_nat44_user_session_details (s, reg, mp->context);
1535
1536       elt_index = elt->next;
1537       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1538       session_index = elt->value;
1539     }
1540 }
1541
1542 static void *
1543 vl_api_nat44_user_session_dump_t_print (vl_api_nat44_user_session_dump_t * mp,
1544                                         void *handle)
1545 {
1546   u8 *s;
1547
1548   s = format (0, "SCRIPT: nat44_user_session_dump ");
1549   s = format (s, "ip_address %U vrf_id %d\n",
1550               format_ip4_address, mp->ip_address,
1551               clib_net_to_host_u32 (mp->vrf_id));
1552
1553   FINISH;
1554 }
1555
1556 static nat44_lb_addr_port_t *
1557 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1558                              u8 addr_port_pair_num)
1559 {
1560   u8 i;
1561   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1562   vl_api_nat44_lb_addr_port_t *ap;
1563
1564   for (i = 0; i < addr_port_pair_num; i++)
1565     {
1566       ap = &addr_port_pairs[i];
1567       memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1568       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1569       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
1570       lb_addr_port.probability = ap->probability;
1571       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1572       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1573     }
1574
1575   return lb_addr_port_pairs;
1576 }
1577
1578 static void
1579   vl_api_nat44_add_del_lb_static_mapping_t_handler
1580   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1581 {
1582   snat_main_t *sm = &snat_main;
1583   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1584   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1585   int rv = 0;
1586   nat44_lb_addr_port_t *locals = 0;
1587   ip4_address_t e_addr;
1588   snat_protocol_t proto;
1589   u8 *tag = 0;
1590
1591   if (!sm->endpoint_dependent)
1592     {
1593       rv = VNET_API_ERROR_UNSUPPORTED;
1594       goto send_reply;
1595     }
1596
1597   locals = unformat_nat44_lb_addr_port (mp->locals, mp->local_num);
1598   clib_memcpy (&e_addr, mp->external_addr, 4);
1599   proto = ip_proto_to_snat_proto (mp->protocol);
1600   if (mp->twice_nat)
1601     twice_nat = TWICE_NAT;
1602   else if (mp->self_twice_nat)
1603     twice_nat = TWICE_NAT_SELF;
1604   mp->tag[sizeof (mp->tag) - 1] = 0;
1605   tag = format (0, "%s", mp->tag);
1606   vec_terminate_c_string (tag);
1607
1608   rv =
1609     nat44_add_del_lb_static_mapping (e_addr,
1610                                      clib_net_to_host_u16 (mp->external_port),
1611                                      proto, locals, mp->is_add, twice_nat,
1612                                      mp->out2in_only, tag,
1613                                      clib_net_to_host_u32 (mp->affinity));
1614
1615   vec_free (locals);
1616   vec_free (tag);
1617
1618 send_reply:
1619   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1620 }
1621
1622 static void *vl_api_nat44_add_del_lb_static_mapping_t_print
1623   (vl_api_nat44_add_del_lb_static_mapping_t * mp, void *handle)
1624 {
1625   u8 *s;
1626
1627   s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping ");
1628   s = format (s, "is_add %d twice_nat %d out2in_only %d ",
1629               mp->is_add, mp->twice_nat, mp->out2in_only);
1630
1631   FINISH;
1632 }
1633
1634 static void
1635 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1636                                       vl_api_registration_t * reg,
1637                                       u32 context)
1638 {
1639   vl_api_nat44_lb_static_mapping_details_t *rmp;
1640   snat_main_t *sm = &snat_main;
1641   nat44_lb_addr_port_t *ap;
1642   vl_api_nat44_lb_addr_port_t *locals;
1643
1644   rmp =
1645     vl_msg_api_alloc (sizeof (*rmp) +
1646                       (vec_len (m->locals) * sizeof (nat44_lb_addr_port_t)));
1647   memset (rmp, 0, sizeof (*rmp));
1648   rmp->_vl_msg_id =
1649     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1650
1651   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1652   rmp->external_port = ntohs (m->external_port);
1653   rmp->protocol = snat_proto_to_ip_proto (m->proto);
1654   rmp->context = context;
1655   if (m->twice_nat == TWICE_NAT)
1656     rmp->twice_nat = 1;
1657   else if (m->twice_nat == TWICE_NAT_SELF)
1658     rmp->self_twice_nat = 1;
1659   rmp->out2in_only = m->out2in_only;
1660   if (m->tag)
1661     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1662
1663   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1664   vec_foreach (ap, m->locals)
1665   {
1666     clib_memcpy (locals->addr, &(ap->addr), 4);
1667     locals->port = htons (ap->port);
1668     locals->probability = ap->probability;
1669     locals->vrf_id = ntohl (ap->vrf_id);
1670     locals++;
1671     rmp->local_num++;
1672   }
1673
1674   vl_api_send_msg (reg, (u8 *) rmp);
1675 }
1676
1677 static void
1678   vl_api_nat44_lb_static_mapping_dump_t_handler
1679   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1680 {
1681   vl_api_registration_t *reg;
1682   snat_main_t *sm = &snat_main;
1683   snat_static_mapping_t *m;
1684
1685   if (!sm->endpoint_dependent)
1686     return;
1687
1688   reg = vl_api_client_index_to_registration (mp->client_index);
1689   if (!reg)
1690     return;
1691
1692   /* *INDENT-OFF* */
1693   pool_foreach (m, sm->static_mappings,
1694   ({
1695       if (vec_len(m->locals))
1696         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1697   }));
1698   /* *INDENT-ON* */
1699 }
1700
1701 static void *vl_api_nat44_lb_static_mapping_dump_t_print
1702   (vl_api_nat44_lb_static_mapping_dump_t * mp, void *handle)
1703 {
1704   u8 *s;
1705
1706   s = format (0, "SCRIPT: nat44_lb_static_mapping_dump ");
1707
1708   FINISH;
1709 }
1710
1711 static void
1712 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1713 {
1714   snat_main_t *sm = &snat_main;
1715   vl_api_nat44_del_session_reply_t *rmp;
1716   ip4_address_t addr, eh_addr;
1717   u16 port, eh_port;
1718   u32 vrf_id;
1719   int rv = 0;
1720   snat_protocol_t proto;
1721
1722   if (sm->deterministic)
1723     {
1724       rv = VNET_API_ERROR_UNSUPPORTED;
1725       goto send_reply;
1726     }
1727
1728   memcpy (&addr.as_u8, mp->address, 4);
1729   port = clib_net_to_host_u16 (mp->port);
1730   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1731   proto = ip_proto_to_snat_proto (mp->protocol);
1732   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1733   eh_port = clib_net_to_host_u16 (mp->ext_host_port);
1734
1735   if (mp->ext_host_valid)
1736     rv =
1737       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1738                             vrf_id, mp->is_in);
1739   else
1740     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
1741
1742 send_reply:
1743   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1744 }
1745
1746 static void *
1747 vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
1748                                   void *handle)
1749 {
1750   u8 *s;
1751
1752   s = format (0, "SCRIPT: nat44_add_del_static_mapping ");
1753   s = format (s, "addr %U port %d protocol %d vrf_id %d is_in %d",
1754               format_ip4_address, mp->address,
1755               clib_net_to_host_u16 (mp->port),
1756               mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
1757   if (mp->ext_host_valid)
1758     s = format (s, "ext_host_address %U ext_host_port %d",
1759                 format_ip4_address, mp->ext_host_address,
1760                 clib_net_to_host_u16 (mp->ext_host_port));
1761
1762   FINISH;
1763 }
1764
1765 static void
1766   vl_api_nat44_forwarding_enable_disable_t_handler
1767   (vl_api_nat44_forwarding_enable_disable_t * mp)
1768 {
1769   snat_main_t *sm = &snat_main;
1770   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1771   int rv = 0;
1772   u32 *ses_to_be_removed = 0, *ses_index;
1773   snat_main_per_thread_data_t *tsm;
1774   snat_session_t *s;
1775
1776   sm->forwarding_enabled = mp->enable != 0;
1777
1778   if (mp->enable == 0)
1779     {
1780       /* *INDENT-OFF* */
1781       vec_foreach (tsm, sm->per_thread_data)
1782       {
1783         pool_foreach (s, tsm->sessions,
1784         ({
1785           if (is_fwd_bypass_session(s))
1786             {
1787               vec_add1 (ses_to_be_removed, s - tsm->sessions);
1788             }
1789         }));
1790         vec_foreach (ses_index, ses_to_be_removed)
1791         {
1792           s = pool_elt_at_index(tsm->sessions, ses_index[0]);
1793           nat_free_session_data (sm, s, tsm - sm->per_thread_data);
1794           nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1795         }
1796         vec_free (ses_to_be_removed);
1797       }
1798       /* *INDENT-ON* */
1799     }
1800
1801   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1802 }
1803
1804 static void *vl_api_nat44_forwarding_enable_disable_t_print
1805   (vl_api_nat44_forwarding_enable_disable_t * mp, void *handle)
1806 {
1807   u8 *s;
1808
1809   s = format (0, "SCRIPT: nat44_forwarding_enable_disable ");
1810   s = format (s, "enable %d", mp->enable != 0);
1811
1812   FINISH;
1813 }
1814
1815 static void
1816   vl_api_nat44_forwarding_is_enabled_t_handler
1817   (vl_api_nat44_forwarding_is_enabled_t * mp)
1818 {
1819   vl_api_registration_t *reg;
1820   snat_main_t *sm = &snat_main;
1821   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1822
1823   reg = vl_api_client_index_to_registration (mp->client_index);
1824   if (!reg)
1825     return;
1826
1827   rmp = vl_msg_api_alloc (sizeof (*rmp));
1828   memset (rmp, 0, sizeof (*rmp));
1829   rmp->_vl_msg_id =
1830     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1831   rmp->context = mp->context;
1832
1833   rmp->enabled = sm->forwarding_enabled;
1834
1835   vl_api_send_msg (reg, (u8 *) rmp);
1836 }
1837
1838 static void *vl_api_nat44_forwarding_is_enabled_t_print
1839   (vl_api_nat44_forwarding_is_enabled_t * mp, void *handle)
1840 {
1841   u8 *s;
1842
1843   s = format (0, "SCRIPT: nat44_forwarding_is_enabled ");
1844
1845   FINISH;
1846 }
1847
1848 /*******************************/
1849 /*** Deterministic NAT (CGN) ***/
1850 /*******************************/
1851
1852 static void
1853 vl_api_nat_det_add_del_map_t_handler (vl_api_nat_det_add_del_map_t * mp)
1854 {
1855   snat_main_t *sm = &snat_main;
1856   vl_api_nat_det_add_del_map_reply_t *rmp;
1857   int rv = 0;
1858   ip4_address_t in_addr, out_addr;
1859
1860   if (!sm->deterministic)
1861     {
1862       rv = VNET_API_ERROR_UNSUPPORTED;
1863       goto send_reply;
1864     }
1865
1866   if (!mp->is_nat44)
1867     {
1868       rv = VNET_API_ERROR_UNIMPLEMENTED;
1869       goto send_reply;
1870     }
1871
1872   clib_memcpy (&in_addr, mp->in_addr, 4);
1873   clib_memcpy (&out_addr, mp->out_addr, 4);
1874   rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
1875                          mp->out_plen, mp->is_add);
1876
1877 send_reply:
1878   REPLY_MACRO (VL_API_NAT_DET_ADD_DEL_MAP_REPLY);
1879 }
1880
1881 static void *
1882 vl_api_nat_det_add_del_map_t_print (vl_api_nat_det_add_del_map_t * mp,
1883                                     void *handle)
1884 {
1885   u8 *s;
1886
1887   s = format (0, "SCRIPT: nat_det_add_del_map ");
1888   s = format (s, "inside address %U/%d outside address %U/%d\n",
1889               format_ip4_address, mp->in_addr, mp->in_plen,
1890               format_ip4_address, mp->out_addr, mp->out_plen);
1891
1892   FINISH;
1893 }
1894
1895 static void
1896 vl_api_nat_det_forward_t_handler (vl_api_nat_det_forward_t * mp)
1897 {
1898   snat_main_t *sm = &snat_main;
1899   vl_api_nat_det_forward_reply_t *rmp;
1900   int rv = 0;
1901   u16 lo_port = 0, hi_port = 0;
1902   snat_det_map_t *dm;
1903   ip4_address_t in_addr, out_addr;
1904
1905   if (!sm->deterministic)
1906     {
1907       rv = VNET_API_ERROR_UNSUPPORTED;
1908       REPLY_MACRO (VL_API_NAT_DET_FORWARD_REPLY);
1909       return;
1910     }
1911
1912   if (!mp->is_nat44)
1913     {
1914       out_addr.as_u32 = 0;
1915       rv = VNET_API_ERROR_UNIMPLEMENTED;
1916       goto send_reply;
1917     }
1918
1919   out_addr.as_u32 = 0;
1920   clib_memcpy (&in_addr, mp->in_addr, 4);
1921   dm = snat_det_map_by_user (sm, &in_addr);
1922   if (!dm)
1923     {
1924       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1925       goto send_reply;
1926     }
1927
1928   snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1929   hi_port = lo_port + dm->ports_per_host - 1;
1930
1931 send_reply:
1932   /* *INDENT-OFF* */
1933   REPLY_MACRO2 (VL_API_NAT_DET_FORWARD_REPLY,
1934   ({
1935     rmp->out_port_lo = ntohs (lo_port);
1936     rmp->out_port_hi = ntohs (hi_port);
1937     clib_memcpy (rmp->out_addr, &out_addr, 4);
1938   }))
1939   /* *INDENT-ON* */
1940 }
1941
1942 static void *
1943 vl_api_nat_det_forward_t_print (vl_api_nat_det_forward_t * mp, void *handle)
1944 {
1945   u8 *s;
1946
1947   s = format (0, "SCRIPT: nat_det_forward");
1948   s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
1949
1950   FINISH;
1951 }
1952
1953 static void
1954 vl_api_nat_det_reverse_t_handler (vl_api_nat_det_reverse_t * mp)
1955 {
1956   snat_main_t *sm = &snat_main;
1957   vl_api_nat_det_reverse_reply_t *rmp;
1958   int rv = 0;
1959   ip4_address_t out_addr, in_addr;
1960   snat_det_map_t *dm;
1961
1962   if (!sm->deterministic)
1963     {
1964       rv = VNET_API_ERROR_UNSUPPORTED;
1965       REPLY_MACRO (VL_API_NAT_DET_REVERSE_REPLY);
1966       return;
1967     }
1968
1969   in_addr.as_u32 = 0;
1970   clib_memcpy (&out_addr, mp->out_addr, 4);
1971   dm = snat_det_map_by_out (sm, &out_addr);
1972   if (!dm)
1973     {
1974       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1975       goto send_reply;
1976     }
1977
1978   snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
1979
1980 send_reply:
1981   /* *INDENT-OFF* */
1982   REPLY_MACRO2 (VL_API_NAT_DET_REVERSE_REPLY,
1983   ({
1984     rmp->is_nat44 = 1;
1985     memset (rmp->in_addr, 0, 16);
1986     clib_memcpy (rmp->in_addr, &in_addr, 4);
1987   }))
1988   /* *INDENT-ON* */
1989 }
1990
1991 static void *
1992 vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle)
1993 {
1994   u8 *s;
1995
1996   s = format (0, "SCRIPT: nat_det_reverse");
1997   s = format (s, "outside ip address %U outside port %d",
1998               format_ip4_address, mp->out_addr, ntohs (mp->out_port));
1999
2000   FINISH;
2001 }
2002
2003 static void
2004 sent_nat_det_map_details (snat_det_map_t * m, vl_api_registration_t * reg,
2005                           u32 context)
2006 {
2007   vl_api_nat_det_map_details_t *rmp;
2008   snat_main_t *sm = &snat_main;
2009
2010   rmp = vl_msg_api_alloc (sizeof (*rmp));
2011   memset (rmp, 0, sizeof (*rmp));
2012   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_MAP_DETAILS + sm->msg_id_base);
2013   rmp->is_nat44 = 1;
2014   clib_memcpy (rmp->in_addr, &m->in_addr, 4);
2015   rmp->in_plen = m->in_plen;
2016   clib_memcpy (rmp->out_addr, &m->out_addr, 4);
2017   rmp->out_plen = m->out_plen;
2018   rmp->sharing_ratio = htonl (m->sharing_ratio);
2019   rmp->ports_per_host = htons (m->ports_per_host);
2020   rmp->ses_num = htonl (m->ses_num);
2021   rmp->context = context;
2022
2023   vl_api_send_msg (reg, (u8 *) rmp);
2024 }
2025
2026 static void
2027 vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp)
2028 {
2029   vl_api_registration_t *reg;
2030   snat_main_t *sm = &snat_main;
2031   snat_det_map_t *m;
2032
2033   if (!sm->deterministic)
2034     return;
2035
2036   reg = vl_api_client_index_to_registration (mp->client_index);
2037   if (!reg)
2038     return;
2039
2040   /* *INDENT-OFF* */
2041   vec_foreach(m, sm->det_maps)
2042     sent_nat_det_map_details(m, reg, mp->context);
2043   /* *INDENT-ON* */
2044 }
2045
2046 static void *
2047 vl_api_nat_det_map_dump_t_print (vl_api_nat_det_map_dump_t * mp, void *handle)
2048 {
2049   u8 *s;
2050
2051   s = format (0, "SCRIPT: nat_det_map_dump ");
2052
2053   FINISH;
2054 }
2055
2056 static void
2057 vl_api_nat_det_close_session_out_t_handler (vl_api_nat_det_close_session_out_t
2058                                             * mp)
2059 {
2060   snat_main_t *sm = &snat_main;
2061   vl_api_nat_det_close_session_out_reply_t *rmp;
2062   ip4_address_t out_addr, ext_addr, in_addr;
2063   snat_det_out_key_t key;
2064   snat_det_map_t *dm;
2065   snat_det_session_t *ses;
2066   int rv = 0;
2067
2068   if (!sm->deterministic)
2069     {
2070       rv = VNET_API_ERROR_UNSUPPORTED;
2071       goto send_reply;
2072     }
2073
2074   clib_memcpy (&out_addr, mp->out_addr, 4);
2075   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2076
2077   dm = snat_det_map_by_out (sm, &out_addr);
2078   if (!dm)
2079     {
2080       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2081       goto send_reply;
2082     }
2083   snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
2084   key.ext_host_addr = ext_addr;
2085   key.ext_host_port = mp->ext_port;
2086   key.out_port = mp->out_port;
2087   ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
2088   if (!ses)
2089     {
2090       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2091       goto send_reply;
2092     }
2093   snat_det_ses_close (dm, ses);
2094
2095 send_reply:
2096   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2097 }
2098
2099 static void *
2100 vl_api_nat_det_close_session_out_t_print (vl_api_nat_det_close_session_out_t *
2101                                           mp, void *handle)
2102 {
2103   u8 *s;
2104
2105   s = format (0, "SCRIPT: nat_det_close_session_out ");
2106   s = format (s, "out_addr %U out_port %d "
2107               "ext_addr %U ext_port %d\n",
2108               format_ip4_address, mp->out_addr, ntohs (mp->out_port),
2109               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2110
2111   FINISH;
2112 }
2113
2114 static void
2115 vl_api_nat_det_close_session_in_t_handler (vl_api_nat_det_close_session_in_t *
2116                                            mp)
2117 {
2118   snat_main_t *sm = &snat_main;
2119   vl_api_nat_det_close_session_in_reply_t *rmp;
2120   ip4_address_t in_addr, ext_addr;
2121   snat_det_out_key_t key;
2122   snat_det_map_t *dm;
2123   snat_det_session_t *ses;
2124   int rv = 0;
2125
2126   if (!sm->deterministic)
2127     {
2128       rv = VNET_API_ERROR_UNSUPPORTED;
2129       goto send_reply;
2130     }
2131
2132   if (!mp->is_nat44)
2133     {
2134       rv = VNET_API_ERROR_UNIMPLEMENTED;
2135       goto send_reply;
2136     }
2137
2138   clib_memcpy (&in_addr, mp->in_addr, 4);
2139   clib_memcpy (&ext_addr, mp->ext_addr, 4);
2140
2141   dm = snat_det_map_by_user (sm, &in_addr);
2142   if (!dm)
2143     {
2144       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2145       goto send_reply;
2146     }
2147   key.ext_host_addr = ext_addr;
2148   key.ext_host_port = mp->ext_port;
2149   ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
2150   if (!ses)
2151     {
2152       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2153       goto send_reply;
2154     }
2155   snat_det_ses_close (dm, ses);
2156
2157 send_reply:
2158   REPLY_MACRO (VL_API_NAT_DET_CLOSE_SESSION_OUT_REPLY);
2159 }
2160
2161 static void *
2162 vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t *
2163                                          mp, void *handle)
2164 {
2165   u8 *s;
2166   s = format (0, "SCRIPT: nat_det_close_session_in ");
2167   s = format (s, "in_addr %U in_port %d ext_addr %U ext_port %d\n",
2168               format_ip4_address, mp->in_addr, ntohs (mp->in_port),
2169               format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
2170
2171   FINISH;
2172 }
2173
2174 static void
2175 send_nat_det_session_details (snat_det_session_t * s,
2176                               vl_api_registration_t * reg, u32 context)
2177 {
2178   vl_api_nat_det_session_details_t *rmp;
2179   snat_main_t *sm = &snat_main;
2180
2181   rmp = vl_msg_api_alloc (sizeof (*rmp));
2182   memset (rmp, 0, sizeof (*rmp));
2183   rmp->_vl_msg_id = ntohs (VL_API_NAT_DET_SESSION_DETAILS + sm->msg_id_base);
2184   rmp->in_port = s->in_port;
2185   clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
2186   rmp->ext_port = s->out.ext_host_port;
2187   rmp->out_port = s->out.out_port;
2188   rmp->state = s->state;
2189   rmp->expire = ntohl (s->expire);
2190   rmp->context = context;
2191
2192   vl_api_send_msg (reg, (u8 *) rmp);
2193 }
2194
2195 static void
2196 vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp)
2197 {
2198   vl_api_registration_t *reg;
2199   snat_main_t *sm = &snat_main;
2200   ip4_address_t user_addr;
2201   snat_det_map_t *dm;
2202   snat_det_session_t *s, empty_ses;
2203   u16 i;
2204
2205   if (!sm->deterministic)
2206     return;
2207
2208   reg = vl_api_client_index_to_registration (mp->client_index);
2209   if (!reg)
2210     return;
2211   if (!mp->is_nat44)
2212     return;
2213
2214   memset (&empty_ses, 0, sizeof (empty_ses));
2215   clib_memcpy (&user_addr, mp->user_addr, 4);
2216   dm = snat_det_map_by_user (sm, &user_addr);
2217   if (!dm)
2218     return;
2219
2220   s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
2221   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
2222     {
2223       if (s->out.as_u64)
2224         send_nat_det_session_details (s, reg, mp->context);
2225       s++;
2226     }
2227 }
2228
2229 static void *
2230 vl_api_nat_det_session_dump_t_print (vl_api_nat_det_session_dump_t * mp,
2231                                      void *handle)
2232 {
2233   u8 *s;
2234
2235   s = format (0, "SCRIPT: nat_det_session_dump ");
2236   s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
2237
2238   FINISH;
2239 }
2240
2241 /*************/
2242 /*** NAT64 ***/
2243 /*************/
2244
2245 static void
2246   vl_api_nat64_add_del_pool_addr_range_t_handler
2247   (vl_api_nat64_add_del_pool_addr_range_t * mp)
2248 {
2249   vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
2250   snat_main_t *sm = &snat_main;
2251   int rv = 0;
2252   ip4_address_t this_addr;
2253   u32 start_host_order, end_host_order;
2254   u32 vrf_id;
2255   int i, count;
2256   u32 *tmp;
2257
2258   tmp = (u32 *) mp->start_addr;
2259   start_host_order = clib_host_to_net_u32 (tmp[0]);
2260   tmp = (u32 *) mp->end_addr;
2261   end_host_order = clib_host_to_net_u32 (tmp[0]);
2262
2263   count = (end_host_order - start_host_order) + 1;
2264
2265   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
2266
2267   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2268
2269   for (i = 0; i < count; i++)
2270     {
2271       if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
2272         goto send_reply;
2273
2274       increment_v4_address (&this_addr);
2275     }
2276
2277 send_reply:
2278   REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2279 }
2280
2281 static void *vl_api_nat64_add_del_pool_addr_range_t_print
2282   (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
2283 {
2284   u8 *s;
2285
2286   s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
2287   s = format (s, "%U - %U vrf_id %u %s\n",
2288               format_ip4_address, mp->start_addr,
2289               format_ip4_address, mp->end_addr,
2290               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2291
2292   FINISH;
2293 }
2294
2295 typedef struct nat64_api_walk_ctx_t_
2296 {
2297   vl_api_registration_t *reg;
2298   u32 context;
2299   nat64_db_t *db;
2300 } nat64_api_walk_ctx_t;
2301
2302 static int
2303 nat64_api_pool_walk (snat_address_t * a, void *arg)
2304 {
2305   vl_api_nat64_pool_addr_details_t *rmp;
2306   snat_main_t *sm = &snat_main;
2307   nat64_api_walk_ctx_t *ctx = arg;
2308
2309   rmp = vl_msg_api_alloc (sizeof (*rmp));
2310   memset (rmp, 0, sizeof (*rmp));
2311   rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
2312   clib_memcpy (rmp->address, &(a->addr), 4);
2313   if (a->fib_index != ~0)
2314     {
2315       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
2316       if (!fib)
2317         return -1;
2318       rmp->vrf_id = ntohl (fib->ft_table_id);
2319     }
2320   else
2321     rmp->vrf_id = ~0;
2322   rmp->context = ctx->context;
2323
2324   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2325
2326   return 0;
2327 }
2328
2329 static void
2330 vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
2331 {
2332   vl_api_registration_t *reg;
2333
2334   reg = vl_api_client_index_to_registration (mp->client_index);
2335   if (!reg)
2336     return;
2337
2338   nat64_api_walk_ctx_t ctx = {
2339     .reg = reg,
2340     .context = mp->context,
2341   };
2342
2343   nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
2344 }
2345
2346 static void *
2347 vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
2348                                      void *handle)
2349 {
2350   u8 *s;
2351
2352   s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
2353
2354   FINISH;
2355 }
2356
2357 static void
2358 vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
2359                                           mp)
2360 {
2361   snat_main_t *sm = &snat_main;
2362   vl_api_nat64_add_del_interface_reply_t *rmp;
2363   int rv = 0;
2364
2365   VALIDATE_SW_IF_INDEX (mp);
2366
2367   rv =
2368     nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
2369                              mp->is_add);
2370
2371   BAD_SW_IF_INDEX_LABEL;
2372
2373   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
2374 }
2375
2376 static void *
2377 vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
2378                                         void *handle)
2379 {
2380   u8 *s;
2381
2382   s = format (0, "SCRIPT: nat64_add_del_interface ");
2383   s = format (s, "sw_if_index %d %s %s",
2384               clib_host_to_net_u32 (mp->sw_if_index),
2385               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2386
2387   FINISH;
2388 }
2389
2390 static int
2391 nat64_api_interface_walk (snat_interface_t * i, void *arg)
2392 {
2393   vl_api_nat64_interface_details_t *rmp;
2394   snat_main_t *sm = &snat_main;
2395   nat64_api_walk_ctx_t *ctx = arg;
2396
2397   rmp = vl_msg_api_alloc (sizeof (*rmp));
2398   memset (rmp, 0, sizeof (*rmp));
2399   rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
2400   rmp->sw_if_index = ntohl (i->sw_if_index);
2401   rmp->is_inside = (nat_interface_is_inside (i)
2402                     && nat_interface_is_outside (i)) ? 2 :
2403     nat_interface_is_inside (i);
2404   rmp->context = ctx->context;
2405
2406   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2407
2408   return 0;
2409 }
2410
2411 static void
2412 vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
2413 {
2414   vl_api_registration_t *reg;
2415
2416   reg = vl_api_client_index_to_registration (mp->client_index);
2417   if (!reg)
2418     return;
2419
2420   nat64_api_walk_ctx_t ctx = {
2421     .reg = reg,
2422     .context = mp->context,
2423   };
2424
2425   nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
2426 }
2427
2428 static void *
2429 vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
2430                                      void *handle)
2431 {
2432   u8 *s;
2433
2434   s = format (0, "SCRIPT: snat_interface_dump ");
2435
2436   FINISH;
2437 }
2438
2439 static void
2440   vl_api_nat64_add_del_static_bib_t_handler
2441   (vl_api_nat64_add_del_static_bib_t * mp)
2442 {
2443   snat_main_t *sm = &snat_main;
2444   vl_api_nat64_add_del_static_bib_reply_t *rmp;
2445   ip6_address_t in_addr;
2446   ip4_address_t out_addr;
2447   int rv = 0;
2448
2449   memcpy (&in_addr.as_u8, mp->i_addr, 16);
2450   memcpy (&out_addr.as_u8, mp->o_addr, 4);
2451
2452   rv =
2453     nat64_add_del_static_bib_entry (&in_addr, &out_addr,
2454                                     clib_net_to_host_u16 (mp->i_port),
2455                                     clib_net_to_host_u16 (mp->o_port),
2456                                     mp->proto,
2457                                     clib_net_to_host_u32 (mp->vrf_id),
2458                                     mp->is_add);
2459
2460   REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
2461 }
2462
2463 static void *vl_api_nat64_add_del_static_bib_t_print
2464   (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
2465 {
2466   u8 *s;
2467
2468   s = format (0, "SCRIPT: nat64_add_del_static_bib ");
2469   s = format (s, "protocol %d i_addr %U o_addr %U ",
2470               mp->proto,
2471               format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
2472
2473   if (mp->vrf_id != ~0)
2474     s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
2475
2476   FINISH;
2477 }
2478
2479 static int
2480 nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
2481 {
2482   vl_api_nat64_bib_details_t *rmp;
2483   snat_main_t *sm = &snat_main;
2484   nat64_api_walk_ctx_t *ctx = arg;
2485   fib_table_t *fib;
2486
2487   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2488   if (!fib)
2489     return -1;
2490
2491   rmp = vl_msg_api_alloc (sizeof (*rmp));
2492   memset (rmp, 0, sizeof (*rmp));
2493   rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
2494   rmp->context = ctx->context;
2495   clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
2496   clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
2497   rmp->i_port = bibe->in_port;
2498   rmp->o_port = bibe->out_port;
2499   rmp->vrf_id = ntohl (fib->ft_table_id);
2500   rmp->proto = bibe->proto;
2501   rmp->is_static = bibe->is_static;
2502   rmp->ses_num = ntohl (bibe->ses_num);
2503
2504   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2505
2506   return 0;
2507 }
2508
2509 static void
2510 vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
2511 {
2512   vl_api_registration_t *reg;
2513   nat64_main_t *nm = &nat64_main;
2514   nat64_db_t *db;
2515
2516   reg = vl_api_client_index_to_registration (mp->client_index);
2517   if (!reg)
2518     return;
2519
2520   nat64_api_walk_ctx_t ctx = {
2521     .reg = reg,
2522     .context = mp->context,
2523   };
2524
2525   /* *INDENT-OFF* */
2526   vec_foreach (db, nm->db)
2527     nat64_db_bib_walk (db, mp->proto, nat64_api_bib_walk, &ctx);
2528   /* *INDENT-ON* */
2529 }
2530
2531 static void *
2532 vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
2533 {
2534   u8 *s;
2535
2536   s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
2537
2538   FINISH;
2539 }
2540
2541 static int
2542 nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
2543 {
2544   vl_api_nat64_st_details_t *rmp;
2545   snat_main_t *sm = &snat_main;
2546   nat64_api_walk_ctx_t *ctx = arg;
2547   nat64_db_bib_entry_t *bibe;
2548   fib_table_t *fib;
2549
2550   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
2551   if (!bibe)
2552     return -1;
2553
2554   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
2555   if (!fib)
2556     return -1;
2557
2558   rmp = vl_msg_api_alloc (sizeof (*rmp));
2559   memset (rmp, 0, sizeof (*rmp));
2560   rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
2561   rmp->context = ctx->context;
2562   clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
2563   clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
2564   rmp->il_port = bibe->in_port;
2565   rmp->ol_port = bibe->out_port;
2566   clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
2567   clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
2568   rmp->il_port = ste->r_port;
2569   rmp->vrf_id = ntohl (fib->ft_table_id);
2570   rmp->proto = ste->proto;
2571
2572   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2573
2574   return 0;
2575 }
2576
2577 static void
2578 vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
2579 {
2580   vl_api_registration_t *reg;
2581   nat64_main_t *nm = &nat64_main;
2582   nat64_db_t *db;
2583
2584   reg = vl_api_client_index_to_registration (mp->client_index);
2585   if (!reg)
2586     return;
2587
2588   nat64_api_walk_ctx_t ctx = {
2589     .reg = reg,
2590     .context = mp->context,
2591   };
2592
2593   /* *INDENT-OFF* */
2594   vec_foreach (db, nm->db)
2595     {
2596       ctx.db = db;
2597       nat64_db_st_walk (db, mp->proto, nat64_api_st_walk, &ctx);
2598     }
2599   /* *INDENT-ON* */
2600 }
2601
2602 static void *
2603 vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
2604 {
2605   u8 *s;
2606
2607   s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
2608
2609   FINISH;
2610 }
2611
2612 static void
2613 vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
2614 {
2615   vl_api_nat64_add_del_prefix_reply_t *rmp;
2616   snat_main_t *sm = &snat_main;
2617   ip6_address_t prefix;
2618   int rv = 0;
2619
2620   memcpy (&prefix.as_u8, mp->prefix, 16);
2621
2622   rv =
2623     nat64_add_del_prefix (&prefix, mp->prefix_len,
2624                           clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
2625   REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
2626 }
2627
2628 static void *
2629 vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
2630                                      void *handle)
2631 {
2632   u8 *s;
2633
2634   s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
2635               format_ip6_address, mp->prefix, mp->prefix_len,
2636               ntohl (mp->vrf_id), mp->is_add ? "" : "del");
2637
2638   FINISH;
2639 }
2640
2641 static int
2642 nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
2643 {
2644   vl_api_nat64_prefix_details_t *rmp;
2645   snat_main_t *sm = &snat_main;
2646   nat64_api_walk_ctx_t *ctx = arg;
2647
2648   rmp = vl_msg_api_alloc (sizeof (*rmp));
2649   memset (rmp, 0, sizeof (*rmp));
2650   rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
2651   clib_memcpy (rmp->prefix, &(p->prefix), 16);
2652   rmp->prefix_len = p->plen;
2653   rmp->vrf_id = ntohl (p->vrf_id);
2654   rmp->context = ctx->context;
2655
2656   vl_api_send_msg (ctx->reg, (u8 *) rmp);
2657
2658   return 0;
2659 }
2660
2661 static void
2662 vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
2663 {
2664   vl_api_registration_t *reg;
2665
2666   reg = vl_api_client_index_to_registration (mp->client_index);
2667   if (!reg)
2668     return;
2669
2670   nat64_api_walk_ctx_t ctx = {
2671     .reg = reg,
2672     .context = mp->context,
2673   };
2674
2675   nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
2676 }
2677
2678 static void *
2679 vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
2680                                   void *handle)
2681 {
2682   u8 *s;
2683
2684   s = format (0, "SCRIPT: nat64_prefix_dump\n");
2685
2686   FINISH;
2687 }
2688
2689 static void
2690   vl_api_nat64_add_del_interface_addr_t_handler
2691   (vl_api_nat64_add_del_interface_addr_t * mp)
2692 {
2693   snat_main_t *sm = &snat_main;
2694   vl_api_nat64_add_del_interface_addr_reply_t *rmp;
2695   u32 sw_if_index = ntohl (mp->sw_if_index);
2696   int rv = 0;
2697
2698   VALIDATE_SW_IF_INDEX (mp);
2699
2700   rv = nat64_add_interface_address (sw_if_index, mp->is_add);
2701
2702   BAD_SW_IF_INDEX_LABEL;
2703
2704   REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
2705 }
2706
2707 static void *vl_api_nat64_add_del_interface_addr_t_print
2708   (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
2709 {
2710   u8 *s;
2711
2712   s = format (0, "SCRIPT: nat64_add_del_interface_addr ");
2713   s = format (s, "sw_if_index %d %s",
2714               clib_host_to_net_u32 (mp->sw_if_index),
2715               mp->is_add ? "" : "del");
2716
2717   FINISH;
2718 }
2719
2720 /***************/
2721 /*** DS-Lite ***/
2722 /***************/
2723
2724 static void
2725 vl_api_dslite_set_aftr_addr_t_handler (vl_api_dslite_set_aftr_addr_t * mp)
2726 {
2727   vl_api_dslite_set_aftr_addr_reply_t *rmp;
2728   snat_main_t *sm = &snat_main;
2729   dslite_main_t *dm = &dslite_main;
2730   int rv = 0;
2731   ip6_address_t ip6_addr;
2732   ip4_address_t ip4_addr;
2733
2734   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2735   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2736
2737   rv = dslite_set_aftr_ip6_addr (dm, &ip6_addr);
2738   if (rv == 0)
2739     rv = dslite_set_aftr_ip4_addr (dm, &ip4_addr);
2740
2741   REPLY_MACRO (VL_API_DSLITE_SET_AFTR_ADDR_REPLY);
2742 }
2743
2744 static void *
2745 vl_api_dslite_set_aftr_addr_t_print (vl_api_dslite_set_aftr_addr_t * mp,
2746                                      void *handle)
2747 {
2748   u8 *s;
2749
2750   s = format (0, "SCRIPT: dslite_set_aftr_addr ");
2751   s = format (s, "ip6_addr %U ip4_addr %U\n",
2752               format_ip6_address, mp->ip6_addr,
2753               format_ip4_address, mp->ip4_addr);
2754
2755   FINISH;
2756 }
2757
2758 static void
2759 vl_api_dslite_get_aftr_addr_t_handler (vl_api_dslite_get_aftr_addr_t * mp)
2760 {
2761   snat_main_t *sm = &snat_main;
2762   vl_api_dslite_get_aftr_addr_reply_t *rmp;
2763   dslite_main_t *dm = &dslite_main;
2764   int rv = 0;
2765
2766   /* *INDENT-OFF* */
2767   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2768   ({
2769     memcpy (rmp->ip4_addr, &dm->aftr_ip4_addr.as_u8, 4);
2770     memcpy (rmp->ip6_addr, &dm->aftr_ip6_addr.as_u8, 16);
2771   }))
2772   /* *INDENT-ON* */
2773 }
2774
2775 static void *
2776 vl_api_dslite_get_aftr_addr_t_print (vl_api_dslite_get_aftr_addr_t * mp,
2777                                      void *handle)
2778 {
2779   u8 *s;
2780
2781   s = format (0, "SCRIPT: dslite_get_aftr_addr");
2782
2783   FINISH;
2784 }
2785
2786 static void
2787 vl_api_dslite_set_b4_addr_t_handler (vl_api_dslite_set_b4_addr_t * mp)
2788 {
2789   vl_api_dslite_set_b4_addr_reply_t *rmp;
2790   snat_main_t *sm = &snat_main;
2791   dslite_main_t *dm = &dslite_main;
2792   int rv = 0;
2793   ip6_address_t ip6_addr;
2794   ip4_address_t ip4_addr;
2795
2796   memcpy (&ip6_addr.as_u8, mp->ip6_addr, 16);
2797   memcpy (&ip4_addr.as_u8, mp->ip4_addr, 4);
2798
2799   rv = dslite_set_b4_ip6_addr (dm, &ip6_addr);
2800   if (rv == 0)
2801     rv = dslite_set_b4_ip4_addr (dm, &ip4_addr);
2802
2803   REPLY_MACRO (VL_API_DSLITE_SET_B4_ADDR_REPLY);
2804 }
2805
2806 static void *
2807 vl_api_dslite_set_b4_addr_t_print (vl_api_dslite_set_b4_addr_t * mp,
2808                                    void *handle)
2809 {
2810   u8 *s;
2811
2812   s = format (0, "SCRIPT: dslite_set_b4_addr ");
2813   s = format (s, "ip6_addr %U ip4_addr %U\n",
2814               format_ip6_address, mp->ip6_addr,
2815               format_ip6_address, mp->ip4_addr);
2816
2817   FINISH;
2818 }
2819
2820 static void
2821 vl_api_dslite_get_b4_addr_t_handler (vl_api_dslite_get_b4_addr_t * mp)
2822 {
2823   snat_main_t *sm = &snat_main;
2824   vl_api_dslite_get_b4_addr_reply_t *rmp;
2825   dslite_main_t *dm = &dslite_main;
2826   int rv = 0;
2827
2828   /* *INDENT-OFF* */
2829   REPLY_MACRO2 (VL_API_DSLITE_GET_AFTR_ADDR_REPLY,
2830   ({
2831     memcpy (rmp->ip4_addr, &dm->b4_ip4_addr.as_u8, 4);
2832     memcpy (rmp->ip6_addr, &dm->b4_ip6_addr.as_u8, 16);
2833   }))
2834   /* *INDENT-ON* */
2835 }
2836
2837 static void *
2838 vl_api_dslite_get_b4_addr_t_print (vl_api_dslite_get_b4_addr_t * mp,
2839                                    void *handle)
2840 {
2841   u8 *s;
2842
2843   s = format (0, "SCRIPT: dslite_get_b4_addr");
2844
2845   FINISH;
2846 }
2847
2848 static void
2849   vl_api_dslite_add_del_pool_addr_range_t_handler
2850   (vl_api_dslite_add_del_pool_addr_range_t * mp)
2851 {
2852   vl_api_dslite_add_del_pool_addr_range_reply_t *rmp;
2853   snat_main_t *sm = &snat_main;
2854   dslite_main_t *dm = &dslite_main;
2855   int rv = 0;
2856   ip4_address_t this_addr;
2857   u32 start_host_order, end_host_order;
2858   int i, count;
2859   u32 *tmp;
2860
2861   tmp = (u32 *) mp->start_addr;
2862   start_host_order = clib_host_to_net_u32 (tmp[0]);
2863   tmp = (u32 *) mp->end_addr;
2864   end_host_order = clib_host_to_net_u32 (tmp[0]);
2865
2866   count = (end_host_order - start_host_order) + 1;
2867   memcpy (&this_addr.as_u8, mp->start_addr, 4);
2868
2869   for (i = 0; i < count; i++)
2870     {
2871       if ((rv = dslite_add_del_pool_addr (dm, &this_addr, mp->is_add)))
2872         goto send_reply;
2873
2874       increment_v4_address (&this_addr);
2875     }
2876
2877 send_reply:
2878   REPLY_MACRO (VL_API_DSLITE_ADD_DEL_POOL_ADDR_RANGE_REPLY);
2879 }
2880
2881 static void
2882 send_dslite_address_details (snat_address_t * ap,
2883                              vl_api_registration_t * reg, u32 context)
2884 {
2885   vl_api_dslite_address_details_t *rmp;
2886   snat_main_t *sm = &snat_main;
2887
2888   rmp = vl_msg_api_alloc (sizeof (*rmp));
2889
2890   memset (rmp, 0, sizeof (*rmp));
2891
2892   rmp->_vl_msg_id = ntohs (VL_API_DSLITE_ADDRESS_DETAILS + sm->msg_id_base);
2893   clib_memcpy (rmp->ip_address, &(ap->addr), 4);
2894   rmp->context = context;
2895
2896   vl_api_send_msg (reg, (u8 *) rmp);
2897 }
2898
2899 static void
2900 vl_api_dslite_address_dump_t_handler (vl_api_dslite_address_dump_t * mp)
2901 {
2902   vl_api_registration_t *reg;
2903   dslite_main_t *dm = &dslite_main;
2904   snat_address_t *ap;
2905
2906   reg = vl_api_client_index_to_registration (mp->client_index);
2907   if (!reg)
2908     return;
2909
2910   /* *INDENT-OFF* */
2911   vec_foreach (ap, dm->addr_pool)
2912     {
2913       send_dslite_address_details (ap, reg, mp->context);
2914     }
2915   /* *INDENT-ON* */
2916 }
2917
2918 static void *
2919 vl_api_dslite_address_dump_t_print (vl_api_dslite_address_dump_t * mp,
2920                                     void *handle)
2921 {
2922   u8 *s;
2923
2924   s = format (0, "SCRIPT: dslite_address_dump ");
2925
2926   FINISH;
2927 }
2928
2929 static void *vl_api_dslite_add_del_pool_addr_range_t_print
2930   (vl_api_dslite_add_del_pool_addr_range_t * mp, void *handle)
2931 {
2932   u8 *s;
2933
2934   s = format (0, "SCRIPT: dslite_add_del_pool_addr_range ");
2935   s = format (s, "%U - %U\n",
2936               format_ip4_address, mp->start_addr,
2937               format_ip4_address, mp->end_addr);
2938
2939   FINISH;
2940 }
2941
2942
2943 /*************/
2944 /*** NAT66 ***/
2945 /*************/
2946
2947 static void
2948 vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
2949                                           mp)
2950 {
2951   snat_main_t *sm = &snat_main;
2952   vl_api_nat66_add_del_interface_reply_t *rmp;
2953   int rv = 0;
2954
2955   VALIDATE_SW_IF_INDEX (mp);
2956
2957   rv =
2958     nat66_interface_add_del (ntohl (mp->sw_if_index), mp->is_inside,
2959                              mp->is_add);
2960
2961   BAD_SW_IF_INDEX_LABEL;
2962
2963   REPLY_MACRO (VL_API_NAT66_ADD_DEL_INTERFACE_REPLY);
2964 }
2965
2966 static void *
2967 vl_api_nat66_add_del_interface_t_print (vl_api_nat66_add_del_interface_t * mp,
2968                                         void *handle)
2969 {
2970   u8 *s;
2971
2972   s = format (0, "SCRIPT: nat66_add_del_interface ");
2973   s = format (s, "sw_if_index %d %s %s",
2974               clib_host_to_net_u32 (mp->sw_if_index),
2975               mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
2976
2977   FINISH;
2978 }
2979
2980 static void
2981   vl_api_nat66_add_del_static_mapping_t_handler
2982   (vl_api_nat66_add_del_static_mapping_t * mp)
2983 {
2984   snat_main_t *sm = &snat_main;
2985   vl_api_nat66_add_del_static_mapping_reply_t *rmp;
2986   ip6_address_t l_addr, e_addr;
2987   int rv = 0;
2988
2989   memcpy (&l_addr.as_u8, mp->local_ip_address, 16);
2990   memcpy (&e_addr.as_u8, mp->external_ip_address, 16);
2991
2992   rv =
2993     nat66_static_mapping_add_del (&l_addr, &e_addr,
2994                                   clib_net_to_host_u32 (mp->vrf_id),
2995                                   mp->is_add);
2996
2997   REPLY_MACRO (VL_API_NAT66_ADD_DEL_STATIC_MAPPING_REPLY);
2998 }
2999
3000 static void *vl_api_nat66_add_del_static_mapping_t_print
3001   (vl_api_nat66_add_del_static_mapping_t * mp, void *handle)
3002 {
3003   u8 *s;
3004
3005   s = format (0, "SCRIPT: nat66_add_del_static_mapping ");
3006   s = format (s, "local_ip_address %U external_ip_address %U vrf_id %d %s",
3007               format_ip6_address, mp->local_ip_address,
3008               format_ip6_address, mp->external_ip_address,
3009               clib_net_to_host_u32 (mp->vrf_id), mp->is_add ? "" : "del");
3010
3011   FINISH;
3012 }
3013
3014 typedef struct nat66_api_walk_ctx_t_
3015 {
3016   svm_queue_t *q;
3017   u32 context;
3018 } nat66_api_walk_ctx_t;
3019
3020 static int
3021 nat66_api_interface_walk (snat_interface_t * i, void *arg)
3022 {
3023   vl_api_nat66_interface_details_t *rmp;
3024   snat_main_t *sm = &snat_main;
3025   nat66_api_walk_ctx_t *ctx = arg;
3026
3027   rmp = vl_msg_api_alloc (sizeof (*rmp));
3028   memset (rmp, 0, sizeof (*rmp));
3029   rmp->_vl_msg_id = ntohs (VL_API_NAT66_INTERFACE_DETAILS + sm->msg_id_base);
3030   rmp->sw_if_index = ntohl (i->sw_if_index);
3031   rmp->is_inside = nat_interface_is_inside (i);
3032   rmp->context = ctx->context;
3033
3034   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3035
3036   return 0;
3037 }
3038
3039 static void
3040 vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
3041 {
3042   svm_queue_t *q;
3043
3044   q = vl_api_client_index_to_input_queue (mp->client_index);
3045   if (q == 0)
3046     return;
3047
3048   nat66_api_walk_ctx_t ctx = {
3049     .q = q,
3050     .context = mp->context,
3051   };
3052
3053   nat66_interfaces_walk (nat66_api_interface_walk, &ctx);
3054 }
3055
3056 static void *
3057 vl_api_nat66_interface_dump_t_print (vl_api_nat66_interface_dump_t * mp,
3058                                      void *handle)
3059 {
3060   u8 *s;
3061
3062   s = format (0, "SCRIPT: nat66_interface_dump ");
3063
3064   FINISH;
3065 }
3066
3067 static int
3068 nat66_api_static_mapping_walk (nat66_static_mapping_t * m, void *arg)
3069 {
3070   vl_api_nat66_static_mapping_details_t *rmp;
3071   nat66_main_t *nm = &nat66_main;
3072   snat_main_t *sm = &snat_main;
3073   nat66_api_walk_ctx_t *ctx = arg;
3074   fib_table_t *fib;
3075   vlib_counter_t vc;
3076
3077   fib = fib_table_get (m->fib_index, FIB_PROTOCOL_IP6);
3078   if (!fib)
3079     return -1;
3080
3081   vlib_get_combined_counter (&nm->session_counters, m - nm->sm, &vc);
3082
3083   rmp = vl_msg_api_alloc (sizeof (*rmp));
3084   memset (rmp, 0, sizeof (*rmp));
3085   rmp->_vl_msg_id =
3086     ntohs (VL_API_NAT66_STATIC_MAPPING_DETAILS + sm->msg_id_base);
3087   clib_memcpy (rmp->local_ip_address, &m->l_addr, 16);
3088   clib_memcpy (rmp->external_ip_address, &m->e_addr, 16);
3089   rmp->vrf_id = ntohl (fib->ft_table_id);
3090   rmp->total_bytes = clib_host_to_net_u64 (vc.bytes);
3091   rmp->total_pkts = clib_host_to_net_u64 (vc.packets);
3092   rmp->context = ctx->context;
3093
3094   vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
3095
3096   return 0;
3097 }
3098
3099 static void
3100 vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
3101                                             * mp)
3102 {
3103   svm_queue_t *q;
3104
3105   q = vl_api_client_index_to_input_queue (mp->client_index);
3106   if (q == 0)
3107     return;
3108
3109   nat66_api_walk_ctx_t ctx = {
3110     .q = q,
3111     .context = mp->context,
3112   };
3113
3114   nat66_static_mappings_walk (nat66_api_static_mapping_walk, &ctx);
3115 }
3116
3117 static void *
3118 vl_api_nat66_static_mapping_dump_t_print (vl_api_nat66_static_mapping_dump_t *
3119                                           mp, void *handle)
3120 {
3121   u8 *s;
3122
3123   s = format (0, "SCRIPT: nat66_static_mapping_dump ");
3124
3125   FINISH;
3126 }
3127
3128
3129 /* List of message types that this plugin understands */
3130 #define foreach_snat_plugin_api_msg                                     \
3131 _(NAT_CONTROL_PING, nat_control_ping)                                   \
3132 _(NAT_SHOW_CONFIG, nat_show_config)                                     \
3133 _(NAT_SET_WORKERS, nat_set_workers)                                     \
3134 _(NAT_WORKER_DUMP, nat_worker_dump)                                     \
3135 _(NAT_IPFIX_ENABLE_DISABLE, nat_ipfix_enable_disable)                   \
3136 _(NAT_SET_REASS, nat_set_reass)                                         \
3137 _(NAT_GET_REASS, nat_get_reass)                                         \
3138 _(NAT_REASS_DUMP, nat_reass_dump)                                       \
3139 _(NAT_SET_TIMEOUTS, nat_set_timeouts)                                   \
3140 _(NAT_GET_TIMEOUTS, nat_get_timeouts)                                   \
3141 _(NAT_SET_ADDR_AND_PORT_ALLOC_ALG, nat_set_addr_and_port_alloc_alg)     \
3142 _(NAT_GET_ADDR_AND_PORT_ALLOC_ALG, nat_get_addr_and_port_alloc_alg)     \
3143 _(NAT_SET_MSS_CLAMPING, nat_set_mss_clamping)                           \
3144 _(NAT_GET_MSS_CLAMPING, nat_get_mss_clamping)                           \
3145 _(NAT44_ADD_DEL_ADDRESS_RANGE, nat44_add_del_address_range)             \
3146 _(NAT44_INTERFACE_ADD_DEL_FEATURE, nat44_interface_add_del_feature)     \
3147 _(NAT44_ADD_DEL_STATIC_MAPPING, nat44_add_del_static_mapping)           \
3148 _(NAT44_ADD_DEL_IDENTITY_MAPPING, nat44_add_del_identity_mapping)       \
3149 _(NAT44_STATIC_MAPPING_DUMP, nat44_static_mapping_dump)                 \
3150 _(NAT44_IDENTITY_MAPPING_DUMP, nat44_identity_mapping_dump)             \
3151 _(NAT44_ADDRESS_DUMP, nat44_address_dump)                               \
3152 _(NAT44_INTERFACE_DUMP, nat44_interface_dump)                           \
3153 _(NAT44_ADD_DEL_INTERFACE_ADDR, nat44_add_del_interface_addr)           \
3154 _(NAT44_INTERFACE_ADDR_DUMP, nat44_interface_addr_dump)                 \
3155 _(NAT44_USER_DUMP, nat44_user_dump)                                     \
3156 _(NAT44_USER_SESSION_DUMP, nat44_user_session_dump)                     \
3157 _(NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE,                               \
3158   nat44_interface_add_del_output_feature)                               \
3159 _(NAT44_INTERFACE_OUTPUT_FEATURE_DUMP,                                  \
3160   nat44_interface_output_feature_dump)                                  \
3161 _(NAT44_ADD_DEL_LB_STATIC_MAPPING, nat44_add_del_lb_static_mapping)     \
3162 _(NAT44_LB_STATIC_MAPPING_DUMP, nat44_lb_static_mapping_dump)           \
3163 _(NAT44_DEL_SESSION, nat44_del_session)                                 \
3164 _(NAT44_FORWARDING_ENABLE_DISABLE, nat44_forwarding_enable_disable)     \
3165 _(NAT44_FORWARDING_IS_ENABLED, nat44_forwarding_is_enabled)             \
3166 _(NAT_DET_ADD_DEL_MAP, nat_det_add_del_map)                             \
3167 _(NAT_DET_FORWARD, nat_det_forward)                                     \
3168 _(NAT_DET_REVERSE, nat_det_reverse)                                     \
3169 _(NAT_DET_MAP_DUMP, nat_det_map_dump)                                   \
3170 _(NAT_DET_CLOSE_SESSION_OUT, nat_det_close_session_out)                 \
3171 _(NAT_DET_CLOSE_SESSION_IN, nat_det_close_session_in)                   \
3172 _(NAT_DET_SESSION_DUMP, nat_det_session_dump)                           \
3173 _(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range)         \
3174 _(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump)                           \
3175 _(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface)                     \
3176 _(NAT64_INTERFACE_DUMP, nat64_interface_dump)                           \
3177 _(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib)                   \
3178 _(NAT64_BIB_DUMP, nat64_bib_dump)                                       \
3179 _(NAT64_ST_DUMP, nat64_st_dump)                                         \
3180 _(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix)                           \
3181 _(NAT64_PREFIX_DUMP, nat64_prefix_dump)                                 \
3182 _(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr)           \
3183 _(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range)       \
3184 _(DSLITE_ADDRESS_DUMP, dslite_address_dump)                             \
3185 _(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)                           \
3186 _(DSLITE_GET_AFTR_ADDR, dslite_get_aftr_addr)                           \
3187 _(DSLITE_SET_B4_ADDR, dslite_set_b4_addr)                               \
3188 _(DSLITE_GET_B4_ADDR, dslite_get_b4_addr)                               \
3189 _(NAT66_ADD_DEL_INTERFACE, nat66_add_del_interface)                     \
3190 _(NAT66_INTERFACE_DUMP, nat66_interface_dump)                           \
3191 _(NAT66_ADD_DEL_STATIC_MAPPING, nat66_add_del_static_mapping)           \
3192 _(NAT66_STATIC_MAPPING_DUMP, nat66_static_mapping_dump)
3193
3194 /* Set up the API message handling tables */
3195 static clib_error_t *
3196 snat_plugin_api_hookup (vlib_main_t * vm)
3197 {
3198   snat_main_t *sm __attribute__ ((unused)) = &snat_main;
3199 #define _(N,n)                                                  \
3200     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
3201                            #n,                                  \
3202                            vl_api_##n##_t_handler,              \
3203                            vl_noop_handler,                     \
3204                            vl_api_##n##_t_endian,               \
3205                            vl_api_##n##_t_print,                \
3206                            sizeof(vl_api_##n##_t), 1);
3207   foreach_snat_plugin_api_msg;
3208 #undef _
3209
3210   return 0;
3211 }
3212
3213 #define vl_msg_name_crc_list
3214 #include <nat/nat_all_api_h.h>
3215 #undef vl_msg_name_crc_list
3216
3217 static void
3218 setup_message_id_table (snat_main_t * sm, api_main_t * am)
3219 {
3220 #define _(id,n,crc) \
3221   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
3222   foreach_vl_msg_name_crc_nat;
3223 #undef _
3224 }
3225
3226 static void
3227 plugin_custom_dump_configure (snat_main_t * sm)
3228 {
3229 #define _(n,f) sm->api_main->msg_print_handlers \
3230   [VL_API_##n + sm->msg_id_base]                \
3231     = (void *) vl_api_##f##_t_print;
3232   foreach_snat_plugin_api_msg;
3233 #undef _
3234 }
3235
3236 clib_error_t *
3237 snat_api_init (vlib_main_t * vm, snat_main_t * sm)
3238 {
3239   u8 *name;
3240   clib_error_t *error = 0;
3241
3242   name = format (0, "nat_%08x%c", api_version, 0);
3243
3244   /* Ask for a correctly-sized block of API message decode slots */
3245   sm->msg_id_base =
3246     vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
3247
3248   error = snat_plugin_api_hookup (vm);
3249
3250   /* Add our API messages to the global name_crc hash table */
3251   setup_message_id_table (sm, sm->api_main);
3252
3253   plugin_custom_dump_configure (sm);
3254
3255   vec_free (name);
3256
3257   return error;
3258 }
3259
3260 /*
3261  * fd.io coding-style-patch-verification: ON
3262  *
3263  * Local Variables:
3264  * eval: (c-set-style "gnu")
3265  * End:
3266  */