summaryrefslogtreecommitdiff
path: root/src/ntp.c
diff options
context:
space:
mode:
authorSeonah Moon <seonah1.moon@samsung.com>2018-01-23 14:50:50 +0900
committerSeonah Moon <seonah1.moon@samsung.com>2018-01-23 14:50:55 +0900
commit30602f521a85820a9f6b7ac04876400e00c68b15 (patch)
treef035a4fcc014a034f3b492886d1e8395f327fd25 /src/ntp.c
parenta079cfe6f815f8c69055de834d1ccbdf1fd94ba7 (diff)
parent9362752a471a5c892d679548fbf2828d5fc5684b (diff)
downloadconnman-30602f521a85820a9f6b7ac04876400e00c68b15.tar.gz
connman-30602f521a85820a9f6b7ac04876400e00c68b15.tar.bz2
connman-30602f521a85820a9f6b7ac04876400e00c68b15.zip
Updated connman to version 1.35
Change-Id: I13526fbf80296a79be15548fc226a308941ac9ec Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Diffstat (limited to 'src/ntp.c')
-rwxr-xr-xsrc/ntp.c205
1 files changed, 141 insertions, 64 deletions
diff --git a/src/ntp.c b/src/ntp.c
index bc553bf3..11512a02 100755
--- a/src/ntp.c
+++ b/src/ntp.c
@@ -30,10 +30,12 @@
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
+#include <sys/timex.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
+#include <netdb.h>
#include <glib.h>
@@ -65,9 +67,13 @@ struct ntp_msg {
#define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */
-#define STEPTIME_MIN_OFFSET 0.128
+#define STEPTIME_MIN_OFFSET 0.4
#define LOGTOD(a) ((a) < 0 ? 1. / (1L << -(a)) : 1L << (int)(a))
+#define NSEC_PER_SEC ((uint64_t)1000000000ULL)
+#ifndef ADJ_SETOFFSET
+#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
+#endif
#define NTP_SEND_TIMEOUT 2
#define NTP_SEND_RETRIES 3
@@ -117,12 +123,12 @@ static struct timespec mtx_time;
static int transmit_fd = 0;
static char *timeserver = NULL;
-static struct sockaddr_in timeserver_addr;
+static struct sockaddr_in6 timeserver_addr;
static gint poll_id = 0;
static gint timeout_id = 0;
static guint retries = 0;
-static void send_packet(int fd, const char *server, uint32_t timeout);
+static void send_packet(int fd, struct sockaddr *server, uint32_t timeout);
static void next_server(void)
{
@@ -143,17 +149,19 @@ static gboolean send_timeout(gpointer user_data)
if (retries++ == NTP_SEND_RETRIES)
next_server();
else
- send_packet(transmit_fd, timeserver, timeout << 1);
+ send_packet(transmit_fd, (struct sockaddr *)&timeserver_addr, timeout << 1);
return FALSE;
}
-static void send_packet(int fd, const char *server, uint32_t timeout)
+static void send_packet(int fd, struct sockaddr *server, uint32_t timeout)
{
struct ntp_msg msg;
- struct sockaddr_in addr;
struct timeval transmit_timeval;
ssize_t len;
+ void * addr;
+ int size;
+ char ipaddrstring[INET6_ADDRSTRLEN + 1];
/*
* At some point, we could specify the actual system precision with:
@@ -164,14 +172,19 @@ static void send_packet(int fd, const char *server, uint32_t timeout)
memset(&msg, 0, sizeof(msg));
msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4,
NTP_FLAG_MD_CLIENT);
- msg.poll = 4; // min
- msg.poll = 10; // max
+ msg.poll = 10;
msg.precision = NTP_PRECISION_S;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(123);
- addr.sin_addr.s_addr = inet_addr(server);
+ if (server->sa_family == AF_INET) {
+ size = sizeof(struct sockaddr_in);
+ addr = (void *)&(((struct sockaddr_in *)&timeserver_addr)->sin_addr);
+ } else if (server->sa_family == AF_INET6) {
+ size = sizeof(struct sockaddr_in6);
+ addr = (void *)&timeserver_addr.sin6_addr;
+ } else {
+ connman_error("Family is neither ipv4 nor ipv6");
+ return;
+ }
gettimeofday(&transmit_timeval, NULL);
clock_gettime(CLOCK_MONOTONIC, &mtx_time);
@@ -180,10 +193,12 @@ static void send_packet(int fd, const char *server, uint32_t timeout)
msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT,
- &addr, sizeof(addr));
+ server, size);
+
if (len < 0) {
connman_error("Time request for server %s failed (%d/%s)",
- server, errno, strerror(errno));
+ inet_ntop(server->sa_family, addr, ipaddrstring, sizeof(ipaddrstring)),
+ errno, strerror(errno));
if (errno == ENETUNREACH)
__connman_timeserver_sync_next();
@@ -192,7 +207,8 @@ static void send_packet(int fd, const char *server, uint32_t timeout)
}
if (len != sizeof(msg)) {
- connman_error("Broken time request for server %s", server);
+ connman_error("Broken time request for server %s",
+ inet_ntop(server->sa_family, addr, ipaddrstring, sizeof(ipaddrstring)));
return;
}
@@ -213,7 +229,7 @@ static gboolean next_poll(gpointer user_data)
if (!timeserver || transmit_fd == 0)
return FALSE;
- send_packet(transmit_fd, timeserver, NTP_SEND_TIMEOUT);
+ send_packet(transmit_fd, (struct sockaddr *)&timeserver_addr, NTP_SEND_TIMEOUT);
return FALSE;
}
@@ -235,7 +251,9 @@ static void decode_msg(void *base, size_t len, struct timeval *tv,
double m_delta, org, rec, xmt, dst;
double delay, offset;
static guint transmit_delay;
-
+#if !defined TIZEN_EXT
+ struct timex tmx = {};
+#endif
if (len < sizeof(*msg)) {
connman_error("Invalid response from time server");
return;
@@ -324,8 +342,6 @@ static void decode_msg(void *base, size_t len, struct timeval *tv,
poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL);
- connman_info("ntp: time slew %+.6f s", offset);
-
#if defined TIZEN_EXT
//send the dbus message to alram-manager
{
@@ -387,37 +403,44 @@ static void decode_msg(void *base, size_t len, struct timeval *tv,
}
#else
if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
- struct timeval adj;
-
- adj.tv_sec = (long) offset;
- adj.tv_usec = (offset - adj.tv_sec) * 1000000;
-
- DBG("adjusting time");
-
- if (adjtime(&adj, &adj) < 0) {
- connman_error("Failed to adjust time");
- return;
- }
-
- DBG("%lu seconds, %lu msecs", adj.tv_sec, adj.tv_usec);
+ tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
+ tmx.status = STA_PLL;
+ tmx.offset = offset * NSEC_PER_SEC;
+ tmx.constant = msg->poll - 4;
+ tmx.maxerror = 0;
+ tmx.esterror = 0;
+
+ connman_info("ntp: adjust (slew): %+.6f sec", offset);
} else {
- struct timeval cur;
- double dtime;
-
- gettimeofday(&cur, NULL);
- dtime = offset + cur.tv_sec + 1.0e-6 * cur.tv_usec;
- cur.tv_sec = (long) dtime;
- cur.tv_usec = (dtime - cur.tv_sec) * 1000000;
+ tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR;
+
+ /* ADJ_NANO uses nanoseconds in the microseconds field */
+ tmx.time.tv_sec = (long)offset;
+ tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
+ tmx.maxerror = 0;
+ tmx.esterror = 0;
+
+ /* the kernel expects -0.3s as {-1, 7000.000.000} */
+ if (tmx.time.tv_usec < 0) {
+ tmx.time.tv_sec -= 1;
+ tmx.time.tv_usec += NSEC_PER_SEC;
+ }
- DBG("setting time");
+ connman_info("ntp: adjust (jump): %+.6f sec", offset);
+ }
- if (settimeofday(&cur, NULL) < 0) {
- connman_error("Failed to set time");
- return;
- }
+ if (NTP_FLAGS_LI_DECODE(msg->flags) & NTP_FLAG_LI_ADDSECOND)
+ tmx.status |= STA_INS;
+ else if (NTP_FLAGS_LI_DECODE(msg->flags) & NTP_FLAG_LI_DELSECOND)
+ tmx.status |= STA_DEL;
- DBG("%lu seconds, %lu msecs", cur.tv_sec, cur.tv_usec);
+ if (adjtimex(&tmx) < 0) {
+ connman_error("Failed to adjust time");
+ return;
}
+
+ DBG("interval/delta/delay/drift %fs/%+.3fs/%.3fs/%+ldppm",
+ LOGTOD(msg->poll), offset, delay, tmx.freq / 65536);
#endif
}
@@ -425,7 +448,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
gpointer user_data)
{
unsigned char buf[128];
- struct sockaddr_in sender_addr;
+ struct sockaddr_in6 sender_addr;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
@@ -434,6 +457,9 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
char aux[128];
ssize_t len;
int fd;
+ int size;
+ void * addr_ptr;
+ void * src_ptr;
if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
connman_error("Problem with timer server channel");
@@ -458,8 +484,20 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
if (len < 0)
return TRUE;
- if (timeserver_addr.sin_addr.s_addr != sender_addr.sin_addr.s_addr)
- /* only accept messages from the timeserver */
+ if (sender_addr.sin6_family == AF_INET) {
+ size = 4;
+ addr_ptr = &((struct sockaddr_in *)&timeserver_addr)->sin_addr;
+ src_ptr = &((struct sockaddr_in *)&sender_addr)->sin_addr;
+ } else if (sender_addr.sin6_family == AF_INET6) {
+ size = 16;
+ addr_ptr = &((struct sockaddr_in6 *)&timeserver_addr)->sin6_addr;
+ src_ptr = &((struct sockaddr_in6 *)&sender_addr)->sin6_addr;
+ } else {
+ connman_error("Not a valid family type");
+ return TRUE;
+ }
+
+ if(memcmp(addr_ptr, src_ptr, size) != 0)
return TRUE;
tv = NULL;
@@ -484,36 +522,76 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
static void start_ntp(char *server)
{
GIOChannel *channel;
- struct sockaddr_in addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+ struct sockaddr * addr;
+ struct sockaddr_in * in4addr;
+ struct sockaddr_in6 in6addr;
+ int size;
+ int family;
int tos = IPTOS_LOWDELAY, timestamp = 1;
+ int ret;
if (!server)
return;
- DBG("server %s", server);
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ret = getaddrinfo(server, NULL, &hint, &info);
- if (channel_watch > 0)
- goto send;
+ if (ret) {
+ connman_error("cannot get server info");
+ return;
+ }
- transmit_fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (transmit_fd < 0) {
- connman_error("Failed to open time server socket");
+ family = info->ai_family;
+
+ memcpy(&timeserver_addr, info->ai_addr, info->ai_addrlen);
+ freeaddrinfo(info);
+ memset(&in6addr, 0, sizeof(in6addr));
+
+ if (family == AF_INET) {
+ ((struct sockaddr_in *)&timeserver_addr)->sin_port = htons(123);
+ in4addr = (struct sockaddr_in *)&in6addr;
+ in4addr->sin_family = family;
+ addr = (struct sockaddr *)in4addr;
+ size = sizeof(struct sockaddr_in);
+ } else if (family == AF_INET6) {
+ timeserver_addr.sin6_port = htons(123);
+ in6addr.sin6_family = family;
+ addr = (struct sockaddr *)&in6addr;
+ size = sizeof(in6addr);
+ } else {
+ connman_error("Family is neither ipv4 nor ipv6");
return;
}
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
+ DBG("server %s family %d", server, family);
- if (bind(transmit_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ if (channel_watch > 0)
+ goto send;
+
+ transmit_fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+
+ if (transmit_fd <= 0) {
+ connman_error("Failed to open time server socket");
+ return;
+ }
+
+ if (bind(transmit_fd, (struct sockaddr *) addr, size) < 0) {
connman_error("Failed to bind time server socket");
close(transmit_fd);
return;
}
- if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
- connman_error("Failed to set type of service option");
- close(transmit_fd);
- return;
+ if (family == AF_INET) {
+ if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
+ connman_error("Failed to set type of service option");
+ close(transmit_fd);
+ return;
+ }
}
if (setsockopt(transmit_fd, SOL_SOCKET, SO_TIMESTAMP, &timestamp,
@@ -541,7 +619,7 @@ static void start_ntp(char *server)
g_io_channel_unref(channel);
send:
- send_packet(transmit_fd, server, NTP_SEND_TIMEOUT);
+ send_packet(transmit_fd, (struct sockaddr*)&timeserver_addr, NTP_SEND_TIMEOUT);
}
int __connman_ntp_start(char *server)
@@ -555,7 +633,6 @@ int __connman_ntp_start(char *server)
g_free(timeserver);
timeserver = g_strdup(server);
- timeserver_addr.sin_addr.s_addr = inet_addr(server);
start_ntp(timeserver);