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