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