LCOV - code coverage report
Current view: top level - plugins/nat/nat44-ed - nat44_ed_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 351 778 45.1 %
Date: 2023-10-26 01:39:38 Functions: 30 59 50.8 %

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

Generated by: LCOV version 1.14