summaryrefslogtreecommitdiff
path: root/vpn/main.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-11-12 14:07:21 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-11-23 12:58:50 +0200
commit4ba04eb6172f898402e0aa66f0dc8f564a12279f (patch)
tree7a67e489ea3de6f65e65d6034b2a0951db709cd0 /vpn/main.c
parenta426464354273a5586612b6577288e3662e3f8ac (diff)
downloadconnman-4ba04eb6172f898402e0aa66f0dc8f564a12279f.tar.gz
connman-4ba04eb6172f898402e0aa66f0dc8f564a12279f.tar.bz2
connman-4ba04eb6172f898402e0aa66f0dc8f564a12279f.zip
vpn: New vpn daemon that handles vpn connections and clients
Diffstat (limited to 'vpn/main.c')
-rw-r--r--vpn/main.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/vpn/main.c b/vpn/main.c
new file mode 100644
index 00000000..35daca77
--- /dev/null
+++ b/vpn/main.c
@@ -0,0 +1,257 @@
+/*
+ *
+ * ConnMan VPN daemon
+ *
+ * Copyright (C) 2012 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <netdb.h>
+
+#include <gdbus.h>
+
+#include "../src/connman.h"
+#include "vpn.h"
+
+#include "connman/vpn-dbus.h"
+
+static GMainLoop *main_loop = NULL;
+
+static unsigned int __terminated = 0;
+
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+ gpointer user_data)
+{
+ struct signalfd_siginfo si;
+ ssize_t result;
+ int fd;
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ fd = g_io_channel_unix_get_fd(channel);
+
+ result = read(fd, &si, sizeof(si));
+ if (result != sizeof(si))
+ return FALSE;
+
+ switch (si.ssi_signo) {
+ case SIGINT:
+ case SIGTERM:
+ if (__terminated == 0) {
+ connman_info("Terminating");
+ g_main_loop_quit(main_loop);
+ }
+
+ __terminated = 1;
+ break;
+ }
+
+ return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+ GIOChannel *channel;
+ guint source;
+ sigset_t mask;
+ int fd;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+
+ if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+ perror("Failed to set signal mask");
+ return 0;
+ }
+
+ fd = signalfd(-1, &mask, 0);
+ if (fd < 0) {
+ perror("Failed to create signal descriptor");
+ return 0;
+ }
+
+ channel = g_io_channel_unix_new(fd);
+
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+
+ source = g_io_add_watch(channel,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ signal_handler, NULL);
+
+ g_io_channel_unref(channel);
+
+ return source;
+}
+
+static void disconnect_callback(DBusConnection *conn, void *user_data)
+{
+ connman_error("D-Bus disconnect");
+
+ g_main_loop_quit(main_loop);
+}
+
+static gchar *option_debug = NULL;
+static gchar *option_plugin = NULL;
+static gchar *option_noplugin = NULL;
+static gboolean option_detach = TRUE;
+static gboolean option_version = FALSE;
+
+static gboolean parse_debug(const char *key, const char *value,
+ gpointer user_data, GError **error)
+{
+ if (value)
+ option_debug = g_strdup(value);
+ else
+ option_debug = g_strdup("*");
+
+ return TRUE;
+}
+
+static GOptionEntry options[] = {
+ { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
+ G_OPTION_ARG_CALLBACK, parse_debug,
+ "Specify debug options to enable", "DEBUG" },
+ { "plugin", 'p', 0, G_OPTION_ARG_STRING, &option_plugin,
+ "Specify plugins to load", "NAME,..." },
+ { "noplugin", 'P', 0, G_OPTION_ARG_STRING, &option_noplugin,
+ "Specify plugins not to load", "NAME,..." },
+ { "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &option_detach,
+ "Don't fork daemon to background" },
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
+ "Show version information and exit" },
+ { NULL },
+};
+
+int main(int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ DBusConnection *conn;
+ DBusError err;
+ guint signal;
+
+ context = g_option_context_new(NULL);
+ g_option_context_add_main_entries(context, options, NULL);
+
+ if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
+ if (error != NULL) {
+ g_printerr("%s\n", error->message);
+ g_error_free(error);
+ } else
+ g_printerr("An unknown error occurred\n");
+ exit(1);
+ }
+
+ g_option_context_free(context);
+
+ if (option_version == TRUE) {
+ printf("%s\n", VERSION);
+ exit(0);
+ }
+
+ if (option_detach == TRUE) {
+ if (daemon(0, 0)) {
+ perror("Can't start daemon");
+ exit(1);
+ }
+ }
+
+ if (mkdir(STATEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
+ S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
+ if (errno != EEXIST)
+ perror("Failed to create state directory");
+ }
+
+ if (mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
+ S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
+ if (errno != EEXIST)
+ perror("Failed to create storage directory");
+ }
+
+ umask(0077);
+
+ main_loop = g_main_loop_new(NULL, FALSE);
+
+ signal = setup_signalfd();
+
+ dbus_error_init(&err);
+
+ conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, VPN_SERVICE, &err);
+ if (conn == NULL) {
+ if (dbus_error_is_set(&err) == TRUE) {
+ fprintf(stderr, "%s\n", err.message);
+ dbus_error_free(&err);
+ } else
+ fprintf(stderr, "Can't register with system bus\n");
+ exit(1);
+ }
+
+ g_dbus_set_disconnect_function(conn, disconnect_callback, NULL, NULL);
+
+ __connman_log_init(argv[0], option_debug, option_detach, FALSE,
+ "Connection Manager VPN daemon", VERSION);
+ __connman_dbus_init(conn);
+ __vpn_provider_init();
+ __vpn_manager_init();
+ __vpn_ipconfig_init();
+ __vpn_rtnl_init();
+ __connman_task_init();
+ __connman_plugin_init(option_plugin, option_noplugin);
+
+ __vpn_rtnl_start();
+
+ g_free(option_plugin);
+ g_free(option_noplugin);
+
+ g_main_loop_run(main_loop);
+
+ g_source_remove(signal);
+
+ __connman_task_cleanup();
+ __vpn_rtnl_cleanup();
+ __vpn_ipconfig_cleanup();
+ __vpn_manager_cleanup();
+ __vpn_provider_cleanup();
+ __connman_dbus_cleanup();
+ __connman_log_cleanup(FALSE);
+
+ dbus_connection_unref(conn);
+
+ g_main_loop_unref(main_loop);
+
+ g_free(option_debug);
+
+ return 0;
+}