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