summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2010-05-31 15:09:28 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2010-05-31 17:39:56 +0200
commitec6dc19bbeb4c93e951ba5419ccf6768d5811ae6 (patch)
tree1673a4b201f6f6cdc1d5277a5c2821cb569f9d5a
parentdba90159b8bf8f065fcbce48432ef5da36a0c5ce (diff)
downloadconnman-ec6dc19bbeb4c93e951ba5419ccf6768d5811ae6.tar.gz
connman-ec6dc19bbeb4c93e951ba5419ccf6768d5811ae6.tar.bz2
connman-ec6dc19bbeb4c93e951ba5419ccf6768d5811ae6.zip
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.
-rw-r--r--Makefile.am1
-rw-r--r--Makefile.plugins12
-rw-r--r--configure.ac18
-rw-r--r--plugins/ntpd.c245
-rw-r--r--src/service.c3
5 files changed, 279 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 511f088d..0e98e8b4 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 0748c3ec..7df46a48 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 fc0c519f..13c1a3a5 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 00000000..ce140276
--- /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 <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/plugin.h>
+#include <connman/task.h>
+#include <connman/timeserver.h>
+#include <connman/driver.h>
+#include <connman/log.h>
+
+/*
+ * 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 d9d3fafe..1d4cde38 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;