From ec6dc19bbeb4c93e951ba5419ccf6768d5811ae6 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 31 May 2010 15:09:28 +0200 Subject: [PATCH] ntpd plugin The ntpd plugin triggers an ntpd -q task whenever a service goes online. It either uses the meego ntp service or the one it potentially fetches from a DHCP response. --- Makefile.am | 1 + Makefile.plugins | 12 +++ configure.ac | 18 ++++ plugins/ntpd.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/service.c | 3 + 5 files changed, 279 insertions(+) create mode 100644 plugins/ntpd.c diff --git a/Makefile.am b/Makefile.am index 511f088..0e98e8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -186,6 +186,7 @@ DISTCHECK_CONFIGURE_FLAGS = --disable-gtk-doc \ --enable-client \ --enable-portal \ --enable-hh2serial-gps \ + --enable-ntpd \ --enable-tools DISTCLEANFILES = $(pkgconfig_DATA) diff --git a/Makefile.plugins b/Makefile.plugins index 0748c3e..7df46a4 100644 --- a/Makefile.plugins +++ b/Makefile.plugins @@ -249,6 +249,18 @@ script_PROGRAMS += scripts/dhclient-script scripts_dhclient_script_LDADD = @DBUS_LIBS@ endif +if NTPD +if NTPD_BUILTIN +builtin_modules += ntpd +builtin_sources += plugins/ntpd.c +builtin_cflags += -DNTPD=\"@NTPD@\" +else +plugin_LTLIBRARIES += plugins/ntpd.la +plugin_objects += $(plugins_ntpd_la_OBJECTS) +plugins_ntpd_la_CFLAGS = $(plugin_cflags) -DNTPD=\"@NTPD@\" +plugins_ntpd_la_LDFLAGS = $(plugin_ldflags) +endif +endif EXTRA_DIST += plugins/polkit.policy scripts/dhclient.conf diff --git a/configure.ac b/configure.ac index fc0c519..13c1a3a 100644 --- a/configure.ac +++ b/configure.ac @@ -280,6 +280,24 @@ AC_ARG_ENABLE(iospm, AC_HELP_STRING([--enable-iospm], [enable Intel OSPM support]), [enable_iospm=${enableval}]) AM_CONDITIONAL(IOSPM, test "${enable_iospm}" = "yes") +AC_ARG_WITH(ntpd, AC_HELP_STRING([--with-=PROGRAM], + [specify ntpd binary location]), [path_ntpd=${withval}]) + +AC_ARG_ENABLE(ntpd, + AC_HELP_STRING([--enable-ntpd], [enable ntpd support]), + [enable_ntpd=${enableval}], [enable_ntpd="no"]) + +if (test "${enable_ntpd}" != "no"); then + if (test -z "${path_ntpd}"); then + AC_PATH_PROG(NTPD, [ntpd], [], $PATH:/sbin:/usr/sbin) + else + NTPD="${path_ntpd}" + AC_SUBST(NTPD) + fi +fi +AM_CONDITIONAL(NTPD, test "${enable_ntpd}" != "no") +AM_CONDITIONAL(NTPD_BUILTIN, test "${enable_ntpd}" = "builtin") + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, AC_MSG_ERROR(GLib >= 2.16 is required)) AC_SUBST(GLIB_CFLAGS) diff --git a/plugins/ntpd.c b/plugins/ntpd.c new file mode 100644 index 0000000..ce14027 --- /dev/null +++ b/plugins/ntpd.c @@ -0,0 +1,245 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#define CONNMAN_API_SUBJECT_TO_CHANGE +#include +#include +#include +#include +#include + +/* + * The peers list are the peers currently added to a running ntpd, + * while pending_peers are the one appended but not used by ntpd yet. + */ +static GList *peers = NULL; +static GList *pending_peers = NULL; + +#define NTPD_PORT 123 +#define DEFAULT_NTP_PEER "ntp.meego.com" + +struct ntpdate_task { + struct connman_task *task; + gint conf_fd; + char *conf_path; +}; + +static connman_bool_t ntpd_running(void) +{ + int sock; + connman_bool_t ret; + struct sockaddr_in server_addr; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + return FALSE; + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(NTPD_PORT); + server_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(server_addr.sin_zero), 0, 8); + + if (bind(sock, (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)) == -1) { + if (errno == EADDRINUSE) + ret = TRUE; + else + ret = FALSE; + } + + close(sock); + + return ret; +} + +static void ntpdate_died(struct connman_task *task, void *user_data) +{ + struct ntpdate_task *ntpdate = user_data; + + DBG(""); + + unlink(ntpdate->conf_path); + g_free(ntpdate->conf_path); + connman_task_destroy(ntpdate->task); +} + +static void ntpdate_add_peer(struct ntpdate_task *ntpdate, char *peer) +{ + FILE *conf_file; + + DBG("%s", peer); + + conf_file = fdopen(ntpdate->conf_fd, "a+"); + if (conf_file == NULL) { + connman_error("fdopen failed"); + return; + } + + fprintf(conf_file, "server %s iburst\n", peer); + + fclose(conf_file); +} + +static int ntpdate(void) +{ + int err; + GError *g_err; + GList *list; + struct ntpdate_task *ntpdate; + + DBG(""); + + ntpdate = g_try_new0(struct ntpdate_task, 1); + if (ntpdate == NULL) + return -ENOMEM; + + /* ntpdate is deprecated, we use ntpd -q instead */ + ntpdate->task = connman_task_create(NTPD); + if (ntpdate->task == NULL) { + err = -ENOMEM; + goto error_task; + } + + connman_task_add_argument(ntpdate->task, "-q", NULL); + + /* The servers are added through a temp configuration file */ + ntpdate->conf_fd = g_file_open_tmp("connman.ntp.conf_XXXXXX", + &ntpdate->conf_path, &g_err); + if (ntpdate->conf_fd == -1) { + err = g_err->code; + g_free(g_err); + goto error_open; + } + + connman_task_add_argument(ntpdate->task, "-c", ntpdate->conf_path); + + DBG("conf path %s", ntpdate->conf_path); + + if (pending_peers == NULL && peers == NULL) + ntpdate_add_peer(ntpdate, DEFAULT_NTP_PEER); + + for (list = pending_peers; list; list = list->next) + ntpdate_add_peer(ntpdate, list->data); + + for (list = peers; list; list = list->next) + ntpdate_add_peer(ntpdate, list->data); + + close(ntpdate->conf_fd); + + return connman_task_run(ntpdate->task, ntpdate_died, ntpdate, + NULL, NULL, NULL); +error_open: + connman_task_destroy(ntpdate->task); + +error_task: + g_free(ntpdate); + + return err; +} + +static int ntpd_add_peer(char *peer) +{ + DBG("%s", peer); + + return 0; +} + +static void ntpd_sync(void) +{ + int err; + GList *list; + + DBG(""); + + if (!ntpd_running()) { + ntpdate(); + return; + } + + /* TODO Grab ntp keys path */ + + list = g_list_first(pending_peers); + while(list) { + char *peer = list->data; + + err = ntpd_add_peer(peer); + if (err) + continue; + + peers = g_list_prepend(peers, peer); + + list = g_list_next(list); + + pending_peers = g_list_remove(pending_peers, peer); + }; +} + +static int ntpd_append(char *server) +{ + DBG(""); + + pending_peers = g_list_prepend(pending_peers, server); + + return 0; +} + +static int ntpd_remove(char *server) +{ + DBG(""); + + peers = g_list_remove(peers, server); + /* TODO: send ntpd remove command */ + + pending_peers = g_list_remove(pending_peers, server); + + return 0; +} + +static struct connman_timeserver_driver ntpd_driver = { + .name = "ntpd", + .priority = CONNMAN_DRIVER_PRIORITY_DEFAULT, + .append = ntpd_append, + .remove = ntpd_remove, + .sync = ntpd_sync, +}; + +static int ntpd_init(void) +{ + return connman_timeserver_driver_register(&ntpd_driver); +} + +static void ntpd_exit(void) +{ + connman_timeserver_driver_unregister(&ntpd_driver); +} + +CONNMAN_PLUGIN_DEFINE(ntpd, "ntpd plugin", VERSION, + CONNMAN_PLUGIN_PRIORITY_DEFAULT, ntpd_init, ntpd_exit) diff --git a/src/service.c b/src/service.c index d9d3faf..1d4cde3 100644 --- a/src/service.c +++ b/src/service.c @@ -1901,6 +1901,9 @@ int __connman_service_indicate_state(struct connman_service *service, service->state = state; state_changed(service); + if (state == CONNMAN_SERVICE_STATE_ONLINE) + connman_timeserver_sync(); + if (state == CONNMAN_SERVICE_STATE_IDLE) { connman_bool_t reconnect; -- 2.7.4