05a79719261bd329aa2d29d85bd4572e1d535136
[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   is_del = !mp->is_add;
1161
1162   VALIDATE_SW_IF_INDEX (mp);
1163
1164   rv = snat_add_interface_address (sm, sw_if_index, is_del,
1165                                    mp->flags & NAT_API_IS_TWICE_NAT);
1166
1167   BAD_SW_IF_INDEX_LABEL;
1168   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
1169 }
1170
1171 static void
1172 send_nat44_interface_addr_details (u32 sw_if_index,
1173                                    vl_api_registration_t * reg, u32 context,
1174                                    u8 twice_nat)
1175 {
1176   vl_api_nat44_interface_addr_details_t *rmp;
1177   snat_main_t *sm = &snat_main;
1178
1179   rmp = vl_msg_api_alloc (sizeof (*rmp));
1180   clib_memset (rmp, 0, sizeof (*rmp));
1181   rmp->_vl_msg_id =
1182     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
1183   rmp->sw_if_index = ntohl (sw_if_index);
1184
1185   if (twice_nat)
1186     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_TWICE_NAT;
1187   rmp->context = context;
1188
1189   vl_api_send_msg (reg, (u8 *) rmp);
1190 }
1191
1192 static void
1193 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
1194                                             * mp)
1195 {
1196   vl_api_registration_t *reg;
1197   snat_main_t *sm = &snat_main;
1198   u32 *i;
1199
1200   reg = vl_api_client_index_to_registration (mp->client_index);
1201   if (!reg)
1202     return;
1203
1204   /* *INDENT-OFF* */
1205   vec_foreach (i, sm->auto_add_sw_if_indices)
1206     send_nat44_interface_addr_details(*i, reg, mp->context, 0);
1207   vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
1208     send_nat44_interface_addr_details(*i, reg, mp->context, 1);
1209   /* *INDENT-ON* */
1210 }
1211
1212 static void
1213 send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg,
1214                          u32 context)
1215 {
1216   vl_api_nat44_user_details_t *rmp;
1217   snat_main_t *sm = &snat_main;
1218   ip4_main_t *im = &ip4_main;
1219
1220   rmp = vl_msg_api_alloc (sizeof (*rmp));
1221   clib_memset (rmp, 0, sizeof (*rmp));
1222   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1223
1224   if (!pool_is_free_index (im->fibs, u->fib_index))
1225     {
1226       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1227       rmp->vrf_id = ntohl (fib->ft_table_id);
1228     }
1229
1230   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1231   rmp->nsessions = ntohl (u->nsessions);
1232   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1233   rmp->context = context;
1234
1235   vl_api_send_msg (reg, (u8 *) rmp);
1236 }
1237
1238 static void
1239 nat_ed_user_create_helper (snat_main_per_thread_data_t * tsm,
1240                            snat_session_t * s)
1241 {
1242   snat_user_key_t k;
1243   k.addr = s->in2out.addr;
1244   k.fib_index = s->in2out.fib_index;
1245   clib_bihash_kv_8_8_t key, value;
1246   key.key = k.as_u64;
1247   snat_user_t *u;
1248   if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1249     {
1250       pool_get (tsm->users, u);
1251       u->addr = k.addr;
1252       u->fib_index = k.fib_index;
1253       u->nsessions = 0;
1254       u->nstaticsessions = 0;
1255       key.value = u - tsm->users;
1256       clib_bihash_add_del_8_8 (&tsm->user_hash, &key, 1);
1257     }
1258   else
1259     {
1260       u = pool_elt_at_index (tsm->users, value.value);
1261     }
1262   if (snat_is_session_static (s))
1263     {
1264       ++u->nstaticsessions;
1265     }
1266   else
1267     {
1268       ++u->nsessions;
1269     }
1270 }
1271
1272 static void
1273 nat_ed_users_create (snat_main_per_thread_data_t * tsm)
1274 {
1275   snat_session_t *s;
1276   /* *INDENT-OFF* */
1277   pool_foreach (s, tsm->sessions) { nat_ed_user_create_helper (tsm, s); }
1278   /* *INDENT-ON* */
1279 }
1280
1281 static void
1282 nat_ed_users_destroy (snat_main_per_thread_data_t * tsm)
1283 {
1284   snat_user_t *u;
1285   /* *INDENT-OFF* */
1286   pool_flush (u, tsm->users, { });
1287   /* *INDENT-ON* */
1288   clib_bihash_free_8_8 (&tsm->user_hash);
1289   clib_bihash_init_8_8 (&tsm->user_hash, "users", snat_main.user_buckets, 0);
1290   clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp);
1291 }
1292
1293 static void
1294 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1295 {
1296   vl_api_registration_t *reg;
1297   snat_main_t *sm = &snat_main;
1298   snat_main_per_thread_data_t *tsm;
1299   snat_user_t *u;
1300
1301   reg = vl_api_client_index_to_registration (mp->client_index);
1302   if (!reg)
1303     return;
1304
1305   /* *INDENT-OFF* */
1306   vec_foreach (tsm, sm->per_thread_data)
1307     {
1308       if (sm->endpoint_dependent)
1309         {
1310           nat_ed_users_create (tsm);
1311         }
1312       pool_foreach (u, tsm->users)
1313        {
1314         send_nat44_user_details (u, reg, mp->context);
1315       }
1316       if (sm->endpoint_dependent)
1317         {
1318           nat_ed_users_destroy (tsm);
1319         }
1320     }
1321   /* *INDENT-ON* */
1322 }
1323
1324 static void
1325 send_nat44_user_session_details (snat_session_t * s,
1326                                  vl_api_registration_t * reg, u32 context)
1327 {
1328   vl_api_nat44_user_session_details_t *rmp;
1329   snat_main_t *sm = &snat_main;
1330
1331   rmp = vl_msg_api_alloc (sizeof (*rmp));
1332   clib_memset (rmp, 0, sizeof (*rmp));
1333   rmp->_vl_msg_id =
1334     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1335   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1336   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1337
1338   if (snat_is_session_static (s))
1339     rmp->flags |= NAT_API_IS_STATIC;
1340
1341   if (is_twice_nat_session (s))
1342     rmp->flags |= NAT_API_IS_TWICE_NAT;
1343
1344   if (is_ed_session (s) || is_fwd_bypass_session (s))
1345     rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1346
1347   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1348   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1349   rmp->total_pkts = ntohl (s->total_pkts);
1350   rmp->context = context;
1351   if (snat_is_unk_proto_session (s))
1352     {
1353       rmp->outside_port = 0;
1354       rmp->inside_port = 0;
1355       rmp->protocol = ntohs (s->in2out.port);
1356     }
1357   else
1358     {
1359       rmp->outside_port = s->out2in.port;
1360       rmp->inside_port = s->in2out.port;
1361       rmp->protocol = ntohs (nat_proto_to_ip_proto (s->nat_proto));
1362     }
1363   if (is_ed_session (s) || is_fwd_bypass_session (s))
1364     {
1365       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1366       rmp->ext_host_port = s->ext_host_port;
1367       if (is_twice_nat_session (s))
1368         {
1369           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1370           rmp->ext_host_nat_port = s->ext_host_nat_port;
1371         }
1372     }
1373
1374   vl_api_send_msg (reg, (u8 *) rmp);
1375 }
1376
1377 static void
1378 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1379                                           mp)
1380 {
1381   vl_api_registration_t *reg;
1382   snat_main_t *sm = &snat_main;
1383   snat_main_per_thread_data_t *tsm;
1384   snat_session_t *s;
1385   clib_bihash_kv_8_8_t key, value;
1386   snat_user_key_t ukey;
1387   snat_user_t *u;
1388   u32 session_index, head_index, elt_index;
1389   dlist_elt_t *head, *elt;
1390   ip4_header_t ip;
1391
1392   reg = vl_api_client_index_to_registration (mp->client_index);
1393   if (!reg)
1394     return;
1395
1396   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1397   ip.src_address.as_u32 = ukey.addr.as_u32;
1398   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1399   key.key = ukey.as_u64;
1400   if (sm->num_workers > 1)
1401     tsm =
1402       vec_elt_at_index (sm->per_thread_data,
1403                         sm->worker_in2out_cb (&ip, ukey.fib_index, 0));
1404   else
1405     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1406   if (!sm->endpoint_dependent)
1407     {
1408       if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value))
1409         return;
1410       u = pool_elt_at_index (tsm->users, value.value);
1411       if (!u->nsessions && !u->nstaticsessions)
1412         return;
1413
1414       head_index = u->sessions_per_user_list_head_index;
1415       head = pool_elt_at_index (tsm->list_pool, head_index);
1416       elt_index = head->next;
1417       elt = pool_elt_at_index (tsm->list_pool, elt_index);
1418       session_index = elt->value;
1419       while (session_index != ~0)
1420         {
1421           s = pool_elt_at_index (tsm->sessions, session_index);
1422
1423           send_nat44_user_session_details (s, reg, mp->context);
1424
1425           elt_index = elt->next;
1426           elt = pool_elt_at_index (tsm->list_pool, elt_index);
1427           session_index = elt->value;
1428         }
1429     }
1430   else
1431     {
1432       /* *INDENT-OFF* */
1433       pool_foreach (s, tsm->sessions) {
1434         if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1435           {
1436             send_nat44_user_session_details (s, reg, mp->context);
1437           }
1438       }
1439       /* *INDENT-ON* */
1440     }
1441 }
1442
1443 static nat44_lb_addr_port_t *
1444 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
1445                              u32 addr_port_pair_num)
1446 {
1447   u8 i;
1448   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
1449   vl_api_nat44_lb_addr_port_t *ap;
1450
1451   for (i = 0; i < addr_port_pair_num; i++)
1452     {
1453       ap = &addr_port_pairs[i];
1454       clib_memset (&lb_addr_port, 0, sizeof (lb_addr_port));
1455       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
1456       lb_addr_port.port = ap->port;
1457       lb_addr_port.probability = ap->probability;
1458       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
1459       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1460     }
1461
1462   return lb_addr_port_pairs;
1463 }
1464
1465 static void
1466   vl_api_nat44_add_del_lb_static_mapping_t_handler
1467   (vl_api_nat44_add_del_lb_static_mapping_t * mp)
1468 {
1469   snat_main_t *sm = &snat_main;
1470   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1471   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1472   int rv = 0;
1473   nat44_lb_addr_port_t *locals = 0;
1474   ip4_address_t e_addr;
1475   nat_protocol_t proto;
1476   u8 *tag = 0;
1477
1478   if (!sm->endpoint_dependent)
1479     {
1480       rv = VNET_API_ERROR_UNSUPPORTED;
1481       goto send_reply;
1482     }
1483
1484   locals =
1485     unformat_nat44_lb_addr_port (mp->locals,
1486                                  clib_net_to_host_u32 (mp->local_num));
1487   clib_memcpy (&e_addr, mp->external_addr, 4);
1488   proto = ip_proto_to_nat_proto (mp->protocol);
1489
1490   if (mp->flags & NAT_API_IS_TWICE_NAT)
1491     twice_nat = TWICE_NAT;
1492   else if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
1493     twice_nat = TWICE_NAT_SELF;
1494   mp->tag[sizeof (mp->tag) - 1] = 0;
1495   tag = format (0, "%s", mp->tag);
1496   vec_terminate_c_string (tag);
1497
1498   rv =
1499     nat44_add_del_lb_static_mapping (e_addr,
1500                                      mp->external_port,
1501                                      proto, locals, mp->is_add,
1502                                      twice_nat,
1503                                      mp->flags & NAT_API_IS_OUT2IN_ONLY, tag,
1504                                      clib_net_to_host_u32 (mp->affinity));
1505
1506   vec_free (locals);
1507   vec_free (tag);
1508
1509 send_reply:
1510   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1511 }
1512
1513 static void
1514   vl_api_nat44_lb_static_mapping_add_del_local_t_handler
1515   (vl_api_nat44_lb_static_mapping_add_del_local_t * mp)
1516 {
1517   snat_main_t *sm = &snat_main;
1518   vl_api_nat44_lb_static_mapping_add_del_local_reply_t *rmp;
1519   int rv = 0;
1520   ip4_address_t e_addr, l_addr;
1521   nat_protocol_t proto;
1522
1523   if (!sm->endpoint_dependent)
1524     {
1525       rv = VNET_API_ERROR_UNSUPPORTED;
1526       goto send_reply;
1527     }
1528
1529   clib_memcpy (&e_addr, mp->external_addr, 4);
1530   clib_memcpy (&l_addr, mp->local.addr, 4);
1531   proto = ip_proto_to_nat_proto (mp->protocol);
1532
1533   rv =
1534     nat44_lb_static_mapping_add_del_local (e_addr,
1535                                            mp->external_port,
1536                                            l_addr,
1537                                            mp->local.port,
1538                                            proto,
1539                                            clib_net_to_host_u32 (mp->
1540                                                                  local.vrf_id),
1541                                            mp->local.probability, mp->is_add);
1542
1543 send_reply:
1544   REPLY_MACRO (VL_API_NAT44_LB_STATIC_MAPPING_ADD_DEL_LOCAL_REPLY);
1545 }
1546
1547 static void
1548 send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
1549                                       vl_api_registration_t * reg,
1550                                       u32 context)
1551 {
1552   vl_api_nat44_lb_static_mapping_details_t *rmp;
1553   snat_main_t *sm = &snat_main;
1554   nat44_lb_addr_port_t *ap;
1555   vl_api_nat44_lb_addr_port_t *locals;
1556   u32 local_num = 0;
1557
1558   rmp =
1559     vl_msg_api_alloc (sizeof (*rmp) +
1560                       (pool_elts (m->locals) *
1561                        sizeof (nat44_lb_addr_port_t)));
1562   clib_memset (rmp, 0, sizeof (*rmp));
1563   rmp->_vl_msg_id =
1564     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1565
1566   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1567   rmp->external_port = m->external_port;
1568   rmp->protocol = nat_proto_to_ip_proto (m->proto);
1569   rmp->context = context;
1570
1571   if (m->twice_nat == TWICE_NAT)
1572     rmp->flags |= NAT_API_IS_TWICE_NAT;
1573   else if (m->twice_nat == TWICE_NAT_SELF)
1574     rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
1575   if (is_out2in_only_static_mapping (m))
1576     rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
1577   if (m->tag)
1578     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1579
1580   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1581   /* *INDENT-OFF* */
1582   pool_foreach (ap, m->locals)
1583    {
1584     clib_memcpy (locals->addr, &(ap->addr), 4);
1585     locals->port = ap->port;
1586     locals->probability = ap->probability;
1587     locals->vrf_id = ntohl (ap->vrf_id);
1588     locals++;
1589     local_num++;
1590   }
1591   /* *INDENT-ON* */
1592   rmp->local_num = ntohl (local_num);
1593
1594   vl_api_send_msg (reg, (u8 *) rmp);
1595 }
1596
1597 static void
1598   vl_api_nat44_lb_static_mapping_dump_t_handler
1599   (vl_api_nat44_lb_static_mapping_dump_t * mp)
1600 {
1601   vl_api_registration_t *reg;
1602   snat_main_t *sm = &snat_main;
1603   snat_static_mapping_t *m;
1604
1605   if (!sm->endpoint_dependent)
1606     return;
1607
1608   reg = vl_api_client_index_to_registration (mp->client_index);
1609   if (!reg)
1610     return;
1611
1612   /* *INDENT-OFF* */
1613   pool_foreach (m, sm->static_mappings)
1614    {
1615       if (is_lb_static_mapping(m))
1616         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1617   }
1618   /* *INDENT-ON* */
1619 }
1620
1621 static void
1622 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
1623 {
1624   snat_main_t *sm = &snat_main;
1625   vl_api_nat44_del_session_reply_t *rmp;
1626   ip4_address_t addr, eh_addr;
1627   u16 port, eh_port;
1628   u32 vrf_id;
1629   int rv = 0;
1630   u8 is_in;
1631   nat_protocol_t proto;
1632
1633   memcpy (&addr.as_u8, mp->address, 4);
1634   port = mp->port;
1635   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1636   proto = ip_proto_to_nat_proto (mp->protocol);
1637   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1638   eh_port = mp->ext_host_port;
1639
1640   is_in = mp->flags & NAT_API_IS_INSIDE;
1641
1642   if (mp->flags & NAT_API_IS_EXT_HOST_VALID)
1643     rv =
1644       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1645                             vrf_id, is_in);
1646   else
1647     rv = nat44_ei_del_session (sm, &addr, port, proto, vrf_id, is_in);
1648
1649   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1650 }
1651
1652 static void
1653   vl_api_nat44_forwarding_enable_disable_t_handler
1654   (vl_api_nat44_forwarding_enable_disable_t * mp)
1655 {
1656   snat_main_t *sm = &snat_main;
1657   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1658   int rv = 0;
1659   u32 *ses_to_be_removed = 0, *ses_index;
1660   snat_main_per_thread_data_t *tsm;
1661   snat_session_t *s;
1662
1663   sm->forwarding_enabled = mp->enable != 0;
1664
1665   if (mp->enable == 0)
1666     {
1667       /* *INDENT-OFF* */
1668       vec_foreach (tsm, sm->per_thread_data)
1669       {
1670         pool_foreach (s, tsm->sessions)
1671          {
1672           if (is_fwd_bypass_session(s))
1673             {
1674               vec_add1 (ses_to_be_removed, s - tsm->sessions);
1675             }
1676         }
1677         if(sm->endpoint_dependent){
1678             vec_foreach (ses_index, ses_to_be_removed)
1679               {
1680                 s = pool_elt_at_index(tsm->sessions, ses_index[0]);
1681                 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1682                 nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1);
1683               }
1684         }else{
1685             vec_foreach (ses_index, ses_to_be_removed)
1686               {
1687                 s = pool_elt_at_index(tsm->sessions, ses_index[0]);
1688                 nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0);
1689                 nat44_delete_session (sm, s, tsm - sm->per_thread_data);
1690               }
1691         }
1692         vec_free (ses_to_be_removed);
1693       }
1694       /* *INDENT-ON* */
1695     }
1696
1697   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1698 }
1699
1700 static void
1701   vl_api_nat44_forwarding_is_enabled_t_handler
1702   (vl_api_nat44_forwarding_is_enabled_t * mp)
1703 {
1704   vl_api_registration_t *reg;
1705   snat_main_t *sm = &snat_main;
1706   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1707
1708   reg = vl_api_client_index_to_registration (mp->client_index);
1709   if (!reg)
1710     return;
1711
1712   rmp = vl_msg_api_alloc (sizeof (*rmp));
1713   clib_memset (rmp, 0, sizeof (*rmp));
1714   rmp->_vl_msg_id =
1715     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1716   rmp->context = mp->context;
1717
1718   rmp->enabled = sm->forwarding_enabled;
1719
1720   vl_api_send_msg (reg, (u8 *) rmp);
1721 }
1722
1723 /* API definitions */
1724 #include <vnet/format_fns.h>
1725 #include <nat/nat44.api.c>
1726
1727 /* Set up the API message handling tables */
1728 clib_error_t *
1729 nat44_api_hookup (vlib_main_t * vm)
1730 {
1731   snat_main_t *sm = &snat_main;
1732   sm->msg_id_base = setup_message_id_table ();
1733   return 0;
1734 }
1735
1736 /*
1737  * fd.io coding-style-patch-verification: ON
1738  *
1739  * Local Variables:
1740  * eval: (c-set-style "gnu")
1741  * End:
1742  */