X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmain.c;h=48a956cc7e37a19e42e62baa189ea5ec137d9173;hb=3ba2d070a7349a0f35e74be9eb995d43db5e7a7c;hp=402ccf437f0fbbb41412a80028300af0866c6cd9;hpb=249a12194decb4b7a06d717bcd5284d1467e759b;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/main.c b/src/main.c index 402ccf4..48a956c 100644 --- a/src/main.c +++ b/src/main.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * Copyright (C) 2007-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 @@ -23,100 +23,422 @@ #include #endif +#include #include #include #include #include #include +#include #include #include #include +#include #include #include "connman.h" +static struct { + connman_bool_t bg_scan; + char **pref_timeservers; + unsigned int *auto_connect; + unsigned int *preferred_techs; + char **fallback_nameservers; +} connman_settings = { + .bg_scan = TRUE, + .pref_timeservers = NULL, + .auto_connect = NULL, + .preferred_techs = NULL, + .fallback_nameservers = NULL, +}; + +static GKeyFile *load_config(const char *file) +{ + GError *err = NULL; + GKeyFile *keyfile; + + keyfile = g_key_file_new(); + + g_key_file_set_list_separator(keyfile, ','); + + if (!g_key_file_load_from_file(keyfile, file, 0, &err)) { + if (err->code != G_FILE_ERROR_NOENT) { + connman_error("Parsing %s failed: %s", file, + err->message); + } + + g_error_free(err); + g_key_file_free(keyfile); + return NULL; + } + + return keyfile; +} + +static uint *parse_service_types(char **str_list, gsize len) +{ + unsigned int *type_list; + int i, j; + enum connman_service_type type; + + type_list = g_try_new0(unsigned int, len + 1); + if (type_list == NULL) + return NULL; + + i = 0; + j = 0; + while (str_list[i] != NULL) + { + type = __connman_service_string2type(str_list[i]); + + if (type != CONNMAN_SERVICE_TYPE_UNKNOWN) { + type_list[j] = type; + j += 1; + } + i += 1; + } + + return type_list; +} + +static char **parse_fallback_nameservers(char **nameservers, gsize len) +{ + char **servers; + int i, j; + struct addrinfo hints; + struct addrinfo *addr; + + servers = g_try_new0(char *, len + 1); + if (servers == NULL) + return NULL; + + i = 0; + j = 0; + while (nameservers[i] != NULL) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + addr = NULL; + if (getaddrinfo(nameservers[i], NULL, &hints, &addr) == 0) { + servers[j] = g_strdup(nameservers[i]); + j += 1; + } + + freeaddrinfo(addr); + i += 1; + } + + return servers; +} + +static void parse_config(GKeyFile *config) +{ + GError *error = NULL; + gboolean boolean; + char **timeservers; + char **str_list; + gsize len; + char *default_auto_connect[] = { + "wifi", + "ethernet", + "cellular", + NULL + }; + + if (config == NULL) { + connman_settings.auto_connect = + parse_service_types(default_auto_connect, 3); + return; + } + + DBG("parsing main.conf"); + + boolean = g_key_file_get_boolean(config, "General", + "BackgroundScanning", &error); + if (error == NULL) + connman_settings.bg_scan = boolean; + + g_clear_error(&error); + + timeservers = g_key_file_get_string_list(config, "General", + "FallbackTimeservers", NULL, &error); + if (error == NULL) + connman_settings.pref_timeservers = timeservers; + + g_clear_error(&error); + + str_list = g_key_file_get_string_list(config, "General", + "DefaultAutoConnectTechnologies", &len, &error); + + if (error == NULL) + connman_settings.auto_connect = + parse_service_types(str_list, len); + else + connman_settings.auto_connect = + parse_service_types(default_auto_connect, 3); + + g_strfreev(str_list); + + g_clear_error(&error); + + str_list = g_key_file_get_string_list(config, "General", + "PreferredTechnologies", &len, &error); + + if (error == NULL) + connman_settings.preferred_techs = + parse_service_types(str_list, len); + + g_strfreev(str_list); + + g_clear_error(&error); + + str_list = g_key_file_get_string_list(config, "General", + "FallbackNameservers", &len, &error); + + if (error == NULL) + connman_settings.fallback_nameservers = + parse_fallback_nameservers(str_list, len); + + g_strfreev(str_list); + + g_clear_error(&error); +} + static GMainLoop *main_loop = NULL; -static void sig_term(int sig) +static unsigned int __terminated = 0; + +static gboolean signal_handler(GIOChannel *channel, GIOCondition cond, + gpointer user_data) { - g_main_loop_quit(main_loop); + 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 usage(void) +static void disconnect_callback(DBusConnection *conn, void *user_data) { - printf("Connection Manager version %s\n\n", VERSION); + connman_error("D-Bus disconnect"); - printf("Usage:\n" - "\tconnmand [-i ] [options]\n" - "\n"); + g_main_loop_quit(main_loop); +} + +static gchar *option_debug = NULL; +static gchar *option_device = NULL; +static gchar *option_plugin = NULL; +static gchar *option_nodevice = NULL; +static gchar *option_noplugin = NULL; +static gchar *option_wifi = NULL; +static gboolean option_detach = TRUE; +static gboolean option_dnsproxy = TRUE; +static gboolean option_compat = FALSE; +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("*"); - printf("Options:\n" - "\t-c, --compat Enable Network Manager compatibility\n" - "\t-n, --nodaemon Don't fork daemon to background\n" - "\t-h, --help Display help\n" - "\n"); + return TRUE; } -static struct option options[] = { - { "interface", 1, 0, 'i' }, - { "nodaemon", 0, 0, 'n' }, - { "compat", 0, 0, 'c' }, - { "debug", 0, 0, 'd' }, - { "help", 0, 0, 'h' }, - { } +static GOptionEntry options[] = { + { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG, + G_OPTION_ARG_CALLBACK, parse_debug, + "Specify debug options to enable", "DEBUG" }, + { "device", 'i', 0, G_OPTION_ARG_STRING, &option_device, + "Specify networking device or interface", "DEV" }, + { "nodevice", 'I', 0, G_OPTION_ARG_STRING, &option_nodevice, + "Specify networking interface to ignore", "DEV" }, + { "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,..." }, + { "wifi", 'W', 0, G_OPTION_ARG_STRING, &option_wifi, + "Specify driver for WiFi/Supplicant", "NAME" }, + { "nodaemon", 'n', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &option_detach, + "Don't fork daemon to background" }, + { "nodnsproxy", 'r', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &option_dnsproxy, + "Don't enable DNS Proxy" }, + { "compat", 'c', 0, G_OPTION_ARG_NONE, &option_compat, + "(obsolete)" }, + { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version, + "Show version information and exit" }, + { NULL }, }; +const char *connman_option_get_string(const char *key) +{ + if (g_strcmp0(key, "wifi") == 0) { + if (option_wifi == NULL) + return "nl80211,wext"; + else + return option_wifi; + } + + return NULL; +} + +connman_bool_t connman_setting_get_bool(const char *key) +{ + if (g_str_equal(key, "BackgroundScanning") == TRUE) + return connman_settings.bg_scan; + + return FALSE; +} + +char **connman_setting_get_string_list(const char *key) +{ + if (g_str_equal(key, "FallbackTimeservers") == TRUE) + return connman_settings.pref_timeservers; + + if (g_str_equal(key, "FallbackNameservers") == TRUE) + return connman_settings.fallback_nameservers; + + return NULL; +} + +unsigned int *connman_setting_get_uint_list(const char *key) +{ + if (g_str_equal(key, "DefaultAutoConnectTechnologies") == TRUE) + return connman_settings.auto_connect; + + if (g_str_equal(key, "PreferredTechnologies") == TRUE) + return connman_settings.preferred_techs; + + return NULL; +} + int main(int argc, char *argv[]) { + GOptionContext *context; + GError *error = NULL; DBusConnection *conn; DBusError err; - struct sigaction sa; - char interface[IFNAMSIZ]; - int opt, detach = 1, compat = 0, debug = 0; - - memset(interface, 0, IFNAMSIZ); - - while ((opt = getopt_long(argc, argv, "+i:ncdh", options, NULL)) != EOF) { - switch (opt) { - case 'i': - snprintf(interface, IFNAMSIZ, "%s", optarg); - break; - case 'n': - detach = 0; - break; - case 'c': - compat = 1; - break; - case 'd': - debug = 1; - break; - case 'h': - default: - usage(); - exit(0); - } + GKeyFile *config; + guint signal; + +#ifdef NEED_THREADS + if (g_thread_supported() == FALSE) + g_thread_init(NULL); +#endif + + 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); } - argc -= optind; - argv += optind; - optind = 0; + g_option_context_free(context); + + if (option_version == TRUE) { + printf("%s\n", VERSION); + exit(0); + } - if (detach) { + if (option_detach == TRUE) { if (daemon(0, 0)) { perror("Can't start daemon"); exit(1); } } - mkdir(STATEDIR, S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + 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"); + } - mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + umask(0077); main_loop = g_main_loop_new(NULL, FALSE); +#ifdef NEED_THREADS + if (dbus_threads_init_default() == FALSE) { + fprintf(stderr, "Can't init usage of threads\n"); + exit(1); + } +#endif + + signal = setup_signalfd(); + dbus_error_init(&err); conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, CONNMAN_SERVICE, &err); @@ -129,55 +451,113 @@ int main(int argc, char *argv[]) exit(1); } - if (compat) { - if (g_dbus_request_name(conn, NM_SERVICE, NULL) == FALSE) { - fprintf(stderr, "Can't register compat service\n"); - compat = 0; - } - } - - __connman_log_init(detach, debug); - - __connman_agent_init(conn); - - __connman_manager_init(conn, compat); - - __connman_plugin_init(); - + g_dbus_set_disconnect_function(conn, disconnect_callback, NULL, NULL); + + __connman_log_init(argv[0], option_debug, option_detach); + + __connman_dbus_init(conn); + + config = load_config(CONFIGDIR "/main.conf"); + parse_config(config); + if (config != NULL) + g_key_file_free(config); + + __connman_storage_migrate(); + __connman_technology_init(); + __connman_notifier_init(); + __connman_service_init(); + __connman_provider_init(); + __connman_network_init(); + __connman_device_init(option_device, option_nodevice); + + __connman_agent_init(); + __connman_ippool_init(); + __connman_iptables_init(); + __connman_nat_init(); + __connman_tethering_init(); + __connman_counter_init(); + __connman_manager_init(); + __connman_config_init(); + __connman_stats_init(); + __connman_clock_init(); + + __connman_resolver_init(option_dnsproxy); + __connman_ipconfig_init(); __connman_rtnl_init(); - - __connman_network_init(conn); - - __connman_iface_init(conn, interface); - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = sig_term; - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); + __connman_task_init(); + __connman_proxy_init(); + __connman_detect_init(); + __connman_session_init(); + __connman_timeserver_init(); + __connman_connection_init(); + + __connman_plugin_init(option_plugin, option_noplugin); + + __connman_rtnl_start(); + __connman_dhcp_init(); + __connman_dhcpv6_init(); + __connman_wpad_init(); + __connman_wispr_init(); + __connman_rfkill_init(); + + g_free(option_device); + g_free(option_plugin); + g_free(option_nodevice); + g_free(option_noplugin); g_main_loop_run(main_loop); - __connman_iface_cleanup(); - - __connman_network_cleanup(); - - __connman_rtnl_cleanup(); + g_source_remove(signal); + __connman_rfkill_cleanup(); + __connman_wispr_cleanup(); + __connman_wpad_cleanup(); + __connman_dhcpv6_cleanup(); + __connman_dhcp_cleanup(); + __connman_provider_cleanup(); __connman_plugin_cleanup(); + __connman_connection_cleanup(); + __connman_timeserver_cleanup(); + __connman_session_cleanup(); + __connman_detect_cleanup(); + __connman_proxy_cleanup(); + __connman_task_cleanup(); + __connman_rtnl_cleanup(); + __connman_resolver_cleanup(); + __connman_clock_cleanup(); + __connman_stats_cleanup(); + __connman_config_cleanup(); __connman_manager_cleanup(); - + __connman_counter_cleanup(); __connman_agent_cleanup(); + __connman_tethering_cleanup(); + __connman_nat_cleanup(); + __connman_iptables_cleanup(); + __connman_ippool_cleanup(); + __connman_device_cleanup(); + __connman_network_cleanup(); + __connman_service_cleanup(); + __connman_ipconfig_cleanup(); + __connman_notifier_cleanup(); + __connman_technology_cleanup(); + + __connman_dbus_cleanup(); __connman_log_cleanup(); - g_dbus_cleanup_connection(conn); + dbus_connection_unref(conn); g_main_loop_unref(main_loop); - rmdir(STORAGEDIR); + if (connman_settings.pref_timeservers != NULL) + g_strfreev(connman_settings.pref_timeservers); + + g_free(connman_settings.auto_connect); + g_free(connman_settings.preferred_techs); + g_strfreev(connman_settings.fallback_nameservers); - rmdir(STATEDIR); + g_free(option_debug); return 0; }