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