nat: nat44-ed disable protection for api/cli
[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   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
500
501   snat_main_t *sm = &snat_main;
502   int rv = 0;
503
504   ip4_address_t l_addr, e_addr, pool_addr = { 0 };
505   u32 sw_if_index, flags = 0, vrf_id;
506   u16 l_port = 0, e_port = 0;
507   nat_protocol_t proto = 0;
508   u8 *tag = 0;
509
510   memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
511
512   if (mp->flags & NAT_API_IS_ADDR_ONLY)
513     {
514       flags |= NAT_SM_FLAG_ADDR_ONLY;
515     }
516   else
517     {
518       l_port = mp->local_port;
519       e_port = mp->external_port;
520       proto = ip_proto_to_nat_proto (mp->protocol);
521     }
522
523   if (mp->flags & NAT_API_IS_TWICE_NAT)
524     {
525       flags |= NAT_SM_FLAG_TWICE_NAT;
526     }
527
528   if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
529     {
530       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
531     }
532
533   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
534     {
535       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
536     }
537
538   sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
539   if (sw_if_index != ~0)
540     {
541       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
542     }
543   else
544     {
545       memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
546     }
547
548   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
549
550   if (mp->is_add)
551     {
552       mp->tag[sizeof (mp->tag) - 1] = 0;
553       tag = format (0, "%s", mp->tag);
554       vec_terminate_c_string (tag);
555
556       rv = nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
557                                         vrf_id, sw_if_index, flags, pool_addr,
558                                         tag);
559       vec_free (tag);
560     }
561   else
562     {
563       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
564                                         vrf_id, sw_if_index, flags);
565     }
566   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
567 }
568
569 static void
570   vl_api_nat44_add_del_static_mapping_v2_t_handler
571   (vl_api_nat44_add_del_static_mapping_v2_t * mp)
572 {
573   vl_api_nat44_add_del_static_mapping_v2_reply_t *rmp;
574
575   snat_main_t *sm = &snat_main;
576   int rv = 0;
577
578   ip4_address_t l_addr, e_addr, pool_addr;
579   u32 sw_if_index, flags = 0, vrf_id;
580   u16 l_port = 0, e_port = 0;
581   nat_protocol_t proto;
582   u8 *tag = 0;
583
584   memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
585   memcpy (&pool_addr.as_u8, mp->pool_ip_address, 4);
586
587   if (pool_addr.as_u32 != 0)
588     {
589       flags |= NAT_SM_FLAG_EXACT_ADDRESS;
590     }
591
592   if (mp->flags & NAT_API_IS_ADDR_ONLY)
593     {
594       flags |= NAT_SM_FLAG_ADDR_ONLY;
595     }
596   else
597     {
598       l_port = mp->local_port;
599       e_port = mp->external_port;
600     }
601
602   if (mp->flags & NAT_API_IS_TWICE_NAT)
603     {
604       flags |= NAT_SM_FLAG_TWICE_NAT;
605     }
606
607   if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
608     {
609       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
610     }
611
612   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
613     {
614       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
615     }
616
617   sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
618   if (sw_if_index)
619     {
620       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
621     }
622   else
623     {
624       memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
625     }
626
627   proto = ip_proto_to_nat_proto (mp->protocol);
628   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
629
630   if (mp->is_add)
631     {
632       mp->tag[sizeof (mp->tag) - 1] = 0;
633       tag = format (0, "%s", mp->tag);
634       vec_terminate_c_string (tag);
635
636       rv = nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
637                                         vrf_id, sw_if_index, flags, pool_addr,
638                                         tag);
639       vec_free (tag);
640     }
641   else
642     {
643       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
644                                         vrf_id, sw_if_index, flags);
645     }
646   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_V2_REPLY);
647 }
648
649 static void
650 send_nat44_static_mapping_details (snat_static_mapping_t * m,
651                                    vl_api_registration_t * reg, u32 context)
652 {
653   vl_api_nat44_static_mapping_details_t *rmp;
654   snat_main_t *sm = &snat_main;
655   u32 len = sizeof (*rmp);
656
657   rmp = vl_msg_api_alloc (len);
658   clib_memset (rmp, 0, len);
659   rmp->_vl_msg_id =
660     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
661
662   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
663   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
664   rmp->external_sw_if_index = ~0;
665   rmp->vrf_id = htonl (m->vrf_id);
666   rmp->context = context;
667
668   // convert these in new api
669
670   if (is_sm_self_twice_nat (m->flags))
671     {
672       rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
673     }
674
675   if (is_sm_out2in_only (m->flags))
676     {
677       rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
678     }
679
680   if (is_sm_twice_nat (m->flags))
681     {
682       rmp->flags |= NAT_API_IS_TWICE_NAT;
683     }
684
685   if (is_sm_addr_only (m->flags))
686     {
687       rmp->flags |= NAT_API_IS_ADDR_ONLY;
688     }
689   else
690     {
691       rmp->protocol = nat_proto_to_ip_proto (m->proto);
692       rmp->external_port = m->external_port;
693       rmp->local_port = m->local_port;
694     }
695
696   if (m->tag)
697     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
698
699   vl_api_send_msg (reg, (u8 *) rmp);
700 }
701
702 static void
703 send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
704                                        vl_api_registration_t * reg,
705                                        u32 context)
706 {
707   vl_api_nat44_static_mapping_details_t *rmp;
708   snat_main_t *sm = &snat_main;
709
710   rmp = vl_msg_api_alloc (sizeof (*rmp));
711   clib_memset (rmp, 0, sizeof (*rmp));
712   rmp->_vl_msg_id =
713     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
714   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
715   rmp->external_sw_if_index = htonl (m->sw_if_index);
716   rmp->vrf_id = htonl (m->vrf_id);
717   rmp->context = context;
718
719   if (m->twice_nat)
720     rmp->flags |= NAT_API_IS_TWICE_NAT;
721
722   if (m->addr_only)
723     {
724       rmp->flags |= NAT_API_IS_ADDR_ONLY;
725     }
726   else
727     {
728       rmp->protocol = nat_proto_to_ip_proto (m->proto);
729       rmp->external_port = m->e_port;
730       rmp->local_port = m->l_port;
731     }
732   if (m->tag)
733     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
734
735   vl_api_send_msg (reg, (u8 *) rmp);
736 }
737
738 static void
739 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
740                                             * mp)
741 {
742   vl_api_registration_t *reg;
743   snat_main_t *sm = &snat_main;
744   snat_static_mapping_t *m;
745   snat_static_map_resolve_t *rp;
746   int j;
747
748   reg = vl_api_client_index_to_registration (mp->client_index);
749   if (!reg)
750     return;
751
752   pool_foreach (m, sm->static_mappings)
753    {
754      if (!is_sm_identity_nat (m->flags) && !is_sm_lb (m->flags))
755        send_nat44_static_mapping_details (m, reg, mp->context);
756   }
757
758   for (j = 0; j < vec_len (sm->to_resolve); j++)
759     {
760       rp = sm->to_resolve + j;
761       if (!rp->identity_nat)
762         send_nat44_static_map_resolve_details (rp, reg, mp->context);
763     }
764 }
765
766 static void
767   vl_api_nat44_add_del_identity_mapping_t_handler
768   (vl_api_nat44_add_del_identity_mapping_t * mp)
769 {
770   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
771
772   snat_main_t *sm = &snat_main;
773   int rv = 0;
774
775   ip4_address_t addr, pool_addr = { 0 };
776   u32 sw_if_index, flags, vrf_id;
777   nat_protocol_t proto = 0;
778   u16 port = 0;
779   u8 *tag = 0;
780
781   flags = NAT_SM_FLAG_IDENTITY_NAT;
782
783   if (mp->flags & NAT_API_IS_ADDR_ONLY)
784     {
785       flags |= NAT_SM_FLAG_ADDR_ONLY;
786     }
787   else
788     {
789       port = mp->port;
790       proto = ip_proto_to_nat_proto (mp->protocol);
791     }
792
793   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
794   if (sw_if_index != ~0)
795     {
796       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
797     }
798   else
799     {
800       memcpy (&addr.as_u8, mp->ip_address, 4);
801     }
802
803   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
804
805   if (mp->is_add)
806     {
807       mp->tag[sizeof (mp->tag) - 1] = 0;
808       tag = format (0, "%s", mp->tag);
809       vec_terminate_c_string (tag);
810
811       rv = nat44_ed_add_static_mapping (addr, addr, port, port, proto, vrf_id,
812                                         sw_if_index, flags, pool_addr, tag);
813       vec_free (tag);
814     }
815   else
816     {
817       rv = nat44_ed_del_static_mapping (addr, addr, port, port, proto, vrf_id,
818                                         sw_if_index, flags);
819     }
820   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
821 }
822
823 static void
824 send_nat44_identity_mapping_details (snat_static_mapping_t * m, int index,
825                                      vl_api_registration_t * reg, u32 context)
826 {
827   vl_api_nat44_identity_mapping_details_t *rmp;
828   snat_main_t *sm = &snat_main;
829   nat44_lb_addr_port_t *local = pool_elt_at_index (m->locals, index);
830
831   rmp = vl_msg_api_alloc (sizeof (*rmp));
832   clib_memset (rmp, 0, sizeof (*rmp));
833   rmp->_vl_msg_id =
834     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
835
836   if (is_sm_addr_only (m->flags))
837     rmp->flags |= NAT_API_IS_ADDR_ONLY;
838
839   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
840   rmp->port = m->local_port;
841   rmp->sw_if_index = ~0;
842   rmp->vrf_id = htonl (local->vrf_id);
843   rmp->protocol = nat_proto_to_ip_proto (m->proto);
844   rmp->context = context;
845   if (m->tag)
846     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
847
848   vl_api_send_msg (reg, (u8 *) rmp);
849 }
850
851 static void
852 send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
853                                          vl_api_registration_t * reg,
854                                          u32 context)
855 {
856   vl_api_nat44_identity_mapping_details_t *rmp;
857   snat_main_t *sm = &snat_main;
858
859   rmp = vl_msg_api_alloc (sizeof (*rmp));
860   clib_memset (rmp, 0, sizeof (*rmp));
861   rmp->_vl_msg_id =
862     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
863
864   if (m->addr_only)
865     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_ADDR_ONLY;
866
867   rmp->port = m->l_port;
868   rmp->sw_if_index = htonl (m->sw_if_index);
869   rmp->vrf_id = htonl (m->vrf_id);
870   rmp->protocol = nat_proto_to_ip_proto (m->proto);
871   rmp->context = context;
872   if (m->tag)
873     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
874
875   vl_api_send_msg (reg, (u8 *) rmp);
876 }
877
878 static void
879   vl_api_nat44_identity_mapping_dump_t_handler
880   (vl_api_nat44_identity_mapping_dump_t * mp)
881 {
882   vl_api_registration_t *reg;
883   snat_main_t *sm = &snat_main;
884   snat_static_mapping_t *m;
885   snat_static_map_resolve_t *rp;
886   int j;
887
888   reg = vl_api_client_index_to_registration (mp->client_index);
889   if (!reg)
890     return;
891
892   pool_foreach (m, sm->static_mappings)
893    {
894      if (is_sm_identity_nat (m->flags) && !is_sm_lb (m->flags))
895        {
896          pool_foreach_index (j, m->locals)
897            {
898              send_nat44_identity_mapping_details (m, j, reg, mp->context);
899            }
900        }
901   }
902
903   for (j = 0; j < vec_len (sm->to_resolve); j++)
904     {
905       rp = sm->to_resolve + j;
906       if (rp->identity_nat)
907         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
908     }
909 }
910
911 static void
912   vl_api_nat44_add_del_interface_addr_t_handler
913   (vl_api_nat44_add_del_interface_addr_t * mp)
914 {
915   snat_main_t *sm = &snat_main;
916   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
917   u32 sw_if_index = ntohl (mp->sw_if_index);
918   int rv = 0;
919   u8 is_del;
920
921   if (sm->static_mapping_only)
922     {
923       rv = VNET_API_ERROR_FEATURE_DISABLED;
924       goto send_reply;
925     }
926
927   is_del = !mp->is_add;
928
929   VALIDATE_SW_IF_INDEX (mp);
930
931   rv = snat_add_interface_address (sm, sw_if_index, is_del,
932                                    mp->flags & NAT_API_IS_TWICE_NAT);
933
934   BAD_SW_IF_INDEX_LABEL;
935
936 send_reply:
937   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
938 }
939
940 static void
941 send_nat44_interface_addr_details (u32 sw_if_index,
942                                    vl_api_registration_t * reg, u32 context,
943                                    u8 twice_nat)
944 {
945   vl_api_nat44_interface_addr_details_t *rmp;
946   snat_main_t *sm = &snat_main;
947
948   rmp = vl_msg_api_alloc (sizeof (*rmp));
949   clib_memset (rmp, 0, sizeof (*rmp));
950   rmp->_vl_msg_id =
951     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
952   rmp->sw_if_index = ntohl (sw_if_index);
953
954   if (twice_nat)
955     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_TWICE_NAT;
956   rmp->context = context;
957
958   vl_api_send_msg (reg, (u8 *) rmp);
959 }
960
961 static void
962 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
963                                             * mp)
964 {
965   vl_api_registration_t *reg;
966   snat_main_t *sm = &snat_main;
967   u32 *i;
968
969   reg = vl_api_client_index_to_registration (mp->client_index);
970   if (!reg)
971     return;
972
973   vec_foreach (i, sm->auto_add_sw_if_indices)
974     {
975       send_nat44_interface_addr_details (*i, reg, mp->context, 0);
976     }
977   vec_foreach (i, sm->auto_add_sw_if_indices_twice_nat)
978     {
979       send_nat44_interface_addr_details (*i, reg, mp->context, 1);
980     }
981 }
982
983 static nat44_lb_addr_port_t *
984 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t *addr_port_pairs,
985                              u32 addr_port_pair_num)
986 {
987   u8 i;
988   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
989   vl_api_nat44_lb_addr_port_t *ap;
990
991   for (i = 0; i < addr_port_pair_num; i++)
992     {
993       ap = &addr_port_pairs[i];
994       clib_memset (&lb_addr_port, 0, sizeof (lb_addr_port));
995       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
996       lb_addr_port.port = ap->port;
997       lb_addr_port.probability = ap->probability;
998       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
999       vec_add1 (lb_addr_port_pairs, lb_addr_port);
1000     }
1001
1002   return lb_addr_port_pairs;
1003 }
1004
1005 static void
1006 vl_api_nat44_add_del_lb_static_mapping_t_handler (
1007   vl_api_nat44_add_del_lb_static_mapping_t *mp)
1008 {
1009   snat_main_t *sm = &snat_main;
1010   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
1011   nat44_lb_addr_port_t *locals = 0;
1012   ip4_address_t e_addr;
1013   nat_protocol_t proto;
1014   u32 flags = 0;
1015   u8 *tag = 0;
1016   int rv = 0;
1017
1018   locals = unformat_nat44_lb_addr_port (mp->locals,
1019                                         clib_net_to_host_u32 (mp->local_num));
1020   clib_memcpy (&e_addr, mp->external_addr, 4);
1021   proto = ip_proto_to_nat_proto (mp->protocol);
1022
1023   if (mp->flags & NAT_API_IS_TWICE_NAT)
1024     {
1025       flags |= NAT_SM_FLAG_TWICE_NAT;
1026     }
1027   else if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
1028     {
1029       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
1030     }
1031
1032   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
1033     {
1034       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
1035     }
1036
1037   if (mp->is_add)
1038     {
1039       mp->tag[sizeof (mp->tag) - 1] = 0;
1040       tag = format (0, "%s", mp->tag);
1041       vec_terminate_c_string (tag);
1042
1043       rv = nat44_ed_add_lb_static_mapping (
1044         e_addr, mp->external_port, proto, locals, flags, tag,
1045         clib_net_to_host_u32 (mp->affinity));
1046     }
1047   else
1048     {
1049       rv = nat44_ed_del_lb_static_mapping (e_addr, mp->external_port, proto,
1050                                            flags);
1051     }
1052
1053   vec_free (locals);
1054   vec_free (tag);
1055   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1056 }
1057
1058 static void
1059 vl_api_nat44_lb_static_mapping_add_del_local_t_handler (
1060   vl_api_nat44_lb_static_mapping_add_del_local_t *mp)
1061 {
1062   snat_main_t *sm = &snat_main;
1063   vl_api_nat44_lb_static_mapping_add_del_local_reply_t *rmp;
1064   int rv = 0;
1065   ip4_address_t e_addr, l_addr;
1066   nat_protocol_t proto;
1067
1068   clib_memcpy (&e_addr, mp->external_addr, 4);
1069   clib_memcpy (&l_addr, mp->local.addr, 4);
1070   proto = ip_proto_to_nat_proto (mp->protocol);
1071
1072   rv = nat44_ed_add_del_lb_static_mapping_local (
1073     e_addr, mp->external_port, l_addr, mp->local.port, proto,
1074     clib_net_to_host_u32 (mp->local.vrf_id), mp->local.probability,
1075     mp->is_add);
1076
1077   REPLY_MACRO (VL_API_NAT44_LB_STATIC_MAPPING_ADD_DEL_LOCAL_REPLY);
1078 }
1079
1080 static void
1081 send_nat44_lb_static_mapping_details (snat_static_mapping_t *m,
1082                                       vl_api_registration_t *reg, u32 context)
1083 {
1084   vl_api_nat44_lb_static_mapping_details_t *rmp;
1085   snat_main_t *sm = &snat_main;
1086   nat44_lb_addr_port_t *ap;
1087   vl_api_nat44_lb_addr_port_t *locals;
1088   u32 local_num = 0;
1089
1090   rmp = vl_msg_api_alloc (
1091     sizeof (*rmp) + (pool_elts (m->locals) * sizeof (nat44_lb_addr_port_t)));
1092   clib_memset (rmp, 0, sizeof (*rmp));
1093   rmp->_vl_msg_id =
1094     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1095
1096   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1097   rmp->external_port = m->external_port;
1098   rmp->protocol = nat_proto_to_ip_proto (m->proto);
1099   rmp->context = context;
1100
1101   if (is_sm_self_twice_nat (m->flags))
1102     {
1103       rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
1104     }
1105
1106   if (is_sm_out2in_only (m->flags))
1107     {
1108       rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
1109     }
1110
1111   if (is_sm_twice_nat (m->flags))
1112     {
1113       rmp->flags |= NAT_API_IS_TWICE_NAT;
1114     }
1115
1116   if (m->tag)
1117     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1118
1119   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1120   pool_foreach (ap, m->locals)
1121     {
1122       clib_memcpy (locals->addr, &(ap->addr), 4);
1123       locals->port = ap->port;
1124       locals->probability = ap->probability;
1125       locals->vrf_id = ntohl (ap->vrf_id);
1126       locals++;
1127       local_num++;
1128     }
1129   rmp->local_num = ntohl (local_num);
1130
1131   vl_api_send_msg (reg, (u8 *) rmp);
1132 }
1133
1134 static void
1135 vl_api_nat44_lb_static_mapping_dump_t_handler (
1136   vl_api_nat44_lb_static_mapping_dump_t *mp)
1137 {
1138   vl_api_registration_t *reg;
1139   snat_main_t *sm = &snat_main;
1140   snat_static_mapping_t *m;
1141
1142   reg = vl_api_client_index_to_registration (mp->client_index);
1143   if (!reg)
1144     return;
1145
1146   pool_foreach (m, sm->static_mappings)
1147     {
1148       if (is_sm_lb (m->flags))
1149         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1150     }
1151 }
1152
1153 static void
1154 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t *mp)
1155 {
1156   snat_main_t *sm = &snat_main;
1157   vl_api_nat44_del_session_reply_t *rmp;
1158   ip4_address_t addr, eh_addr;
1159   u16 port, eh_port;
1160   u32 vrf_id;
1161   int rv = 0;
1162   u8 is_in;
1163
1164   memcpy (&addr.as_u8, mp->address, 4);
1165   port = mp->port;
1166   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1167   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1168   eh_port = mp->ext_host_port;
1169
1170   is_in = mp->flags & NAT_API_IS_INSIDE;
1171
1172   rv = nat44_ed_del_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1173                              vrf_id, is_in);
1174
1175   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1176 }
1177
1178 static void
1179 vl_api_nat44_forwarding_enable_disable_t_handler (
1180   vl_api_nat44_forwarding_enable_disable_t *mp)
1181 {
1182   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1183   snat_main_t *sm = &snat_main;
1184   int rv = 0;
1185   nat44_ed_forwarding_enable_disable (mp->enable);
1186   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1187 }
1188
1189 static void
1190 vl_api_nat44_forwarding_is_enabled_t_handler (
1191   vl_api_nat44_forwarding_is_enabled_t *mp)
1192 {
1193   vl_api_registration_t *reg;
1194   snat_main_t *sm = &snat_main;
1195   vl_api_nat44_forwarding_is_enabled_reply_t *rmp;
1196
1197   reg = vl_api_client_index_to_registration (mp->client_index);
1198   if (!reg)
1199     return;
1200
1201   rmp = vl_msg_api_alloc (sizeof (*rmp));
1202   clib_memset (rmp, 0, sizeof (*rmp));
1203   rmp->_vl_msg_id =
1204     ntohs (VL_API_NAT44_FORWARDING_IS_ENABLED_REPLY + sm->msg_id_base);
1205   rmp->context = mp->context;
1206
1207   rmp->enabled = sm->forwarding_enabled;
1208
1209   vl_api_send_msg (reg, (u8 *) rmp);
1210 }
1211
1212 /* Obsolete calls hold back because of deprecation
1213  * should not be used */
1214
1215 static void
1216 vl_api_nat_set_addr_and_port_alloc_alg_t_handler (
1217   vl_api_nat_set_addr_and_port_alloc_alg_t *mp)
1218 {
1219   snat_main_t *sm = &snat_main;
1220   vl_api_nat_set_addr_and_port_alloc_alg_reply_t *rmp;
1221   int rv = VNET_API_ERROR_UNSUPPORTED;
1222   REPLY_MACRO (VL_API_NAT_SET_ADDR_AND_PORT_ALLOC_ALG_REPLY);
1223 }
1224
1225 static void
1226 vl_api_nat_get_addr_and_port_alloc_alg_t_handler (
1227   vl_api_nat_get_addr_and_port_alloc_alg_t *mp)
1228 {
1229   snat_main_t *sm = &snat_main;
1230   vl_api_nat_get_addr_and_port_alloc_alg_reply_t *rmp;
1231   int rv = VNET_API_ERROR_UNSUPPORTED;
1232   REPLY_MACRO (VL_API_NAT_GET_ADDR_AND_PORT_ALLOC_ALG_REPLY);
1233 }
1234
1235 static void
1236 vl_api_nat_ha_set_listener_t_handler (vl_api_nat_ha_set_listener_t *mp)
1237 {
1238   snat_main_t *sm = &snat_main;
1239   vl_api_nat_ha_set_listener_reply_t *rmp;
1240   int rv = VNET_API_ERROR_UNSUPPORTED;
1241   REPLY_MACRO (VL_API_NAT_HA_SET_LISTENER_REPLY);
1242 }
1243
1244 static void
1245 vl_api_nat_ha_get_listener_t_handler (vl_api_nat_ha_get_listener_t *mp)
1246 {
1247   snat_main_t *sm = &snat_main;
1248   vl_api_nat_ha_get_listener_reply_t *rmp;
1249   int rv = VNET_API_ERROR_UNSUPPORTED;
1250   REPLY_MACRO (VL_API_NAT_HA_GET_LISTENER_REPLY);
1251 }
1252
1253 static void
1254 vl_api_nat_ha_set_failover_t_handler (vl_api_nat_ha_set_failover_t *mp)
1255 {
1256   snat_main_t *sm = &snat_main;
1257   vl_api_nat_ha_set_failover_reply_t *rmp;
1258   int rv = VNET_API_ERROR_UNSUPPORTED;
1259   REPLY_MACRO (VL_API_NAT_HA_SET_FAILOVER_REPLY);
1260 }
1261
1262 static void
1263 vl_api_nat_ha_get_failover_t_handler (vl_api_nat_ha_get_failover_t *mp)
1264 {
1265   snat_main_t *sm = &snat_main;
1266   vl_api_nat_ha_get_failover_reply_t *rmp;
1267   int rv = VNET_API_ERROR_UNSUPPORTED;
1268   REPLY_MACRO (VL_API_NAT_HA_GET_FAILOVER_REPLY);
1269 }
1270
1271 static void
1272 vl_api_nat_ha_flush_t_handler (vl_api_nat_ha_flush_t *mp)
1273 {
1274   snat_main_t *sm = &snat_main;
1275   vl_api_nat_ha_flush_reply_t *rmp;
1276   int rv = VNET_API_ERROR_UNSUPPORTED;
1277   REPLY_MACRO (VL_API_NAT_HA_FLUSH_REPLY);
1278 }
1279
1280 static void
1281 vl_api_nat_ha_resync_t_handler (vl_api_nat_ha_resync_t *mp)
1282 {
1283   snat_main_t *sm = &snat_main;
1284   vl_api_nat_ha_resync_reply_t *rmp;
1285   int rv = VNET_API_ERROR_UNSUPPORTED;
1286   REPLY_MACRO (VL_API_NAT_HA_RESYNC_REPLY);
1287 }
1288
1289 static void
1290 vl_api_nat44_del_user_t_handler (vl_api_nat44_del_user_t *mp)
1291 {
1292   snat_main_t *sm = &snat_main;
1293   vl_api_nat44_del_user_reply_t *rmp;
1294   int rv = VNET_API_ERROR_UNSUPPORTED;
1295   REPLY_MACRO (VL_API_NAT44_DEL_USER_REPLY);
1296 }
1297
1298 static void
1299 vl_api_nat44_session_cleanup_t_handler (vl_api_nat44_session_cleanup_t *mp)
1300 {
1301   snat_main_t *sm = &snat_main;
1302   vl_api_nat44_session_cleanup_reply_t *rmp;
1303   int rv = VNET_API_ERROR_UNSUPPORTED;
1304   REPLY_MACRO (VL_API_NAT44_SESSION_CLEANUP_REPLY);
1305 }
1306
1307 static void
1308 vl_api_nat44_plugin_enable_disable_t_handler (
1309   vl_api_nat44_plugin_enable_disable_t *mp)
1310 {
1311   snat_main_t *sm = &snat_main;
1312   nat44_config_t c = { 0 };
1313   vl_api_nat44_plugin_enable_disable_reply_t *rmp;
1314   int rv = 0;
1315
1316   if (mp->enable)
1317     {
1318       if (mp->users || mp->user_sessions)
1319         {
1320           rv = VNET_API_ERROR_UNSUPPORTED;
1321         }
1322       else
1323         {
1324           c.static_mapping_only = mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY;
1325           c.connection_tracking = mp->flags & NAT44_API_IS_CONNECTION_TRACKING;
1326
1327           c.inside_vrf = ntohl (mp->inside_vrf);
1328           c.outside_vrf = ntohl (mp->outside_vrf);
1329
1330           c.sessions = ntohl (mp->sessions);
1331
1332           rv = nat44_plugin_enable (c);
1333         }
1334     }
1335   else
1336     {
1337       rv = nat44_plugin_disable ();
1338     }
1339
1340   REPLY_MACRO (VL_API_NAT44_PLUGIN_ENABLE_DISABLE_REPLY);
1341 }
1342
1343 static void
1344 vl_api_nat_control_ping_t_handler (vl_api_nat_control_ping_t *mp)
1345 {
1346   vl_api_nat_control_ping_reply_t *rmp;
1347   snat_main_t *sm = &snat_main;
1348   int rv = 0;
1349
1350   REPLY_MACRO2 (VL_API_NAT_CONTROL_PING_REPLY,
1351                 ({ rmp->vpe_pid = ntohl (getpid ()); }));
1352 }
1353
1354 static void
1355 vl_api_nat_show_config_t_handler (vl_api_nat_show_config_t *mp)
1356 {
1357   vl_api_nat_show_config_reply_t *rmp;
1358   snat_main_t *sm = &snat_main;
1359   int rv = 0;
1360
1361   REPLY_MACRO2_ZERO (VL_API_NAT_SHOW_CONFIG_REPLY, ({
1362                        rmp->translation_buckets =
1363                          htonl (sm->translation_buckets);
1364                        rmp->user_buckets = 0;
1365                        rmp->max_translations_per_user = 0;
1366                        rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
1367                        rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
1368                        rmp->static_mapping_only = sm->static_mapping_only;
1369                        rmp->static_mapping_connection_tracking =
1370                          sm->static_mapping_connection_tracking;
1371                        rmp->endpoint_dependent = 1;
1372                        rmp->out2in_dpo = 0;
1373                      }));
1374 }
1375
1376 static void
1377 vl_api_nat_show_config_2_t_handler (vl_api_nat_show_config_2_t *mp)
1378 {
1379   vl_api_nat_show_config_2_reply_t *rmp;
1380   snat_main_t *sm = &snat_main;
1381   int rv = 0;
1382
1383   REPLY_MACRO2_ZERO (
1384     VL_API_NAT_SHOW_CONFIG_2_REPLY, ({
1385       rmp->translation_buckets = htonl (sm->translation_buckets);
1386       rmp->user_buckets = 0;
1387       rmp->max_translations_per_user = 0;
1388       rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
1389       rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
1390       rmp->static_mapping_only = sm->static_mapping_only;
1391       rmp->static_mapping_connection_tracking =
1392         sm->static_mapping_connection_tracking;
1393       rmp->endpoint_dependent = 1;
1394       rmp->out2in_dpo = 0;
1395       rmp->max_translations_per_thread =
1396         clib_net_to_host_u32 (sm->max_translations_per_thread);
1397       rmp->max_users_per_thread = 0;
1398     }));
1399 }
1400
1401 static void
1402 vl_api_nat44_show_running_config_t_handler (
1403   vl_api_nat44_show_running_config_t *mp)
1404 {
1405   vl_api_nat44_show_running_config_reply_t *rmp;
1406   snat_main_t *sm = &snat_main;
1407   nat44_config_t *rc = &sm->rconfig;
1408   int rv = 0;
1409
1410   REPLY_MACRO2_ZERO (
1411     VL_API_NAT44_SHOW_RUNNING_CONFIG_REPLY, ({
1412       rmp->inside_vrf = htonl (rc->inside_vrf);
1413       rmp->outside_vrf = htonl (rc->outside_vrf);
1414
1415       rmp->sessions = htonl (rc->sessions);
1416       rmp->translation_buckets = htonl (sm->translation_buckets);
1417
1418       // OBSOLETE
1419       rmp->users = 0;
1420       rmp->user_buckets = 0;
1421       rmp->user_sessions = 0;
1422
1423       rmp->timeouts.udp = htonl (sm->timeouts.udp);
1424       rmp->timeouts.tcp_established = htonl (sm->timeouts.tcp.established);
1425       rmp->timeouts.tcp_transitory = htonl (sm->timeouts.tcp.transitory);
1426       rmp->timeouts.icmp = htonl (sm->timeouts.icmp);
1427
1428       rmp->forwarding_enabled = sm->forwarding_enabled == 1;
1429       // consider how to split functionality between subplugins
1430       rmp->ipfix_logging_enabled = nat_ipfix_logging_enabled ();
1431       rmp->flags |= NAT44_IS_ENDPOINT_DEPENDENT;
1432       if (rc->static_mapping_only)
1433         rmp->flags |= NAT44_IS_STATIC_MAPPING_ONLY;
1434       if (rc->connection_tracking)
1435         rmp->flags |= NAT44_IS_CONNECTION_TRACKING;
1436     }));
1437 }
1438
1439 /* user (internal host) key */
1440 typedef struct
1441 {
1442   union
1443   {
1444     struct
1445     {
1446       ip4_address_t addr;
1447       u32 fib_index;
1448     };
1449     u64 as_u64;
1450   };
1451 } snat_user_key_t;
1452
1453 typedef struct
1454 {
1455   ip4_address_t addr;
1456   u32 fib_index;
1457   u32 nsessions;
1458   u32 nstaticsessions;
1459 } snat_user_t;
1460
1461 typedef struct
1462 {
1463   u32 user_buckets;
1464   snat_user_t *users;
1465   clib_bihash_8_8_t user_hash;
1466 } user_create_helper_t;
1467
1468 static void
1469 send_nat44_user_details (snat_user_t *u, vl_api_registration_t *reg,
1470                          u32 context)
1471 {
1472   vl_api_nat44_user_details_t *rmp;
1473   snat_main_t *sm = &snat_main;
1474   ip4_main_t *im = &ip4_main;
1475
1476   rmp = vl_msg_api_alloc (sizeof (*rmp));
1477   clib_memset (rmp, 0, sizeof (*rmp));
1478   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1479
1480   if (!pool_is_free_index (im->fibs, u->fib_index))
1481     {
1482       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1483       rmp->vrf_id = ntohl (fib->ft_table_id);
1484     }
1485
1486   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1487   rmp->nsessions = ntohl (u->nsessions);
1488   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1489   rmp->context = context;
1490
1491   vl_api_send_msg (reg, (u8 *) rmp);
1492 }
1493
1494 static void
1495 nat_ed_user_create_helper (user_create_helper_t *uch, snat_session_t *s)
1496 {
1497   snat_user_key_t k;
1498   k.addr = s->in2out.addr;
1499   k.fib_index = s->in2out.fib_index;
1500   clib_bihash_kv_8_8_t key, value;
1501   key.key = k.as_u64;
1502   snat_user_t *u;
1503
1504   if (clib_bihash_search_8_8 (&uch->user_hash, &key, &value))
1505     {
1506       pool_get (uch->users, u);
1507       u->addr = k.addr;
1508       u->fib_index = k.fib_index;
1509       u->nsessions = 0;
1510       u->nstaticsessions = 0;
1511       key.value = u - uch->users;
1512       clib_bihash_add_del_8_8 (&uch->user_hash, &key, 1);
1513     }
1514   else
1515     {
1516       u = pool_elt_at_index (uch->users, value.value);
1517     }
1518   if (snat_is_session_static (s))
1519     {
1520       ++u->nstaticsessions;
1521     }
1522   else
1523     {
1524       ++u->nsessions;
1525     }
1526 }
1527
1528 u8 *
1529 format_user_kvp (u8 *s, va_list *args)
1530 {
1531   clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
1532   snat_user_key_t k;
1533   k.as_u64 = v->key;
1534   s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
1535               k.fib_index, v->value);
1536   return s;
1537 }
1538
1539 static void
1540 nat_ed_users_create (snat_main_per_thread_data_t *tsm,
1541                      user_create_helper_t *uch)
1542 {
1543   snat_session_t *s;
1544   clib_bihash_init_8_8 (&uch->user_hash, "users", uch->user_buckets, 0);
1545   clib_bihash_set_kvp_format_fn_8_8 (&uch->user_hash, format_user_kvp);
1546   pool_foreach (s, tsm->sessions)
1547     {
1548       nat_ed_user_create_helper (uch, s);
1549     }
1550 }
1551
1552 static void
1553 nat_ed_users_destroy (user_create_helper_t *uch)
1554 {
1555   pool_free (uch->users);
1556   clib_bihash_free_8_8 (&uch->user_hash);
1557 }
1558
1559 static void
1560 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1561 {
1562   user_create_helper_t uch;
1563   vl_api_registration_t *reg;
1564   snat_main_t *sm = &snat_main;
1565   snat_main_per_thread_data_t *tsm;
1566   snat_user_t *u;
1567
1568   clib_memset (&uch, 0, sizeof (uch));
1569
1570   uch.user_buckets = nat_calc_bihash_buckets (1024);
1571
1572   reg = vl_api_client_index_to_registration (mp->client_index);
1573   if (!reg)
1574     return;
1575
1576   vec_foreach (tsm, sm->per_thread_data)
1577     {
1578       nat_ed_users_create (tsm, &uch);
1579       pool_foreach (u, uch.users)
1580         {
1581           send_nat44_user_details (u, reg, mp->context);
1582         }
1583       nat_ed_users_destroy (&uch);
1584     }
1585 }
1586
1587 static void
1588 send_nat44_user_session_details (snat_session_t * s,
1589                                  vl_api_registration_t * reg, u32 context)
1590 {
1591   vl_api_nat44_user_session_details_t *rmp;
1592   snat_main_t *sm = &snat_main;
1593
1594   rmp = vl_msg_api_alloc (sizeof (*rmp));
1595   clib_memset (rmp, 0, sizeof (*rmp));
1596   rmp->_vl_msg_id =
1597     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1598   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1599   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1600
1601   if (snat_is_session_static (s))
1602     rmp->flags |= NAT_API_IS_STATIC;
1603
1604   if (is_twice_nat_session (s))
1605     rmp->flags |= NAT_API_IS_TWICE_NAT;
1606
1607   if (is_ed_session (s) || is_fwd_bypass_session (s))
1608     rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1609
1610   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1611   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1612   rmp->total_pkts = ntohl (s->total_pkts);
1613   rmp->context = context;
1614   if (snat_is_unk_proto_session (s))
1615     {
1616       rmp->outside_port = 0;
1617       rmp->inside_port = 0;
1618       rmp->protocol = ntohs (s->in2out.port);
1619     }
1620   else
1621     {
1622       rmp->outside_port = s->out2in.port;
1623       rmp->inside_port = s->in2out.port;
1624       rmp->protocol = ntohs (nat_proto_to_ip_proto (s->nat_proto));
1625     }
1626   if (is_ed_session (s) || is_fwd_bypass_session (s))
1627     {
1628       clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1629       rmp->ext_host_port = s->ext_host_port;
1630       if (is_twice_nat_session (s))
1631         {
1632           clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1633           rmp->ext_host_nat_port = s->ext_host_nat_port;
1634         }
1635     }
1636
1637   vl_api_send_msg (reg, (u8 *) rmp);
1638 }
1639
1640 static void
1641 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1642                                           mp)
1643 {
1644   snat_main_per_thread_data_t *tsm;
1645   snat_main_t *sm = &snat_main;
1646   vl_api_registration_t *reg;
1647   snat_user_key_t ukey;
1648   snat_session_t *s;
1649   ip4_header_t ip;
1650
1651   reg = vl_api_client_index_to_registration (mp->client_index);
1652   if (!reg)
1653     return;
1654
1655   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1656   ip.src_address.as_u32 = ukey.addr.as_u32;
1657   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1658   if (sm->num_workers > 1)
1659     tsm = vec_elt_at_index (
1660       sm->per_thread_data,
1661       nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
1662   else
1663     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1664
1665       pool_foreach (s, tsm->sessions) {
1666         if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1667           {
1668             send_nat44_user_session_details (s, reg, mp->context);
1669           }
1670       }
1671 }
1672
1673 /* API definitions */
1674 #include <vnet/format_fns.h>
1675 #include <nat/nat44-ed/nat44_ed.api.c>
1676
1677 /* Set up the API message handling tables */
1678 clib_error_t *
1679 nat44_api_hookup (vlib_main_t * vm)
1680 {
1681   snat_main_t *sm = &snat_main;
1682   sm->msg_id_base = setup_message_id_table ();
1683   return 0;
1684 }
1685
1686 /*
1687  * fd.io coding-style-patch-verification: ON
1688  *
1689  * Local Variables:
1690  * eval: (c-set-style "gnu")
1691  * End:
1692  */