int main (int argc, char **argv) { const char *arg0 = *argv++; const command_t *command = NULL; gboolean status = TRUE; nm_g_type_init (); if (*argv && !g_strcmp0 (argv[1], "--fake")) { nm_fake_platform_setup (); } else nm_linux_platform_setup (); if (*argv) for (command = commands; command->name; command++) if (g_str_has_prefix (command->name, *argv)) break; if (command && command->name) { argv++; if (g_strv_length (argv) == command->argc) status = command->handler (argv); else { error ("Wrong number of arguments to '%s' (expected %d).\n\nUsage: %s %s %s\n-- %s\n", command->name, command->argc, arg0, command->name, command->arghelp, command->help); return EXIT_FAILURE; } } else { error ("Usage: %s COMMAND\n\n", arg0); error ("COMMAND\n"); for (command = commands; command->name; command++) error (" %s %s\n -- %s\n", command->name, command->arghelp, command->help); error ("\n"); } return EXIT_SUCCESS; }
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; guint sd_id; nm_g_type_init (); 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); } nm_main_utils_ensure_root (); if (!global_opt.ifname || !global_opt.uuid) { fprintf (stderr, _("An interface name and UUID are required\n")); exit (1); } 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, _("%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); } if (global_opt.become_daemon && !global_opt.debug) { if (daemon (0, 0) < 0) { int saved_errno; saved_errno = errno; fprintf (stderr, _("Could not daemonize: %s [error %u]\n"), g_strerror (saved_errno), saved_errno); exit (1); } if (nm_main_utils_write_pidfile (pidfile)) wrote_pidfile = TRUE; } /* Set up unix signal handling - before creating threads, but after daemonizing! */ main_loop = g_main_loop_new (NULL, FALSE); setup_signals (); nm_logging_syslog_openlog (global_opt.logging_backend ? global_opt.logging_backend : (global_opt.debug ? "debug" : NULL)); nm_log_info (LOGD_CORE, "nm-iface-helper (version " NM_DIST_VERSION ") is starting..."); /* Set up platform interaction layer */ nm_linux_platform_setup (); tmp = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddr_len); if (tmp) { hwaddr = g_byte_array_sized_new (hwaddr_len); g_byte_array_append (hwaddr, tmp, hwaddr_len); } if (global_opt.iid_str) { GBytes *bytes; gsize ignored = 0; bytes = nm_utils_hexstr2bin (global_opt.iid_str); if (!bytes || g_bytes_get_size (bytes) != sizeof (*iid)) { 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 (global_opt.dhcp4_address) { nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip4_property_path (global_opt.ifname, "promote_secondaries"), "1"); dhcp4_client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), global_opt.ifname, ifindex, hwaddr, global_opt.uuid, global_opt.priority_v4, !!global_opt.dhcp4_hostname, global_opt.dhcp4_hostname, global_opt.dhcp4_fqdn, global_opt.dhcp4_clientid, 45, NULL, global_opt.dhcp4_address); g_assert (dhcp4_client); g_signal_connect (dhcp4_client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (dhcp4_state_changed), NULL); } if (global_opt.slaac) { nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, TRUE); rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL); g_assert (rdisc); if (iid) nm_rdisc_set_iid (rdisc, *iid); nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra"), "1"); nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_defrtr"), "0"); nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_pinfo"), "0"); nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_rtr_pref"), "0"); g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (ip6_address_changed), rdisc); g_signal_connect (rdisc, NM_RDISC_CONFIG_CHANGED, G_CALLBACK (rdisc_config_changed), NULL); g_signal_connect (rdisc, NM_RDISC_RA_TIMEOUT, G_CALLBACK (rdisc_ra_timeout), NULL); nm_rdisc_start (rdisc); } sd_id = nm_sd_event_attach_default (); g_main_loop_run (main_loop); g_clear_pointer (&hwaddr, g_byte_array_unref); if (pidfile && wrote_pidfile) unlink (pidfile); nm_log_info (LOGD_CORE, "exiting"); nm_clear_g_source (&sd_id); exit (0); }
int main (int argc, char *argv[]) { int t_secs = 30; gboolean exit_no_nm = FALSE; gboolean wait_startup = FALSE; Timeout timeout; GOptionContext *opt_ctx = NULL; gboolean success; NMClient *client; NMState state = NM_STATE_UNKNOWN; GMainLoop *loop; gint64 remaining_ms; GError *error = NULL; GOptionEntry options[] = { {"timeout", 't', 0, G_OPTION_ARG_INT, &t_secs, N_("Time to wait for a connection, in seconds (without the option, default value is 30)"), "<timeout>"}, {"exit", 'x', 0, G_OPTION_ARG_NONE, &exit_no_nm, N_("Exit immediately if NetworkManager is not running or connecting"), NULL}, {"quiet", 'q', 0, G_OPTION_ARG_NONE, &timeout.quiet, N_("Don't print anything"), NULL}, {"wait-for-startup", 's', 0, G_OPTION_ARG_NONE, &wait_startup, N_("Wait for NetworkManager startup instead of a connection"), NULL}, {NULL} }; timeout.start_timestamp_ms = g_get_monotonic_time () / (G_USEC_PER_SEC / 1000); timeout.quiet = FALSE; /* Set locale to be able to use environment variables */ setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); opt_ctx = g_option_context_new (NULL); g_option_context_set_translation_domain (opt_ctx, GETTEXT_PACKAGE); g_option_context_set_ignore_unknown_options (opt_ctx, FALSE); g_option_context_set_help_enabled (opt_ctx, TRUE); g_option_context_add_main_entries (opt_ctx, options, NULL); g_option_context_set_summary (opt_ctx, _("Waits for NetworkManager to finish activating startup network connections.")); success = g_option_context_parse (opt_ctx, &argc, &argv, NULL); g_option_context_free (opt_ctx); if (!success) { g_printerr ("%s: %s\n", argv[0], _("Invalid option. Please use --help to see a list of valid options.")); return 2; } if (t_secs < 0 || t_secs > 3600) { g_printerr ("%s: %s\n", argv[0], _("Invalid option. Please use --help to see a list of valid options.")); return 2; } remaining_ms = t_secs * 1000; nm_g_type_init (); client = nm_client_new (NULL, &error); if (!client) { g_printerr (_("Error: Could not create NMClient object: %s."), error->message); g_error_free (error); return 2; } loop = g_main_loop_new (NULL, FALSE); g_object_set_data (G_OBJECT (client), WAIT_STARTUP_TAG, GUINT_TO_POINTER (wait_startup)); state = nm_client_get_state (client); if (!nm_client_get_nm_running (client)) { if (exit_no_nm) { g_object_unref (client); return 1; } } else if (wait_startup) { if (!nm_client_get_startup (client)) { g_object_unref (client); return 0; } } else { if ( state == NM_STATE_CONNECTED_LOCAL || state == NM_STATE_CONNECTED_SITE || state == NM_STATE_CONNECTED_GLOBAL) { g_object_unref (client); return 0; } } if (exit_no_nm && (state != NM_STATE_CONNECTING)) { g_object_unref (client); return 1; } if (remaining_ms == 0) { g_object_unref (client); return 1; } g_signal_connect (client, "notify", G_CALLBACK (client_properties_changed), loop); timeout.end_timestamp_ms = timeout.start_timestamp_ms + remaining_ms; timeout.progress_step_duration = (timeout.end_timestamp_ms - timeout.start_timestamp_ms + PROGRESS_STEPS/2) / PROGRESS_STEPS; g_timeout_add (timeout.quiet ? remaining_ms : 0, handle_timeout, &timeout); g_main_loop_run (loop); g_main_loop_unref (loop); g_object_unref (client); return 0; }
/* * main * */ int main (int argc, char *argv[]) { gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE; gboolean success = FALSE; NMConfig *config; GError *error = NULL; gboolean wrote_pidfile = FALSE; char *bad_domains = NULL; NMConfigCmdLineOptions *config_cli; nm_g_type_init (); /* Known to cause a possible deadlock upon GDBus initialization: * https://bugzilla.gnome.org/show_bug.cgi?id=674885 */ g_type_ensure (G_TYPE_SOCKET); g_type_ensure (G_TYPE_DBUS_CONNECTION); g_type_ensure (NM_TYPE_BUS_MANAGER); _nm_utils_is_manager_process = TRUE; main_loop = g_main_loop_new (NULL, FALSE); config_cli = nm_config_cmd_line_options_new (); do_early_setup (&argc, &argv, config_cli); if (global_opt.g_fatal_warnings) _set_g_fatal_warnings (); if (global_opt.show_version) { fprintf (stdout, NM_DIST_VERSION "\n"); exit (0); } 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); } 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 (global_opt.run_from_build_dir) { char *path, *slash; int g; /* exe is <basedir>/src/.libs/lt-NetworkManager, so chop off * the last three components */ path = realpath ("/proc/self/exe", NULL); g_assert (path != NULL); for (g = 0; g < 3; ++g) { slash = strrchr (path, '/'); g_assert (slash != NULL); *slash = '\0'; } /* don't free these strings, we need them for the entire * process lifetime */ nm_dhcp_helper_path = g_strdup_printf ("%s/src/dhcp-manager/nm-dhcp-helper", path); g_free (path); } 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); } /* Read the config file and CLI overrides */ config = nm_config_setup (config_cli, NULL, &error); nm_config_cmd_line_options_free (config_cli); config_cli = NULL; if (config == NULL) { fprintf (stderr, _("Failed to read configuration: (%d) %s\n"), error ? error->code : -1, (error && error->message) ? error->message : _("unknown")); exit (1); } _init_nm_debug (nm_config_get_debug (config)); /* Initialize logging from config file *only* if not explicitly * specified by commandline. */ 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, &error)) { fprintf (stderr, _("Error in configuration file: %s.\n"), error->message); exit (1); } else if (bad_domains) { fprintf (stderr, _("Ignoring unrecognized log domain(s) '%s' from config files.\n"), bad_domains); g_clear_pointer (&bad_domains, g_free); } } if (global_opt.become_daemon && !nm_config_get_is_debug (config)) { if (daemon (0, 0) < 0) { int saved_errno; saved_errno = errno; fprintf (stderr, _("Could not daemonize: %s [error %u]\n"), g_strerror (saved_errno), saved_errno); exit (1); } wrote_pidfile = nm_main_utils_write_pidfile (global_opt.pidfile); } /* Set up unix signal handling - before creating threads, but after daemonizing! */ nm_main_utils_setup_signals (main_loop); nm_logging_syslog_openlog (nm_config_get_is_debug (config) ? "debug" : nm_config_data_get_value_cached (NM_CONFIG_GET_DATA_ORIG, NM_CONFIG_KEYFILE_GROUP_LOGGING, NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND, NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY)); nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); /* Parse the state file */ if (!parse_state_file (global_opt.state_file, &net_enabled, &wifi_enabled, &wwan_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); nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); nm_config_data_log (nm_config_get_data (config), "CONFIG: "); nm_log_dbg (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT "enabled" #else "disabled" #endif ); nm_auth_manager_setup (nm_config_get_auth_polkit (config)); nm_manager_setup (global_opt.state_file, net_enabled, wifi_enabled, wwan_enabled); if (!nm_bus_manager_get_connection (nm_bus_manager_get ())) { nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available"); } else { /* Start our DBus service */ if (!nm_bus_manager_start_service (nm_bus_manager_get ())) { nm_log_err (LOGD_CORE, "failed to start the dbus service."); goto done; } } /* Set up platform interaction layer */ nm_linux_platform_setup (); NM_UTILS_KEEP_ALIVE (config, NM_PLATFORM_GET, "NMConfig-depends-on-NMPlatform"); nm_dispatcher_init (); g_signal_connect (nm_manager_get (), NM_MANAGER_CONFIGURE_QUIT, G_CALLBACK (manager_configure_quit), config); if (!nm_manager_start (nm_manager_get (), &error)) { nm_log_err (LOGD_CORE, "failed to initialize: %s", error->message); goto done; } /* Make sure the loopback interface is up. If interface is down, we bring * it up and kernel will assign it link-local IPv4 and IPv6 addresses. If * it was already up, we assume is in clean state. * * TODO: it might be desirable to check the list of addresses and compare * it with a list of expected addresses (one of the protocol families * could be disabled). The 'lo' interface is sometimes used for assigning * global addresses so their availability doesn't depend on the state of * physical interfaces. */ nm_log_dbg (LOGD_CORE, "setting up local loopback"); nm_platform_link_set_up (NM_PLATFORM_GET, 1, NULL); success = TRUE; if (configure_and_quit == FALSE) g_main_loop_run (main_loop); nm_manager_stop (nm_manager_get ()); done: if (global_opt.pidfile && wrote_pidfile) unlink (global_opt.pidfile); nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error"); exit (success ? 0 : 1); }
int main (int argc, char *argv[]) { gs_unref_object GDBusConnection *connection = NULL; gs_free_error GError *error = NULL; gs_unref_variant GVariant *parameters = NULL; gs_unref_variant GVariant *result = NULL; gboolean success = FALSE; guint try_count = 0; gint64 time_end; nm_g_type_init (); /* FIXME: g_dbus_connection_new_for_address_sync() tries to connect to the socket in * non-blocking mode, which can easily fail with EAGAIN, causing the creation of the * socket to fail with "Could not connect: Resource temporarily unavailable". * * We should instead create the GIOStream ourself and block on connecting to * the socket. */ connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private-dhcp", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, NULL, &error); if (!connection) { g_dbus_error_strip_remote_error (error); _LOGE ("could not connect to NetworkManager D-Bus socket: %s", error->message); goto out; } parameters = build_signal_parameters (); time_end = g_get_monotonic_time () + (200 * 1000L); /* retry for at most 200 milliseconds */ do_notify: try_count++; result = g_dbus_connection_call_sync (connection, NULL, NM_DHCP_HELPER_SERVER_OBJECT_PATH, NM_DHCP_HELPER_SERVER_INTERFACE_NAME, NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, parameters, NULL, G_DBUS_CALL_FLAGS_NONE, 1000, NULL, &error); if (!result) { gs_free char *s_err = NULL; s_err = g_dbus_error_get_remote_error (error); if (NM_IN_STRSET (s_err, "org.freedesktop.DBus.Error.UnknownMethod")) { gint64 remaining_time = time_end - g_get_monotonic_time (); /* I am not sure that a race can actually happen, as we register the object * on the server side during GDBusServer:new-connection signal. * * However, there was also a race for subscribing to an event, so let's just * do some retry. */ if (remaining_time > 0) { _LOGi ("failure to call notify: %s (retry %u)", error->message, try_count); g_usleep (NM_MIN (NM_CLAMP ((gint64) (100L * (1L << try_count)), 5000, 25000), remaining_time)); g_clear_error (&error); goto do_notify; } } _LOGW ("failure to call notify: %s (try signal via Event)", error->message); g_clear_error (&error); /* for backward compatibilty, try to emit the signal. There is no stable * API between the dhcp-helper and NetworkManager. However, while upgrading * the NetworkManager package, a newer helper might want to notify an * older server, which still uses the "Event". */ if (!g_dbus_connection_emit_signal (connection, NULL, "/", NM_DHCP_CLIENT_DBUS_IFACE, "Event", parameters, &error)) { g_dbus_error_strip_remote_error (error); _LOGE ("could not send DHCP Event signal: %s", error->message); goto out; } /* We were able to send the asynchronous Event. Consider that a success. */ success = TRUE; } else success = TRUE; if (!g_dbus_connection_flush_sync (connection, NULL, &error)) { g_dbus_error_strip_remote_error (error); _LOGE ("could not flush D-Bus connection: %s", error->message); success = FALSE; goto out; } out: if (!success) kill_pid (); return success ? EXIT_SUCCESS : EXIT_FAILURE; }