static NMActStageReturn
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
{
	NMActStageReturn ret;
	NMActRequest *req;
	NMConnection *connection;
	NMSettingInfiniband *s_infiniband;
	const char *transport_mode;
	char *mode_path;
	gboolean ok;

	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);

	ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason);
	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
		return ret;

	req = nm_device_get_act_request (dev);
	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);

	connection = nm_act_request_get_connection (req);
	g_assert (connection);
	s_infiniband = nm_connection_get_setting_infiniband (connection);
	g_assert (s_infiniband);

	transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband);

	mode_path = g_strdup_printf ("/sys/class/net/%s/mode",
	                             ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (dev)));
	if (!g_file_test (mode_path, G_FILE_TEST_EXISTS)) {
		g_free (mode_path);

		if (!strcmp (transport_mode, "datagram"))
			return NM_ACT_STAGE_RETURN_SUCCESS;
		else {
			*reason = NM_DEVICE_STATE_REASON_INFINIBAND_MODE;
			return NM_ACT_STAGE_RETURN_FAILURE;
		}
	}

	ok = nm_platform_sysctl_set (mode_path, transport_mode);
	g_free (mode_path);

	if (!ok) {
		*reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
		return NM_ACT_STAGE_RETURN_FAILURE;
	}

	return NM_ACT_STAGE_RETURN_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);
}
static void
rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_data)
{
    static NMIP6Config *rdisc_config = NULL;
    NMIP6Config *existing;
    static int system_support = -1;
    guint32 ifa_flags = 0x00;
    int i;

    if (system_support == -1) {
        /*
         * Check, whether kernel is recent enough, to help user space handling RA.
         * If it's not supported, we have no ipv6-privacy and must add autoconf
         * addresses as /128.
         * The reason for the /128 is to prevent the kernel
         * from adding a prefix route for this address.
         **/
        system_support = nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET);
    }

    if (system_support)
        ifa_flags = IFA_F_NOPREFIXROUTE;
    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;
    }

    existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr);
    if (rdisc_config)
        nm_ip6_config_subtract (existing, rdisc_config);
    else
        rdisc_config = nm_ip6_config_new (ifindex);

    if (changed & NM_RDISC_CONFIG_GATEWAYS) {
        /* Use the first gateway as ordered in router discovery cache. */
        if (rdisc->gateways->len) {
            NMRDiscGateway *gateway = &g_array_index (rdisc->gateways, NMRDiscGateway, 0);

            nm_ip6_config_set_gateway (rdisc_config, &gateway->address);
        } else
            nm_ip6_config_set_gateway (rdisc_config, NULL);
    }

    if (changed & NM_RDISC_CONFIG_ADDRESSES) {
        /* Rebuild address list from router discovery cache. */
        nm_ip6_config_reset_addresses (rdisc_config);

        /* rdisc->addresses contains at most max_addresses entries.
         * This is different from what the kernel does, which
         * also counts static and temporary addresses when checking
         * max_addresses.
         **/
        for (i = 0; i < rdisc->addresses->len; i++) {
            NMRDiscAddress *discovered_address = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
            NMPlatformIP6Address address;

            memset (&address, 0, sizeof (address));
            address.address = discovered_address->address;
            address.plen = system_support ? 64 : 128;
            address.timestamp = discovered_address->timestamp;
            address.lifetime = discovered_address->lifetime;
            address.preferred = discovered_address->preferred;
            if (address.preferred > address.lifetime)
                address.preferred = address.lifetime;
            address.source = NM_IP_CONFIG_SOURCE_RDISC;
            address.n_ifa_flags = ifa_flags;

            nm_ip6_config_add_address (rdisc_config, &address);
        }
    }

    if (changed & NM_RDISC_CONFIG_ROUTES) {
        /* Rebuild route list from router discovery cache. */
        nm_ip6_config_reset_routes (rdisc_config);

        for (i = 0; i < rdisc->routes->len; i++) {
            NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i);
            NMPlatformIP6Route route;

            /* Only accept non-default routes.  The router has no idea what the
             * local configuration or user preferences are, so sending routes
             * with a prefix length of 0 is quite rude and thus ignored.
             */
            if (   discovered_route->plen > 0
                    && discovered_route->plen <= 128) {
                memset (&route, 0, sizeof (route));
                route.network = discovered_route->network;
                route.plen = discovered_route->plen;
                route.gateway = discovered_route->gateway;
                route.source = NM_IP_CONFIG_SOURCE_RDISC;
                route.metric = global_opt.priority_v6;

                nm_ip6_config_add_route (rdisc_config, &route);
            }
        }
    }

    if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) {
        /* Unsupported until systemd DHCPv6 is ready */
    }

    if (changed & NM_RDISC_CONFIG_HOP_LIMIT)
        nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, global_opt.ifname, rdisc->hop_limit);

    if (changed & NM_RDISC_CONFIG_MTU) {
        char val[16];

        g_snprintf (val, sizeof (val), "%d", rdisc->mtu);
        nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "mtu"), val);
    }

    nm_ip6_config_merge (existing, rdisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
    if (!nm_ip6_config_commit (existing, ifindex, TRUE))
        nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname);
}
Esempio n. 4
0
static gboolean
do_sysctl_set (char **argv)
{
	return nm_platform_sysctl_set (NM_PLATFORM_GET, argv[0], argv[1]);
}
Esempio n. 5
0
static gboolean
do_sysctl_set (char **argv)
{
	return nm_platform_sysctl_set (argv[0], argv[1]);
}