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