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