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