LCOV - code coverage report
Current view: top level - plugins/dhcp - dhcp_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 299 404 74.0 %
Date: 2023-10-26 01:39:38 Functions: 24 29 82.8 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * dhcp_api.c - dhcp api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <vnet/vnet.h>
      21             : #include <vlibmemory/api.h>
      22             : 
      23             : #include <vnet/interface.h>
      24             : #include <vnet/api_errno.h>
      25             : #include <dhcp/dhcp_proxy.h>
      26             : #include <dhcp/client.h>
      27             : #include <dhcp/dhcp6_pd_client_dp.h>
      28             : #include <dhcp/dhcp6_ia_na_client_dp.h>
      29             : #include <dhcp/dhcp6_client_common_dp.h>
      30             : #include <vnet/fib/fib_table.h>
      31             : #include <vnet/ip/ip_types_api.h>
      32             : 
      33             : /* define message IDs */
      34             : #include <vnet/format_fns.h>
      35             : #include <dhcp/dhcp.api_enum.h>
      36             : #include <dhcp/dhcp.api_types.h>
      37             : 
      38             : /**
      39             :  * Base message ID fot the plugin
      40             :  */
      41             : static u32 dhcp_base_msg_id;
      42             : #define REPLY_MSG_ID_BASE dhcp_base_msg_id
      43             : 
      44             : #include <vlibapi/api_helper_macros.h>
      45             : 
      46             : #define  DHCP_PLUGIN_VERSION_MAJOR 1
      47             : #define  DHCP_PLUGIN_VERSION_MINOR 0
      48             : 
      49             : static void
      50           0 : vl_api_dhcp_plugin_get_version_t_handler (vl_api_dhcp_plugin_get_version_t *
      51             :                                           mp)
      52             : {
      53             :   vl_api_dhcp_plugin_get_version_reply_t *rmp;
      54           0 :   int msg_size = sizeof (*rmp);
      55             :   vl_api_registration_t *reg;
      56             : 
      57           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
      58           0 :   if (!reg)
      59           0 :     return;
      60             : 
      61           0 :   rmp = vl_msg_api_alloc (msg_size);
      62           0 :   clib_memset (rmp, 0, msg_size);
      63           0 :   rmp->_vl_msg_id =
      64           0 :     ntohs (VL_API_DHCP_PLUGIN_GET_VERSION_REPLY + REPLY_MSG_ID_BASE);
      65           0 :   rmp->context = mp->context;
      66           0 :   rmp->major = htonl (DHCP_PLUGIN_VERSION_MAJOR);
      67           0 :   rmp->minor = htonl (DHCP_PLUGIN_VERSION_MINOR);
      68             : 
      69           0 :   vl_api_send_msg (reg, (u8 *) rmp);
      70             : }
      71             : 
      72             : static void
      73           0 : vl_api_dhcp_plugin_control_ping_t_handler (vl_api_dhcp_plugin_control_ping_t *
      74             :                                            mp)
      75             : {
      76             :   vl_api_dhcp_plugin_control_ping_reply_t *rmp;
      77           0 :   int rv = 0;
      78             : 
      79             :   /* *INDENT-OFF* */
      80           0 :   REPLY_MACRO2 (VL_API_DHCP_PLUGIN_CONTROL_PING_REPLY,
      81             :   ({
      82             :     rmp->vpe_pid = ntohl (getpid ());
      83             :   }));
      84             :   /* *INDENT-ON* */
      85             : }
      86             : 
      87             : static void
      88           0 : vl_api_dhcp6_duid_ll_set_t_handler (vl_api_dhcp6_duid_ll_set_t * mp)
      89             : {
      90             :   vl_api_dhcp6_duid_ll_set_reply_t *rmp;
      91             :   dhcpv6_duid_ll_string_t *duid;
      92           0 :   int rv = 0;
      93             : 
      94           0 :   duid = (dhcpv6_duid_ll_string_t *) mp->duid_ll;
      95           0 :   if (duid->duid_type != htonl (DHCPV6_DUID_LL))
      96             :     {
      97           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
      98           0 :       goto reply;
      99             :     }
     100           0 :   clib_memcpy (&client_duid, &duid, sizeof (client_duid));
     101             : 
     102           0 : reply:
     103           0 :   REPLY_MACRO (VL_API_DHCP6_DUID_LL_SET_REPLY);
     104             : }
     105             : 
     106             : static void
     107           7 : vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
     108             : {
     109             :   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
     110             :   u8 *vpn_ascii_id;
     111             :   int rv;
     112             : 
     113           7 :   mp->vpn_ascii_id[sizeof (mp->vpn_ascii_id) - 1] = 0;
     114           7 :   vpn_ascii_id = format (0, "%s", mp->vpn_ascii_id);
     115             :   rv =
     116           7 :     dhcp_proxy_set_vss ((mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4),
     117           7 :                         ntohl (mp->tbl_id), ntohl (mp->vss_type),
     118             :                         vpn_ascii_id, ntohl (mp->oui), ntohl (mp->vpn_index),
     119           7 :                         mp->is_add == 0);
     120             : 
     121           7 :   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
     122             : }
     123             : 
     124             : 
     125          16 : static void vl_api_dhcp_proxy_config_t_handler
     126             :   (vl_api_dhcp_proxy_config_t * mp)
     127             : {
     128             :   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
     129             :   ip46_address_t src, server;
     130          16 :   int rv = -1;
     131             : 
     132          16 :   if (mp->dhcp_src_address.af != mp->dhcp_server.af)
     133             :     {
     134           0 :       rv = VNET_API_ERROR_INVALID_ARGUMENT;
     135           0 :       goto reply;
     136             :     }
     137             : 
     138          16 :   ip_address_decode (&mp->dhcp_src_address, &src);
     139          16 :   ip_address_decode (&mp->dhcp_server, &server);
     140             : 
     141          16 :   if (mp->dhcp_src_address.af == ADDRESS_IP4)
     142             :     {
     143           8 :       rv = dhcp4_proxy_set_server (&server,
     144             :                                    &src,
     145           8 :                                    (u32) ntohl (mp->rx_vrf_id),
     146           8 :                                    (u32) ntohl (mp->server_vrf_id),
     147           8 :                                    (int) (mp->is_add == 0));
     148             :     }
     149             :   else
     150             :     {
     151           8 :       rv = dhcp6_proxy_set_server (&server,
     152             :                                    &src,
     153           8 :                                    (u32) ntohl (mp->rx_vrf_id),
     154           8 :                                    (u32) ntohl (mp->server_vrf_id),
     155           8 :                                    (int) (mp->is_add == 0));
     156             :     }
     157             : 
     158          16 : reply:
     159          16 :   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
     160             : }
     161             : 
     162             : static void
     163           6 : vl_api_dhcp_proxy_dump_t_handler (vl_api_dhcp_proxy_dump_t * mp)
     164             : {
     165             :   vl_api_registration_t *reg;
     166             : 
     167           6 :   reg = vl_api_client_index_to_registration (mp->client_index);
     168           6 :   if (!reg)
     169           0 :     return;;
     170             : 
     171           6 :   dhcp_proxy_dump ((mp->is_ip6 == 1 ?
     172             :                     FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4), reg, mp->context);
     173             : }
     174             : 
     175             : void
     176           0 : dhcp_send_details (fib_protocol_t proto,
     177             :                    void *opaque, u32 context, dhcp_proxy_t * proxy)
     178             : {
     179             :   vl_api_dhcp_proxy_details_t *mp;
     180           0 :   vl_api_registration_t *reg = opaque;
     181             :   vl_api_dhcp_server_t *v_server;
     182             :   dhcp_server_t *server;
     183             :   fib_table_t *s_fib;
     184             :   dhcp_vss_t *vss;
     185             :   u32 count;
     186             :   size_t n;
     187             : 
     188           0 :   count = vec_len (proxy->dhcp_servers);
     189           0 :   n = sizeof (*mp) + (count * sizeof (vl_api_dhcp_server_t));
     190           0 :   mp = vl_msg_api_alloc (n);
     191           0 :   if (!mp)
     192           0 :     return;
     193           0 :   clib_memset (mp, 0, n);
     194           0 :   mp->_vl_msg_id = ntohs (VL_API_DHCP_PROXY_DETAILS + REPLY_MSG_ID_BASE);
     195           0 :   mp->context = context;
     196           0 :   mp->count = count;
     197             : 
     198           0 :   mp->is_ipv6 = (proto == FIB_PROTOCOL_IP6);
     199           0 :   mp->rx_vrf_id =
     200           0 :     htonl (dhcp_proxy_rx_table_get_table_id (proto, proxy->rx_fib_index));
     201             : 
     202           0 :   vss = dhcp_get_vss_info (&dhcp_proxy_main, proxy->rx_fib_index, proto);
     203             : 
     204           0 :   if (vss)
     205             :     {
     206           0 :       mp->vss_type = ntohl (vss->vss_type);
     207           0 :       if (vss->vss_type == VSS_TYPE_ASCII)
     208             :         {
     209           0 :           u32 id_len = vec_len (vss->vpn_ascii_id);
     210           0 :           clib_memcpy (mp->vss_vpn_ascii_id, vss->vpn_ascii_id, id_len);
     211             :         }
     212           0 :       else if (vss->vss_type == VSS_TYPE_VPN_ID)
     213             :         {
     214           0 :           u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8)
     215           0 :             + ((u32) vss->vpn_id[2]);
     216           0 :           u32 fib_id = ((u32) vss->vpn_id[3] << 24) +
     217           0 :             ((u32) vss->vpn_id[4] << 16) + ((u32) vss->vpn_id[5] << 8) +
     218           0 :             ((u32) vss->vpn_id[6]);
     219           0 :           mp->vss_oui = htonl (oui);
     220           0 :           mp->vss_fib_id = htonl (fib_id);
     221             :         }
     222             :     }
     223             :   else
     224           0 :     mp->vss_type = VSS_TYPE_INVALID;
     225             : 
     226           0 :   vec_foreach_index (count, proxy->dhcp_servers)
     227             :   {
     228           0 :     server = &proxy->dhcp_servers[count];
     229           0 :     v_server = &mp->servers[count];
     230             : 
     231           0 :     s_fib = fib_table_get (server->server_fib_index, proto);
     232             : 
     233           0 :     v_server->server_vrf_id = htonl (s_fib->ft_table_id);
     234             : 
     235           0 :     if (mp->is_ipv6)
     236             :       {
     237           0 :         memcpy (&v_server->dhcp_server.un, &server->dhcp_server.ip6, 16);
     238             :       }
     239             :     else
     240             :       {
     241             :         /* put the address in the first bytes */
     242           0 :         memcpy (&v_server->dhcp_server.un, &server->dhcp_server.ip4, 4);
     243             :       }
     244             :   }
     245             : 
     246           0 :   if (mp->is_ipv6)
     247             :     {
     248           0 :       memcpy (&mp->dhcp_src_address.un, &proxy->dhcp_src_address.ip6, 16);
     249             :     }
     250             :   else
     251             :     {
     252             :       /* put the address in the first bytes */
     253           0 :       memcpy (&mp->dhcp_src_address.un, &proxy->dhcp_src_address.ip4, 4);
     254             :     }
     255           0 :   vl_api_send_msg (reg, (u8 *) mp);
     256             : }
     257             : 
     258             : static void
     259           4 : dhcp_client_lease_encode (vl_api_dhcp_lease_t * lease,
     260             :                           const dhcp_client_t * client)
     261             : {
     262             :   size_t len;
     263             :   u8 i;
     264             : 
     265           4 :   lease->is_ipv6 = 0;                // only support IPv4 clients
     266           4 :   lease->sw_if_index = ntohl (client->sw_if_index);
     267           4 :   lease->state = ntohl (client->state);
     268           4 :   len = clib_min (sizeof (lease->hostname) - 1, vec_len (client->hostname));
     269           4 :   clib_memcpy (&lease->hostname, client->hostname, len);
     270           4 :   lease->hostname[len] = 0;
     271             : 
     272           4 :   lease->mask_width = client->installed.subnet_mask_width;
     273           4 :   clib_memcpy (&lease->host_address.un,
     274             :                (u8 *) & client->installed.leased_address,
     275             :                sizeof (ip4_address_t));
     276           4 :   clib_memcpy (&lease->router_address.un,
     277             :                (u8 *) & client->installed.router_address,
     278             :                sizeof (ip4_address_t));
     279             : 
     280           4 :   lease->count = vec_len (client->domain_server_address);
     281           4 :   for (i = 0; i < lease->count; i++)
     282           0 :     clib_memcpy (&lease->domain_server[i].address.un.ip4,
     283             :                  (u8 *) &client->domain_server_address[i],
     284             :                  sizeof (ip4_address_t));
     285             : 
     286           4 :   clib_memcpy (&lease->host_mac[0], client->client_hardware_address, 6);
     287           4 : }
     288             : 
     289             : static void
     290           4 : dhcp_client_data_encode (vl_api_dhcp_client_t * vclient,
     291             :                          const dhcp_client_t * client)
     292             : {
     293             :   size_t len;
     294             : 
     295           4 :   vclient->sw_if_index = ntohl (client->sw_if_index);
     296           4 :   len = clib_min (sizeof (vclient->hostname) - 1, vec_len (client->hostname));
     297           4 :   clib_memcpy (&vclient->hostname, client->hostname, len);
     298           4 :   vclient->hostname[len] = 0;
     299             : 
     300           4 :   len = clib_min (sizeof (vclient->id) - 1,
     301             :                   vec_len (client->client_identifier));
     302           4 :   clib_memcpy (&vclient->id, client->client_identifier, len);
     303           4 :   vclient->id[len] = 0;
     304             : 
     305           4 :   if (NULL != client->event_callback)
     306           0 :     vclient->want_dhcp_event = 1;
     307             :   else
     308           4 :     vclient->want_dhcp_event = 0;
     309           4 :   vclient->set_broadcast_flag = client->set_broadcast_flag;
     310           4 :   vclient->dscp = ip_dscp_encode (client->dscp);
     311           4 :   vclient->pid = client->pid;
     312           4 : }
     313             : 
     314             : static void
     315           0 : dhcp_compl_event_callback (u32 client_index, const dhcp_client_t * client)
     316             : {
     317             :   vl_api_registration_t *reg;
     318             :   vl_api_dhcp_compl_event_t *mp;
     319             : 
     320           0 :   reg = vl_api_client_index_to_registration (client_index);
     321           0 :   if (!reg)
     322           0 :     return;
     323             : 
     324           0 :   mp = vl_msg_api_alloc (sizeof (*mp) +
     325           0 :                          sizeof (vl_api_domain_server_t) *
     326           0 :                            vec_len (client->domain_server_address));
     327           0 :   mp->client_index = client_index;
     328           0 :   mp->pid = client->pid;
     329           0 :   dhcp_client_lease_encode (&mp->lease, client);
     330             : 
     331           0 :   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT + REPLY_MSG_ID_BASE);
     332             : 
     333           0 :   vl_api_send_msg (reg, (u8 *) mp);
     334             : }
     335             : 
     336          10 : static void vl_api_dhcp_client_config_t_handler
     337             :   (vl_api_dhcp_client_config_t * mp)
     338             : {
     339          10 :   vlib_main_t *vm = vlib_get_main ();
     340             :   vl_api_dhcp_client_config_reply_t *rmp;
     341             :   u32 sw_if_index;
     342             :   ip_dscp_t dscp;
     343          10 :   int rv = 0;
     344             : 
     345          10 :   VALIDATE_SW_IF_INDEX (&(mp->client));
     346             : 
     347          10 :   sw_if_index = ntohl (mp->client.sw_if_index);
     348          10 :   dscp = ip_dscp_decode (mp->client.dscp);
     349             : 
     350          10 :   rv = dhcp_client_config (mp->is_add,
     351             :                            mp->client_index,
     352             :                            vm,
     353             :                            sw_if_index,
     354          10 :                            mp->client.hostname,
     355          10 :                            mp->client.id,
     356          10 :                            (mp->client.want_dhcp_event ?
     357             :                             dhcp_compl_event_callback :
     358             :                             NULL),
     359          10 :                            mp->client.set_broadcast_flag,
     360             :                            dscp, mp->client.pid);
     361             : 
     362          10 :   BAD_SW_IF_INDEX_LABEL;
     363          10 :   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
     364             : }
     365             : 
     366             : typedef struct dhcp_client_send_walk_ctx_t_
     367             : {
     368             :   vl_api_registration_t *reg;
     369             :   u32 context;
     370             : } dhcp_client_send_walk_ctx_t;
     371             : 
     372             : static int
     373           4 : send_dhcp_client_entry (const dhcp_client_t * client, void *arg)
     374             : {
     375             :   dhcp_client_send_walk_ctx_t *ctx;
     376             :   vl_api_dhcp_client_details_t *mp;
     377             :   u32 count;
     378             :   size_t n;
     379             : 
     380           4 :   ctx = arg;
     381             : 
     382           4 :   count = vec_len (client->domain_server_address);
     383           4 :   n = sizeof (*mp) + (count * sizeof (vl_api_domain_server_t));
     384           4 :   mp = vl_msg_api_alloc (n);
     385           4 :   if (!mp)
     386           0 :     return 0;
     387           4 :   clib_memset (mp, 0, n);
     388             : 
     389           4 :   mp->_vl_msg_id = ntohs (VL_API_DHCP_CLIENT_DETAILS + REPLY_MSG_ID_BASE);
     390           4 :   mp->context = ctx->context;
     391             : 
     392           4 :   dhcp_client_data_encode (&mp->client, client);
     393           4 :   dhcp_client_lease_encode (&mp->lease, client);
     394             : 
     395           4 :   vl_api_send_msg (ctx->reg, (u8 *) mp);
     396             : 
     397           4 :   return (1);
     398             : }
     399             : 
     400             : static void
     401          10 : vl_api_dhcp_client_dump_t_handler (vl_api_dhcp_client_dump_t * mp)
     402             : {
     403             :   vl_api_registration_t *reg;
     404             : 
     405          10 :   reg = vl_api_client_index_to_registration (mp->client_index);
     406          10 :   if (!reg)
     407           0 :     return;
     408             : 
     409          10 :   dhcp_client_send_walk_ctx_t ctx = {
     410             :     .reg = reg,
     411          10 :     .context = mp->context,
     412             :   };
     413          10 :   dhcp_client_walk (send_dhcp_client_entry, &ctx);
     414             : }
     415             : 
     416             : static void
     417           4 :   vl_api_dhcp6_clients_enable_disable_t_handler
     418             :   (vl_api_dhcp6_clients_enable_disable_t * mp)
     419             : {
     420             :   vl_api_dhcp6_clients_enable_disable_reply_t *rmp;
     421           4 :   int rv = 0;
     422             : 
     423           4 :   dhcp6_clients_enable_disable (mp->enable);
     424             : 
     425           4 :   REPLY_MACRO (VL_API_DHCP6_CLIENTS_ENABLE_DISABLE_REPLY);
     426             : }
     427             : 
     428             : void
     429           2 :   vl_api_want_dhcp6_reply_events_t_handler
     430             :   (vl_api_want_dhcp6_reply_events_t * mp)
     431             : {
     432           2 :   vpe_api_main_t *am = &vpe_api_main;
     433             :   vl_api_want_dhcp6_reply_events_reply_t *rmp;
     434           2 :   int rv = 0;
     435             : 
     436             :   uword *p =
     437           2 :     hash_get (am->dhcp6_reply_events_registration_hash, mp->client_index);
     438             :   vpe_client_registration_t *rp;
     439           2 :   if (p)
     440             :     {
     441           1 :       if (mp->enable_disable)
     442             :         {
     443           0 :           clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
     444           0 :           rv = VNET_API_ERROR_INVALID_REGISTRATION;
     445           0 :           goto reply;
     446             :         }
     447             :       else
     448             :         {
     449           1 :           rp = pool_elt_at_index (am->dhcp6_reply_events_registrations, p[0]);
     450           1 :           pool_put (am->dhcp6_reply_events_registrations, rp);
     451           1 :           hash_unset (am->dhcp6_reply_events_registration_hash,
     452             :                       mp->client_index);
     453           1 :           if (pool_elts (am->dhcp6_reply_events_registrations) == 0)
     454           1 :             dhcp6_set_publisher_node (~0, DHCP6_DP_REPORT_MAX);
     455           1 :           goto reply;
     456             :         }
     457             :     }
     458           1 :   if (mp->enable_disable == 0)
     459             :     {
     460           0 :       clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
     461           0 :       rv = VNET_API_ERROR_INVALID_REGISTRATION;
     462           0 :       goto reply;
     463             :     }
     464           1 :   pool_get (am->dhcp6_reply_events_registrations, rp);
     465           1 :   rp->client_index = mp->client_index;
     466           1 :   rp->client_pid = ntohl (mp->pid);
     467           1 :   hash_set (am->dhcp6_reply_events_registration_hash, rp->client_index,
     468             :             rp - am->dhcp6_reply_events_registrations);
     469           1 :   dhcp6_set_publisher_node (dhcp6_reply_process_node.index,
     470             :                             DHCP6_DP_REPLY_REPORT);
     471             : 
     472           2 : reply:
     473           2 :   REPLY_MACRO (VL_API_WANT_DHCP6_REPLY_EVENTS_REPLY);
     474             : }
     475             : 
     476             : void
     477           2 :   vl_api_want_dhcp6_pd_reply_events_t_handler
     478             :   (vl_api_want_dhcp6_pd_reply_events_t * mp)
     479             : {
     480           2 :   vpe_api_main_t *am = &vpe_api_main;
     481             :   vl_api_want_dhcp6_pd_reply_events_reply_t *rmp;
     482           2 :   int rv = 0;
     483             : 
     484             :   uword *p =
     485           2 :     hash_get (am->dhcp6_pd_reply_events_registration_hash, mp->client_index);
     486             :   vpe_client_registration_t *rp;
     487           2 :   if (p)
     488             :     {
     489           1 :       if (mp->enable_disable)
     490             :         {
     491           0 :           clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
     492           0 :           rv = VNET_API_ERROR_INVALID_REGISTRATION;
     493           0 :           goto reply;
     494             :         }
     495             :       else
     496             :         {
     497           1 :           rp =
     498           1 :             pool_elt_at_index (am->dhcp6_pd_reply_events_registrations, p[0]);
     499           1 :           pool_put (am->dhcp6_pd_reply_events_registrations, rp);
     500           1 :           hash_unset (am->dhcp6_pd_reply_events_registration_hash,
     501             :                       mp->client_index);
     502           1 :           if (pool_elts (am->dhcp6_pd_reply_events_registrations) == 0)
     503           1 :             dhcp6_pd_set_publisher_node (~0, DHCP6_PD_DP_REPORT_MAX);
     504           1 :           goto reply;
     505             :         }
     506             :     }
     507           1 :   if (mp->enable_disable == 0)
     508             :     {
     509           0 :       clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
     510           0 :       rv = VNET_API_ERROR_INVALID_REGISTRATION;
     511           0 :       goto reply;
     512             :     }
     513           1 :   pool_get (am->dhcp6_pd_reply_events_registrations, rp);
     514           1 :   rp->client_index = mp->client_index;
     515           1 :   rp->client_pid = ntohl (mp->pid);
     516           1 :   hash_set (am->dhcp6_pd_reply_events_registration_hash, rp->client_index,
     517             :             rp - am->dhcp6_pd_reply_events_registrations);
     518           1 :   dhcp6_pd_set_publisher_node (dhcp6_pd_reply_process_node.index,
     519             :                                DHCP6_PD_DP_REPLY_REPORT);
     520             : 
     521           2 : reply:
     522           2 :   REPLY_MACRO (VL_API_WANT_DHCP6_PD_REPLY_EVENTS_REPLY);
     523             : }
     524             : 
     525             : void
     526           1 :   vl_api_dhcp6_send_client_message_t_handler
     527             :   (vl_api_dhcp6_send_client_message_t * mp)
     528             : {
     529             :   vl_api_dhcp6_send_client_message_reply_t *rmp;
     530             :   dhcp6_send_client_message_params_t params;
     531           1 :   vlib_main_t *vm = vlib_get_main ();
     532             :   u32 n_addresses;
     533             :   u32 i;
     534           1 :   int rv = 0;
     535             : 
     536           1 :   VALIDATE_SW_IF_INDEX (mp);
     537             : 
     538           1 :   BAD_SW_IF_INDEX_LABEL;
     539           1 :   REPLY_MACRO (VL_API_DHCP6_SEND_CLIENT_MESSAGE_REPLY);
     540             : 
     541           1 :   if (rv != 0)
     542           0 :     return;
     543             : 
     544           1 :   params.sw_if_index = ntohl (mp->sw_if_index);
     545           1 :   params.server_index = ntohl (mp->server_index);
     546           1 :   params.irt = ntohl (mp->irt);
     547           1 :   params.mrt = ntohl (mp->mrt);
     548           1 :   params.mrc = ntohl (mp->mrc);
     549           1 :   params.mrd = ntohl (mp->mrd);
     550           1 :   params.msg_type = ntohl (mp->msg_type);
     551           1 :   params.T1 = ntohl (mp->T1);
     552           1 :   params.T2 = ntohl (mp->T2);
     553           1 :   n_addresses = ntohl (mp->n_addresses);
     554             :   /* Make sure that the number of addresses is sane */
     555           1 :   if (n_addresses * sizeof (params.addresses) > vl_msg_api_max_length (mp))
     556             :     {
     557           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     558           0 :       goto bad_sw_if_index;
     559             :     }
     560           1 :   params.addresses = 0;
     561           1 :   if (n_addresses > 0)
     562           1 :     vec_validate (params.addresses, n_addresses - 1);
     563           2 :   for (i = 0; i < n_addresses; i++)
     564             :     {
     565           1 :       vl_api_dhcp6_address_info_t *ai = &mp->addresses[i];
     566           1 :       dhcp6_send_client_message_params_address_t *addr = &params.addresses[i];
     567           1 :       addr->preferred_lt = ntohl (ai->preferred_time);
     568           1 :       addr->valid_lt = ntohl (ai->valid_time);
     569           1 :       ip6_address_decode (ai->address, &addr->address);
     570             :     }
     571             : 
     572           1 :   dhcp6_send_client_message (vm, ntohl (mp->sw_if_index), mp->stop, &params);
     573             : }
     574             : 
     575             : void
     576           1 :   vl_api_dhcp6_pd_send_client_message_t_handler
     577             :   (vl_api_dhcp6_pd_send_client_message_t * mp)
     578             : {
     579             :   vl_api_dhcp6_pd_send_client_message_reply_t *rmp;
     580             :   dhcp6_pd_send_client_message_params_t params;
     581           1 :   vlib_main_t *vm = vlib_get_main ();
     582             :   u32 n_prefixes;
     583             :   u32 i;
     584           1 :   int rv = 0;
     585             : 
     586           1 :   VALIDATE_SW_IF_INDEX (mp);
     587             : 
     588           1 :   BAD_SW_IF_INDEX_LABEL;
     589           1 :   REPLY_MACRO (VL_API_DHCP6_PD_SEND_CLIENT_MESSAGE_REPLY);
     590             : 
     591           1 :   if (rv != 0)
     592           0 :     return;
     593             : 
     594           1 :   params.sw_if_index = ntohl (mp->sw_if_index);
     595           1 :   params.server_index = ntohl (mp->server_index);
     596           1 :   params.irt = ntohl (mp->irt);
     597           1 :   params.mrt = ntohl (mp->mrt);
     598           1 :   params.mrc = ntohl (mp->mrc);
     599           1 :   params.mrd = ntohl (mp->mrd);
     600           1 :   params.msg_type = ntohl (mp->msg_type);
     601           1 :   params.T1 = ntohl (mp->T1);
     602           1 :   params.T2 = ntohl (mp->T2);
     603           1 :   n_prefixes = ntohl (mp->n_prefixes);
     604             : 
     605             :   /* Minimal check to see that the number of prefixes is sane */
     606           1 :   if (n_prefixes * sizeof (params.prefixes) > vl_msg_api_max_length (mp))
     607             :     {
     608           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     609           0 :       goto bad_sw_if_index;
     610             :     }
     611             : 
     612           1 :   params.prefixes = 0;
     613           1 :   if (n_prefixes > 0)
     614           1 :     vec_validate (params.prefixes, n_prefixes - 1);
     615           2 :   for (i = 0; i < n_prefixes; i++)
     616             :     {
     617           1 :       vl_api_dhcp6_pd_prefix_info_t *pi = &mp->prefixes[i];
     618           1 :       dhcp6_pd_send_client_message_params_prefix_t *pref =
     619           1 :         &params.prefixes[i];
     620           1 :       pref->preferred_lt = ntohl (pi->preferred_time);
     621           1 :       pref->valid_lt = ntohl (pi->valid_time);
     622           1 :       ip6_address_decode (pi->prefix.address, &pref->prefix);
     623           1 :       pref->prefix_length = pi->prefix.len;
     624             :     }
     625             : 
     626           1 :   dhcp6_pd_send_client_message (vm, ntohl (mp->sw_if_index), mp->stop,
     627             :                                 &params);
     628             : }
     629             : 
     630             : static clib_error_t *
     631          14 : call_dhcp6_reply_event_callbacks (void *data,
     632             :                                   _vnet_dhcp6_reply_event_function_list_elt_t
     633             :                                   * elt)
     634             : {
     635          14 :   clib_error_t *error = 0;
     636             : 
     637          28 :   while (elt)
     638             :     {
     639          14 :       error = elt->fp (data);
     640          14 :       if (error)
     641           0 :         return error;
     642          14 :       elt = elt->next_dhcp6_reply_event_function;
     643             :     }
     644             : 
     645          14 :   return error;
     646             : }
     647             : 
     648             : static uword
     649         589 : dhcp6_reply_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
     650             :                      vlib_frame_t * f)
     651             : {
     652             :   /* These cross the longjmp  boundary (vlib_process_wait_for_event)
     653             :    * and need to be volatile - to prevent them from being optimized into
     654             :    * a register - which could change during suspension */
     655             : 
     656             :   while (1)
     657          14 :     {
     658         589 :       vlib_process_wait_for_event (vm);
     659          14 :       uword event_type = DHCP6_DP_REPLY_REPORT;
     660          14 :       void *event_data = vlib_process_get_event_data (vm, &event_type);
     661             : 
     662             :       int i;
     663          14 :       if (event_type == DHCP6_DP_REPLY_REPORT)
     664             :         {
     665          14 :           address_report_t *events = event_data;
     666          28 :           for (i = 0; i < vec_len (events); i++)
     667             :             {
     668          10 :               u32 event_size =
     669             :                 sizeof (vl_api_dhcp6_reply_event_t) +
     670          14 :                 vec_len (events[i].addresses) *
     671             :                 sizeof (vl_api_dhcp6_address_info_t);
     672          14 :               vl_api_dhcp6_reply_event_t *event = clib_mem_alloc (event_size);
     673          14 :               clib_memset (event, 0, event_size);
     674             : 
     675          14 :               event->sw_if_index = htonl (events[i].body.sw_if_index);
     676          14 :               event->server_index = htonl (events[i].body.server_index);
     677          14 :               event->msg_type = events[i].body.msg_type;
     678          14 :               event->T1 = htonl (events[i].body.T1);
     679          14 :               event->T2 = htonl (events[i].body.T2);
     680          14 :               event->inner_status_code =
     681          14 :                 htons (events[i].body.inner_status_code);
     682          14 :               event->status_code = htons (events[i].body.status_code);
     683          14 :               event->preference = events[i].body.preference;
     684             : 
     685          14 :               event->n_addresses = htonl (vec_len (events[i].addresses));
     686          14 :               vl_api_dhcp6_address_info_t *address =
     687             :                 (typeof (address)) event->addresses;
     688             :               u32 j;
     689          18 :               for (j = 0; j < vec_len (events[i].addresses); j++)
     690             :                 {
     691           4 :                   dhcp6_address_info_t *info = &events[i].addresses[j];
     692           4 :                   ip6_address_encode (&info->address, address->address);
     693           4 :                   address->valid_time = htonl (info->valid_time);
     694           4 :                   address->preferred_time = htonl (info->preferred_time);
     695           4 :                   address++;
     696             :                 }
     697          14 :               vec_free (events[i].addresses);
     698             : 
     699          14 :               dhcp6_ia_na_client_public_main_t *dcpm =
     700             :                 &dhcp6_ia_na_client_public_main;
     701          14 :               call_dhcp6_reply_event_callbacks (event, dcpm->functions);
     702             : 
     703             :               vpe_client_registration_t *reg;
     704             :               /* *INDENT-OFF* */
     705          15 :               pool_foreach (reg, vpe_api_main.dhcp6_reply_events_registrations)
     706             :                {
     707             :                 vl_api_registration_t *vl_reg;
     708             :                 vl_reg =
     709           1 :                   vl_api_client_index_to_registration (reg->client_index);
     710           1 :                 if (vl_reg && vl_api_can_send_msg (vl_reg))
     711             :                   {
     712             :                     vl_api_dhcp6_reply_event_t *msg =
     713           1 :                       vl_msg_api_alloc (event_size);
     714           1 :                     clib_memcpy (msg, event, event_size);
     715           1 :                     msg->_vl_msg_id = htons (VL_API_DHCP6_REPLY_EVENT + REPLY_MSG_ID_BASE);
     716           1 :                     msg->client_index = reg->client_index;
     717           1 :                     msg->pid = reg->client_pid;
     718           1 :                     vl_api_send_msg (vl_reg, (u8 *) msg);
     719             :                   }
     720             :               }
     721             :               /* *INDENT-ON* */
     722             : 
     723          14 :               clib_mem_free (event);
     724             :             }
     725             :         }
     726          14 :       vlib_process_put_event_data (vm, event_data);
     727             :     }
     728             : 
     729             :   return 0;
     730             : }
     731             : 
     732             : /* *INDENT-OFF* */
     733      153836 : VLIB_REGISTER_NODE (dhcp6_reply_process_node) = {
     734             :   .function = dhcp6_reply_process,
     735             :   .type = VLIB_NODE_TYPE_PROCESS,
     736             :   .name = "dhcp6-reply-publisher-process",
     737             : };
     738             : /* *INDENT-ON* */
     739             : 
     740             : static clib_error_t *
     741          14 : call_dhcp6_pd_reply_event_callbacks (void *data,
     742             :                                      _vnet_dhcp6_pd_reply_event_function_list_elt_t
     743             :                                      * elt)
     744             : {
     745          14 :   clib_error_t *error = 0;
     746             : 
     747          28 :   while (elt)
     748             :     {
     749          14 :       error = elt->fp (data);
     750          14 :       if (error)
     751           0 :         return error;
     752          14 :       elt = elt->next_dhcp6_pd_reply_event_function;
     753             :     }
     754             : 
     755          14 :   return error;
     756             : }
     757             : 
     758             : static uword
     759         589 : dhcp6_pd_reply_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
     760             :                         vlib_frame_t * f)
     761             : {
     762             :   /* These cross the longjmp  boundary (vlib_process_wait_for_event)
     763             :    * and need to be volatile - to prevent them from being optimized into
     764             :    * a register - which could change during suspension */
     765             : 
     766             :   while (1)
     767          14 :     {
     768         589 :       vlib_process_wait_for_event (vm);
     769          14 :       uword event_type = DHCP6_PD_DP_REPLY_REPORT;
     770          14 :       void *event_data = vlib_process_get_event_data (vm, &event_type);
     771             : 
     772             :       int i;
     773          14 :       if (event_type == DHCP6_PD_DP_REPLY_REPORT)
     774             :         {
     775          14 :           prefix_report_t *events = event_data;
     776          28 :           for (i = 0; i < vec_len (events); i++)
     777             :             {
     778          10 :               u32 event_size =
     779             :                 sizeof (vl_api_dhcp6_pd_reply_event_t) +
     780          14 :                 vec_len (events[i].prefixes) *
     781             :                 sizeof (vl_api_dhcp6_pd_prefix_info_t);
     782             :               vl_api_dhcp6_pd_reply_event_t *event =
     783          14 :                 clib_mem_alloc (event_size);
     784          14 :               clib_memset (event, 0, event_size);
     785             : 
     786          14 :               event->sw_if_index = htonl (events[i].body.sw_if_index);
     787          14 :               event->server_index = htonl (events[i].body.server_index);
     788          14 :               event->msg_type = events[i].body.msg_type;
     789          14 :               event->T1 = htonl (events[i].body.T1);
     790          14 :               event->T2 = htonl (events[i].body.T2);
     791          14 :               event->inner_status_code =
     792          14 :                 htons (events[i].body.inner_status_code);
     793          14 :               event->status_code = htons (events[i].body.status_code);
     794          14 :               event->preference = events[i].body.preference;
     795             : 
     796          14 :               event->n_prefixes = htonl (vec_len (events[i].prefixes));
     797          14 :               vl_api_dhcp6_pd_prefix_info_t *prefix =
     798             :                 (typeof (prefix)) event->prefixes;
     799             :               u32 j;
     800          18 :               for (j = 0; j < vec_len (events[i].prefixes); j++)
     801             :                 {
     802           4 :                   dhcp6_prefix_info_t *info = &events[i].prefixes[j];
     803           4 :                   ip6_address_encode (&info->prefix, prefix->prefix.address);
     804           4 :                   prefix->prefix.len = info->prefix_length;
     805           4 :                   prefix->valid_time = htonl (info->valid_time);
     806           4 :                   prefix->preferred_time = htonl (info->preferred_time);
     807           4 :                   prefix++;
     808             :                 }
     809          14 :               vec_free (events[i].prefixes);
     810             : 
     811          14 :               dhcp6_pd_client_public_main_t *dpcpm =
     812             :                 &dhcp6_pd_client_public_main;
     813          14 :               call_dhcp6_pd_reply_event_callbacks (event, dpcpm->functions);
     814             : 
     815             :               vpe_client_registration_t *reg;
     816             :               /* *INDENT-OFF* */
     817          15 :               pool_foreach (reg, vpe_api_main.dhcp6_pd_reply_events_registrations)
     818             :                {
     819             :                 vl_api_registration_t *vl_reg;
     820             :                 vl_reg =
     821           1 :                   vl_api_client_index_to_registration (reg->client_index);
     822           1 :                 if (vl_reg && vl_api_can_send_msg (vl_reg))
     823             :                   {
     824             :                     vl_api_dhcp6_pd_reply_event_t *msg =
     825           1 :                       vl_msg_api_alloc (event_size);
     826           1 :                     clib_memcpy (msg, event, event_size);
     827           1 :                     msg->_vl_msg_id = htons (VL_API_DHCP6_PD_REPLY_EVENT + REPLY_MSG_ID_BASE);
     828           1 :                     msg->client_index = reg->client_index;
     829           1 :                     msg->pid = reg->client_pid;
     830           1 :                     vl_api_send_msg (vl_reg, (u8 *) msg);
     831             :                   }
     832             :               }
     833             :               /* *INDENT-ON* */
     834             : 
     835          14 :               clib_mem_free (event);
     836             :             }
     837             :         }
     838          14 :       vlib_process_put_event_data (vm, event_data);
     839             :     }
     840             : 
     841             :   return 0;
     842             : }
     843             : 
     844             : /* *INDENT-OFF* */
     845      153836 : VLIB_REGISTER_NODE (dhcp6_pd_reply_process_node) = {
     846             :   .function = dhcp6_pd_reply_process,
     847             :   .type = VLIB_NODE_TYPE_PROCESS,
     848             :   .name = "dhcp6-pd-reply-publisher-process",
     849             : };
     850             : /* *INDENT-ON* */
     851             : 
     852             : /*
     853             :  * dhcp_api_hookup
     854             :  * Add vpe's API message handlers to the table.
     855             :  * vlib has already mapped shared memory and
     856             :  * added the client registration handlers.
     857             :  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
     858             :  */
     859             : #include <dhcp/dhcp.api.c>
     860             : 
     861             : static clib_error_t *
     862         575 : dhcp_api_hookup (vlib_main_t * vm)
     863             : {
     864             :   /*
     865             :    * Set up the (msg_name, crc, message-id) table
     866             :    */
     867         575 :   dhcp_base_msg_id = setup_message_id_table ();
     868             : 
     869         575 :   dhcp6_pd_set_publisher_node (dhcp6_pd_reply_process_node.index,
     870             :                                DHCP6_PD_DP_REPLY_REPORT);
     871         575 :   dhcp6_set_publisher_node (dhcp6_reply_process_node.index,
     872             :                             DHCP6_DP_REPLY_REPORT);
     873             : 
     874         575 :   return 0;
     875             : }
     876             : 
     877        1151 : VLIB_API_INIT_FUNCTION (dhcp_api_hookup);
     878             : 
     879             : #include <vlib/unix/plugin.h>
     880             : #include <vpp/app/version.h>
     881             : 
     882             : /* *INDENT-OFF* */
     883             : VLIB_PLUGIN_REGISTER () = {
     884             :     .version = VPP_BUILD_VER,
     885             :     .description = "Dynamic Host Configuration Protocol (DHCP)",
     886             : };
     887             : /* *INDENT-ON* */
     888             : 
     889             : /*
     890             :  * fd.io coding-style-patch-verification: ON
     891             :  *
     892             :  * Local Variables:
     893             :  * eval: (c-set-style "gnu")
     894             :  * End:
     895             :  */

Generated by: LCOV version 1.14