nat: TCP state tracking based on RFC 7857/RFC 6146
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_api.c
1 /*
2  * Copyright (c) 2020 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 NAT44 plugin API implementation
19  */
20
21 #include <vnet/ip/ip_types_api.h>
22 #include <vlibmemory/api.h>
23
24 #include <vnet/fib/fib_table.h>
25
26 #include <nat/lib/nat_inlines.h>
27 #include <nat/lib/ipfix_logging.h>
28
29 #include <nat/nat44-ed/nat44_ed.h>
30
31 #include <nat/nat44-ed/nat44_ed.api_enum.h>
32 #include <nat/nat44-ed/nat44_ed.api_types.h>
33
34 #include <nat/nat44-ed/nat44_ed_inlines.h>
35
36 #define REPLY_MSG_ID_BASE sm->msg_id_base
37 #include <vlibapi/api_helper_macros.h>
38
39 /* New API calls */
40
41 static void
42 vl_api_nat44_ed_plugin_enable_disable_t_handler (
43   vl_api_nat44_ed_plugin_enable_disable_t *mp)
44 {
45   snat_main_t *sm = &snat_main;
46   nat44_config_t c = { 0 };
47   vl_api_nat44_ed_plugin_enable_disable_reply_t *rmp;
48   int rv = 0;
49
50   if (mp->enable)
51     {
52       if ((mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY) ||
53           (mp->flags & NAT44_API_IS_CONNECTION_TRACKING))
54         {
55           rv = VNET_API_ERROR_UNSUPPORTED;
56         }
57       else
58         {
59           c.sessions = ntohl (mp->sessions);
60           c.inside_vrf = ntohl (mp->inside_vrf);
61           c.outside_vrf = ntohl (mp->outside_vrf);
62
63           rv = nat44_plugin_enable (c);
64         }
65     }
66   else
67     {
68       rv = nat44_plugin_disable ();
69     }
70
71   REPLY_MACRO (VL_API_NAT44_ED_PLUGIN_ENABLE_DISABLE_REPLY);
72 }
73
74 static void
75 vl_api_nat44_ed_set_fq_options_t_handler (vl_api_nat44_ed_set_fq_options_t *mp)
76 {
77   snat_main_t *sm = &snat_main;
78   vl_api_nat44_ed_set_fq_options_reply_t *rmp;
79   int rv = 0;
80   u32 frame_queue_nelts = ntohl (mp->frame_queue_nelts);
81   rv = nat44_ed_set_frame_queue_nelts (frame_queue_nelts);
82   REPLY_MACRO (VL_API_NAT44_ED_SET_FQ_OPTIONS_REPLY);
83 }
84
85 static void
86 vl_api_nat44_ed_show_fq_options_t_handler (
87   vl_api_nat44_ed_show_fq_options_t *mp)
88 {
89   snat_main_t *sm = &snat_main;
90   vl_api_nat44_ed_show_fq_options_reply_t *rmp;
91   int rv = 0;
92   /* clang-format off */
93   REPLY_MACRO2_ZERO (VL_API_NAT44_ED_SHOW_FQ_OPTIONS_REPLY,
94   ({
95     rmp->frame_queue_nelts = htonl (sm->frame_queue_nelts);
96   }));
97   /* clang-format on */
98 }
99
100 /* Old API calls hold back because of deprecation
101  * nat44_ed replacement should be used */
102
103 static void
104 vl_api_nat_set_workers_t_handler (vl_api_nat_set_workers_t * mp)
105 {
106   snat_main_t *sm = &snat_main;
107   vl_api_nat_set_workers_reply_t *rmp;
108   int rv = 0;
109   uword *bitmap = 0;
110   u64 mask;
111
112   mask = clib_net_to_host_u64 (mp->worker_mask);
113
114   if (sm->num_workers < 2)
115     {
116       rv = VNET_API_ERROR_FEATURE_DISABLED;
117       goto send_reply;
118     }
119
120   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
121   rv = snat_set_workers (bitmap);
122   clib_bitmap_free (bitmap);
123
124 send_reply:
125   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
126 }
127
128 static void
129 send_nat_worker_details (u32 worker_index, vl_api_registration_t * reg,
130                          u32 context)
131 {
132   vl_api_nat_worker_details_t *rmp;
133   snat_main_t *sm = &snat_main;
134   vlib_worker_thread_t *w =
135     vlib_worker_threads + worker_index + sm->first_worker_index;
136
137   rmp = vl_msg_api_alloc (sizeof (*rmp));
138   clib_memset (rmp, 0, sizeof (*rmp));
139   rmp->_vl_msg_id = ntohs (VL_API_NAT_WORKER_DETAILS + sm->msg_id_base);
140   rmp->context = context;
141   rmp->worker_index = htonl (worker_index);
142   rmp->lcore_id = htonl (w->cpu_id);
143   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
144
145   vl_api_send_msg (reg, (u8 *) rmp);
146 }
147
148 static void
149 vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp)
150 {
151   vl_api_registration_t *reg;
152   snat_main_t *sm = &snat_main;
153   u32 *worker_index;
154
155   reg = vl_api_client_index_to_registration (mp->client_index);
156   if (!reg)
157     return;
158
159   vec_foreach (worker_index, sm->workers)
160     {
161       send_nat_worker_details (*worker_index, reg, mp->context);
162     }
163 }
164
165 static void
166 vl_api_nat44_set_session_limit_t_handler (vl_api_nat44_set_session_limit_t *
167                                           mp)
168 {
169   snat_main_t *sm = &snat_main;
170   vl_api_nat44_set_session_limit_reply_t *rmp;
171   int rv = 0;
172
173   rv = nat44_set_session_limit
174     (ntohl (mp->session_limit), ntohl (mp->vrf_id));
175
176   REPLY_MACRO (VL_API_NAT44_SET_SESSION_LIMIT_REPLY);
177 }
178
179 static void
180 vl_api_nat_set_log_level_t_handler (vl_api_nat_set_log_level_t * mp)
181 {
182   snat_main_t *sm = &snat_main;
183   vl_api_nat_set_log_level_reply_t *rmp;
184   int rv = 0;
185
186   if (sm->log_level > NAT_LOG_DEBUG)
187     rv = VNET_API_ERROR_UNSUPPORTED;
188   else
189     sm->log_level = mp->log_level;
190
191   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
192 }
193
194 static void
195 vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t *
196                                            mp)
197 {
198   snat_main_t *sm = &snat_main;
199   vl_api_nat_ipfix_enable_disable_reply_t *rmp;
200   int rv = 0;
201
202   rv = nat_ipfix_logging_enable_disable (mp->enable,
203                                          clib_host_to_net_u32
204                                          (mp->domain_id),
205                                          clib_host_to_net_u16 (mp->src_port));
206
207   REPLY_MACRO (VL_API_NAT_IPFIX_ENABLE_DISABLE_REPLY);
208 }
209
210 static void
211 vl_api_nat_set_timeouts_t_handler (vl_api_nat_set_timeouts_t * mp)
212 {
213   snat_main_t *sm = &snat_main;
214   vl_api_nat_set_timeouts_reply_t *rmp;
215   int rv = 0;
216
217   sm->timeouts.udp = ntohl (mp->udp);
218   sm->timeouts.tcp.established = ntohl (mp->tcp_established);
219   sm->timeouts.tcp.transitory = ntohl (mp->tcp_transitory);
220   sm->timeouts.icmp = ntohl (mp->icmp);
221
222   REPLY_MACRO (VL_API_NAT_SET_TIMEOUTS_REPLY);
223 }
224
225 static void
226 vl_api_nat_get_timeouts_t_handler (vl_api_nat_get_timeouts_t * mp)
227 {
228   snat_main_t *sm = &snat_main;
229   vl_api_nat_get_timeouts_reply_t *rmp;
230   int rv = 0;
231
232   REPLY_MACRO2 (VL_API_NAT_GET_TIMEOUTS_REPLY,
233   ({
234     rmp->udp = htonl (sm->timeouts.udp);
235     rmp->tcp_established = htonl (sm->timeouts.tcp.established);
236     rmp->tcp_transitory = htonl (sm->timeouts.tcp.transitory);
237     rmp->icmp = htonl (sm->timeouts.icmp);
238   }))
239 }
240
241 static void
242 vl_api_nat_set_mss_clamping_t_handler (vl_api_nat_set_mss_clamping_t * mp)
243 {
244   snat_main_t *sm = &snat_main;
245   vl_api_nat_set_mss_clamping_reply_t *rmp;
246   int rv = 0;
247
248   if (mp->enable)
249     sm->mss_clamping = ntohs (mp->mss_value);
250   else
251     sm->mss_clamping = 0;
252
253   REPLY_MACRO (VL_API_NAT_SET_MSS_CLAMPING_REPLY);
254 }
255
256 static void
257 vl_api_nat_get_mss_clamping_t_handler (vl_api_nat_get_mss_clamping_t * mp)
258 {
259   snat_main_t *sm = &snat_main;
260   vl_api_nat_get_mss_clamping_reply_t *rmp;
261   int rv = 0;
262
263   REPLY_MACRO2 (VL_API_NAT_GET_MSS_CLAMPING_REPLY,
264   ({
265     rmp->enable = sm->mss_clamping ? 1 : 0;
266     rmp->mss_value = htons (sm->mss_clamping);
267   }))
268 }
269
270 static void
271   vl_api_nat44_add_del_address_range_t_handler
272   (vl_api_nat44_add_del_address_range_t * mp)
273 {
274   snat_main_t *sm = &snat_main;
275   vl_api_nat44_add_del_address_range_reply_t *rmp;
276   ip4_address_t this_addr;
277   u8 is_add, twice_nat;
278   u32 start_host_order, end_host_order;
279   u32 vrf_id;
280   int i, count;
281   int rv = 0;
282   u32 *tmp;
283
284   is_add = mp->is_add;
285   twice_nat = mp->flags & NAT_API_IS_TWICE_NAT;
286
287   tmp = (u32 *) mp->first_ip_address;
288   start_host_order = clib_host_to_net_u32 (tmp[0]);
289   tmp = (u32 *) mp->last_ip_address;
290   end_host_order = clib_host_to_net_u32 (tmp[0]);
291
292   count = (end_host_order - start_host_order) + 1;
293
294   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
295
296   if (count > 1024)
297     nat_log_info ("%U - %U, %d addresses...",
298                   format_ip4_address, mp->first_ip_address,
299                   format_ip4_address, mp->last_ip_address, count);
300
301   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
302
303   for (i = 0; i < count; i++)
304     {
305       if (is_add)
306         {
307           rv = nat44_ed_add_address (&this_addr, vrf_id, twice_nat);
308         }
309       else
310         {
311           rv = nat44_ed_del_address (this_addr, twice_nat);
312         }
313
314       if (rv)
315         goto send_reply;
316
317       increment_v4_address (&this_addr);
318     }
319
320 send_reply:
321   REPLY_MACRO (VL_API_NAT44_ADD_DEL_ADDRESS_RANGE_REPLY);
322 }
323
324 static void
325 send_nat44_address_details (snat_address_t * a,
326                             vl_api_registration_t * reg, u32 context,
327                             u8 twice_nat)
328 {
329   vl_api_nat44_address_details_t *rmp;
330   snat_main_t *sm = &snat_main;
331
332   rmp = vl_msg_api_alloc (sizeof (*rmp));
333   clib_memset (rmp, 0, sizeof (*rmp));
334   rmp->_vl_msg_id = ntohs (VL_API_NAT44_ADDRESS_DETAILS + sm->msg_id_base);
335   clib_memcpy (rmp->ip_address, &(a->addr), 4);
336   if (a->fib_index != ~0)
337     {
338       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
339       rmp->vrf_id = ntohl (fib->ft_table_id);
340     }
341   else
342     rmp->vrf_id = ~0;
343   if (twice_nat)
344     rmp->flags |= NAT_API_IS_TWICE_NAT;
345   rmp->context = context;
346
347   vl_api_send_msg (reg, (u8 *) rmp);
348 }
349
350 static void
351 vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp)
352 {
353   vl_api_registration_t *reg;
354   snat_main_t *sm = &snat_main;
355   snat_address_t *a;
356
357   reg = vl_api_client_index_to_registration (mp->client_index);
358   if (!reg)
359     return;
360
361   vec_foreach (a, sm->addresses)
362     send_nat44_address_details (a, reg, mp->context, 0);
363   vec_foreach (a, sm->twice_nat_addresses)
364     send_nat44_address_details (a, reg, mp->context, 1);
365 }
366
367 static void
368   vl_api_nat44_interface_add_del_feature_t_handler
369   (vl_api_nat44_interface_add_del_feature_t * mp)
370 {
371   vl_api_nat44_interface_add_del_feature_reply_t *rmp;
372   snat_main_t *sm = &snat_main;
373   u32 sw_if_index;
374   u8 is_inside;
375   int rv = 0;
376
377   VALIDATE_SW_IF_INDEX (mp);
378
379   is_inside = mp->flags & NAT_API_IS_INSIDE;
380   sw_if_index = ntohl (mp->sw_if_index);
381
382   if (mp->is_add)
383     {
384       rv = nat44_ed_add_interface (sw_if_index, is_inside);
385     }
386   else
387     {
388       rv = nat44_ed_del_interface (sw_if_index, is_inside);
389     }
390
391   BAD_SW_IF_INDEX_LABEL;
392   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY);
393 }
394
395 static void
396 send_nat44_interface_details (snat_interface_t * i,
397                               vl_api_registration_t * reg, u32 context)
398 {
399   vl_api_nat44_interface_details_t *rmp;
400   snat_main_t *sm = &snat_main;
401
402   rmp = vl_msg_api_alloc (sizeof (*rmp));
403   clib_memset (rmp, 0, sizeof (*rmp));
404   rmp->_vl_msg_id = ntohs (VL_API_NAT44_INTERFACE_DETAILS + sm->msg_id_base);
405   rmp->sw_if_index = ntohl (i->sw_if_index);
406
407   if (nat44_ed_is_interface_inside (i))
408     rmp->flags |= NAT_API_IS_INSIDE;
409   if (nat44_ed_is_interface_outside (i))
410     rmp->flags |= NAT_API_IS_OUTSIDE;
411
412   rmp->context = context;
413
414   vl_api_send_msg (reg, (u8 *) rmp);
415 }
416
417 static void
418 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
419 {
420   vl_api_registration_t *reg;
421   snat_main_t *sm = &snat_main;
422   snat_interface_t *i;
423
424   reg = vl_api_client_index_to_registration (mp->client_index);
425   if (!reg)
426     return;
427
428   pool_foreach (i, sm->interfaces)
429     {
430       send_nat44_interface_details (i, reg, mp->context);
431     }
432 }
433
434 static_always_inline int
435 add_del_dummy_output_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
436 {
437   snat_main_t *sm = &snat_main;
438   snat_interface_t *i;
439   int rv = 1;
440
441   pool_foreach (i, sm->output_feature_dummy_interfaces)
442     {
443       if (i->sw_if_index == sw_if_index)
444         {
445           if (!is_add)
446             {
447               pool_put (sm->output_feature_dummy_interfaces, i);
448               rv = 0;
449             }
450           goto done;
451         }
452     }
453
454   if (is_add)
455     {
456       pool_get (sm->output_feature_dummy_interfaces, i);
457       i->sw_if_index = sw_if_index;
458
459       if (is_inside)
460         {
461           i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
462         }
463       else
464         {
465           i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
466         }
467
468       rv = 0;
469     }
470
471 done:
472   return rv;
473 }
474
475 static void
476   vl_api_nat44_interface_add_del_output_feature_t_handler
477   (vl_api_nat44_interface_add_del_output_feature_t * mp)
478 {
479   vl_api_nat44_interface_add_del_output_feature_reply_t *rmp;
480   snat_main_t *sm = &snat_main;
481   u32 sw_if_index;
482   int rv = 0;
483
484   VALIDATE_SW_IF_INDEX (mp);
485
486   sw_if_index = ntohl (mp->sw_if_index);
487
488   // register all interfaces in the dummy structure
489   rv = add_del_dummy_output_interface (
490     sw_if_index, mp->flags & NAT_API_IS_INSIDE, mp->is_add);
491
492   if (!(mp->flags & NAT_API_IS_INSIDE))
493     {
494       if (mp->is_add)
495         {
496           rv = nat44_ed_add_output_interface (sw_if_index);
497         }
498       else
499         {
500           rv = nat44_ed_del_output_interface (sw_if_index);
501         }
502     }
503
504   BAD_SW_IF_INDEX_LABEL;
505   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
506 }
507
508 static void
509 send_nat44_interface_output_feature_details (snat_interface_t * i,
510                                              vl_api_registration_t * reg,
511                                              u32 context)
512 {
513   vl_api_nat44_interface_output_feature_details_t *rmp;
514   snat_main_t *sm = &snat_main;
515
516   rmp = vl_msg_api_alloc (sizeof (*rmp));
517   clib_memset (rmp, 0, sizeof (*rmp));
518   rmp->_vl_msg_id =
519     ntohs (VL_API_NAT44_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
520   rmp->sw_if_index = ntohl (i->sw_if_index);
521   rmp->context = context;
522
523   if (nat44_ed_is_interface_inside (i))
524     {
525       rmp->flags |= NAT_API_IS_INSIDE;
526     }
527
528   vl_api_send_msg (reg, (u8 *) rmp);
529 }
530
531 static void
532   vl_api_nat44_interface_output_feature_dump_t_handler
533   (vl_api_nat44_interface_output_feature_dump_t * mp)
534 {
535   vl_api_registration_t *reg;
536   snat_main_t *sm = &snat_main;
537   snat_interface_t *i;
538
539   reg = vl_api_client_index_to_registration (mp->client_index);
540   if (!reg)
541     return;
542
543   pool_foreach (i, sm->output_feature_dummy_interfaces)
544     {
545       send_nat44_interface_output_feature_details (i, reg, mp->context);
546     }
547 }
548
549 static void
550 vl_api_nat44_ed_add_del_output_interface_t_handler (
551   vl_api_nat44_ed_add_del_output_interface_t *mp)
552 {
553   vl_api_nat44_ed_add_del_output_interface_reply_t *rmp;
554   snat_main_t *sm = &snat_main;
555   int rv = 0;
556
557   VALIDATE_SW_IF_INDEX_END (mp);
558
559   if (mp->is_add)
560     {
561       rv = nat44_ed_add_output_interface (mp->sw_if_index);
562     }
563   else
564     {
565       rv = nat44_ed_del_output_interface (mp->sw_if_index);
566     }
567
568 bad_sw_if_index:
569   REPLY_MACRO_END (VL_API_NAT44_ED_ADD_DEL_OUTPUT_INTERFACE_REPLY);
570 }
571
572 #define vl_endianfun
573 #include <nat/nat44-ed/nat44_ed.api.h>
574 #undef vl_endianfun
575 static void
576 send_nat44_ed_output_interface_details (u32 index, vl_api_registration_t *rp,
577                                         u32 context)
578 {
579   snat_main_t *sm = &snat_main;
580   vl_api_nat44_ed_output_interface_details_t *rmp;
581   snat_interface_t *i =
582     pool_elt_at_index (sm->output_feature_interfaces, index);
583
584   /* Make sure every field is initiated (or don't skip the clib_memset()) */
585   REPLY_MACRO_DETAILS4 (
586     VL_API_NAT44_ED_OUTPUT_INTERFACE_DETAILS, rp, context, ({
587       rmp->sw_if_index = i->sw_if_index;
588
589       /* Endian hack until apigen registers _details
590        * endian functions */
591       vl_api_nat44_ed_output_interface_details_t_endian (rmp);
592       rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
593       rmp->context = htonl (rmp->context);
594     }));
595 }
596
597 static void
598 vl_api_nat44_ed_output_interface_get_t_handler (
599   vl_api_nat44_ed_output_interface_get_t *mp)
600 {
601   vl_api_nat44_ed_output_interface_get_reply_t *rmp;
602   snat_main_t *sm = &snat_main;
603   i32 rv = 0;
604
605   if (pool_elts (sm->output_feature_interfaces) == 0)
606     {
607       REPLY_MACRO (VL_API_NAT44_ED_OUTPUT_INTERFACE_GET_REPLY);
608       return;
609     }
610
611   REPLY_AND_DETAILS_MACRO (
612     VL_API_NAT44_ED_OUTPUT_INTERFACE_GET_REPLY, sm->output_feature_interfaces,
613     ({ send_nat44_ed_output_interface_details (cursor, rp, mp->context); }));
614 }
615
616 static void
617   vl_api_nat44_add_del_static_mapping_t_handler
618   (vl_api_nat44_add_del_static_mapping_t * mp)
619 {
620   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
621
622   snat_main_t *sm = &snat_main;
623   int rv = 0;
624
625   ip4_address_t l_addr, e_addr, pool_addr = { 0 };
626   u32 sw_if_index, flags = 0, vrf_id;
627   u16 l_port = 0, e_port = 0;
628   ip_protocol_t proto = 0;
629   u8 *tag = 0;
630
631   memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
632
633   if (mp->flags & NAT_API_IS_ADDR_ONLY)
634     {
635       flags |= NAT_SM_FLAG_ADDR_ONLY;
636     }
637   else
638     {
639       l_port = mp->local_port;
640       e_port = mp->external_port;
641       proto = mp->protocol;
642     }
643
644   if (mp->flags & NAT_API_IS_TWICE_NAT)
645     {
646       flags |= NAT_SM_FLAG_TWICE_NAT;
647     }
648
649   if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
650     {
651       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
652     }
653
654   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
655     {
656       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
657     }
658
659   sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
660   if (sw_if_index != ~0)
661     {
662       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
663     }
664   else
665     {
666       memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
667     }
668
669   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
670
671   if (mp->is_add)
672     {
673       mp->tag[sizeof (mp->tag) - 1] = 0;
674       tag = format (0, "%s", mp->tag);
675       vec_terminate_c_string (tag);
676
677       rv = nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
678                                         vrf_id, sw_if_index, flags, pool_addr,
679                                         tag);
680       vec_free (tag);
681     }
682   else
683     {
684       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
685                                         vrf_id, sw_if_index, flags);
686     }
687   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
688 }
689
690 static void
691   vl_api_nat44_add_del_static_mapping_v2_t_handler
692   (vl_api_nat44_add_del_static_mapping_v2_t * mp)
693 {
694   vl_api_nat44_add_del_static_mapping_v2_reply_t *rmp;
695
696   snat_main_t *sm = &snat_main;
697   int rv = 0;
698
699   ip4_address_t l_addr, e_addr, pool_addr;
700   u32 sw_if_index, flags = 0, vrf_id;
701   u16 l_port = 0, e_port = 0;
702   ip_protocol_t proto;
703   u8 *tag = 0;
704
705   memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
706   memcpy (&pool_addr.as_u8, mp->pool_ip_address, 4);
707
708   if (pool_addr.as_u32 != 0)
709     {
710       flags |= NAT_SM_FLAG_EXACT_ADDRESS;
711     }
712
713   if (mp->flags & NAT_API_IS_ADDR_ONLY)
714     {
715       flags |= NAT_SM_FLAG_ADDR_ONLY;
716     }
717   else
718     {
719       l_port = mp->local_port;
720       e_port = mp->external_port;
721     }
722
723   if (mp->flags & NAT_API_IS_TWICE_NAT)
724     {
725       flags |= NAT_SM_FLAG_TWICE_NAT;
726     }
727
728   if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
729     {
730       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
731     }
732
733   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
734     {
735       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
736     }
737
738   sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
739   if (sw_if_index)
740     {
741       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
742     }
743   else
744     {
745       memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
746     }
747
748   proto = mp->protocol;
749   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
750
751   if (mp->is_add)
752     {
753       mp->tag[sizeof (mp->tag) - 1] = 0;
754       tag = format (0, "%s", mp->tag);
755       vec_terminate_c_string (tag);
756
757       rv = nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
758                                         vrf_id, sw_if_index, flags, pool_addr,
759                                         tag);
760       vec_free (tag);
761     }
762   else
763     {
764       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
765                                         vrf_id, sw_if_index, flags);
766     }
767   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_V2_REPLY);
768 }
769
770 static void
771 send_nat44_static_mapping_details (snat_static_mapping_t * m,
772                                    vl_api_registration_t * reg, u32 context)
773 {
774   vl_api_nat44_static_mapping_details_t *rmp;
775   snat_main_t *sm = &snat_main;
776   u32 len = sizeof (*rmp);
777
778   rmp = vl_msg_api_alloc (len);
779   clib_memset (rmp, 0, len);
780   rmp->_vl_msg_id =
781     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
782
783   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
784   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
785   rmp->external_sw_if_index = ~0;
786   rmp->vrf_id = htonl (m->vrf_id);
787   rmp->context = context;
788
789   // convert these in new api
790
791   if (is_sm_self_twice_nat (m->flags))
792     {
793       rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
794     }
795
796   if (is_sm_out2in_only (m->flags))
797     {
798       rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
799     }
800
801   if (is_sm_twice_nat (m->flags))
802     {
803       rmp->flags |= NAT_API_IS_TWICE_NAT;
804     }
805
806   if (is_sm_addr_only (m->flags))
807     {
808       rmp->flags |= NAT_API_IS_ADDR_ONLY;
809     }
810   else
811     {
812       rmp->protocol = m->proto;
813       rmp->external_port = m->external_port;
814       rmp->local_port = m->local_port;
815     }
816
817   if (m->tag)
818     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
819
820   vl_api_send_msg (reg, (u8 *) rmp);
821 }
822
823 static void
824 send_nat44_static_map_resolve_details (snat_static_mapping_resolve_t *m,
825                                        vl_api_registration_t *reg, u32 context)
826 {
827   vl_api_nat44_static_mapping_details_t *rmp;
828   snat_main_t *sm = &snat_main;
829
830   rmp = vl_msg_api_alloc (sizeof (*rmp));
831   clib_memset (rmp, 0, sizeof (*rmp));
832   rmp->_vl_msg_id =
833     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
834   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
835   rmp->external_sw_if_index = htonl (m->sw_if_index);
836   rmp->vrf_id = htonl (m->vrf_id);
837   rmp->context = context;
838
839   if (is_sm_twice_nat (m->flags))
840     {
841       rmp->flags |= NAT_API_IS_TWICE_NAT;
842     }
843
844   if (is_sm_addr_only (m->flags))
845     {
846       rmp->flags |= NAT_API_IS_ADDR_ONLY;
847     }
848   else
849     {
850       rmp->protocol = m->proto;
851       rmp->external_port = m->e_port;
852       rmp->local_port = m->l_port;
853     }
854
855   if (m->tag)
856     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
857
858   vl_api_send_msg (reg, (u8 *) rmp);
859 }
860
861 static void
862 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
863                                             * mp)
864 {
865   vl_api_registration_t *reg;
866   snat_main_t *sm = &snat_main;
867   snat_static_mapping_t *m;
868   snat_static_mapping_resolve_t *rp;
869   int j;
870
871   reg = vl_api_client_index_to_registration (mp->client_index);
872   if (!reg)
873     return;
874
875   pool_foreach (m, sm->static_mappings)
876    {
877      if (!is_sm_identity_nat (m->flags) && !is_sm_lb (m->flags))
878        send_nat44_static_mapping_details (m, reg, mp->context);
879   }
880
881   for (j = 0; j < vec_len (sm->sm_to_resolve); j++)
882     {
883       rp = sm->sm_to_resolve + j;
884       if (!is_sm_identity_nat (rp->flags))
885         send_nat44_static_map_resolve_details (rp, reg, mp->context);
886     }
887 }
888
889 static void
890   vl_api_nat44_add_del_identity_mapping_t_handler
891   (vl_api_nat44_add_del_identity_mapping_t * mp)
892 {
893   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
894
895   snat_main_t *sm = &snat_main;
896   int rv = 0;
897
898   ip4_address_t addr, pool_addr = { 0 };
899   u32 sw_if_index, flags, vrf_id;
900   ip_protocol_t proto = 0;
901   u16 port = 0;
902   u8 *tag = 0;
903
904   flags = NAT_SM_FLAG_IDENTITY_NAT;
905
906   if (mp->flags & NAT_API_IS_ADDR_ONLY)
907     {
908       flags |= NAT_SM_FLAG_ADDR_ONLY;
909     }
910   else
911     {
912       port = mp->port;
913       proto = mp->protocol;
914     }
915
916   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
917   if (sw_if_index != ~0)
918     {
919       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
920     }
921   else
922     {
923       memcpy (&addr.as_u8, mp->ip_address, 4);
924     }
925
926   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
927
928   if (mp->is_add)
929     {
930       mp->tag[sizeof (mp->tag) - 1] = 0;
931       tag = format (0, "%s", mp->tag);
932       vec_terminate_c_string (tag);
933
934       rv = nat44_ed_add_static_mapping (addr, addr, port, port, proto, vrf_id,
935                                         sw_if_index, flags, pool_addr, tag);
936       vec_free (tag);
937     }
938   else
939     {
940       rv = nat44_ed_del_static_mapping (addr, addr, port, port, proto, vrf_id,
941                                         sw_if_index, flags);
942     }
943   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
944 }
945
946 static void
947 send_nat44_identity_mapping_details (snat_static_mapping_t * m, int index,
948                                      vl_api_registration_t * reg, u32 context)
949 {
950   vl_api_nat44_identity_mapping_details_t *rmp;
951   snat_main_t *sm = &snat_main;
952   nat44_lb_addr_port_t *local = pool_elt_at_index (m->locals, index);
953
954   rmp = vl_msg_api_alloc (sizeof (*rmp));
955   clib_memset (rmp, 0, sizeof (*rmp));
956   rmp->_vl_msg_id =
957     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
958
959   if (is_sm_addr_only (m->flags))
960     rmp->flags |= NAT_API_IS_ADDR_ONLY;
961
962   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
963   rmp->port = m->local_port;
964   rmp->sw_if_index = ~0;
965   rmp->vrf_id = htonl (local->vrf_id);
966   rmp->protocol = m->proto;
967   rmp->context = context;
968   if (m->tag)
969     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
970
971   vl_api_send_msg (reg, (u8 *) rmp);
972 }
973
974 static void
975 send_nat44_identity_map_resolve_details (snat_static_mapping_resolve_t *m,
976                                          vl_api_registration_t *reg,
977                                          u32 context)
978 {
979   vl_api_nat44_identity_mapping_details_t *rmp;
980   snat_main_t *sm = &snat_main;
981
982   rmp = vl_msg_api_alloc (sizeof (*rmp));
983   clib_memset (rmp, 0, sizeof (*rmp));
984   rmp->_vl_msg_id =
985     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
986
987   if (is_sm_addr_only (m->flags))
988     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_ADDR_ONLY;
989
990   rmp->port = m->l_port;
991   rmp->sw_if_index = htonl (m->sw_if_index);
992   rmp->vrf_id = htonl (m->vrf_id);
993   rmp->protocol = m->proto;
994   rmp->context = context;
995   if (m->tag)
996     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
997
998   vl_api_send_msg (reg, (u8 *) rmp);
999 }
1000
1001 static void
1002   vl_api_nat44_identity_mapping_dump_t_handler
1003   (vl_api_nat44_identity_mapping_dump_t * mp)
1004 {
1005   vl_api_registration_t *reg;
1006   snat_main_t *sm = &snat_main;
1007   snat_static_mapping_t *m;
1008   snat_static_mapping_resolve_t *rp;
1009   int j;
1010
1011   reg = vl_api_client_index_to_registration (mp->client_index);
1012   if (!reg)
1013     return;
1014
1015   pool_foreach (m, sm->static_mappings)
1016     {
1017       if (is_sm_identity_nat (m->flags) && !is_sm_lb (m->flags))
1018         {
1019           pool_foreach_index (j, m->locals)
1020             {
1021               send_nat44_identity_mapping_details (m, j, reg, mp->context);
1022             }
1023         }
1024     }
1025
1026   for (j = 0; j < vec_len (sm->sm_to_resolve); j++)
1027     {
1028       rp = sm->sm_to_resolve + j;
1029       if (is_sm_identity_nat (rp->flags))
1030         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
1031     }
1032 }
1033
1034 static void
1035   vl_api_nat44_add_del_interface_addr_t_handler
1036   (vl_api_nat44_add_del_interface_addr_t * mp)
1037 {
1038   snat_main_t *sm = &snat_main;
1039   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
1040   u32 sw_if_index = ntohl (mp->sw_if_index);
1041   u8 twice_nat;
1042   int rv = 0;
1043
1044   VALIDATE_SW_IF_INDEX (mp);
1045
1046   twice_nat = mp->flags & NAT_API_IS_TWICE_NAT;
1047
1048   if (mp->is_add)
1049     {
1050       rv = nat44_ed_add_interface_address (sw_if_index, twice_nat);
1051     }
1052   else
1053     {
1054       rv = nat44_ed_del_interface_address (sw_if_index, twice_nat);
1055     }
1056
1057   BAD_SW_IF_INDEX_LABEL;
1058
1059   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1060 }
1061
1062 static void
1063 send_nat44_interface_addr_details (u32 sw_if_index,
1064                                    vl_api_registration_t * reg, u32 context,
1065                                    u8 twice_nat)
1066 {
1067   vl_api_nat44_interface_addr_details_t *rmp;
1068   snat_main_t *sm = &snat_main;
1069
1070   rmp = vl_msg_api_alloc (sizeof (*rmp));
1071   clib_memset (rmp, 0, sizeof (*rmp));
1072   rmp->_vl_msg_id =
1073     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1074   rmp->sw_if_index = ntohl (sw_if_index);
1075
1076   if (twice_nat)
1077     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_TWICE_NAT;
1078   rmp->context = context;
1079
1080   vl_api_send_msg (reg, (u8 *) rmp);
1081 }
1082
1083 static void
1084 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1085                                             * mp)
1086 {
1087   snat_main_t *sm = &snat_main;
1088   vl_api_registration_t *reg;
1089   snat_address_resolve_t *ap;
1090
1091   reg = vl_api_client_index_to_registration (mp->client_index);
1092   if (!reg)
1093     return;
1094
1095   vec_foreach (ap, sm->addr_to_resolve)
1096     {
1097       send_nat44_interface_addr_details (ap->sw_if_index, reg, mp->context,
1098                                          ap->is_twice_nat);
1099     }
1100 }
1101
1102 static nat44_lb_addr_port_t *
1103 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t *addr_port_pairs,
1104                              u32 addr_port_pair_num)
1105 {
1106   u8 i;
1107   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1108   vl_api_nat44_lb_addr_port_t *ap;
1109
1110   for (i = 0; i < addr_port_pair_num; i++)
1111     {
1112       ap = &addr_port_pairs[i];
1113       clib_memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1114       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1115       lb_addr_port.port = ap->port;
1116       lb_addr_port.probability = ap->probability;
1117       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1118       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1119     }
1120
1121   return lb_addr_port_pairs;
1122 }
1123
1124 static void
1125 vl_api_nat44_add_del_lb_static_mapping_t_handler (
1126   vl_api_nat44_add_del_lb_static_mapping_t *mp)
1127 {
1128   snat_main_t *sm = &snat_main;
1129   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1130   nat44_lb_addr_port_t *locals = 0;
1131   ip4_address_t e_addr;
1132   ip_protocol_t proto;
1133   u32 flags = 0;
1134   u8 *tag = 0;
1135   int rv = 0;
1136
1137   locals = unformat_nat44_lb_addr_port (mp->locals,
1138                                         clib_net_to_host_u32 (mp->local_num));
1139   clib_memcpy (&e_addr, mp->external_addr, 4);
1140   proto = mp->protocol;
1141
1142   if (mp->flags & NAT_API_IS_TWICE_NAT)
1143     {
1144       flags |= NAT_SM_FLAG_TWICE_NAT;
1145     }
1146   else if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
1147     {
1148       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
1149     }
1150
1151   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
1152     {
1153       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
1154     }
1155
1156   if (mp->is_add)
1157     {
1158       mp->tag[sizeof (mp->tag) - 1] = 0;
1159       tag = format (0, "%s", mp->tag);
1160       vec_terminate_c_string (tag);
1161
1162       rv = nat44_ed_add_lb_static_mapping (
1163         e_addr, mp->external_port, proto, locals, flags, tag,
1164         clib_net_to_host_u32 (mp->affinity));
1165     }
1166   else
1167     {
1168       rv = nat44_ed_del_lb_static_mapping (e_addr, mp->external_port, proto,
1169                                            flags);
1170     }
1171
1172   vec_free (locals);
1173   vec_free (tag);
1174   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1175 }
1176
1177 static void
1178 vl_api_nat44_lb_static_mapping_add_del_local_t_handler (
1179   vl_api_nat44_lb_static_mapping_add_del_local_t *mp)
1180 {
1181   snat_main_t *sm = &snat_main;
1182   vl_api_nat44_lb_static_mapping_add_del_local_reply_t *rmp;
1183   int rv = 0;
1184   ip4_address_t e_addr, l_addr;
1185   ip_protocol_t proto;
1186
1187   clib_memcpy (&e_addr, mp->external_addr, 4);
1188   clib_memcpy (&l_addr, mp->local.addr, 4);
1189   proto = mp->protocol;
1190
1191   rv = nat44_ed_add_del_lb_static_mapping_local (
1192     e_addr, mp->external_port, l_addr, mp->local.port, proto,
1193     clib_net_to_host_u32 (mp->local.vrf_id), mp->local.probability,
1194     mp->is_add);
1195
1196   REPLY_MACRO (VL_API_NAT44_LB_STATIC_MAPPING_ADD_DEL_LOCAL_REPLY);
1197 }
1198
1199 static void
1200 send_nat44_lb_static_mapping_details (snat_static_mapping_t *m,
1201                                       vl_api_registration_t *reg, u32 context)
1202 {
1203   vl_api_nat44_lb_static_mapping_details_t *rmp;
1204   snat_main_t *sm = &snat_main;
1205   nat44_lb_addr_port_t *ap;
1206   vl_api_nat44_lb_addr_port_t *locals;
1207   u32 local_num = 0;
1208
1209   rmp = vl_msg_api_alloc (
1210     sizeof (*rmp) + (pool_elts (m->locals) * sizeof (nat44_lb_addr_port_t)));
1211
1212   clib_memset (rmp, 0, sizeof (*rmp));
1213   rmp->_vl_msg_id =
1214     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1215
1216   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1217   rmp->external_port = m->external_port;
1218   rmp->protocol = m->proto;
1219   rmp->context = context;
1220
1221   if (is_sm_self_twice_nat (m->flags))
1222     {
1223       rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
1224     }
1225
1226   if (is_sm_out2in_only (m->flags))
1227     {
1228       rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
1229     }
1230
1231   if (is_sm_twice_nat (m->flags))
1232     {
1233       rmp->flags |= NAT_API_IS_TWICE_NAT;
1234     }
1235
1236   if (m->tag)
1237     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1238
1239   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1240   pool_foreach (ap, m->locals)
1241     {
1242       clib_memcpy (locals->addr, &(ap->addr), 4);
1243       locals->port = ap->port;
1244       locals->probability = ap->probability;
1245       locals->vrf_id = ntohl (ap->vrf_id);
1246       locals++;
1247       local_num++;
1248     }
1249   rmp->local_num = ntohl (local_num);
1250
1251   vl_api_send_msg (reg, (u8 *) rmp);
1252 }
1253
1254 static void
1255 vl_api_nat44_lb_static_mapping_dump_t_handler (
1256   vl_api_nat44_lb_static_mapping_dump_t *mp)
1257 {
1258   vl_api_registration_t *reg;
1259   snat_main_t *sm = &snat_main;
1260   snat_static_mapping_t *m;
1261
1262   reg = vl_api_client_index_to_registration (mp->client_index);
1263   if (!reg)
1264     return;
1265
1266   pool_foreach (m, sm->static_mappings)
1267     {
1268       if (is_sm_lb (m->flags))
1269         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1270     }
1271 }
1272
1273 static void
1274 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t *mp)
1275 {
1276   snat_main_t *sm = &snat_main;
1277   vl_api_nat44_del_session_reply_t *rmp;
1278   ip4_address_t addr, eh_addr;
1279   u16 port, eh_port;
1280   u32 vrf_id;
1281   int rv = 0;
1282   u8 is_in;
1283
1284   memcpy (&addr.as_u8, mp->address, 4);
1285   port = mp->port;
1286   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1287   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1288   eh_port = mp->ext_host_port;
1289
1290   is_in = mp->flags & NAT_API_IS_INSIDE;
1291
1292   rv = nat44_ed_del_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1293                              vrf_id, is_in);
1294
1295   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1296 }
1297
1298 static void
1299 vl_api_nat44_forwarding_enable_disable_t_handler (
1300   vl_api_nat44_forwarding_enable_disable_t *mp)
1301 {
1302   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1303   snat_main_t *sm = &snat_main;
1304   int rv = 0;
1305   nat44_ed_forwarding_enable_disable (mp->enable);
1306   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1307 }
1308
1309 static void
1310 vl_api_nat44_forwarding_is_enabled_t_handler (
1311   vl_api_nat44_forwarding_is_enabled_t *mp)
1312 {
1313   vl_api_registration_t *reg;
1314   snat_main_t *sm = &snat_main;
1315   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1316
1317   reg = vl_api_client_index_to_registration (mp->client_index);
1318   if (!reg)
1319     return;
1320
1321   rmp = vl_msg_api_alloc (sizeof (*rmp));
1322   clib_memset (rmp, 0, sizeof (*rmp));
1323   rmp->_vl_msg_id =
1324     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1325   rmp->context = mp->context;
1326
1327   rmp->enabled = sm->forwarding_enabled;
1328
1329   vl_api_send_msg (reg, (u8 *) rmp);
1330 }
1331
1332 /* Obsolete calls hold back because of deprecation
1333  * should not be used */
1334
1335 static void
1336 vl_api_nat_set_addr_and_port_alloc_alg_t_handler (
1337   vl_api_nat_set_addr_and_port_alloc_alg_t *mp)
1338 {
1339   snat_main_t *sm = &snat_main;
1340   vl_api_nat_set_addr_and_port_alloc_alg_reply_t *rmp;
1341   int rv = VNET_API_ERROR_UNSUPPORTED;
1342   REPLY_MACRO (VL_API_NAT_SET_ADDR_AND_PORT_ALLOC_ALG_REPLY);
1343 }
1344
1345 static void
1346 vl_api_nat_get_addr_and_port_alloc_alg_t_handler (
1347   vl_api_nat_get_addr_and_port_alloc_alg_t *mp)
1348 {
1349   snat_main_t *sm = &snat_main;
1350   vl_api_nat_get_addr_and_port_alloc_alg_reply_t *rmp;
1351   int rv = VNET_API_ERROR_UNSUPPORTED;
1352   REPLY_MACRO (VL_API_NAT_GET_ADDR_AND_PORT_ALLOC_ALG_REPLY);
1353 }
1354
1355 static void
1356 vl_api_nat_ha_set_listener_t_handler (vl_api_nat_ha_set_listener_t *mp)
1357 {
1358   snat_main_t *sm = &snat_main;
1359   vl_api_nat_ha_set_listener_reply_t *rmp;
1360   int rv = VNET_API_ERROR_UNSUPPORTED;
1361   REPLY_MACRO (VL_API_NAT_HA_SET_LISTENER_REPLY);
1362 }
1363
1364 static void
1365 vl_api_nat_ha_get_listener_t_handler (vl_api_nat_ha_get_listener_t *mp)
1366 {
1367   snat_main_t *sm = &snat_main;
1368   vl_api_nat_ha_get_listener_reply_t *rmp;
1369   int rv = VNET_API_ERROR_UNSUPPORTED;
1370   REPLY_MACRO (VL_API_NAT_HA_GET_LISTENER_REPLY);
1371 }
1372
1373 static void
1374 vl_api_nat_ha_set_failover_t_handler (vl_api_nat_ha_set_failover_t *mp)
1375 {
1376   snat_main_t *sm = &snat_main;
1377   vl_api_nat_ha_set_failover_reply_t *rmp;
1378   int rv = VNET_API_ERROR_UNSUPPORTED;
1379   REPLY_MACRO (VL_API_NAT_HA_SET_FAILOVER_REPLY);
1380 }
1381
1382 static void
1383 vl_api_nat_ha_get_failover_t_handler (vl_api_nat_ha_get_failover_t *mp)
1384 {
1385   snat_main_t *sm = &snat_main;
1386   vl_api_nat_ha_get_failover_reply_t *rmp;
1387   int rv = VNET_API_ERROR_UNSUPPORTED;
1388   REPLY_MACRO (VL_API_NAT_HA_GET_FAILOVER_REPLY);
1389 }
1390
1391 static void
1392 vl_api_nat_ha_flush_t_handler (vl_api_nat_ha_flush_t *mp)
1393 {
1394   snat_main_t *sm = &snat_main;
1395   vl_api_nat_ha_flush_reply_t *rmp;
1396   int rv = VNET_API_ERROR_UNSUPPORTED;
1397   REPLY_MACRO (VL_API_NAT_HA_FLUSH_REPLY);
1398 }
1399
1400 static void
1401 vl_api_nat_ha_resync_t_handler (vl_api_nat_ha_resync_t *mp)
1402 {
1403   snat_main_t *sm = &snat_main;
1404   vl_api_nat_ha_resync_reply_t *rmp;
1405   int rv = VNET_API_ERROR_UNSUPPORTED;
1406   REPLY_MACRO (VL_API_NAT_HA_RESYNC_REPLY);
1407 }
1408
1409 static void
1410 vl_api_nat44_del_user_t_handler (vl_api_nat44_del_user_t *mp)
1411 {
1412   snat_main_t *sm = &snat_main;
1413   vl_api_nat44_del_user_reply_t *rmp;
1414   int rv = VNET_API_ERROR_UNSUPPORTED;
1415   REPLY_MACRO (VL_API_NAT44_DEL_USER_REPLY);
1416 }
1417
1418 static void
1419 vl_api_nat44_session_cleanup_t_handler (vl_api_nat44_session_cleanup_t *mp)
1420 {
1421   snat_main_t *sm = &snat_main;
1422   vl_api_nat44_session_cleanup_reply_t *rmp;
1423   int rv = VNET_API_ERROR_UNSUPPORTED;
1424   REPLY_MACRO (VL_API_NAT44_SESSION_CLEANUP_REPLY);
1425 }
1426
1427 static void
1428 vl_api_nat44_plugin_enable_disable_t_handler (
1429   vl_api_nat44_plugin_enable_disable_t *mp)
1430 {
1431   snat_main_t *sm = &snat_main;
1432   nat44_config_t c = { 0 };
1433   vl_api_nat44_plugin_enable_disable_reply_t *rmp;
1434   int rv = 0;
1435
1436   if (mp->enable)
1437     {
1438       if ((mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY) ||
1439           (mp->flags & NAT44_API_IS_CONNECTION_TRACKING) || mp->users ||
1440           mp->user_sessions)
1441         {
1442           rv = VNET_API_ERROR_UNSUPPORTED;
1443         }
1444       else
1445         {
1446           c.sessions = ntohl (mp->sessions);
1447           c.inside_vrf = ntohl (mp->inside_vrf);
1448           c.outside_vrf = ntohl (mp->outside_vrf);
1449
1450           rv = nat44_plugin_enable (c);
1451         }
1452     }
1453   else
1454     {
1455       rv = nat44_plugin_disable ();
1456     }
1457
1458   REPLY_MACRO (VL_API_NAT44_PLUGIN_ENABLE_DISABLE_REPLY);
1459 }
1460
1461 static void
1462 vl_api_nat_control_ping_t_handler (vl_api_nat_control_ping_t *mp)
1463 {
1464   vl_api_nat_control_ping_reply_t *rmp;
1465   snat_main_t *sm = &snat_main;
1466   int rv = 0;
1467
1468   REPLY_MACRO2 (VL_API_NAT_CONTROL_PING_REPLY,
1469                 ({ rmp->vpe_pid = ntohl (getpid ()); }));
1470 }
1471
1472 static void
1473 vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t *mp)
1474 {
1475   vl_api_nat_show_config_reply_t *rmp;
1476   snat_main_t *sm = &snat_main;
1477   int rv = 0;
1478
1479   REPLY_MACRO2_ZERO (VL_API_NAT_SHOW_CONFIG_REPLY, ({
1480                        rmp->translation_buckets =
1481                          htonl (sm->translation_buckets);
1482                        rmp->user_buckets = 0;
1483                        rmp->max_translations_per_user = 0;
1484                        rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
1485                        rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
1486                        rmp->static_mapping_only = 0;
1487                        rmp->static_mapping_connection_tracking = 0;
1488                        rmp->endpoint_dependent = 1;
1489                        rmp->out2in_dpo = 0;
1490                      }));
1491 }
1492
1493 static void
1494 vl_api_nat_show_config_2_t_handler (vl_api_nat_show_config_2_t *mp)
1495 {
1496   vl_api_nat_show_config_2_reply_t *rmp;
1497   snat_main_t *sm = &snat_main;
1498   int rv = 0;
1499
1500   REPLY_MACRO2_ZERO (
1501     VL_API_NAT_SHOW_CONFIG_2_REPLY, ({
1502       rmp->translation_buckets = htonl (sm->translation_buckets);
1503       rmp->user_buckets = 0;
1504       rmp->max_translations_per_user = 0;
1505       rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
1506       rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
1507       rmp->static_mapping_only = 0;
1508       rmp->static_mapping_connection_tracking = 0;
1509       rmp->endpoint_dependent = 1;
1510       rmp->out2in_dpo = 0;
1511       rmp->max_translations_per_thread =
1512         clib_net_to_host_u32 (sm->max_translations_per_thread);
1513       rmp->max_users_per_thread = 0;
1514     }));
1515 }
1516
1517 static void
1518 vl_api_nat44_show_running_config_t_handler (
1519   vl_api_nat44_show_running_config_t *mp)
1520 {
1521   vl_api_nat44_show_running_config_reply_t *rmp;
1522   snat_main_t *sm = &snat_main;
1523   nat44_config_t *rc = &sm->rconfig;
1524   int rv = 0;
1525
1526   REPLY_MACRO2_ZERO (
1527     VL_API_NAT44_SHOW_RUNNING_CONFIG_REPLY, ({
1528       rmp->inside_vrf = htonl (rc->inside_vrf);
1529       rmp->outside_vrf = htonl (rc->outside_vrf);
1530
1531       rmp->sessions = htonl (rc->sessions);
1532       rmp->translation_buckets = htonl (sm->translation_buckets);
1533
1534       // OBSOLETE
1535       rmp->users = 0;
1536       rmp->user_buckets = 0;
1537       rmp->user_sessions = 0;
1538
1539       rmp->timeouts.udp = htonl (sm->timeouts.udp);
1540       rmp->timeouts.tcp_established = htonl (sm->timeouts.tcp.established);
1541       rmp->timeouts.tcp_transitory = htonl (sm->timeouts.tcp.transitory);
1542       rmp->timeouts.icmp = htonl (sm->timeouts.icmp);
1543
1544       rmp->forwarding_enabled = sm->forwarding_enabled == 1;
1545       // consider how to split functionality between subplugins
1546       rmp->ipfix_logging_enabled = nat_ipfix_logging_enabled ();
1547       rmp->flags |= NAT44_IS_ENDPOINT_DEPENDENT;
1548     }));
1549 }
1550
1551 /* user (internal host) key */
1552 typedef struct
1553 {
1554   union
1555   {
1556     struct
1557     {
1558       ip4_address_t addr;
1559       u32 fib_index;
1560     };
1561     u64 as_u64;
1562   };
1563 } snat_user_key_t;
1564
1565 typedef struct
1566 {
1567   ip4_address_t addr;
1568   u32 fib_index;
1569   u32 nsessions;
1570   u32 nstaticsessions;
1571 } snat_user_t;
1572
1573 typedef struct
1574 {
1575   u32 user_buckets;
1576   snat_user_t *users;
1577   clib_bihash_8_8_t user_hash;
1578 } user_create_helper_t;
1579
1580 static void
1581 send_nat44_user_details (snat_user_t *u, vl_api_registration_t *reg,
1582                          u32 context)
1583 {
1584   vl_api_nat44_user_details_t *rmp;
1585   snat_main_t *sm = &snat_main;
1586   ip4_main_t *im = &ip4_main;
1587
1588   rmp = vl_msg_api_alloc (sizeof (*rmp));
1589   clib_memset (rmp, 0, sizeof (*rmp));
1590   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1591
1592   if (!pool_is_free_index (im->fibs, u->fib_index))
1593     {
1594       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1595       rmp->vrf_id = ntohl (fib->ft_table_id);
1596     }
1597
1598   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1599   rmp->nsessions = ntohl (u->nsessions);
1600   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1601   rmp->context = context;
1602
1603   vl_api_send_msg (reg, (u8 *) rmp);
1604 }
1605
1606 static void
1607 nat_ed_user_create_helper (user_create_helper_t *uch, snat_session_t *s)
1608 {
1609   snat_user_key_t k;
1610   k.addr = s->in2out.addr;
1611   k.fib_index = s->in2out.fib_index;
1612   clib_bihash_kv_8_8_t key, value;
1613   key.key = k.as_u64;
1614   snat_user_t *u;
1615
1616   if (clib_bihash_search_8_8 (&uch->user_hash, &key, &value))
1617     {
1618       pool_get (uch->users, u);
1619       u->addr = k.addr;
1620       u->fib_index = k.fib_index;
1621       u->nsessions = 0;
1622       u->nstaticsessions = 0;
1623       key.value = u - uch->users;
1624       clib_bihash_add_del_8_8 (&uch->user_hash, &key, 1);
1625     }
1626   else
1627     {
1628       u = pool_elt_at_index (uch->users, value.value);
1629     }
1630   if (nat44_ed_is_session_static (s))
1631     {
1632       ++u->nstaticsessions;
1633     }
1634   else
1635     {
1636       ++u->nsessions;
1637     }
1638 }
1639
1640 u8 *
1641 format_user_kvp (u8 *s, va_list *args)
1642 {
1643   clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
1644   snat_user_key_t k;
1645   k.as_u64 = v->key;
1646   s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
1647               k.fib_index, v->value);
1648   return s;
1649 }
1650
1651 static void
1652 nat_ed_users_create (snat_main_per_thread_data_t *tsm,
1653                      user_create_helper_t *uch)
1654 {
1655   snat_session_t *s;
1656   clib_bihash_init_8_8 (&uch->user_hash, "users", uch->user_buckets, 0);
1657   clib_bihash_set_kvp_format_fn_8_8 (&uch->user_hash, format_user_kvp);
1658   pool_foreach (s, tsm->sessions)
1659     {
1660       nat_ed_user_create_helper (uch, s);
1661     }
1662 }
1663
1664 static void
1665 nat_ed_users_destroy (user_create_helper_t *uch)
1666 {
1667   pool_free (uch->users);
1668   clib_bihash_free_8_8 (&uch->user_hash);
1669 }
1670
1671 static void
1672 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1673 {
1674   user_create_helper_t uch;
1675   vl_api_registration_t *reg;
1676   snat_main_t *sm = &snat_main;
1677   snat_main_per_thread_data_t *tsm;
1678   snat_user_t *u;
1679
1680   clib_memset (&uch, 0, sizeof (uch));
1681
1682   uch.user_buckets = nat_calc_bihash_buckets (1024);
1683
1684   reg = vl_api_client_index_to_registration (mp->client_index);
1685   if (!reg)
1686     return;
1687
1688   vec_foreach (tsm, sm->per_thread_data)
1689     {
1690       nat_ed_users_create (tsm, &uch);
1691       pool_foreach (u, uch.users)
1692         {
1693           send_nat44_user_details (u, reg, mp->context);
1694         }
1695       nat_ed_users_destroy (&uch);
1696     }
1697 }
1698
1699 static void
1700 send_nat44_user_session_details (snat_session_t * s,
1701                                  vl_api_registration_t * reg, u32 context)
1702 {
1703   vl_api_nat44_user_session_details_t *rmp;
1704   snat_main_t *sm = &snat_main;
1705
1706   rmp = vl_msg_api_alloc (sizeof (*rmp));
1707   clib_memset (rmp, 0, sizeof (*rmp));
1708   rmp->_vl_msg_id =
1709     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1710   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1711   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1712
1713   if (nat44_ed_is_session_static (s))
1714     rmp->flags |= NAT_API_IS_STATIC;
1715
1716   if (nat44_ed_is_twice_nat_session (s))
1717     rmp->flags |= NAT_API_IS_TWICE_NAT;
1718
1719   rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1720
1721   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1722   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1723   rmp->total_pkts = ntohl (s->total_pkts);
1724   rmp->context = context;
1725   rmp->outside_port = s->out2in.port;
1726   rmp->inside_port = s->in2out.port;
1727   rmp->protocol = clib_host_to_net_u16 (s->proto);
1728   clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1729   rmp->ext_host_port = s->ext_host_port;
1730   if (nat44_ed_is_twice_nat_session (s))
1731     {
1732       clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1733       rmp->ext_host_nat_port = s->ext_host_nat_port;
1734     }
1735
1736   vl_api_send_msg (reg, (u8 *) rmp);
1737 }
1738
1739 static void
1740 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1741                                           mp)
1742 {
1743   snat_main_per_thread_data_t *tsm;
1744   snat_main_t *sm = &snat_main;
1745   vl_api_registration_t *reg;
1746   snat_user_key_t ukey;
1747   snat_session_t *s;
1748   ip4_header_t ip;
1749
1750   reg = vl_api_client_index_to_registration (mp->client_index);
1751   if (!reg)
1752     return;
1753
1754   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1755   ip.src_address.as_u32 = ukey.addr.as_u32;
1756   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1757   if (sm->num_workers > 1)
1758     tsm = vec_elt_at_index (
1759       sm->per_thread_data,
1760       nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
1761   else
1762     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1763
1764       pool_foreach (s, tsm->sessions) {
1765         if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1766           {
1767             send_nat44_user_session_details (s, reg, mp->context);
1768           }
1769       }
1770 }
1771
1772 static void
1773 send_nat44_user_session_v2_details (snat_session_t *s,
1774                                     vl_api_registration_t *reg, u32 context)
1775 {
1776   vl_api_nat44_user_session_v2_details_t *rmp;
1777   snat_main_t *sm = &snat_main;
1778   u64 now = vlib_time_now (sm->vnet_main->vlib_main);
1779   u64 sess_timeout_time = 0;
1780
1781   rmp = vl_msg_api_alloc (sizeof (*rmp));
1782   clib_memset (rmp, 0, sizeof (*rmp));
1783   rmp->_vl_msg_id =
1784     ntohs (VL_API_NAT44_USER_SESSION_V2_DETAILS + sm->msg_id_base);
1785   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1786   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1787
1788   if (nat44_ed_is_session_static (s))
1789     rmp->flags |= NAT_API_IS_STATIC;
1790
1791   if (nat44_ed_is_twice_nat_session (s))
1792     rmp->flags |= NAT_API_IS_TWICE_NAT;
1793
1794   rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1795
1796   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1797   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1798   rmp->total_pkts = ntohl (s->total_pkts);
1799   rmp->context = context;
1800   rmp->outside_port = s->out2in.port;
1801   rmp->inside_port = s->in2out.port;
1802   rmp->protocol = clib_host_to_net_u16 (s->proto);
1803   clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1804   rmp->ext_host_port = s->ext_host_port;
1805   if (nat44_ed_is_twice_nat_session (s))
1806     {
1807       clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1808       rmp->ext_host_nat_port = s->ext_host_nat_port;
1809     }
1810
1811   sess_timeout_time = s->last_heard + nat44_session_get_timeout (sm, s);
1812   rmp->is_timed_out = (now >= sess_timeout_time);
1813
1814   vl_api_send_msg (reg, (u8 *) rmp);
1815 }
1816
1817 static void
1818 vl_api_nat44_user_session_v2_dump_t_handler (
1819   vl_api_nat44_user_session_v2_dump_t *mp)
1820 {
1821   snat_main_per_thread_data_t *tsm;
1822   snat_main_t *sm = &snat_main;
1823   vl_api_registration_t *reg;
1824   snat_user_key_t ukey;
1825   snat_session_t *s;
1826   ip4_header_t ip;
1827
1828   reg = vl_api_client_index_to_registration (mp->client_index);
1829   if (!reg)
1830     return;
1831
1832   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1833   ip.src_address.as_u32 = ukey.addr.as_u32;
1834   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1835   if (sm->num_workers > 1)
1836     tsm = vec_elt_at_index (
1837       sm->per_thread_data,
1838       nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
1839   else
1840     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1841
1842   pool_foreach (s, tsm->sessions)
1843     {
1844       if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1845         {
1846           send_nat44_user_session_v2_details (s, reg, mp->context);
1847         }
1848     }
1849 }
1850
1851 /* API definitions */
1852 #include <vnet/format_fns.h>
1853 #include <nat/nat44-ed/nat44_ed.api.c>
1854
1855 /* Set up the API message handling tables */
1856 clib_error_t *
1857 nat44_api_hookup (vlib_main_t * vm)
1858 {
1859   snat_main_t *sm = &snat_main;
1860   sm->msg_id_base = setup_message_id_table ();
1861   return 0;
1862 }
1863
1864 /*
1865  * fd.io coding-style-patch-verification: ON
1866  *
1867  * Local Variables:
1868  * eval: (c-set-style "gnu")
1869  * End:
1870  */