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