Skip to content

Commit a4873bb

Browse files
committed
netutils: use DHCP-provided NTP servers as ntpc fallback
Use the DHCP-learned NTP server list as the ntpc fallback when CONFIG_NETUTILS_NTPCLIENT_SERVER is empty. Signed-off-by: Jerry Ma <masc2008@gmail.com>
1 parent cc7964a commit a4873bb

3 files changed

Lines changed: 255 additions & 39 deletions

File tree

include/netutils/ntpclient.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ int ntpc_start_with_list(FAR const char *ntp_server_list);
119119

120120
int ntpc_start(void);
121121

122+
/****************************************************************************
123+
* Name: ntpc_set_dhcp_servers
124+
*
125+
* Description:
126+
* Update the DHCP-provided NTP server list. The list should contain
127+
* semicolon-separated hostnames or addresses. Passing NULL or an empty
128+
* string clears the DHCP-provided server list.
129+
*
130+
* Returned Value:
131+
* Zero on success; a negated errno value on failure.
132+
*
133+
****************************************************************************/
134+
135+
int ntpc_set_dhcp_servers(FAR const char *ntp_server_list);
136+
122137
/****************************************************************************
123138
* Name: ntpc_stop
124139
*

netutils/netlib/netlib_obtainipv4addr.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@
2525
****************************************************************************/
2626

2727
#include <nuttx/debug.h>
28+
#include <arpa/inet.h>
29+
#include <errno.h>
30+
#include <stdio.h>
31+
#include <string.h>
2832
#include <sys/types.h>
2933

3034
#include "netutils/dhcpc.h"
3135
#include "netutils/netlib.h"
36+
#ifdef CONFIG_NETUTILS_NTPCLIENT
37+
#include "netutils/ntpclient.h"
38+
#endif
3239

3340
/****************************************************************************
3441
* Private Functions
@@ -105,6 +112,57 @@ static int dhcp_setup_result(FAR const char *ifname,
105112
return OK;
106113
}
107114

115+
#ifdef CONFIG_NETUTILS_NTPCLIENT
116+
static int dhcp_set_ntp_servers(FAR const struct dhcpc_state *ds)
117+
{
118+
char ntp_server_list[CONFIG_NETUTILS_DHCPC_NTP_SERVER_NUM *
119+
(INET_ADDRSTRLEN + 1)];
120+
size_t offset = 0;
121+
uint8_t i;
122+
123+
if (ds->num_ntpaddr == 0)
124+
{
125+
return ntpc_set_dhcp_servers(NULL);
126+
}
127+
128+
ntp_server_list[0] = '\0';
129+
130+
for (i = 0; i < ds->num_ntpaddr; i++)
131+
{
132+
char addrbuf[INET_ADDRSTRLEN];
133+
int ret;
134+
135+
if (ds->ntpaddr[i].s_addr == 0)
136+
{
137+
continue;
138+
}
139+
140+
if (inet_ntop(AF_INET, &ds->ntpaddr[i], addrbuf, sizeof(addrbuf)) ==
141+
NULL)
142+
{
143+
return -EINVAL;
144+
}
145+
146+
ret = snprintf(ntp_server_list + offset,
147+
sizeof(ntp_server_list) - offset,
148+
"%s%s", offset == 0 ? "" : ";", addrbuf);
149+
if (ret < 0 || (size_t)ret >= sizeof(ntp_server_list) - offset)
150+
{
151+
return -E2BIG;
152+
}
153+
154+
offset += (size_t)ret;
155+
}
156+
157+
if (offset == 0)
158+
{
159+
return ntpc_set_dhcp_servers(NULL);
160+
}
161+
162+
return ntpc_set_dhcp_servers(ntp_server_list);
163+
}
164+
#endif
165+
108166
/****************************************************************************
109167
* Name: dhcp_obtain_statefuladdr
110168
*
@@ -156,6 +214,18 @@ static int dhcp_obtain_statefuladdr(FAR const char *ifname)
156214
if (ret == OK)
157215
{
158216
ret = dhcp_setup_result(ifname, &ds);
217+
#ifdef CONFIG_NETUTILS_NTPCLIENT
218+
if (ret == OK)
219+
{
220+
ret = dhcp_set_ntp_servers(&ds);
221+
if (ret < 0)
222+
{
223+
nwarn("WARNING: failed to update DHCP NTP server list: %d\n",
224+
ret);
225+
ret = OK;
226+
}
227+
}
228+
#endif
159229
}
160230
else
161231
{

netutils/ntpclient/ntpclient.c

Lines changed: 170 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,31 @@ enum ntpc_daemon_e
126126
NTP_STOPPED
127127
};
128128

129+
enum ntpc_server_source_e
130+
{
131+
NTP_SERVER_SOURCE_NONE = 0,
132+
NTP_SERVER_SOURCE_CONFIG,
133+
NTP_SERVER_SOURCE_DHCP,
134+
NTP_SERVER_SOURCE_EXPLICIT
135+
};
136+
129137
/* This type describes the state of the NTP client daemon. Only one
130138
* instance of the NTP daemon is permitted in this implementation.
131139
*/
132140

133141
struct ntpc_daemon_s
134142
{
135-
uint8_t state; /* See enum ntpc_daemon_e */
136-
sem_t lock; /* Used to protect the whole structure */
137-
sem_t sync; /* Used to synchronize start and stop events */
138-
pid_t pid; /* Task ID of the NTP daemon */
139-
sq_queue_t kod_list; /* KoD excluded server addresses */
140-
int family; /* Allowed address family */
143+
uint8_t state; /* See enum ntpc_daemon_e */
144+
uint8_t source; /* See enum ntpc_server_source_e */
145+
sem_t lock; /* Used to protect the whole structure */
146+
sem_t sync; /* Used to synchronize start and stop events */
147+
pid_t pid; /* Task ID of the NTP daemon */
148+
sq_queue_t kod_list; /* KoD excluded server addresses */
149+
int family; /* Allowed address family */
150+
151+
/* DHCP-provided server list */
152+
153+
FAR char *dhcp_servers;
141154
};
142155

143156
union ntp_addr_u
@@ -194,11 +207,13 @@ struct ntp_kod_exclude_s
194207
static struct ntpc_daemon_s g_ntpc_daemon =
195208
{
196209
NTP_NOT_RUNNING,
210+
NTP_SERVER_SOURCE_NONE,
197211
SEM_INITIALIZER(1),
198212
SEM_INITIALIZER(0),
199213
-1,
200214
{ NULL, NULL },
201215
AF_UNSPEC, /* Default is both IPv4 and IPv6 */
216+
NULL,
202217
};
203218

204219
static struct ntp_sample_s g_last_samples
@@ -209,6 +224,73 @@ unsigned int g_last_nsamples = 0;
209224
* Private Functions
210225
****************************************************************************/
211226

227+
static int ntpc_daemon(int argc, FAR char **argv);
228+
229+
static FAR char *ntpc_dup_server_list(FAR const char *ntp_server_list)
230+
{
231+
if (ntp_server_list == NULL || ntp_server_list[0] == '\0')
232+
{
233+
return NULL;
234+
}
235+
236+
return strdup(ntp_server_list);
237+
}
238+
239+
static FAR const char *ntpc_select_server_list(FAR uint8_t *source)
240+
{
241+
if (CONFIG_NETUTILS_NTPCLIENT_SERVER[0] != '\0')
242+
{
243+
*source = NTP_SERVER_SOURCE_CONFIG;
244+
return CONFIG_NETUTILS_NTPCLIENT_SERVER;
245+
}
246+
247+
if (g_ntpc_daemon.dhcp_servers != NULL &&
248+
g_ntpc_daemon.dhcp_servers[0] != '\0')
249+
{
250+
*source = NTP_SERVER_SOURCE_DHCP;
251+
return g_ntpc_daemon.dhcp_servers;
252+
}
253+
254+
*source = NTP_SERVER_SOURCE_NONE;
255+
return NULL;
256+
}
257+
258+
static int ntpc_start_selected(FAR const char *ntp_server_list,
259+
uint8_t source)
260+
{
261+
FAR char *task_argv[] =
262+
{
263+
(FAR char *)ntp_server_list,
264+
NULL
265+
};
266+
267+
g_ntpc_daemon.state = NTP_STARTED;
268+
g_ntpc_daemon.source = source;
269+
g_ntpc_daemon.pid =
270+
task_create("NTP daemon", CONFIG_NETUTILS_NTPCLIENT_SERVERPRIO,
271+
CONFIG_NETUTILS_NTPCLIENT_STACKSIZE, ntpc_daemon,
272+
task_argv);
273+
274+
if (g_ntpc_daemon.pid < 0)
275+
{
276+
int errval = errno;
277+
DEBUGASSERT(errval > 0);
278+
279+
g_ntpc_daemon.state = NTP_STOPPED;
280+
g_ntpc_daemon.source = NTP_SERVER_SOURCE_NONE;
281+
nerr("ERROR: Failed to start the NTP daemon: %d\n", errval);
282+
return -errval;
283+
}
284+
285+
do
286+
{
287+
sem_wait(&g_ntpc_daemon.sync);
288+
}
289+
while (g_ntpc_daemon.state == NTP_STARTED);
290+
291+
return g_ntpc_daemon.pid;
292+
}
293+
212294
/****************************************************************************
213295
* Name: sample_cmp
214296
****************************************************************************/
@@ -1490,46 +1572,23 @@ void ntpc_dualstack_family(int family)
14901572

14911573
int ntpc_start_with_list(FAR const char *ntp_server_list)
14921574
{
1493-
FAR char *task_argv[] =
1575+
int ret;
1576+
1577+
if (ntp_server_list == NULL || ntp_server_list[0] == '\0')
14941578
{
1495-
(FAR char *)ntp_server_list,
1496-
NULL
1497-
};
1579+
return -EINVAL;
1580+
}
14981581

14991582
/* Is the NTP in a non-running state? */
15001583

15011584
sem_wait(&g_ntpc_daemon.lock);
15021585
if (g_ntpc_daemon.state == NTP_NOT_RUNNING ||
15031586
g_ntpc_daemon.state == NTP_STOPPED)
15041587
{
1505-
/* Start the NTP daemon */
1506-
1507-
g_ntpc_daemon.state = NTP_STARTED;
1508-
g_ntpc_daemon.pid =
1509-
task_create("NTP daemon", CONFIG_NETUTILS_NTPCLIENT_SERVERPRIO,
1510-
CONFIG_NETUTILS_NTPCLIENT_STACKSIZE, ntpc_daemon,
1511-
task_argv);
1512-
1513-
/* Handle failures to start the NTP daemon */
1514-
1515-
if (g_ntpc_daemon.pid < 0)
1516-
{
1517-
int errval = errno;
1518-
DEBUGASSERT(errval > 0);
1519-
1520-
g_ntpc_daemon.state = NTP_STOPPED;
1521-
nerr("ERROR: Failed to start the NTP daemon: %d\n", errval);
1522-
sem_post(&g_ntpc_daemon.lock);
1523-
return -errval;
1524-
}
1525-
1526-
/* Wait for any daemon state change */
1527-
1528-
do
1529-
{
1530-
sem_wait(&g_ntpc_daemon.sync);
1531-
}
1532-
while (g_ntpc_daemon.state == NTP_STARTED);
1588+
ret = ntpc_start_selected(ntp_server_list,
1589+
NTP_SERVER_SOURCE_EXPLICIT);
1590+
sem_post(&g_ntpc_daemon.lock);
1591+
return ret;
15331592
}
15341593

15351594
sem_post(&g_ntpc_daemon.lock);
@@ -1550,7 +1609,79 @@ int ntpc_start_with_list(FAR const char *ntp_server_list)
15501609

15511610
int ntpc_start(void)
15521611
{
1553-
return ntpc_start_with_list(CONFIG_NETUTILS_NTPCLIENT_SERVER);
1612+
FAR const char *ntp_server_list;
1613+
uint8_t source;
1614+
int ret;
1615+
1616+
sem_wait(&g_ntpc_daemon.lock);
1617+
if (g_ntpc_daemon.state != NTP_NOT_RUNNING &&
1618+
g_ntpc_daemon.state != NTP_STOPPED)
1619+
{
1620+
ret = g_ntpc_daemon.pid;
1621+
sem_post(&g_ntpc_daemon.lock);
1622+
return ret;
1623+
}
1624+
1625+
ntp_server_list = ntpc_select_server_list(&source);
1626+
if (ntp_server_list == NULL)
1627+
{
1628+
sem_post(&g_ntpc_daemon.lock);
1629+
return -ENOENT;
1630+
}
1631+
1632+
ret = ntpc_start_selected(ntp_server_list, source);
1633+
sem_post(&g_ntpc_daemon.lock);
1634+
return ret;
1635+
}
1636+
1637+
int ntpc_set_dhcp_servers(FAR const char *ntp_server_list)
1638+
{
1639+
FAR char *new_servers;
1640+
FAR char *old_servers;
1641+
bool restart = false;
1642+
int ret = OK;
1643+
1644+
new_servers = ntpc_dup_server_list(ntp_server_list);
1645+
if (ntp_server_list != NULL && ntp_server_list[0] != '\0' &&
1646+
new_servers == NULL)
1647+
{
1648+
return -ENOMEM;
1649+
}
1650+
1651+
sem_wait(&g_ntpc_daemon.lock);
1652+
1653+
if ((g_ntpc_daemon.dhcp_servers == NULL && new_servers == NULL) ||
1654+
(g_ntpc_daemon.dhcp_servers != NULL && new_servers != NULL &&
1655+
strcmp(g_ntpc_daemon.dhcp_servers, new_servers) == 0))
1656+
{
1657+
sem_post(&g_ntpc_daemon.lock);
1658+
free(new_servers);
1659+
return OK;
1660+
}
1661+
1662+
old_servers = g_ntpc_daemon.dhcp_servers;
1663+
g_ntpc_daemon.dhcp_servers = new_servers;
1664+
1665+
if (g_ntpc_daemon.source == NTP_SERVER_SOURCE_DHCP &&
1666+
(g_ntpc_daemon.state == NTP_STARTED ||
1667+
g_ntpc_daemon.state == NTP_RUNNING))
1668+
{
1669+
restart = true;
1670+
}
1671+
1672+
sem_post(&g_ntpc_daemon.lock);
1673+
free(old_servers);
1674+
1675+
if (restart)
1676+
{
1677+
ret = ntpc_stop();
1678+
if (ret >= 0 && new_servers != NULL)
1679+
{
1680+
ret = ntpc_start();
1681+
}
1682+
}
1683+
1684+
return ret;
15541685
}
15551686

15561687
/****************************************************************************

0 commit comments

Comments
 (0)