mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sntp: initial import
This commit is contained in:
parent
ac94d38657
commit
cf3f02c2e1
@ -19,6 +19,11 @@ ifneq (,$(filter nhdp,$(USEMODULE)))
|
||||
USEMODULE += oonf_rfc5444
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sntp,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sock_udp
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif
|
||||
USEMODULE += gnrc_netdev2
|
||||
|
@ -89,6 +89,10 @@ ifneq (,$(filter gnrc_uhcpc,$(USEMODULE)))
|
||||
DIRS += net/gnrc/application_layer/uhcpc
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sntp,$(USEMODULE)))
|
||||
DIRS += net/application_layer/sntp
|
||||
endif
|
||||
|
||||
ifneq (,$(filter netopt,$(USEMODULE)))
|
||||
DIRS += net/crosslayer/netopt
|
||||
endif
|
||||
|
167
sys/include/net/ntp_packet.h
Normal file
167
sys/include/net/ntp_packet.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_ntp_packet NTP Packet
|
||||
* @ingroup net
|
||||
* @brief The NTP packet module provides functionality to manipulate the NTP header
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief NTP packet definitions
|
||||
*
|
||||
* @author Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NTP_PACKET_H_
|
||||
#define NTP_PACKET_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "byteorder.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Bit positions and masks for ntp_packet_t::li_vn_mode
|
||||
*/
|
||||
/**
|
||||
* @brief Leap indicator position
|
||||
*/
|
||||
#define NTP_PACKET_LI_POS (6U)
|
||||
#define NTP_PACKET_LI_MASK (0xc0) /**< leap indicator mask */
|
||||
#define NTP_PACKET_VN_POS (3U) /**< version position */
|
||||
#define NTP_PACKET_VN_MASK (0x38) /**< version mask */
|
||||
#define NTP_PACKET_MODE_MASK (0x07) /**< mode mask */
|
||||
/** @} */
|
||||
|
||||
#define NTP_VERSION (4U) /**< NTP version */
|
||||
#define NTP_PORT (123U) /**< NTP port number */
|
||||
|
||||
/**
|
||||
* @brief NTP modes
|
||||
*/
|
||||
typedef enum {
|
||||
NTP_MODE_RESERVED = 0, /**< reserved */
|
||||
NTP_MODE_SYM_ACTIVE, /**< symmetric active */
|
||||
NTP_MODE_SYM_PASSIVE, /**< symmetric passive */
|
||||
NTP_MODE_CLIENT, /**< client */
|
||||
NTP_MODE_SERVER, /**< server */
|
||||
NTP_MODE_BROADCAST, /**< broadcast */
|
||||
NTP_MODE_PRIV /**< reserved for private use */
|
||||
} ntp_mode_t;
|
||||
|
||||
/**
|
||||
* @brief NTP timestamp
|
||||
*
|
||||
* @see [RFC 5905, Section 6](https://tools.ietf.org/html/rfc5905#section-6)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
network_uint32_t seconds; /**< seconds since 1 January 1900 00:00 UTC */
|
||||
network_uint32_t fraction; /**< fraction of seconds in 232 picoseconds */
|
||||
} ntp_timestamp_t;
|
||||
|
||||
/**
|
||||
* @brief NTP packet
|
||||
*
|
||||
* @see [RFC 5905, Section 7.3](https://tools.ietf.org/html/rfc5905#section-7.3)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t li_vn_mode; /**< leap indicator, version and mode */
|
||||
uint8_t stratum; /**< stratum */
|
||||
uint8_t poll; /**< poll in log2 seconds */
|
||||
uint8_t precision; /**< precision in log2 seconds */
|
||||
network_uint32_t root_delay; /**< root delay in NTP short format */
|
||||
network_uint32_t root_dispersion; /**< root dispersion in NTP short format */
|
||||
network_uint32_t reference_id; /**< reference ID */
|
||||
ntp_timestamp_t reference; /**< reference timestamp */
|
||||
ntp_timestamp_t origin; /**< origin timesptamp */
|
||||
ntp_timestamp_t receive; /**< receive timestamp */
|
||||
ntp_timestamp_t transmit; /**< transmit timestamp */
|
||||
} ntp_packet_t;
|
||||
|
||||
/**
|
||||
* @brief Set leap indicator in a NTP packet
|
||||
*
|
||||
* @param[in] packet The NTP packet
|
||||
* @param[in] li Leap indicator
|
||||
*/
|
||||
static inline void ntp_packet_set_li(ntp_packet_t *packet, uint8_t li)
|
||||
{
|
||||
packet->li_vn_mode &= ~NTP_PACKET_LI_MASK;
|
||||
packet->li_vn_mode |= li << NTP_PACKET_LI_POS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set version in a NTP packet
|
||||
*
|
||||
* @param[in] packet The NTP packet
|
||||
*/
|
||||
static inline void ntp_packet_set_vn(ntp_packet_t *packet)
|
||||
{
|
||||
packet->li_vn_mode &= ~NTP_PACKET_VN_MASK;
|
||||
packet->li_vn_mode |= (NTP_VERSION << NTP_PACKET_VN_POS) & NTP_PACKET_VN_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set mode in a NTP packet
|
||||
*
|
||||
* @param[in] packet The NTP packet
|
||||
* @param[in] mode Mode
|
||||
*/
|
||||
static inline void ntp_packet_set_mode(ntp_packet_t *packet, ntp_mode_t mode)
|
||||
{
|
||||
packet->li_vn_mode &= ~NTP_PACKET_MODE_MASK;
|
||||
packet->li_vn_mode |= mode & NTP_PACKET_MODE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get leap indicator from a NTP packet
|
||||
*
|
||||
* @param[in] packet The NTP packet
|
||||
*
|
||||
* @return The leap indicator of @p packet
|
||||
*/
|
||||
static inline uint8_t ntp_packet_get_li(ntp_packet_t *packet)
|
||||
{
|
||||
return (packet->li_vn_mode & NTP_PACKET_LI_MASK) >> NTP_PACKET_LI_POS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get version from a NTP packet
|
||||
*
|
||||
* @param[in] packet The NTP packet
|
||||
*
|
||||
* @return The version of @p packet
|
||||
*/
|
||||
static inline uint8_t ntp_packet_get_vn(ntp_packet_t *packet)
|
||||
{
|
||||
return (packet->li_vn_mode & NTP_PACKET_VN_MASK) >> NTP_PACKET_VN_POS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get mode from a NTP packet
|
||||
*
|
||||
* @param[in] packet The NTP packet
|
||||
*
|
||||
* @return The version of @p packet
|
||||
*/
|
||||
static inline ntp_mode_t ntp_packet_get_mode(ntp_packet_t *packet)
|
||||
{
|
||||
return (packet->li_vn_mode & NTP_PACKET_MODE_MASK);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NTP_PACKET_H_ */
|
||||
/** @} */
|
55
sys/include/net/sntp.h
Normal file
55
sys/include/net/sntp.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_sntp Simple Network Time Protocol
|
||||
* @ingroup net
|
||||
* @brief Simple Network Time Protocol (SNTP) implementation
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief SNTP definitions
|
||||
*
|
||||
* @author Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef SNTP_H_
|
||||
#define SNTP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "net/sock/udp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Synchronize with time server
|
||||
*
|
||||
* @param[in] server The time server
|
||||
* @param[in] timeout Timeout for the server response
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return Negative number on error
|
||||
*/
|
||||
int sntp_sync(sock_udp_ep_t *server, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Get real time offset from system time as returned by @ref xtimer_now64()
|
||||
*
|
||||
* @return Real time offset in microseconds relative to 1900-01-01 00:00 UTC
|
||||
*/
|
||||
int64_t sntp_get_offset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SNTP_H_ */
|
||||
/** @} */
|
2
sys/net/application_layer/sntp/Makefile
Normal file
2
sys/net/application_layer/sntp/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
MODULE = sntp
|
||||
include $(RIOTBASE)/Makefile.base
|
89
sys/net/application_layer/sntp/sntp.c
Normal file
89
sys/net/application_layer/sntp/sntp.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief SNTP implementation
|
||||
*
|
||||
* @author Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "net/sntp.h"
|
||||
#include "net/ntp_packet.h"
|
||||
#include "net/sock/udp.h"
|
||||
#include "xtimer.h"
|
||||
#include "mutex.h"
|
||||
#include "byteorder.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
static sock_udp_t _sntp_sock;
|
||||
static int64_t _sntp_offset = 0;
|
||||
static mutex_t _sntp_mutex = MUTEX_INIT;
|
||||
static ntp_packet_t _sntp_packet;
|
||||
|
||||
int sntp_sync(sock_udp_ep_t *server, uint32_t timeout)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&_sntp_mutex);
|
||||
if ((result = sock_udp_create(&_sntp_sock,
|
||||
NULL,
|
||||
server,
|
||||
0)) < 0) {
|
||||
DEBUG("Error creating UDP sock\n");
|
||||
mutex_unlock(&_sntp_mutex);
|
||||
return result;
|
||||
}
|
||||
memset(&_sntp_packet, 0, sizeof(_sntp_packet));
|
||||
ntp_packet_set_vn(&_sntp_packet);
|
||||
ntp_packet_set_mode(&_sntp_packet, NTP_MODE_CLIENT);
|
||||
|
||||
if ((result = (int)sock_udp_send(&_sntp_sock,
|
||||
&_sntp_packet,
|
||||
sizeof(_sntp_packet),
|
||||
NULL)) < 0) {
|
||||
DEBUG("Error sending message\n");
|
||||
sock_udp_close(&_sntp_sock);
|
||||
mutex_unlock(&_sntp_mutex);
|
||||
return result;
|
||||
}
|
||||
if ((result = (int)sock_udp_recv(&_sntp_sock,
|
||||
&_sntp_packet,
|
||||
sizeof(_sntp_packet),
|
||||
timeout,
|
||||
NULL)) < 0) {
|
||||
DEBUG("Error receiving message\n");
|
||||
sock_udp_close(&_sntp_sock);
|
||||
mutex_unlock(&_sntp_mutex);
|
||||
return result;
|
||||
}
|
||||
sock_udp_close(&_sntp_sock);
|
||||
_sntp_offset = (byteorder_ntohl(_sntp_packet.transmit.seconds) * SEC_IN_USEC) +
|
||||
((byteorder_ntohl(_sntp_packet.transmit.fraction) * 232)
|
||||
/ 1000000) - xtimer_now64();
|
||||
mutex_unlock(&_sntp_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t sntp_get_offset(void)
|
||||
{
|
||||
int64_t result;
|
||||
|
||||
mutex_lock(&_sntp_mutex);
|
||||
result = _sntp_offset;
|
||||
mutex_unlock(&_sntp_mutex);
|
||||
return result;
|
||||
}
|
@ -66,6 +66,9 @@ endif
|
||||
ifneq (,$(filter ccn-lite-utils,$(USEMODULE)))
|
||||
SRC += sc_ccnl.c
|
||||
endif
|
||||
ifneq (,$(filter sntp,$(USEMODULE)))
|
||||
SRC += sc_sntp.c
|
||||
endif
|
||||
|
||||
# TODO
|
||||
# Conditional building not possible at the moment due to
|
||||
|
52
sys/shell/commands/sc_sntp.c
Normal file
52
sys/shell/commands/sc_sntp.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup sys_shell_commands
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Prints the real time offset from the system time
|
||||
*
|
||||
* @author Luminița Lăzărescu <cluminita.lazarescu@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "net/sntp.h"
|
||||
#include "net/ntp_packet.h"
|
||||
#include "net/af.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
|
||||
#define _DEFAULT_TIMEOUT (5000U);
|
||||
|
||||
static void _usage(char *cmd)
|
||||
{
|
||||
printf("Usage: %s <server addr> [<timeout>]\n", cmd);
|
||||
puts("default: timeout = 5000");
|
||||
}
|
||||
|
||||
int _ntpdate(int argc, char **argv)
|
||||
{
|
||||
uint32_t timeout = _DEFAULT_TIMEOUT;
|
||||
|
||||
if (argc < 2) {
|
||||
_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
sock_udp_ep_t server = { .port = NTP_PORT, .family = AF_INET6 };
|
||||
ipv6_addr_from_str((ipv6_addr_t *)&server.addr, argv[1]);
|
||||
if (argc > 2) {
|
||||
timeout = atoi(argv[2]);
|
||||
}
|
||||
if (sntp_sync(&server, timeout) < 0) {
|
||||
puts("Error in synchronization");
|
||||
return 1;
|
||||
}
|
||||
printf("Offset: %i\n", (int)sntp_get_offset());
|
||||
return 0;
|
||||
}
|
@ -129,6 +129,10 @@ extern int _ccnl_interest(int argc, char **argv);
|
||||
extern int _ccnl_fib(int argc, char **argv);
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_SNTP
|
||||
extern int _ntpdate(int argc, char **argv);
|
||||
#endif
|
||||
|
||||
const shell_command_t _shell_command_list[] = {
|
||||
{"reboot", "Reboot the node", _reboot_handler},
|
||||
#ifdef MODULE_CONFIG
|
||||
@ -209,10 +213,13 @@ const shell_command_t _shell_command_list[] = {
|
||||
{"saul", "interact with sensors and actuators using SAUL", _saul },
|
||||
#endif
|
||||
#ifdef MODULE_CCN_LITE_UTILS
|
||||
{ "ccnl_open", "opens an interface or socket", _ccnl_open},
|
||||
{ "ccnl_int", "sends an interest", _ccnl_interest},
|
||||
{ "ccnl_cont", "create content and populated it", _ccnl_content},
|
||||
{ "ccnl_fib", "shows or modifies the CCN-Lite FIB", _ccnl_fib},
|
||||
{ "ccnl_open", "opens an interface or socket", _ccnl_open },
|
||||
{ "ccnl_int", "sends an interest", _ccnl_interest },
|
||||
{ "ccnl_cont", "create content and populated it", _ccnl_content },
|
||||
{ "ccnl_fib", "shows or modifies the CCN-Lite FIB", _ccnl_fib },
|
||||
#endif
|
||||
#ifdef MODULE_SNTP
|
||||
{ "ntpdate", "synchronizes with a remote time server", _ntpdate },
|
||||
#endif
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user