Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
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);
}