Esempio n. 1
0
static dbus_bool_t
__ni_objectmodel_bridge_port_from_dict(ni_bridge_port_t *port, const ni_dbus_variant_t *dict,
				DBusError *error,
				int config_only)
{
	const char *string;
	uint32_t value;

	if (dict->array.len == 0)
		return TRUE;

	/* FIXME: should expect object path here and map that to an ifindex */
	if (ni_dbus_dict_get_string(dict, "device", &string) && !ni_string_empty(string))
		ni_string_dup(&port->ifname, string);
	else
		return FALSE;

	if (ni_dbus_dict_get_uint32(dict, "priority", &value))
		port->priority = value;
	if (ni_dbus_dict_get_uint32(dict, "path-cost", &value))
		port->path_cost = value;

	/* FIXME: Really? I don't think so... */
	if (ni_dbus_dict_get_uint32(dict, "state", &value))
		port->status.state = value;
	if (ni_dbus_dict_get_uint32(dict, "port-id", &value))
		port->status.port_id = value;
	if (ni_dbus_dict_get_uint32(dict, "port-no", &value))
		port->status.port_no = value;

	return TRUE;
}
Esempio n. 2
0
static dbus_bool_t
ni_objectmodel_ethtool_set_wake_on_lan(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	ni_ethtool_wake_on_lan_t *wol;
	ni_ethtool_t *ethtool;

	if (!ni_dbus_variant_is_dict(argument))
		return FALSE;

	if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error)))
		return FALSE;

	ni_ethtool_wake_on_lan_free(ethtool->wake_on_lan);
	if (!(ethtool->wake_on_lan = ni_ethtool_wake_on_lan_new()))
		return FALSE;
	wol = ethtool->wake_on_lan;

	ni_dbus_dict_get_uint32(argument, "support", &wol->support);
	ni_dbus_dict_get_uint32(argument, "options", &wol->options);
	__ni_objectmodel_dict_get_hwaddr(argument, "sopass", &wol->sopass);

	return TRUE;
}
Esempio n. 3
0
/* extern */ dbus_bool_t
__ni_objectmodel_set_team_port_config(ni_team_port_config_t *pconf, const ni_dbus_variant_t *dict, DBusError *error)
{
	dbus_bool_t b;
	uint32_t u32;

	(void)error;

	if (!pconf || !dict)
		return FALSE;

	if (ni_dbus_dict_get_uint32(dict, "queue_id", &u32))
		pconf->queue_id = u32;

	if (ni_dbus_dict_get_uint32(dict, "prio", &u32))
		pconf->ab.prio = u32;
	if (ni_dbus_dict_get_bool(dict, "sticky", &b))
		pconf->ab.sticky = b;

	if (ni_dbus_dict_get_uint32(dict, "lacp_prio", &u32))
		pconf->lacp.prio = u32;

	if (ni_dbus_dict_get_uint32(dict, "lacp_key", &u32))
		pconf->lacp.key = u32;

	return TRUE;
}
Esempio n. 4
0
/*
 * Wickedd is sending us a signal indicating internal device state change.
 * We want to wait for this signal and when it is >= device-up return TRUE.
 * After timeout we fail...
 */
void
ni_state_change_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *msg, void *user_data)
{
	const char *signal_name = dbus_message_get_member(msg);
	const char *object_path = dbus_message_get_path(msg);
	ni_dbus_variant_t argv = NI_DBUS_VARIANT_INIT;
	ni_ifworker_array_t *ifworkers = user_data;
	ni_fsm_state_t cur_state, target_state;
	const char *ifname;
	unsigned int i;

	if (ni_string_empty(object_path))
		return;

	/* Deserialize dbus message */
	if (ni_dbus_message_get_args_variants(msg, &argv, 1) < 0 ||
	    !ni_dbus_variant_is_dict(&argv)) {
		ni_error("Unable to retrieve dict from signal %s,  object_path=%s",
			signal_name, object_path);
		return;
	}

	if (!ni_dbus_dict_get_uint32(&argv, "current-state", &cur_state) ||
	    !ni_dbus_dict_get_uint32(&argv, "target-state", &target_state) ||
	    !ni_dbus_dict_get_string(&argv, "ifname", &ifname)) {
		ni_error("Unable to retrieve dict's values from signal %s,  object_path=%s",
			signal_name, object_path);
		return;
	}

	ni_debug_application("received signal %s; object_path=%s; target_state=%s, state_name=%s",
		signal_name, object_path,  ni_ifworker_state_name(target_state),
		ni_ifworker_state_name(cur_state));

	for (i = 0; i < ifworkers->count; ++i) {
		ni_ifworker_t *w = ifworkers->data[i];

		if (cur_state != NI_FSM_STATE_NONE && cur_state != target_state)
			continue;

		if (!ni_string_eq(w->name, ifname))
			continue;

		ni_warn("%s: Device %s", ifname, cur_state == target_state ? "succeeded" : "failed");
		ni_ifworker_array_remove_with_children(ifworkers, w);

	}

	ni_dbus_variant_destroy(&argv);
}
Esempio n. 5
0
static dbus_bool_t
__ni_objectmodel_bonding_set_arpmon(ni_dbus_object_t *object,
				const ni_dbus_property_t *property,
				const ni_dbus_variant_t *result,
				DBusError *error)
{
	ni_bonding_t *bond;
	ni_dbus_variant_t *var;

	if (!(bond = __ni_objectmodel_bonding_write_handle(object, error)))
		return FALSE;

	bond->monitoring |= NI_BOND_MONITOR_ARP;

	ni_dbus_dict_get_uint32(result, "interval", &bond->arpmon.interval);
	ni_dbus_dict_get_uint32(result, "validate", &bond->arpmon.validate);
	if ((var = ni_dbus_dict_get(result, "targets")) != NULL) {
		ni_bool_t valid = TRUE;
		unsigned int i;

		if (!ni_dbus_variant_is_string_array(var)) {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"%s.%s property - expected string array for attribute targets",
				object->path, property->name);
			return FALSE;
		}

		for (i = 0; i < var->array.len; ++i) {
			const char *s = var->string_array_value[i];

			if (!ni_bonding_is_valid_arp_ip_target(s)) {
				valid = FALSE;
				break;
			}
			ni_string_array_append(&bond->arpmon.targets, s);
		}

		if (!valid) {
			ni_string_array_destroy(&bond->arpmon.targets);
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"%s.%s property - invalid arp ip target adddress",
				object->path, property->name);
			return FALSE;
		}
	}

	return TRUE;
}
Esempio n. 6
0
static dbus_bool_t
__ni_objectmodel_team_link_watch_from_dict(ni_team_link_watch_t *lw, const ni_dbus_variant_t *dict,
				DBusError *error, const ni_dbus_property_t *property)
{
	const char *string;
	dbus_bool_t bvalue;
	uint32_t value;

	if (!lw || !dict || !error)
		return FALSE;

	switch(lw->type) {
	case NI_TEAM_LINK_WATCH_ETHTOOL:
		if (ni_dbus_dict_get_uint32(dict, "delay_up", &value))
			lw->ethtool.delay_up = value;
		if (ni_dbus_dict_get_uint32(dict, "delay_down", &value))
			lw->ethtool.delay_down = value;
		break;
	case NI_TEAM_LINK_WATCH_ARP_PING:
		if (ni_dbus_dict_get_string(dict, "source_host", &string))
			ni_string_dup(&lw->arp.source_host, string);
		if (ni_dbus_dict_get_string(dict, "target_host", &string))
			ni_string_dup(&lw->arp.target_host, string);
		if (ni_dbus_dict_get_uint32(dict, "interval", &value))
			lw->arp.interval = value;
		if (ni_dbus_dict_get_uint32(dict, "init_wait", &value))
			lw->arp.init_wait = value;
		if (ni_dbus_dict_get_bool(dict, "validate_active", &bvalue))
			lw->arp.validate_active = bvalue;
		if (ni_dbus_dict_get_bool(dict, "validate_inactive", &bvalue))
			lw->arp.validate_inactive = bvalue;
		if (ni_dbus_dict_get_bool(dict, "send_always", &bvalue))
			lw->arp.send_always = bvalue;
		if (ni_dbus_dict_get_uint32(dict, "missed_max", &value))
			lw->arp.missed_max = value;
		break;
	case NI_TEAM_LINK_WATCH_NSNA_PING:
		if (ni_dbus_dict_get_string(dict, "target_host", &string))
			ni_string_dup(&lw->nsna.target_host, string);
		if (ni_dbus_dict_get_uint32(dict, "interval", &value))
			lw->nsna.interval = value;
		if (ni_dbus_dict_get_uint32(dict, "init_wait", &value))
			lw->nsna.init_wait = value;
		if (ni_dbus_dict_get_uint32(dict, "missed_max", &value))
			lw->nsna.missed_max = value;
		break;
	case NI_TEAM_LINK_WATCH_TIPC:
		if (ni_dbus_dict_get_string(dict, "bearer", &string))
			ni_string_dup(&lw->tipc.bearer, string);
		break;
	default:
		return  FALSE;
	}

	return TRUE;
}
Esempio n. 7
0
static dbus_bool_t
__ni_objectmodel_bonding_set_miimon(ni_dbus_object_t *object,
				const ni_dbus_property_t *property,
				const ni_dbus_variant_t *result,
				DBusError *error)
{
	ni_bonding_t *bond;

	if (!(bond = __ni_objectmodel_bonding_write_handle(object, error)))
		return FALSE;

	bond->monitoring |= NI_BOND_MONITOR_MII;

	ni_dbus_dict_get_uint32(result, "frequency", &bond->miimon.frequency);
	ni_dbus_dict_get_uint32(result, "updelay", &bond->miimon.updelay);
	ni_dbus_dict_get_uint32(result, "downdelay", &bond->miimon.downdelay);
	ni_dbus_dict_get_uint32(result, "carrier-detect", &bond->miimon.carrier_detect);

	return TRUE;
}
Esempio n. 8
0
static dbus_bool_t
__ni_objectmodel_addrconf_generic_set_lease(ni_dbus_object_t *object,
				ni_addrconf_mode_t mode, unsigned int addrfamily,
				const ni_dbus_variant_t *dict,
				DBusError *error)
{
	ni_netdev_t *dev;
	uint32_t state;

	if (!(dev = ni_objectmodel_unwrap_netif(object, error)))
		return FALSE;

	if (ni_dbus_dict_get_uint32(dict, "state", &state)) {
		ni_addrconf_lease_t *lease;

		lease = ni_addrconf_lease_new(mode, addrfamily);
		lease->state = state;
		ni_dbus_dict_get_uuid(dict,   "uuid", &lease->uuid);
		ni_dbus_dict_get_uint32(dict, "flags", &lease->flags);
		ni_netdev_set_lease(dev, lease);
	}
	return TRUE;
}
Esempio n. 9
0
static dbus_bool_t
ni_objectmodel_ethtool_set_channels(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	ni_ethtool_t *ethtool;
	ni_ethtool_channels_t *channels;

	if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error)))
		return FALSE;

	ni_ethtool_channels_free(ethtool->channels);
	if (!(ethtool->channels = ni_ethtool_channels_new()))
		return FALSE;
	channels = ethtool->channels;

	ni_dbus_dict_get_uint32(argument, "tx", &channels->tx);
	ni_dbus_dict_get_uint32(argument, "rx", &channels->rx);
	ni_dbus_dict_get_uint32(argument, "other", &channels->other);
	ni_dbus_dict_get_uint32(argument, "combined", &channels->combined);

	return TRUE;
}
Esempio n. 10
0
static dbus_bool_t
ni_objectmodel_ethtool_set_ring(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	ni_ethtool_t *ethtool;
	ni_ethtool_ring_t *ring;

	if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error)))
		return FALSE;

	ni_ethtool_ring_free(ethtool->ring);
	if (!(ethtool->ring = ni_ethtool_ring_new()))
		return FALSE;
	ring = ethtool->ring;

	ni_dbus_dict_get_uint32(argument, "tx", &ring->tx);
	ni_dbus_dict_get_uint32(argument, "rx", &ring->rx);
	ni_dbus_dict_get_uint32(argument, "rx-mini", &ring->rx_mini);
	ni_dbus_dict_get_uint32(argument, "rx-jumbo", &ring->rx_jumbo);

	return TRUE;
}
Esempio n. 11
0
static dbus_bool_t
ni_objectmodel_ethtool_set_link_settings(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	ni_ethtool_link_settings_t *link;
	const ni_dbus_variant_t *adv;
	uint32_t uv32;
	int32_t sv32;

	if (!(link = ni_objectmodel_ethtool_link_settings_write_handle(object, error)))
		return FALSE;

	if (ni_dbus_dict_get_int32(argument, "autoneg", &sv32) && ni_tristate_is_set(sv32))
		ni_tristate_set(&link->autoneg, sv32);
	if (ni_dbus_dict_get_uint32(argument, "speed",  &uv32) && uv32 <= INT_MAX)
		link->speed  = uv32;
	if (ni_dbus_dict_get_uint32(argument, "duplex", &uv32) && uv32 < NI_ETHTOOL_DUPLEX_UNKNOWN)
		link->duplex = uv32;
	if (ni_dbus_dict_get_uint32(argument, "port",   &uv32) && uv32 <= NI_ETHTOOL_PORT_OTHER)
		link->port   = uv32;

	if (ni_dbus_dict_get_uint32(argument, "mdix", &uv32))
		link->tp_mdix  = uv32;
	if (ni_dbus_dict_get_uint32(argument, "mdio", &uv32))
		link->mdio_support = uv32;
	if (ni_dbus_dict_get_uint32(argument, "phy-address", &uv32))
		link->phy_address  = uv32;
	if (ni_dbus_dict_get_uint32(argument, "transceiver", &uv32))
		link->transceiver  = uv32;

	if ((adv = ni_dbus_dict_get(argument, "advertise"))) {
		/* config */
		ni_objectmodel_ethtool_link_adv_bitfield_from_array(adv,
				&link->advertising, ni_ethtool_link_adv_type);
	} else {
		/* states */
		ni_objectmodel_ethtool_link_adv_from_dict(argument, "supported", &link->supported);
		ni_objectmodel_ethtool_link_adv_from_dict(argument, "advertising", &link->advertising);
		ni_objectmodel_ethtool_link_adv_from_dict(argument, "lp-advertising", &link->lp_advertising);
	}

	return TRUE;
}
Esempio n. 12
0
/*
 * Forward an addrconf request to a supplicant service, such as DHCP or zeroconf
 *
 * What we do here is:
 *
 *  - create an addrconf request handle, and register it with the interface
 *  - assign a uuid
 *  - assign an event ID
 *  - forward the request, along with the uuid
 *  - when we receive a lease event with the matching uuid,
 *    broadcast a corresponding interface event (with the assigned even ID)
 *
 * Note, we do not record the contents of the addrconf request, which may be totally
 * free-form. We just pass it on to the respective addrconf service.
 */
static dbus_bool_t
ni_objectmodel_addrconf_forward_request(ni_dbus_addrconf_forwarder_t *forwarder,
			ni_netdev_t *dev, const ni_dbus_variant_t *dict,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_addrconf_lease_t *lease;
	ni_uuid_t req_uuid;
	dbus_bool_t rv, enabled;
	uint32_t flags = 0;

	/* Check whether we already have a lease on this interface. */
	lease = ni_netdev_get_lease(dev, forwarder->addrfamily, forwarder->addrconf);

	/* Generate a uuid and assign an event ID */
	ni_uuid_generate(&req_uuid);

	/* If the caller tells us to disable this addrconf family, we may need
	 * to do a release() call. */
	if (!ni_dbus_dict_get_bool(dict, "enabled", &enabled) || !enabled)
		return ni_objectmodel_addrconf_forward_release(forwarder, dev, NULL, reply, error);

	if (!ni_dbus_dict_get_uint32(dict, "flags", &flags))
		flags = 0;

	if (lease == NULL) {
		/* We didn't have a lease for this address family and addrconf protocol yet.
		 * Create one and track it. */
		lease = ni_addrconf_lease_new(forwarder->addrconf, forwarder->addrfamily);
		ni_netdev_set_lease(dev, lease);
	}
	lease->uuid = req_uuid;
	lease->state = NI_ADDRCONF_STATE_REQUESTING;
	lease->flags = flags;

	rv = ni_objectmodel_addrconf_forwarder_call(forwarder, dev, "acquire", &req_uuid, dict, error);
	if (rv) {
		/* Tell the client to wait for an addressAcquired event with the given uuid */
		rv =  __ni_objectmodel_return_callback_info(reply, NI_EVENT_ADDRESS_ACQUIRED, &req_uuid, error);
	}
	return rv;
}
Esempio n. 13
0
static dbus_bool_t
ni_objectmodel_ethtool_set_eee(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	const ni_dbus_variant_t *adv;
	ni_ethtool_t *ethtool;
	ni_ethtool_eee_t *eee;

	if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error)))
		return FALSE;

	ni_ethtool_eee_free(ethtool->eee);
	if (!(ethtool->eee = ni_ethtool_eee_new()))
		return FALSE;
	eee = ethtool->eee;

	ni_dbus_dict_get_int32(argument, "enabled", &eee->status.enabled);
	ni_dbus_dict_get_int32(argument, "active",  &eee->status.active);

	ni_dbus_dict_get_int32(argument, "tx-lpi", &eee->tx_lpi.enabled);
	ni_dbus_dict_get_uint32(argument, "tx-timer", &eee->tx_lpi.timer);

	if ((adv = ni_dbus_dict_get(argument, "advertise"))) {
		/* config */
		ni_objectmodel_ethtool_link_adv_bitfield_from_array(adv,
				&eee->speed.advertising, ni_ethtool_link_adv_speed_type);
	} else {
		/* states */
		ni_objectmodel_ethtool_eee_adv_from_dict(argument, "supported", &eee->speed.supported);
		ni_objectmodel_ethtool_eee_adv_from_dict(argument, "advertising", &eee->speed.advertising);
		ni_objectmodel_ethtool_eee_adv_from_dict(argument, "lp-advertising", &eee->speed.lp_advertising);
	}

	return TRUE;
}
Esempio n. 14
0
static dbus_bool_t
ni_objectmodel_ethtool_set_driver_info(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	ni_ethtool_driver_info_t *info;
	ni_ethtool_t *ethtool;
	const char *str;

	if (!ni_dbus_variant_is_dict(argument))
		return FALSE;

	if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error)))
		return FALSE;

	ni_ethtool_driver_info_free(ethtool->driver_info);
	if (!(ethtool->driver_info = ni_ethtool_driver_info_new()))
		return FALSE;

	info = ethtool->driver_info;
	if (ni_dbus_dict_get_string(argument, "driver", &str))
		ni_string_dup(&info->driver, str);
	if (ni_dbus_dict_get_string(argument, "version", &str))
		ni_string_dup(&info->version, str);
	if (ni_dbus_dict_get_string(argument, "bus-info", &str))
		ni_string_dup(&info->bus_info, str);
	if (ni_dbus_dict_get_string(argument, "firmware-version", &str))
		ni_string_dup(&info->fw_version, str);
	if (ni_dbus_dict_get_string(argument, "expansion-rom-version", &str))
		ni_string_dup(&info->erom_version, str);

	ni_dbus_dict_get_uint32(argument, "supports", &info->supports.bitmap);

	return TRUE;
}
Esempio n. 15
0
static dbus_bool_t
ni_objectmodel_ethtool_set_coalesce(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	ni_ethtool_t *ethtool;
	ni_ethtool_coalesce_t *coalesce;

	if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error)))
		return FALSE;

	ni_ethtool_coalesce_free(ethtool->coalesce);
	if (!(ethtool->coalesce = ni_ethtool_coalesce_new()))
		return FALSE;
	coalesce = ethtool->coalesce;

	ni_dbus_dict_get_int32(argument, "adaptive-tx", &coalesce->adaptive_tx);
	ni_dbus_dict_get_int32(argument, "adaptive-rx", &coalesce->adaptive_rx);

	ni_dbus_dict_get_uint32(argument, "pkt-rate-low", &coalesce->pkt_rate_low);
	ni_dbus_dict_get_uint32(argument, "pkt-rate-high", &coalesce->pkt_rate_high);

	ni_dbus_dict_get_uint32(argument, "sample-interval", &coalesce->sample_interval);
	ni_dbus_dict_get_uint32(argument, "stats-block-usecs", &coalesce->stats_block_usecs);

	ni_dbus_dict_get_uint32(argument, "tx-usecs", &coalesce->tx_usecs);
	ni_dbus_dict_get_uint32(argument, "tx-usecs-irq", &coalesce->tx_usecs_irq);
	ni_dbus_dict_get_uint32(argument, "tx-usecs-low", &coalesce->tx_usecs_low);
	ni_dbus_dict_get_uint32(argument, "tx-usecs-high", &coalesce->tx_usecs_high);

	ni_dbus_dict_get_uint32(argument, "tx-frames", &coalesce->tx_frames);
	ni_dbus_dict_get_uint32(argument, "tx-frames-irq", &coalesce->tx_frames_irq);
	ni_dbus_dict_get_uint32(argument, "tx-frames-low", &coalesce->tx_frames_low);
	ni_dbus_dict_get_uint32(argument, "tx-frames-high", &coalesce->tx_frames_high);

	ni_dbus_dict_get_uint32(argument, "rx-usecs", &coalesce->rx_usecs);
	ni_dbus_dict_get_uint32(argument, "rx-usecs-irq", &coalesce->rx_usecs_irq);
	ni_dbus_dict_get_uint32(argument, "rx-usecs-low", &coalesce->rx_usecs_low);
	ni_dbus_dict_get_uint32(argument, "rx-usecs-high", &coalesce->rx_usecs_high);

	ni_dbus_dict_get_uint32(argument, "rx-frames", &coalesce->rx_frames);
	ni_dbus_dict_get_uint32(argument, "rx-frames-irq", &coalesce->rx_frames_irq);
	ni_dbus_dict_get_uint32(argument, "rx-frames-low", &coalesce->rx_frames_low);
	ni_dbus_dict_get_uint32(argument, "rx-frames-high", &coalesce->rx_frames_high);

	return TRUE;
}
Esempio n. 16
0
static dbus_bool_t
__ni_objectmodel_team_set_runner(ni_dbus_object_t *object, const ni_dbus_property_t *property,
				const ni_dbus_variant_t *argument, DBusError *error)
{
	ni_dbus_variant_t *dict;
	const char *name;
	ni_team_t *team;

	if (!(team = __ni_objectmodel_team_write_handle(object, error)))
		return FALSE;

	if (!ni_dbus_struct_get_string(argument, 0, &name)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"bad value for property %s; missed subtype", property->name);
		return FALSE;
	}

	if (!ni_team_runner_name_to_type(name, &team->runner.type)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"bad value for property %s; unsupported subtype %s", property->name, name);
		return FALSE;
	}

	if (!(dict = ni_dbus_struct_get(argument, 1))) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "missed team runner member dict");
		return FALSE;
	}
	if (!ni_dbus_variant_is_dict(dict)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "team runner member is not a dict");
		return FALSE;
	}

	ni_team_runner_init(&team->runner, team->runner.type);
	switch (team->runner.type) {
	case NI_TEAM_RUNNER_ACTIVE_BACKUP: {
			ni_team_runner_active_backup_t *ab = &team->runner.ab;
			uint32_t u32;

			if (ni_dbus_dict_get_uint32(dict, "hwaddr_policy", &u32))
				ab->config.hwaddr_policy = u32;
			else
				ab->config.hwaddr_policy = NI_TEAM_AB_HWADDR_POLICY_SAME_ALL;
		}
		break;

	case NI_TEAM_RUNNER_LOAD_BALANCE: {
			ni_team_runner_load_balance_t *lb = &team->runner.lb;
			ni_dbus_variant_t *txb;
			uint32_t u32;

			if (ni_dbus_dict_get_uint32(dict, "tx_hash", &u32))
				lb->config.tx_hash = u32;
			else	lb->config.tx_hash = NI_TEAM_TX_HASH_NONE;

			txb = ni_dbus_dict_get(dict, "tx_balancer");
			if (txb) {
				if (ni_dbus_dict_get_uint32(txb, "name", &u32) &&
				    ni_team_tx_balancer_type_to_name(u32))
					lb->config.tx_balancer.type = u32;
				else	lb->config.tx_balancer.type = NI_TEAM_TX_BALANCER_BASIC;
				if (ni_dbus_dict_get_uint32(txb, "balancing_interval", &u32))
					lb->config.tx_balancer.interval = u32;
				else	lb->config.tx_balancer.interval = 50;
			}
		}
		break;

	case NI_TEAM_RUNNER_ROUND_ROBIN:
		break;

	case NI_TEAM_RUNNER_BROADCAST:
		break;

	case NI_TEAM_RUNNER_RANDOM:
		break;

	case NI_TEAM_RUNNER_LACP: {
			ni_team_runner_lacp_t *lacp = &team->runner.lacp;
			ni_dbus_variant_t *txb;
			dbus_bool_t b;
			uint16_t u16;
			uint32_t u32;

			if (ni_dbus_dict_get_bool(dict, "active", &b))
				lacp->config.active = b;
			else	lacp->config.active = TRUE;

			if (ni_dbus_dict_get_uint16(dict, "sys_prio", &u16))
				lacp->config.sys_prio = u16;
			else	lacp->config.sys_prio = 255;

			if (ni_dbus_dict_get_bool(dict, "fast_rate", &b))
				lacp->config.fast_rate = b;
			else	lacp->config.fast_rate = FALSE;

			if (ni_dbus_dict_get_uint16(dict, "min_ports", &u16) && u16 < 256)
				lacp->config.sys_prio = u16;
			else	lacp->config.sys_prio = 0;

			if (ni_dbus_dict_get_uint32(dict, "select_policy", &u32))
				lacp->config.select_policy = u32;
			else	lacp->config.select_policy = NI_TEAM_LACP_SELECT_POLICY_PRIO;

			if (ni_dbus_dict_get_uint32(dict, "tx_hash", &u32))
				lacp->config.tx_hash = u32;
			else	lacp->config.tx_hash = NI_TEAM_TX_HASH_NONE;

			txb = ni_dbus_dict_get(dict, "tx_balancer");
			if (txb) {
				if (ni_dbus_dict_get_uint32(txb, "name", &u32) &&
				    ni_team_tx_balancer_type_to_name(u32))
					lacp->config.tx_balancer.type = u32;
				else	lacp->config.tx_balancer.type = NI_TEAM_TX_BALANCER_BASIC;
				if (ni_dbus_dict_get_uint32(txb, "balancing_interval", &u32))
					lacp->config.tx_balancer.interval = u32;
				else	lacp->config.tx_balancer.interval = 50;
			}
		}
		break;

	default:
		return FALSE;
	}
	return TRUE;
}