static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data) { int i; DBG("status %d", status); if (status == G_RESOLV_RESULT_STATUS_SUCCESS) { if (results) { for (i = 0; results[i]; i++) { DBG("result[%d]: %s", i, results[i]); if (i == 0) continue; ts_list = __connman_timeserver_add_list( ts_list, results[i]); } DBG("Using timeserver %s", results[0]); __connman_ntp_start(results[0]); return; } } /* If resolving fails, move to the next server */ __connman_timeserver_sync_next(); }
static void next_server(void) { if (timeserver) { g_free(timeserver); timeserver = NULL; } __connman_timeserver_sync_next(); }
static void send_packet(int fd, const char *server) { struct ntp_msg msg; struct sockaddr_in addr; struct timeval transmit_timeval; ssize_t len; /* * At some point, we could specify the actual system precision with: * * clock_getres(CLOCK_REALTIME, &ts); * msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9)); */ 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.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); gettimeofday(&transmit_timeval, NULL); clock_gettime(CLOCK_MONOTONIC, &mtx_time); msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970); msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000); len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT, &addr, sizeof(addr)); if (len < 0) { connman_error("Time request for server %s failed (%d/%s)", server, errno, strerror(errno)); if (errno == ENETUNREACH) __connman_timeserver_sync_next(); return; } if (len != sizeof(msg)) { connman_error("Broken time request for server %s", server); return; } /* * Add a retry timeout of two seconds to retry the existing * request. After a set number of retries, we'll fallback to * trying another server. */ timeout_id = g_timeout_add_seconds(NTP_SEND_TIMEOUT, send_timeout, NULL); }
/* * This function must be called everytime the default service changes, the * service timeserver(s) or gatway changes or the global timeserver(s) changes. */ int __connman_timeserver_sync(struct connman_service *default_service) { struct connman_service *service; if (default_service) service = default_service; else service = __connman_service_get_default(); if (!service) return -EINVAL; if (!resolv) return 0; /* * Before we start creating the new timeserver list we must stop * any ongoing ntp query and server resolution. */ __connman_ntp_stop(); ts_recheck_disable(); if (resolv_id > 0) g_resolv_cancel_lookup(resolv, resolv_id); g_slist_free_full(ts_list, g_free); ts_list = __connman_timeserver_get_all(service); __connman_service_timeserver_changed(service, ts_list); if (!ts_list) { DBG("No timeservers set."); return 0; } ts_recheck_enable(); __connman_timeserver_sync_next(); return 0; }