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