diff options
author | Thomas Haller <thaller@redhat.com> | 2015-03-20 11:43:40 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-03-20 11:45:11 +0100 |
commit | 6ce7b7df96e5a53b4e43a687dfedd8ae8a383fa0 (patch) | |
tree | 6f96429869e93a9525525d2676059a2a64f93403 | |
parent | b8a2f42a38219b4e1f9c87a78f68d5551e1d6c08 (diff) | |
parent | 21562052ec6d5a044003d222bf5b12da4475f9d2 (diff) | |
download | NetworkManager-6ce7b7df96e5a53b4e43a687dfedd8ae8a383fa0.tar.gz |
core: merge branch 'th/main-order-bgo746254'
Some refactoring of the main() functions for NetworkManager and
nm-iface-helper. Most notably, start the D-Bus service earlier so
that NetworkManager starts faster.
https://bugzilla.gnome.org/show_bug.cgi?id=746254
-rw-r--r-- | src/main-utils.c | 93 | ||||
-rw-r--r-- | src/main-utils.h | 8 | ||||
-rw-r--r-- | src/main.c | 218 | ||||
-rw-r--r-- | src/nm-iface-helper.c | 254 |
4 files changed, 321 insertions, 252 deletions
diff --git a/src/main-utils.c b/src/main-utils.c index 164dc84a99..1d899587ec 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -34,7 +34,9 @@ #include <glib-unix.h> #include <gmodule.h> +#include "gsystem-local-alloc.h" #include "main-utils.h" +#include "NetworkManagerUtils.h" #include "nm-logging.h" static gboolean @@ -108,72 +110,82 @@ nm_main_utils_write_pidfile (const char *pidfile) return success; } +void +nm_main_utils_ensure_rundir () +{ + /* Setup runtime directory */ + if (g_mkdir_with_parents (NMRUNDIR, 0755) != 0) { + fprintf (stderr, _("Cannot create '%s': %s"), NMRUNDIR, strerror (errno)); + exit (1); + } +} + /** - * nm_main_utils_check_pidfile: + * nm_main_utils_ensure_not_running_pidfile: * @pidfile: the pid file - * @name: the process name * * Checks whether the pidfile already exists and contains PID of a running * process. * - * Returns: %TRUE if the specified pidfile already exists and contains the PID - * of a running process named @name, or %FALSE if not + * Exits with code 1 if a conflicting process is running. */ -gboolean -nm_main_utils_check_pidfile (const char *pidfile, const char *name) +void +nm_main_utils_ensure_not_running_pidfile (const char *pidfile) { - char *contents = NULL; + gs_free char *contents = NULL; + gs_free char *proc_cmdline = NULL; gsize len = 0; glong pid; - char *proc_cmdline = NULL; - gboolean nm_running = FALSE; const char *process_name; + const char *prgname = g_get_prgname (); - /* Setup runtime directory */ - if (g_mkdir_with_parents (NMRUNDIR, 0755) != 0) { - nm_log_err (LOGD_CORE, "Cannot create '%s': %s", NMRUNDIR, strerror (errno)); - exit (1); - } + g_return_if_fail (prgname); - if (!g_file_get_contents (pidfile, &contents, &len, NULL)) - return FALSE; + if (!pidfile || !*pidfile) + return; + if (!g_file_get_contents (pidfile, &contents, &len, NULL)) + return; if (len <= 0) - goto done; + return; errno = 0; pid = strtol (contents, NULL, 10); if (pid <= 0 || pid > 65536 || errno) - goto done; + return; - g_free (contents); + g_clear_pointer (&contents, g_free); proc_cmdline = g_strdup_printf ("/proc/%ld/cmdline", pid); if (!g_file_get_contents (proc_cmdline, &contents, &len, NULL)) - goto done; + return; process_name = strrchr (contents, '/'); if (process_name) process_name++; else process_name = contents; - if (strcmp (process_name, name) == 0) { + if (strcmp (process_name, prgname) == 0) { /* Check that the process exists */ if (kill (pid, 0) == 0) { - fprintf (stderr, _("%s is already running (pid %ld)\n"), name, pid); - nm_running = TRUE; + fprintf (stderr, _("%s is already running (pid %ld)\n"), prgname, pid); + exit (1); } } +} -done: - g_free (proc_cmdline); - g_free (contents); - return nm_running; +void +nm_main_utils_ensure_root () +{ + if (getuid () != 0) { + fprintf (stderr, _("You must be root to run %s!\n"), str_if_set (g_get_prgname (), "")); + exit (1); + } } gboolean nm_main_utils_early_setup (const char *progname, - char **argv[], int *argc, + char **argv[], GOptionEntry *options, void (*option_context_hook) (gpointer user_data, GOptionContext *opt_ctx), gpointer option_context_hook_data, @@ -183,6 +195,8 @@ nm_main_utils_early_setup (const char *progname, GError *error = NULL; gboolean success = FALSE; int i; + const char *opt_fmt_log_level = NULL, *opt_fmt_log_domains = NULL; + const char **opt_loc_log_level = NULL, **opt_loc_log_domains = NULL; /* Make GIO ignore the remote VFS service; otherwise it tries to use the * session bus to contact the remote service, and NM shouldn't ever be @@ -201,16 +215,16 @@ nm_main_utils_early_setup (const char *progname, setlocale (LC_ALL, ""); textdomain (GETTEXT_PACKAGE); - if (getuid () != 0) { - fprintf (stderr, _("You must be root to run %s!\n"), progname); - exit (1); - } - for (i = 0; options[i].long_name; i++) { - if (!strcmp (options[i].long_name, "log-level")) + if (!strcmp (options[i].long_name, "log-level")) { + opt_fmt_log_level = options[i].description; + opt_loc_log_level = &options[i].description; options[i].description = g_strdup_printf (options[i].description, nm_logging_all_levels_to_string ()); - else if (!strcmp (options[i].long_name, "log-domains")) + } else if (!strcmp (options[i].long_name, "log-domains")) { + opt_fmt_log_domains = options[i].description; + opt_loc_log_domains = &options[i].description; options[i].description = g_strdup_printf (options[i].description, nm_logging_all_domains_to_string ()); + } } /* Parse options */ @@ -231,6 +245,15 @@ nm_main_utils_early_setup (const char *progname, } g_option_context_free (opt_ctx); + if (opt_loc_log_level) { + g_free ((char *) *opt_loc_log_level); + *opt_loc_log_level = opt_fmt_log_level; + } + if (opt_loc_log_domains) { + g_free ((char *) *opt_loc_log_domains); + *opt_loc_log_domains = opt_fmt_log_domains; + } + return success; } diff --git a/src/main-utils.h b/src/main-utils.h index 9b29866be0..7adfa94940 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -23,15 +23,19 @@ #include <glib.h> +void nm_main_utils_ensure_root (void); + void nm_main_utils_setup_signals (GMainLoop *main_loop); +void nm_main_utils_ensure_rundir (void); + gboolean nm_main_utils_write_pidfile (const char *pidfile); -gboolean nm_main_utils_check_pidfile (const char *pidfile, const char *name); +void nm_main_utils_ensure_not_running_pidfile (const char *pidfile); gboolean nm_main_utils_early_setup (const char *progname, - char **argv[], int *argc, + char **argv[], GOptionEntry *options, void (*option_context_hook) (gpointer user_data, GOptionContext *opt_ctx), gpointer option_context_hook_data, diff --git a/src/main.c b/src/main.c index 3df3e11eb4..2648a08f41 100644 --- a/src/main.c +++ b/src/main.c @@ -67,6 +67,20 @@ static GMainLoop *main_loop = NULL; static gboolean configure_and_quit = FALSE; +static struct { + gboolean show_version; + gboolean become_daemon; + gboolean debug; + gboolean g_fatal_warnings; + gboolean run_from_build_dir; + char *opt_log_level; + char *opt_log_domains; + char *pidfile; + char *state_file; +} global_opt = { + .become_daemon = TRUE, +}; + static gboolean parse_state_file (const char *filename, gboolean *net_enabled, @@ -197,6 +211,37 @@ manager_configure_quit (NMManager *manager, gpointer user_data) configure_and_quit = TRUE; } +static void +do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli) +{ + GOptionEntry options[] = { + { "version", 'V', 0, G_OPTION_ARG_NONE, &global_opt.show_version, N_("Print NetworkManager version and exit"), NULL }, + { "no-daemon", 'n', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &global_opt.become_daemon, N_("Don't become a daemon"), NULL }, + { "debug", 'd', 0, G_OPTION_ARG_NONE, &global_opt.debug, N_("Don't become a daemon, and log to stderr"), NULL }, + { "log-level", 0, 0, G_OPTION_ARG_STRING, &global_opt.opt_log_level, N_("Log level: one of [%s]"), "INFO" }, + { "log-domains", 0, 0, G_OPTION_ARG_STRING, &global_opt.opt_log_domains, + N_("Log domains separated by ',': any combination of [%s]"), + "PLATFORM,RFKILL,WIFI" }, + { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &global_opt.g_fatal_warnings, N_("Make all warnings fatal"), NULL }, + { "pid-file", 'p', 0, G_OPTION_ARG_FILENAME, &global_opt.pidfile, N_("Specify the location of a PID file"), N_("filename") }, + { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &global_opt.state_file, N_("State file location"), N_("/path/to/state.file") }, + { "run-from-build-dir", 0, 0, G_OPTION_ARG_NONE, &global_opt.run_from_build_dir, "Run from build directory", NULL }, + {NULL} + }; + + if (!nm_main_utils_early_setup ("NetworkManager", + argc, + argv, + options, + (void (*)(gpointer, GOptionContext *)) nm_config_cmd_line_options_add_to_entries, + config_cli, + _("NetworkManager monitors all network connections and automatically\nchooses the best connection to use. It also allows the user to\nspecify wireless access points which wireless cards in the computer\nshould associate with."))) + exit (1); + + global_opt.pidfile = global_opt.pidfile ? global_opt.pidfile : g_strdup (NM_DEFAULT_PID_FILE); + global_opt.state_file = global_opt.state_file ? global_opt.state_file : g_strdup (NM_DEFAULT_SYSTEM_STATE_FILE); +} + /* * main * @@ -204,75 +249,55 @@ manager_configure_quit (NMManager *manager, gpointer user_data) int main (int argc, char *argv[]) { - char *opt_log_level = NULL; - char *opt_log_domains = NULL; - gboolean become_daemon = TRUE, run_from_build_dir = FALSE; - gboolean debug = FALSE; - gboolean g_fatal_warnings = FALSE; - gs_free char *pidfile = NULL; - gs_free char *state_file = NULL; gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE, wimax_enabled = TRUE; - gboolean success, show_version = FALSE; + gboolean success = FALSE; NMManager *manager = NULL; gs_unref_object NMSettings *settings = NULL; - gs_unref_object NMConfig *config = NULL; + NMConfig *config; GError *error = NULL; gboolean wrote_pidfile = FALSE; char *bad_domains = NULL; NMConfigCmdLineOptions *config_cli; - GOptionEntry options[] = { - { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Print NetworkManager version and exit"), NULL }, - { "no-daemon", 'n', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &become_daemon, N_("Don't become a daemon"), NULL }, - { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, N_("Don't become a daemon, and log to stderr"), NULL }, - { "log-level", 0, 0, G_OPTION_ARG_STRING, &opt_log_level, N_("Log level: one of [%s]"), "INFO" }, - { "log-domains", 0, 0, G_OPTION_ARG_STRING, &opt_log_domains, - N_("Log domains separated by ',': any combination of [%s]"), - "PLATFORM,RFKILL,WIFI" }, - { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, N_("Make all warnings fatal"), NULL }, - { "pid-file", 'p', 0, G_OPTION_ARG_FILENAME, &pidfile, N_("Specify the location of a PID file"), N_("filename") }, - { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &state_file, N_("State file location"), N_("/path/to/state.file") }, - { "run-from-build-dir", 0, 0, G_OPTION_ARG_NONE, &run_from_build_dir, "Run from build directory", NULL }, - {NULL} - }; +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif _nm_utils_is_manager_process = TRUE; main_loop = g_main_loop_new (NULL, FALSE); config_cli = nm_config_cmd_line_options_new (); - if (!nm_main_utils_early_setup ("NetworkManager", - &argv, - &argc, - options, - (void (*)(gpointer, GOptionContext *)) nm_config_cmd_line_options_add_to_entries, - config_cli, - _("NetworkManager monitors all network connections and automatically\nchooses the best connection to use. It also allows the user to\nspecify wireless access points which wireless cards in the computer\nshould associate with."))) - exit (1); + do_early_setup (&argc, &argv, config_cli); - if (show_version) { + if (global_opt.g_fatal_warnings) { + GLogLevelFlags fatal_mask; + + fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); + fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; + g_log_set_always_fatal (fatal_mask); + } + + if (global_opt.show_version) { fprintf (stdout, NM_DIST_VERSION "\n"); exit (0); } - if (!nm_logging_setup (opt_log_level, - opt_log_domains, - &bad_domains, - &error)) { - fprintf (stderr, - _("%s. Please use --help to see a list of valid options.\n"), - error->message); + nm_main_utils_ensure_root (); + + nm_main_utils_ensure_not_running_pidfile (global_opt.pidfile); + + /* Ensure state directory exists */ + if (g_mkdir_with_parents (NMSTATEDIR, 0755) != 0) { + fprintf (stderr, "Cannot create '%s': %s", NMSTATEDIR, strerror (errno)); exit (1); - } else if (bad_domains) { - fprintf (stderr, - _("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"), - bad_domains); - g_clear_pointer (&bad_domains, g_free); } + nm_main_utils_ensure_rundir (); + /* When running from the build directory, determine our build directory * base and set helper paths in the build tree */ - if (run_from_build_dir) { + if (global_opt.run_from_build_dir) { char *path, *slash; int g; @@ -294,19 +319,21 @@ main (int argc, char *argv[]) g_free (path); } - /* Ensure state directory exists */ - if (g_mkdir_with_parents (NMSTATEDIR, 0755) != 0) { - nm_log_err (LOGD_CORE, "Cannot create '%s': %s", NMSTATEDIR, strerror (errno)); + if (!nm_logging_setup (global_opt.opt_log_level, + global_opt.opt_log_domains, + &bad_domains, + &error)) { + fprintf (stderr, + _("%s. Please use --help to see a list of valid options.\n"), + error->message); exit (1); + } else if (bad_domains) { + fprintf (stderr, + _("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"), + bad_domains); + g_clear_pointer (&bad_domains, g_free); } - pidfile = pidfile ? pidfile : g_strdup (NM_DEFAULT_PID_FILE); - state_file = state_file ? state_file : g_strdup (NM_DEFAULT_SYSTEM_STATE_FILE); - - /* check pid file */ - if (nm_main_utils_check_pidfile (pidfile, "NetworkManager")) - exit (1); - /* Read the config file and CLI overrides */ config = nm_config_setup (config_cli, &error); nm_config_cmd_line_options_free (config_cli); @@ -318,10 +345,12 @@ main (int argc, char *argv[]) exit (1); } + _init_nm_debug (nm_config_get_debug (config)); + /* Initialize logging from config file *only* if not explicitly * specified by commandline. */ - if (opt_log_level == NULL && opt_log_domains == NULL) { + if (global_opt.opt_log_level == NULL && global_opt.opt_log_domains == NULL) { if (!nm_logging_setup (nm_config_get_log_level (config), nm_config_get_log_domains (config), &bad_domains, @@ -337,17 +366,7 @@ main (int argc, char *argv[]) } } - /* Parse the state file */ - if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &wimax_enabled, &error)) { - fprintf (stderr, _("State file %s parsing failed: (%d) %s\n"), - state_file, - error ? error->code : -1, - (error && error->message) ? error->message : _("unknown")); - /* Not a hard failure */ - } - g_clear_error (&error); - - if (become_daemon && !debug) { + if (global_opt.become_daemon && !global_opt.debug) { if (daemon (0, 0) < 0) { int saved_errno; @@ -357,27 +376,25 @@ main (int argc, char *argv[]) saved_errno); exit (1); } - wrote_pidfile = nm_main_utils_write_pidfile (pidfile); + wrote_pidfile = nm_main_utils_write_pidfile (global_opt.pidfile); } - _init_nm_debug (nm_config_get_debug (config)); - /* Set up unix signal handling - before creating threads, but after daemonizing! */ nm_main_utils_setup_signals (main_loop); - if (g_fatal_warnings) { - GLogLevelFlags fatal_mask; - - fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); - fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; - g_log_set_always_fatal (fatal_mask); - } + nm_logging_syslog_openlog (global_opt.debug); - nm_logging_syslog_openlog (debug); + nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif + /* Parse the state file */ + if (!parse_state_file (global_opt.state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &wimax_enabled, &error)) { + nm_log_err (LOGD_CORE, "State file %s parsing failed: (%d) %s", + global_opt.state_file, + error ? error->code : -1, + (error && error->message) ? error->message : _("unknown")); + /* Not a hard failure */ + } + g_clear_error (&error); dbus_threads_init_default (); @@ -386,9 +403,6 @@ main (int argc, char *argv[]) */ dbus_glib_global_set_disable_legacy_property_access (); - nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); - success = FALSE; - nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); nm_log_info (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT @@ -398,6 +412,21 @@ main (int argc, char *argv[]) #endif ); + if (!nm_dbus_manager_get_connection (nm_dbus_manager_get ())) { +#if HAVE_DBUS_GLIB_100 + nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available"); +#else + nm_log_err (LOGD_CORE, "Failed to connect to D-Bus, exiting..."); + goto done; +#endif + } else { + /* Start our DBus service */ + if (!nm_dbus_manager_start_service (nm_dbus_manager_get ())) { + nm_log_err (LOGD_CORE, "failed to start the dbus service."); + goto done; + } + } + /* Set up platform interaction layer */ nm_linux_platform_setup (); @@ -413,7 +442,7 @@ main (int argc, char *argv[]) } manager = nm_manager_new (settings, - state_file, + global_opt.state_file, net_enabled, wifi_enabled, wwan_enabled, @@ -425,21 +454,6 @@ main (int argc, char *argv[]) goto done; } - if (!nm_dbus_manager_get_connection (nm_dbus_manager_get ())) { -#if HAVE_DBUS_GLIB_100 - nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available"); -#else - nm_log_err (LOGD_CORE, "Failed to connect to D-Bus, exiting..."); - goto done; -#endif - } else { - /* Start our DBus service */ - if (!nm_dbus_manager_start_service (nm_dbus_manager_get ())) { - nm_log_err (LOGD_CORE, "failed to start the dbus service."); - goto done; - } - } - g_signal_connect (manager, NM_MANAGER_CONFIGURE_QUIT, G_CALLBACK (manager_configure_quit), config); nm_manager_start (manager); @@ -469,8 +483,8 @@ done: nm_logging_syslog_closelog (); - if (pidfile && wrote_pidfile) - unlink (pidfile); + if (global_opt.pidfile && wrote_pidfile) + unlink (global_opt.pidfile); nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error"); exit (success ? 0 : 1); diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 49eda87718..95fffa7a02 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -34,6 +34,10 @@ #include <sys/stat.h> #include <signal.h> +/* Cannot include <net/if.h> due to conflict with <linux/if.h>. + * Forward declare if_nametoindex. */ +extern unsigned int if_nametoindex (const char *__ifname); + #include "gsystem-local-alloc.h" #include "NetworkManagerUtils.h" #include "nm-linux-platform.h" @@ -51,13 +55,32 @@ #define NMIH_PID_FILE_FMT NMRUNDIR "/nm-iface-helper-%d.pid" static GMainLoop *main_loop = NULL; -static char *ifname = NULL; static int ifindex = -1; -static gboolean slaac_required = FALSE; -static gboolean dhcp4_required = FALSE; -static int tempaddr = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; -static guint32 priority_v4 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4; -static guint32 priority_v6 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6; + +static struct { + gboolean slaac; + gboolean show_version; + gboolean become_daemon; + gboolean debug; + gboolean g_fatal_warnings; + gboolean slaac_required; + gboolean dhcp4_required; + int tempaddr; + char *ifname; + char *uuid; + char *dhcp4_address; + char *dhcp4_clientid; + char *dhcp4_hostname; + char *iid_str; + char *opt_log_level; + char *opt_log_domains; + guint32 priority_v4; + guint32 priority_v6; +} global_opt = { + .tempaddr = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, + .priority_v4 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, + .priority_v6 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, +}; static void dhcp4_state_changed (NMDhcpClient *client, @@ -71,7 +94,7 @@ dhcp4_state_changed (NMDhcpClient *client, g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config)); - nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d", ifname, state); + nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d", global_opt.ifname, state); switch (state) { case NM_DHCP_STATE_BOUND: @@ -81,8 +104,8 @@ dhcp4_state_changed (NMDhcpClient *client, nm_ip4_config_subtract (existing, last_config); nm_ip4_config_merge (existing, ip4_config); - if (!nm_ip4_config_commit (existing, ifindex, priority_v4)) - nm_log_warn (LOGD_DHCP4, "(%s): failed to apply DHCPv4 config", ifname); + if (!nm_ip4_config_commit (existing, ifindex, global_opt.priority_v4)) + nm_log_warn (LOGD_DHCP4, "(%s): failed to apply DHCPv4 config", global_opt.ifname); if (last_config) { g_object_unref (last_config); @@ -93,11 +116,11 @@ dhcp4_state_changed (NMDhcpClient *client, case NM_DHCP_STATE_TIMEOUT: case NM_DHCP_STATE_DONE: case NM_DHCP_STATE_FAIL: - if (dhcp4_required) { - nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 timed out or failed, quitting...", ifname); + if (global_opt.dhcp4_required) { + nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 timed out or failed, quitting...", global_opt.ifname); g_main_loop_quit (main_loop); } else - nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 timed out or failed", ifname); + nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 timed out or failed", global_opt.ifname); break; default: break; @@ -128,8 +151,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da if (system_support) ifa_flags = IFA_F_NOPREFIXROUTE; - if (tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR - || tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) + if (global_opt.tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR + || global_opt.tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) { /* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */ ifa_flags |= IFA_F_MANAGETEMPADDR; @@ -193,7 +216,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da route.plen = discovered_route->plen; route.gateway = discovered_route->gateway; route.source = NM_IP_CONFIG_SOURCE_RDISC; - route.metric = priority_v6; + route.metric = global_opt.priority_v6; nm_ip6_config_add_route (ip6_config, &route); } @@ -210,23 +233,23 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da char val[16]; g_snprintf (val, sizeof (val), "%d", rdisc->hop_limit); - nm_platform_sysctl_set (nm_utils_ip6_property_path (ifname, "hop_limit"), val); + nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "hop_limit"), val); } if (changed & NM_RDISC_CONFIG_MTU) { char val[16]; g_snprintf (val, sizeof (val), "%d", rdisc->mtu); - nm_platform_sysctl_set (nm_utils_ip6_property_path (ifname, "mtu"), val); + nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "mtu"), val); } - existing = nm_ip6_config_capture (ifindex, FALSE, tempaddr); + existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr); if (last_config) nm_ip6_config_subtract (existing, last_config); nm_ip6_config_merge (existing, ip6_config); if (!nm_ip6_config_commit (existing, ifindex)) - nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", ifname); + nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname); if (last_config) { g_object_unref (last_config); @@ -238,11 +261,11 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da static void rdisc_ra_timeout (NMRDisc *rdisc, gpointer user_data) { - if (slaac_required) { - nm_log_warn (LOGD_IP6, "(%s): IPv6 timed out or failed, quitting...", ifname); + if (global_opt.slaac_required) { + nm_log_warn (LOGD_IP6, "(%s): IPv6 timed out or failed, quitting...", global_opt.ifname); g_main_loop_quit (main_loop); } else - nm_log_warn (LOGD_IP6, "(%s): IPv6 timed out or failed", ifname); + nm_log_warn (LOGD_IP6, "(%s): IPv6 timed out or failed", global_opt.ifname); } static gboolean @@ -260,77 +283,113 @@ setup_signals (void) g_unix_signal_add (SIGTERM, quit_handler, NULL); } -int -main (int argc, char *argv[]) +static void +do_early_setup (int *argc, char **argv[]) { - char *opt_log_level = NULL; - char *opt_log_domains = NULL; - gboolean debug = FALSE, g_fatal_warnings = FALSE, become_daemon = FALSE; - gboolean show_version = FALSE, slaac = FALSE; - char *bad_domains = NULL, *dhcp4_hostname = NULL, *uuid = NULL; - char *iid_str = NULL, *dhcp4_clientid = NULL, *dhcp4_address = NULL; - GError *error = NULL; - gboolean wrote_pidfile = FALSE; - gs_free char *pidfile = NULL; - gs_unref_object NMDhcpClient *dhcp4_client = NULL; - gs_unref_object NMRDisc *rdisc = NULL; - GByteArray *hwaddr = NULL; - size_t hwaddr_len = 0; - gconstpointer tmp; - gs_free NMUtilsIPv6IfaceId *iid = NULL; gint64 priority64_v4 = -1; gint64 priority64_v6 = -1; - GOptionEntry options[] = { /* Interface/IP config */ - { "ifname", 'i', 0, G_OPTION_ARG_STRING, &ifname, N_("The interface to manage"), N_("eth0") }, - { "uuid", 'u', 0, G_OPTION_ARG_STRING, &uuid, N_("Connection UUID"), N_("661e8cd0-b618-46b8-9dc9-31a52baaa16b") }, - { "slaac", 's', 0, G_OPTION_ARG_NONE, &slaac, N_("Whether to manage IPv6 SLAAC"), NULL }, - { "slaac-required", '6', 0, G_OPTION_ARG_NONE, &slaac_required, N_("Whether SLAAC must be successful"), NULL }, - { "slaac-tempaddr", 't', 0, G_OPTION_ARG_INT, &tempaddr, N_("Use an IPv6 temporary privacy address"), NULL }, - { "dhcp4", 'd', 0, G_OPTION_ARG_STRING, &dhcp4_address, N_("Current DHCPv4 address"), NULL }, - { "dhcp4-required", '4', 0, G_OPTION_ARG_NONE, &dhcp4_required, N_("Whether DHCPv4 must be successful"), NULL }, - { "dhcp4-clientid", 'c', 0, G_OPTION_ARG_STRING, &dhcp4_clientid, N_("Hex-encoded DHCPv4 client ID"), NULL }, - { "dhcp4-hostname", 'h', 0, G_OPTION_ARG_STRING, &dhcp4_hostname, N_("Hostname to send to DHCP server"), N_("barbar") }, + { "ifname", 'i', 0, G_OPTION_ARG_STRING, &global_opt.ifname, N_("The interface to manage"), N_("eth0") }, + { "uuid", 'u', 0, G_OPTION_ARG_STRING, &global_opt.uuid, N_("Connection UUID"), N_("661e8cd0-b618-46b8-9dc9-31a52baaa16b") }, + { "slaac", 's', 0, G_OPTION_ARG_NONE, &global_opt.slaac, N_("Whether to manage IPv6 SLAAC"), NULL }, + { "slaac-required", '6', 0, G_OPTION_ARG_NONE, &global_opt.slaac_required, N_("Whether SLAAC must be successful"), NULL }, + { "slaac-tempaddr", 't', 0, G_OPTION_ARG_INT, &global_opt.tempaddr, N_("Use an IPv6 temporary privacy address"), NULL }, + { "dhcp4", 'd', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_address, N_("Current DHCPv4 address"), NULL }, + { "dhcp4-required", '4', 0, G_OPTION_ARG_NONE, &global_opt.dhcp4_required, N_("Whether DHCPv4 must be successful"), NULL }, + { "dhcp4-clientid", 'c', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_clientid, N_("Hex-encoded DHCPv4 client ID"), NULL }, + { "dhcp4-hostname", 'h', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_hostname, N_("Hostname to send to DHCP server"), N_("barbar") }, { "priority4", '\0', 0, G_OPTION_ARG_INT64, &priority64_v4, N_("Route priority for IPv4"), N_("0") }, { "priority6", '\0', 0, G_OPTION_ARG_INT64, &priority64_v6, N_("Route priority for IPv6"), N_("1024") }, - { "iid", 'e', 0, G_OPTION_ARG_STRING, &iid_str, N_("Hex-encoded Interface Identifier"), N_("") }, + { "iid", 'e', 0, G_OPTION_ARG_STRING, &global_opt.iid_str, N_("Hex-encoded Interface Identifier"), N_("") }, /* Logging/debugging */ - { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Print NetworkManager version and exit"), NULL }, - { "no-daemon", 'n', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &become_daemon, N_("Don't become a daemon"), NULL }, - { "debug", 'b', 0, G_OPTION_ARG_NONE, &debug, N_("Don't become a daemon, and log to stderr"), NULL }, - { "log-level", 0, 0, G_OPTION_ARG_STRING, &opt_log_level, N_("Log level: one of [%s]"), "INFO" }, - { "log-domains", 0, 0, G_OPTION_ARG_STRING, &opt_log_domains, + { "version", 'V', 0, G_OPTION_ARG_NONE, &global_opt.show_version, N_("Print NetworkManager version and exit"), NULL }, + { "no-daemon", 'n', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &global_opt.become_daemon, N_("Don't become a daemon"), NULL }, + { "debug", 'b', 0, G_OPTION_ARG_NONE, &global_opt.debug, N_("Don't become a daemon, and log to stderr"), NULL }, + { "log-level", 0, 0, G_OPTION_ARG_STRING, &global_opt.opt_log_level, N_("Log level: one of [%s]"), "INFO" }, + { "log-domains", 0, 0, G_OPTION_ARG_STRING, &global_opt.opt_log_domains, N_("Log domains separated by ',': any combination of [%s]"), "PLATFORM,RFKILL,WIFI" }, - { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, N_("Make all warnings fatal"), NULL }, + { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &global_opt.g_fatal_warnings, N_("Make all warnings fatal"), NULL }, {NULL} }; +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + setpgid (getpid (), getpid ()); if (!nm_main_utils_early_setup ("nm-iface-helper", - &argv, - &argc, + argc, + argv, options, NULL, NULL, _("nm-iface-helper is a small, standalone process that manages a single network interface."))) exit (1); - if (show_version) { + if (priority64_v4 >= 0 && priority64_v4 <= G_MAXUINT32) + global_opt.priority_v4 = (guint32) priority64_v4; + if (priority64_v6 >= 0 && priority64_v6 <= G_MAXUINT32) + global_opt.priority_v6 = (guint32) priority64_v6; +} + +int +main (int argc, char *argv[]) +{ + char *bad_domains = NULL; + GError *error = NULL; + gboolean wrote_pidfile = FALSE; + gs_free char *pidfile = NULL; + gs_unref_object NMDhcpClient *dhcp4_client = NULL; + gs_unref_object NMRDisc *rdisc = NULL; + GByteArray *hwaddr = NULL; + size_t hwaddr_len = 0; + gconstpointer tmp; + gs_free NMUtilsIPv6IfaceId *iid = NULL; + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + setpgid (getpid (), getpid ()); + + do_early_setup (&argc, &argv); + + if (global_opt.g_fatal_warnings) { + GLogLevelFlags fatal_mask; + + fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); + fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; + g_log_set_always_fatal (fatal_mask); + } + + if (global_opt.show_version) { fprintf (stdout, NM_DIST_VERSION "\n"); exit (0); } - if (!ifname || !uuid) { + nm_main_utils_ensure_root (); + + if (!global_opt.ifname || !global_opt.uuid) { fprintf (stderr, _("An interface name and UUID are required\n")); exit (1); } - if (!nm_logging_setup (opt_log_level, - opt_log_domains, + ifindex = if_nametoindex (global_opt.ifname); + if (ifindex <= 0) { + fprintf (stderr, _("Failed to find interface index for %s (%s)\n"), global_opt.ifname, strerror (errno)); + exit (1); + } + pidfile = g_strdup_printf (NMIH_PID_FILE_FMT, ifindex); + nm_main_utils_ensure_not_running_pidfile (pidfile); + + nm_main_utils_ensure_rundir (); + + if (!nm_logging_setup (global_opt.opt_log_level, + global_opt.opt_log_domains, &bad_domains, &error)) { fprintf (stderr, @@ -344,14 +403,7 @@ main (int argc, char *argv[]) g_clear_pointer (&bad_domains, g_free); } - pidfile = g_strdup_printf (NMIH_PID_FILE_FMT, ifindex); - g_assert (pidfile); - - /* check pid file */ - if (nm_main_utils_check_pidfile (pidfile, "nm-iface-helper")) - exit (1); - - if (become_daemon && !debug) { + if (global_opt.become_daemon && !global_opt.debug) { if (daemon (0, 0) < 0) { int saved_errno; @@ -369,70 +421,46 @@ main (int argc, char *argv[]) main_loop = g_main_loop_new (NULL, FALSE); setup_signals (); - if (g_fatal_warnings) { - GLogLevelFlags fatal_mask; - - fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); - fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; - g_log_set_always_fatal (fatal_mask); - } - - nm_logging_syslog_openlog (debug); - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif + nm_logging_syslog_openlog (global_opt.debug); nm_log_info (LOGD_CORE, "nm-iface-helper (version " NM_DIST_VERSION ") is starting..."); /* Set up platform interaction layer */ nm_linux_platform_setup (); - ifindex = nm_platform_link_get_ifindex (ifname); - if (ifindex <= 0) { - fprintf (stderr, _("Failed to find interface index for %s\n"), ifname); - exit (1); - } - tmp = nm_platform_link_get_address (ifindex, &hwaddr_len); if (tmp) { hwaddr = g_byte_array_sized_new (hwaddr_len); g_byte_array_append (hwaddr, tmp, hwaddr_len); } - if (iid_str) { + if (global_opt.iid_str) { GBytes *bytes; gsize ignored = 0; - bytes = nm_utils_hexstr2bin (iid_str); + bytes = nm_utils_hexstr2bin (global_opt.iid_str); if (!bytes || g_bytes_get_size (bytes) != sizeof (*iid)) { - fprintf (stderr, _("(%s): Invalid IID %s\n"), ifname, iid_str); + fprintf (stderr, _("(%s): Invalid IID %s\n"), global_opt.ifname, global_opt.iid_str); exit (1); } iid = g_bytes_unref_to_data (bytes, &ignored); } - if (priority64_v4 >= 0 && priority64_v4 <= G_MAXUINT32) - priority_v4 = (guint32) priority64_v4; - - if (priority64_v6 >= 0 && priority64_v6 <= G_MAXUINT32) - priority_v6 = (guint32) priority64_v6; - - if (dhcp4_address) { - nm_platform_sysctl_set (nm_utils_ip4_property_path (ifname, "promote_secondaries"), "1"); + if (global_opt.dhcp4_address) { + nm_platform_sysctl_set (nm_utils_ip4_property_path (global_opt.ifname, "promote_secondaries"), "1"); dhcp4_client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), - ifname, + global_opt.ifname, ifindex, hwaddr, - uuid, - priority_v4, - !!dhcp4_hostname, - dhcp4_hostname, - dhcp4_clientid, + global_opt.uuid, + global_opt.priority_v4, + !!global_opt.dhcp4_hostname, + global_opt.dhcp4_hostname, + global_opt.dhcp4_clientid, 45, NULL, - dhcp4_address); + global_opt.dhcp4_address); g_assert (dhcp4_client); g_signal_connect (dhcp4_client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, @@ -440,19 +468,19 @@ main (int argc, char *argv[]) NULL); } - if (slaac) { + if (global_opt.slaac) { nm_platform_link_set_user_ipv6ll_enabled (ifindex, TRUE); - rdisc = nm_lndp_rdisc_new (ifindex, ifname); + rdisc = nm_lndp_rdisc_new (ifindex, global_opt.ifname); g_assert (rdisc); if (iid) nm_rdisc_set_iid (rdisc, *iid); - nm_platform_sysctl_set (nm_utils_ip6_property_path (ifname, "accept_ra"), "1"); - nm_platform_sysctl_set (nm_utils_ip6_property_path (ifname, "accept_ra_defrtr"), "0"); - nm_platform_sysctl_set (nm_utils_ip6_property_path (ifname, "accept_ra_pinfo"), "0"); - nm_platform_sysctl_set (nm_utils_ip6_property_path (ifname, "accept_ra_rtr_pref"), "0"); + nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "accept_ra"), "1"); + nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_defrtr"), "0"); + nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_pinfo"), "0"); + nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_rtr_pref"), "0"); g_signal_connect (rdisc, NM_RDISC_CONFIG_CHANGED, |