Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/netutils/dhcpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
# define CONFIG_NETDB_DNSSERVER_NAMESERVERS 1
#endif

#if !defined(CONFIG_NETUTILS_DHCPC_NTP_SERVERS)
# define CONFIG_NETUTILS_DHCPC_NTP_SERVERS 1
#endif

/****************************************************************************
* Public Types
****************************************************************************/
Expand All @@ -66,6 +70,8 @@ struct dhcpc_state
struct in_addr netmask;
struct in_addr dnsaddr[CONFIG_NETDB_DNSSERVER_NAMESERVERS];
uint8_t num_dnsaddr; /* Number of DNS addresses received */
struct in_addr ntpaddr[CONFIG_NETUTILS_DHCPC_NTP_SERVERS];
uint8_t num_ntpaddr; /* Number of NTP addresses received */
struct in_addr default_router;
uint32_t lease_time; /* Lease expires in this number of seconds */
uint32_t renewal_time; /* Seconds to transition to RENEW state(T1) */
Expand Down
43 changes: 43 additions & 0 deletions include/netutils/netlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ struct url_s
};
#endif

#ifdef CONFIG_NETUTILS_DHCPC
typedef CODE void (*netlib_dhcp_ntp_callback_t)
(FAR const char *ntp_server_list, FAR void *arg);
#endif

/****************************************************************************
* Public Data
****************************************************************************/
Expand Down Expand Up @@ -247,6 +252,44 @@ ssize_t netlib_get_devices(FAR struct netlib_device_s *devlist,
bool netlib_ipv4addrconv(FAR const char *addrstr, FAR uint8_t *addr);
bool netlib_ethaddrconv(FAR const char *hwstr, FAR uint8_t *hw);

#ifdef CONFIG_NETUTILS_DHCPC
/****************************************************************************
* Name: netlib_set_ntp_servers_from_dhcp
*
* Description:
* Update the currently active DHCP option 42 NTP server list. The list
* contains semicolon-separated hostnames or addresses. Passing NULL or
* an empty string clears the DHCP-provided list.
*
****************************************************************************/

int netlib_set_ntp_servers_from_dhcp(FAR const char *ntp_server_list);

/****************************************************************************
* Name: netlib_register_dhcp_ntp_callback
*
* Description:
* Register a callback to receive DHCP option 42 NTP server list updates.
* The current list, if any, is replayed immediately after registration.
* Only one callback may be registered at a time.
*
****************************************************************************/

int netlib_register_dhcp_ntp_callback(netlib_dhcp_ntp_callback_t callback,
FAR void *arg);

/****************************************************************************
* Name: netlib_unregister_dhcp_ntp_callback
*
* Description:
* Unregister a previously registered DHCP option 42 NTP update callback.
*
****************************************************************************/

int netlib_unregister_dhcp_ntp_callback(netlib_dhcp_ntp_callback_t callback,
FAR void *arg);
#endif

#ifdef CONFIG_NET_ETHERNET
/* Get and set IP/MAC addresses (Ethernet L2 only) */

Expand Down
52 changes: 51 additions & 1 deletion netutils/dhcpc/dhcpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_DNS_SERVER 6
#define DHCP_OPTION_HOST_NAME 12
#define DHCP_OPTION_NTP_SERVER 42
#define DHCP_OPTION_REQ_IPADDR 50
#define DHCP_OPTION_LEASE_TIME 51
#define DHCP_OPTION_MSG_TYPE 53
Expand Down Expand Up @@ -210,10 +211,11 @@ static FAR uint8_t *dhcpc_addclientid(FAR uint8_t *clientid,
static FAR uint8_t *dhcpc_addreqoptions(FAR uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_REQ_LIST;
*optptr++ = 3;
*optptr++ = 4;
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = DHCP_OPTION_DNS_SERVER;
*optptr++ = DHCP_OPTION_NTP_SERVER;
return optptr;
}

Expand Down Expand Up @@ -411,6 +413,39 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult,
}
break;

case DHCP_OPTION_NTP_SERVER:

/* Get the NTP server addresses in network order.
* DHCP option 42 can contain multiple IPv4 addresses,
* each 4 bytes long.
*/

if (optptr + 2 <= end)
{
uint8_t optlen = *(optptr + 1);
uint8_t num_ntp = optlen / 4;
uint8_t i;

if (num_ntp > CONFIG_NETUTILS_DHCPC_NTP_SERVERS)
{
num_ntp = CONFIG_NETUTILS_DHCPC_NTP_SERVERS;
}

presult->num_ntpaddr = 0;
for (i = 0; i < num_ntp && (optptr + 2 + i * 4 + 4) <= end;
i++)
{
memcpy(&presult->ntpaddr[i].s_addr, optptr + 2 + i * 4,
4);
presult->num_ntpaddr++;
}
}
else
{
nerr("Packet too short (NTP address missing)\n");
}
break;

case DHCP_OPTION_MSG_TYPE:

/* Get message type */
Expand Down Expand Up @@ -999,6 +1034,21 @@ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult)
}
}

/* Print all NTP servers received */

if (presult->num_ntpaddr > 0)
{
uint8_t i;
for (i = 0; i < presult->num_ntpaddr; i++)
{
ninfo("Got NTP server %d: %u.%u.%u.%u\n", i,
ip4_addr1(presult->ntpaddr[i].s_addr),
ip4_addr2(presult->ntpaddr[i].s_addr),
ip4_addr3(presult->ntpaddr[i].s_addr),
ip4_addr4(presult->ntpaddr[i].s_addr));
}
}

ninfo("Got default router %u.%u.%u.%u\n",
ip4_addr1(presult->default_router.s_addr),
ip4_addr2(presult->default_router.s_addr),
Expand Down
1 change: 1 addition & 0 deletions netutils/netlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ if(CONFIG_NETUTILS_NETLIB)
endif()
if(CONFIG_NETUTILS_DHCPC)
list(APPEND SRCS netlib_obtainipv4addr.c)
list(APPEND SRCS netlib_dhcp_ntp.c)
endif()
endif()

Expand Down
1 change: 1 addition & 0 deletions netutils/netlib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ CSRCS += netlib_iptables.c
endif
ifeq ($(CONFIG_NETUTILS_DHCPC),y)
CSRCS += netlib_obtainipv4addr.c
CSRCS += netlib_dhcp_ntp.c
endif
endif

Expand Down
182 changes: 182 additions & 0 deletions netutils/netlib/netlib_dhcp_ntp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/****************************************************************************
* apps/netutils/netlib/netlib_dhcp_ntp.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#ifdef CONFIG_NETUTILS_DHCPC

#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

#include "netutils/netlib.h"

/****************************************************************************
* Private Data
****************************************************************************/

static pthread_mutex_t g_dhcp_ntp_lock = PTHREAD_MUTEX_INITIALIZER;
static FAR char *g_dhcp_ntp_servers;
Comment thread
masc2008 marked this conversation as resolved.
static netlib_dhcp_ntp_callback_t g_dhcp_ntp_callback;
static FAR void *g_dhcp_ntp_callback_arg;

/****************************************************************************
* Private Functions
****************************************************************************/

static FAR char *netlib_dhcp_ntp_dup(FAR const char *ntp_server_list)
{
if (ntp_server_list == NULL || ntp_server_list[0] == '\0')
{
return NULL;
}

return strdup(ntp_server_list);
}

/****************************************************************************
* Public Functions
****************************************************************************/

int netlib_set_ntp_servers_from_dhcp(FAR const char *ntp_server_list)
{
FAR char *new_servers;
FAR char *notify_servers = NULL;
FAR char *old_servers;
netlib_dhcp_ntp_callback_t callback;
FAR void *arg;
int ret = OK;

new_servers = netlib_dhcp_ntp_dup(ntp_server_list);
if (ntp_server_list != NULL && ntp_server_list[0] != '\0' &&
new_servers == NULL)
{
return -ENOMEM;
}

pthread_mutex_lock(&g_dhcp_ntp_lock);

if ((g_dhcp_ntp_servers == NULL && new_servers == NULL) ||
(g_dhcp_ntp_servers != NULL && new_servers != NULL &&
strcmp(g_dhcp_ntp_servers, new_servers) == 0))
{
pthread_mutex_unlock(&g_dhcp_ntp_lock);
free(new_servers);
return OK;
}

callback = g_dhcp_ntp_callback;
arg = g_dhcp_ntp_callback_arg;

if (callback != NULL && new_servers != NULL)
{
notify_servers = strdup(new_servers);
if (notify_servers == NULL)
{
ret = -ENOMEM;
goto errout_with_lock;
}
}

old_servers = g_dhcp_ntp_servers;
g_dhcp_ntp_servers = new_servers;
pthread_mutex_unlock(&g_dhcp_ntp_lock);

free(old_servers);

if (callback != NULL)
{
callback(notify_servers, arg);
}

free(notify_servers);
return OK;

errout_with_lock:
pthread_mutex_unlock(&g_dhcp_ntp_lock);
free(new_servers);
return ret;
}

int netlib_register_dhcp_ntp_callback(netlib_dhcp_ntp_callback_t callback,
FAR void *arg)
{
FAR char *notify_servers = NULL;

if (callback == NULL)
{
return -EINVAL;
}

pthread_mutex_lock(&g_dhcp_ntp_lock);

if (g_dhcp_ntp_callback != NULL &&
(g_dhcp_ntp_callback != callback || g_dhcp_ntp_callback_arg != arg))
{
pthread_mutex_unlock(&g_dhcp_ntp_lock);
return -EBUSY;
}

if (g_dhcp_ntp_servers != NULL)
{
notify_servers = strdup(g_dhcp_ntp_servers);
if (notify_servers == NULL)
{
pthread_mutex_unlock(&g_dhcp_ntp_lock);
return -ENOMEM;
}
}

g_dhcp_ntp_callback = callback;
g_dhcp_ntp_callback_arg = arg;

pthread_mutex_unlock(&g_dhcp_ntp_lock);

callback(notify_servers, arg);
free(notify_servers);
return OK;
}

int netlib_unregister_dhcp_ntp_callback(netlib_dhcp_ntp_callback_t callback,
FAR void *arg)
{
int ret = -ENOENT;

pthread_mutex_lock(&g_dhcp_ntp_lock);

if (g_dhcp_ntp_callback == callback && g_dhcp_ntp_callback_arg == arg)
{
g_dhcp_ntp_callback = NULL;
g_dhcp_ntp_callback_arg = NULL;
ret = OK;
}

pthread_mutex_unlock(&g_dhcp_ntp_lock);
return ret;
}

#endif /* CONFIG_NETUTILS_DHCPC */
Loading
Loading