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