Example #1
0
static ni_netdev_t *
__ni_objectmodel_dummy_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *dev_ifp = NULL;
	int rv;

	if (ni_string_empty(ifname)) {
		if (ni_string_empty(cfg_ifp->name) &&
		    (ifname = ni_netdev_make_name(nc, "dummy", 0))) {
			ni_string_dup(&cfg_ifp->name, ifname);
		} else {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Unable to create dummy interface: "
				"name argument missed");
			goto out;
		}
		ifname = NULL;
	} else if(!ni_string_eq(cfg_ifp->name, ifname)) {
		ni_string_dup(&cfg_ifp->name, ifname);
	}

	if (cfg_ifp->link.hwaddr.len) {
		if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID)
			cfg_ifp->link.hwaddr.type = ARPHRD_ETHER;
		if (cfg_ifp->link.hwaddr.type != ARPHRD_ETHER ||
		    cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_ETHER)) {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Cannot create dummy interface: "
				"invalid ethernet address '%s'",
				ni_link_address_print(&cfg_ifp->link.hwaddr));
			return NULL;
		}
	}

	if ((rv = ni_system_dummy_create(nc, cfg_ifp, &dev_ifp)) < 0) {
		if (rv != -NI_ERROR_DEVICE_EXISTS || dev_ifp == NULL
		|| (ifname && dev_ifp && !ni_string_eq(dev_ifp->name, ifname))) {
			dbus_set_error(error, DBUS_ERROR_FAILED,
					"Unable to create dummy interface: %s",
					ni_strerror(rv));
			dev_ifp = NULL;
			goto out;
		}
		ni_debug_dbus("dummy interface exists (and name matches)");
	}

	if (dev_ifp->link.type != NI_IFTYPE_DUMMY) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
				"Unable to create dummy interface: "
				"new interface is of type %s",
				ni_linktype_type_to_name(dev_ifp->link.type));
		dev_ifp = NULL;
	}

out:
	if (cfg_ifp)
		ni_netdev_put(cfg_ifp);
	return dev_ifp;
}
Example #2
0
/*
 * Interface.acquire(dict options)
 * Acquire a lease for the given interface.
 *
 * Server side method implementation
 */
static dbus_bool_t
__wicked_dbus_autoip4_acquire_svc(ni_dbus_object_t *object, const ni_dbus_method_t *method,
			unsigned int argc, const ni_dbus_variant_t *argv,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_autoip_device_t *dev = ni_objectmodel_unwrap_autoip4_device(object);
	dbus_bool_t ret = FALSE;
	int rv;

	ni_debug_dbus("%s(dev=%s)", __func__, dev->ifname);

	/* Ignore all arguments for now */
	if ((rv = ni_autoip_acquire(dev)) < 0) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
				"Cannot configure interface %s: %s", dev->ifname,
				ni_strerror(rv));
		goto failed;
	}

	/* We've now initiated the IPv4ll exchange. It will complete
	 * asynchronously, and when done, we will emit a signal that
	 * notifies the sender of its results. */

	ret = TRUE;

failed:
	return ret;
}
Example #3
0
/*
 * Interface.drop(void)
 * Drop a IPv4ll lease
 */
static dbus_bool_t
__wicked_dbus_autoip4_drop_svc(ni_dbus_object_t *object, const ni_dbus_method_t *method,
			unsigned int argc, const ni_dbus_variant_t *argv,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_autoip_device_t *dev = ni_objectmodel_unwrap_autoip4_device(object);
	dbus_bool_t ret = FALSE;
	ni_uuid_t uuid;
	int rv;

	ni_debug_dbus("%s(dev=%s)", __func__, dev->ifname);

	memset(&uuid, 0, sizeof(uuid));
	if (argc == 1) {
		/* Extract the lease uuid and pass that along to ni_autoip_release.
		 * This makes sure we don't cancel the wrong lease.
		 */
		if (!ni_dbus_variant_get_uuid(&argv[0], &uuid)) {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "bad uuid argument");
			goto failed;
		}
	}

	if ((rv = ni_autoip_release(dev, &uuid)) < 0) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
				"Unable to drop IPv4ll lease for interface %s: %s", dev->ifname,
				ni_strerror(rv));
		goto failed;
	}

	ret = TRUE;

failed:
	return ret;
}
Example #4
0
static dbus_bool_t
ni_objectmodel_addrconf_static_drop(ni_dbus_object_t *object, unsigned int addrfamily,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_addrconf_lease_t *lease = NULL;
	ni_netdev_t *dev;
	int rv;

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

	lease = ni_addrconf_lease_new(NI_ADDRCONF_STATIC, addrfamily);
	lease->state = NI_ADDRCONF_STATE_RELEASED;

	rv = __ni_system_interface_update_lease(dev, &lease);
	if (lease)
		ni_addrconf_lease_free(lease);

	if (rv < 0) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Error dropping static %s addresses: %s",
				ni_addrfamily_type_to_name(addrfamily),
				ni_strerror(rv));
		return FALSE;
	}

	/* Don't return anything */
	return TRUE;
}
Example #5
0
/*
 * InfinibandChild.Factory.newDevice:
 * Create a new infiniband child interface
 */
static ni_netdev_t *
__ni_objectmodel_ib_newchild(ni_netdev_t *cfg, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *dev = NULL;
	const ni_infiniband_t *ib;
	const char *err;
	int rv;

	ib = ni_netdev_get_infiniband(cfg);
	if ((err = ni_infiniband_validate(NI_IFTYPE_INFINIBAND_CHILD,
					ib, &cfg->link.lowerdev)) != NULL) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err);
		return NULL;
	}

	if (ni_string_empty(ifname)) {
		if (ni_string_empty(cfg->name) &&
		    !ni_string_printf(&cfg->name, "%s.%04x",
					cfg->link.lowerdev.name, ib->pkey)) {
			dbus_set_error(error, DBUS_ERROR_FAILED,
				"Unable to create infiniband child: "
				"name argument missed, failed to construct");
			return NULL;
		}
		ifname = NULL;
	} else if (!ni_string_eq(cfg->name, ifname)) {
		ni_string_dup(&cfg->name, ifname);
	}

	if (ni_string_eq(cfg->name, cfg->link.lowerdev.name)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
			"Cannot to create infiniband child: "
			"child name %s equal with parent device name",
			cfg->name);
		return NULL;
	}

	if ((rv = ni_system_infiniband_child_create(nc, cfg, &dev)) < 0) {
		if (rv != -NI_ERROR_DEVICE_EXISTS || !dev
		|| (ifname && dev && !ni_string_eq(ifname, dev->name))) {
			dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to create infiniband child interface: %s",
				ni_strerror(rv));
			return NULL;
		}
	}

	if (dev && dev->link.type != NI_IFTYPE_INFINIBAND_CHILD) {
		dbus_set_error(error,
			DBUS_ERROR_FAILED,
			"Unable to create infiniband child interface %s: it exists with type %s",
			cfg->name, ni_linktype_type_to_name(dev->link.type));
		return NULL;
        }

	return dev;
}
Example #6
0
static ni_netdev_t *
__ni_objectmodel_team_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *new_ifp = NULL;
	int rv;

	ni_netdev_get_team(cfg_ifp);
	if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "team", 0))) {
		dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface - too many interfaces");
		goto out;
	}
	ni_string_dup(&cfg_ifp->name, ifname);

	if (cfg_ifp->link.hwaddr.len) {
		if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID)
			cfg_ifp->link.hwaddr.type = ARPHRD_ETHER;

		if (cfg_ifp->link.hwaddr.type != ARPHRD_ETHER ||
		    cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_ETHER)) {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
					"Cannot create team interface: invalid ethernet address '%s'",
					ni_link_address_print(&cfg_ifp->link.hwaddr));
			goto out;
		}
	}

	if ((rv = ni_system_team_create(nc, cfg_ifp, &new_ifp)) < 0) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
				"Unable to create team interface '%s'", cfg_ifp->name);
		new_ifp = NULL;
		goto out;
#if 0
		if (rv != -NI_ERROR_DEVICE_EXISTS
		 && (ifname != NULL && strcmp(ifname, new_ifp->name))) {
			dbus_set_error(error,
					DBUS_ERROR_FAILED,
					"Unable to create team interface: %s",
					ni_strerror(rv));
			goto out;
		}
		ni_debug_dbus("Bonding interface exists (and name matches)");
#endif
	}

	if (new_ifp->link.type != NI_IFTYPE_TEAM) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to create team interface: new interface is of type %s",
				ni_linktype_type_to_name(new_ifp->link.type));
		new_ifp = NULL;
	}

out:
	if (cfg_ifp)
		ni_netdev_put(cfg_ifp);
	return new_ifp;
}
Example #7
0
/*
 * Generic functions for static address configuration
 */
static dbus_bool_t
ni_objectmodel_addrconf_static_request(ni_dbus_object_t *object, unsigned int addrfamily,
			unsigned int argc, const ni_dbus_variant_t *argv,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_addrconf_lease_t *lease = NULL;
	const ni_dbus_variant_t *dict;
	const char *string_value;
	ni_netdev_t *dev;
	ni_address_t *ap;
	int rv;

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

	if (argc != 1 || !ni_dbus_variant_is_dict(&argv[0])) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"requestLease: expected one dict argument");
		return FALSE;
	}
	dict = &argv[0];

	lease = ni_addrconf_lease_new(NI_ADDRCONF_STATIC, addrfamily);
	lease->state = NI_ADDRCONF_STATE_GRANTED;
	ni_uuid_generate(&lease->uuid);

	if (!__ni_objectmodel_set_address_dict(&lease->addrs, dict, error)
	 || !__ni_objectmodel_set_route_dict(&lease->routes, dict, error)
	 || !__ni_objectmodel_set_resolver_dict(&lease->resolver, dict, error)) {
		ni_addrconf_lease_free(lease);
		return FALSE;
	}
	if (__ni_objectmodel_get_domain_string(dict, "hostname", &string_value))
		ni_string_dup(&lease->hostname, string_value);

	/* mark all addresses tentative, causing to verify them */
	for (ap = lease->addrs; ap; ap = ap->next)
		ni_address_set_tentative(ap, TRUE);

	rv = __ni_system_interface_update_lease(dev, &lease);
	if (lease)
		ni_addrconf_lease_free(lease);

	if (rv < 0) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Error configuring static %s addresses: %s",
				ni_addrfamily_type_to_name(addrfamily),
				ni_strerror(rv));
		return FALSE;
	}

	/* Don't return anything. */
	return TRUE;
}
Example #8
0
/*
 * Refresh the device mtu and MAC address info prior to taking any actions
 */
int
ni_dhcp4_device_refresh(ni_dhcp4_device_t *dev)
{
	ni_netconfig_t *nih = ni_global_state_handle(0);
	int rv;

	if ((rv = __ni_device_refresh_link_info(nih, &dev->link)) < 0) {
		ni_error("%s: cannot refresh interface: %s",
				__func__, ni_strerror(rv));
		return rv;
	}

	return ni_capture_devinfo_refresh(&dev->system, dev->ifname, &dev->link);
}
Example #9
0
/*
 * Process a request to reconfigure the device (ie rebind a lease, or discover
 * a new lease).
 */
int
ni_autoip_device_refresh(ni_autoip_device_t *dev)
{
	ni_netconfig_t *nih = ni_global_state_handle(0);
	int rv;

	/* Go back to INIT state to force a reclaim */
	dev->fsm.state = NI_AUTOIP_STATE_INIT;

	if ((rv = __ni_device_refresh_link_info(nih, &dev->link)) < 0) {
		ni_error("%s: cannot refresh interface: %s", __func__, ni_strerror(rv));
		return rv;
	}

	return ni_capture_devinfo_refresh(&dev->devinfo, dev->ifname, &dev->link);
}
Example #10
0
static ni_netdev_t *
__ni_objectmodel_bond_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *new_ifp = NULL;
	const ni_bonding_t *bond;
	int rv;

	bond = ni_netdev_get_bonding(cfg_ifp);

	if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "bond", 0))) {
		dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface - too many interfaces");
		goto out;
	}
	ni_string_dup(&cfg_ifp->name, ifname);

	if ((rv = ni_system_bond_create(nc, cfg_ifp->name, bond, &new_ifp)) < 0) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
				"Unable to create bonding interface '%s'", cfg_ifp->name);
		new_ifp = NULL;
		goto out;
#if 0
		if (rv != -NI_ERROR_DEVICE_EXISTS
		 && (ifname != NULL && strcmp(ifname, new_ifp->name))) {
			dbus_set_error(error,
					DBUS_ERROR_FAILED,
					"Unable to create bonding interface: %s",
					ni_strerror(rv));
			goto out;
		}
		ni_debug_dbus("Bonding interface exists (and name matches)");
#endif
	}

	if (new_ifp->link.type != NI_IFTYPE_BOND) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to create bonding interface: new interface is of type %s",
				ni_linktype_type_to_name(new_ifp->link.type));
		new_ifp = NULL;
	}

out:
	if (cfg_ifp)
		ni_netdev_put(cfg_ifp);
	return new_ifp;
}
Example #11
0
/*
 * Bring up the device
 */
void
ni_managed_device_down(ni_managed_device_t *mdev)
{
	ni_fsm_t *fsm = mdev->nanny->fsm;
	ni_ifworker_t *w = mdev->worker;
	int rv;

	ni_ifworker_set_completion_callback(w, ni_managed_device_down_done, mdev->nanny);

	ni_ifworker_set_config(w, mdev->selected_config, w->config.meta.origin);
	w->target_range.min = NI_FSM_STATE_NONE;
	w->target_range.max = NI_FSM_STATE_DEVICE_DOWN;

	if ((rv = ni_ifworker_start(fsm, w, fsm->worker_timeout)) >= 0) {
		mdev->state = NI_MANAGED_STATE_STOPPING;
	} else {
		ni_error("%s: cannot stop device: %s", w->name, ni_strerror(rv));
		mdev->state = NI_MANAGED_STATE_FAILED;
	}
}
Example #12
0
static ni_netdev_t *
__ni_objectmodel_ovs_bridge_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *new_ifp = NULL;
	int rv;

	ni_netdev_get_ovs_bridge(cfg_ifp);
	if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "ovsbr", 0))) {
		dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ovs bridge interface - too many interfaces");
		goto out;
	}
	ni_string_dup(&cfg_ifp->name, ifname);

	if ((rv = ni_system_ovs_bridge_create(nc, cfg_ifp, &new_ifp)) < 0) {
		if (rv != -NI_ERROR_DEVICE_EXISTS || new_ifp == NULL
		|| (ifname && new_ifp && !ni_string_eq(ifname, new_ifp->name))) {
			dbus_set_error(error,
					DBUS_ERROR_FAILED,
					"Unable to create OVS bridge device: %s",
					ni_strerror(rv));
			new_ifp = NULL;
			goto out;
		}
		ni_debug_dbus("OVS bridge device %s exists (and with correct type)", ifname);
	}

	if (new_ifp->link.type != NI_IFTYPE_OVS_BRIDGE) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to create ovs bridge interface: new interface is of type %s",
				ni_linktype_type_to_name(new_ifp->link.type));
		new_ifp = NULL;
	}

out:
	if (cfg_ifp)
		ni_netdev_put(cfg_ifp);
	return new_ifp;
}
Example #13
0
File: ppp.c Project: mchf/wicked
/*
 * Delete a PPP interface
 */
dbus_bool_t
ni_objectmodel_ppp_delete(ni_dbus_object_t *object, const ni_dbus_method_t *method,
			unsigned int argc, const ni_dbus_variant_t *argv,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_netdev_t *dev;
	int rv;

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

	NI_TRACE_ENTER_ARGS("dev=%s", dev->name);
	if ((rv = ni_system_ppp_delete(dev)) < 0) {
		ni_dbus_set_error_from_code(error, rv,
				"Unable to delete PPP interface %s: %s",
				dev->name, ni_strerror(rv));
		return FALSE;
	}

	ni_dbus_object_free(object);
	return TRUE;
}
Example #14
0
static dbus_bool_t
__ni_objectmodel_macvlan_delete(ni_dbus_object_t *object, const ni_dbus_method_t *method,
			unsigned int argc, const ni_dbus_variant_t *argv,
			ni_dbus_message_t *reply, DBusError *error)
{
	ni_netdev_t *dev;
	int rv;

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

	NI_TRACE_ENTER_ARGS("dev=%s", dev->name);
	if ((rv = ni_system_macvlan_delete(dev)) < 0) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
			"Error deleting macvlan interface %s: %s",
			dev->name, ni_strerror(rv));
		return FALSE;
	}

	ni_client_state_drop(dev->link.ifindex);
	return TRUE;
}
Example #15
0
static ni_netdev_t *
__ni_objectmodel_bridge_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *new_ifp = NULL;
	const ni_bridge_t *bridge;
	int rv;

	bridge = ni_netdev_get_bridge(cfg_ifp);

	if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "br", 0))) {
		dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface - too many interfaces");
		goto out;
	}
	ni_string_dup(&cfg_ifp->name, ifname);

	if ((rv = ni_system_bridge_create(nc, cfg_ifp->name, bridge, &new_ifp)) < 0) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to create bridging interface: %s",
				ni_strerror(rv));
		new_ifp = NULL;
		goto out;
	}

	if (new_ifp->link.type != NI_IFTYPE_BRIDGE) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to create bridging interface: new interface is of type %s",
				ni_linktype_type_to_name(new_ifp->link.type));
		new_ifp = NULL;
	}

out:
	if (cfg_ifp)
		ni_netdev_put(cfg_ifp);
	return new_ifp;
}
Example #16
0
/*
 * Bring up the device
 */
static int
ni_managed_device_up(ni_managed_device_t *mdev, const char *origin)
{
	ni_fsm_t *fsm = mdev->nanny->fsm;
	ni_ifworker_t *w = mdev->worker;
	unsigned int previous_state;
	unsigned int target_state;
	ni_security_id_t security_id = NI_SECURITY_ID_INIT;
	ni_ifworker_array_t ifmarked = NI_IFWORKER_ARRAY_INIT;
	ni_ifmarker_t ifmarker;
	int rv = -NI_ERROR_DEVICE_NOT_COMPATIBLE;

	memset(&ifmarker, 0, sizeof(ifmarker));

	switch (w->type) {
	case NI_IFWORKER_TYPE_NETDEV:
		mdev->max_fail_count = 3;
		if (w->device->link.type == NI_IFTYPE_WIRELESS) {
			const char *essid;

			ni_security_id_init(&security_id, "wireless");
			if ((essid = ni_managed_device_get_essid(mdev->selected_config)) != NULL)
				ni_security_id_set_attr(&security_id, "essid", essid);
		}

		target_state = NI_FSM_STATE_ADDRCONF_UP;
		break;

	case NI_IFWORKER_TYPE_MODEM:
		mdev->max_fail_count = 1;

		ni_security_id_init(&security_id, "modem");
		if (w->modem->identify.equipment)
			ni_security_id_set_attr(&security_id, "equipment-id", w->modem->identify.equipment);

		target_state = NI_FSM_STATE_LINK_UP;
		break;

	default:
		goto failed;
	}

	if (ni_security_id_valid(&security_id))
		ni_managed_device_set_security_id(mdev, &security_id);

	ni_ifworker_set_completion_callback(w, ni_managed_device_up_done, mdev->nanny);

	ni_ifworker_set_config(w, mdev->selected_config, origin);

	ifmarker.target_range.min = target_state;
	ifmarker.target_range.max = __NI_FSM_STATE_MAX;
	ifmarker.persistent = w->control.persistent;

	ni_ifworker_array_append(&ifmarked, w);
	ni_fsm_pull_in_children(&ifmarked);

	/* Binding: this validates the XML configuration document,
	 * resolves any references to other devices (if there are any),
	 * and retrieves any keys/passwords etc via the prompt callback.
	 * Inside the prompt callback, we record all secrets for tracking
	 */
	ni_secret_array_destroy(&mdev->secrets);

	previous_state = mdev->state;
	mdev->state = NI_MANAGED_STATE_BINDING;
	if ((rv = ni_ifworker_bind_early(w, fsm, TRUE)) < 0)
		goto failed;

	if (mdev->missing_secrets) {
		/* FIXME: Emit an event listing the secrets we're missing.
		 */
		mdev->state = previous_state;
		return -1;
	}

	mdev->state = NI_MANAGED_STATE_STARTING;
	ni_fsm_mark_matching_workers(fsm, &ifmarked, &ifmarker);
	ni_ifworker_array_destroy(&ifmarked);

	return 0;

failed:
	ni_error("%s: cannot start device: %s", w->name, ni_strerror(rv));
	mdev->state = NI_MANAGED_STATE_FAILED;
	return -1;
}
Example #17
0
/*
 * Install information from a lease, and remember that we did
 */
static ni_bool_t
ni_system_updater_install(ni_updater_t *updater, const ni_addrconf_lease_t *lease, const char *ifname)
{
	ni_string_array_t arguments = NI_STRING_ARRAY_INIT;
	const char *statedir = NULL;
	char *file = NULL;
	ni_bool_t result = FALSE;
	int rv = 0;

	ni_debug_ifconfig("Updating system %s settings from %s/%s lease",
					ni_updater_name(updater->kind),
					ni_addrconf_type_to_name(lease->type),
					ni_addrfamily_type_to_name(lease->family));

	if (!updater->proc_install)
		return TRUE;

	if (!ifname || (!updater->have_backup && !ni_system_updater_backup(updater, ifname)))
		return FALSE;

	ni_string_array_append(&arguments, "-i");
	ni_string_array_append(&arguments, ifname);

	ni_string_array_append(&arguments, "-t");
	ni_string_array_append(&arguments, ni_addrconf_type_to_name(lease->type));

	ni_string_array_append(&arguments, "-f");
	ni_string_array_append(&arguments, ni_addrfamily_type_to_name(lease->family));

	switch (updater->kind) {
	case NI_ADDRCONF_UPDATER_GENERIC:
		switch (updater->format) {
		case NI_ADDRCONF_UPDATER_FORMAT_INFO:
			ni_leaseinfo_dump(NULL, lease, ifname, NULL);
			if (!(file = ni_leaseinfo_path(ifname, lease->type, lease->family))) {
				ni_error("Unable to determine leaseinfo file path.");
				goto done;
			}
			ni_string_array_append(&arguments, file);
			break;

		default:
			ni_error("Unsupported %s updater data format.",
				ni_updater_name(updater->kind));
			goto done;
		}

		ni_string_array_append(&arguments,
				ni_updater_format_name(updater->format));
		break;

	case NI_ADDRCONF_UPDATER_RESOLVER:
		statedir = ni_extension_statedir(ni_updater_name(updater->kind));
		if (!statedir) {
			ni_error("failed to get %s statedir", ni_updater_name(updater->kind));
			goto done;
		}
		ni_string_printf(&file, "%s/resolv.conf.%s.%s.%s",
				statedir, ifname,
				ni_addrconf_type_to_name(lease->type),
				ni_addrfamily_type_to_name(lease->family));
		ni_string_array_append(&arguments, file);

		if ((rv = ni_resolver_write_resolv_conf(file, lease->resolver, NULL)) < 0) {
			ni_error("failed to write resolver info to file: %s",
					ni_strerror(rv));
			goto done;
		}
		break;

	case NI_ADDRCONF_UPDATER_HOSTNAME:
		if (!ni_string_empty(lease->hostname)) {
			ni_string_array_append(&arguments, lease->hostname);
		} else {
			const ni_address_t *ap;
			char *name = NULL;
			unsigned int count;

			/* bnc#861476 workaround */
			if (!can_try_reverse_lookup(lease))
				goto done;

			for (count = 0, ap = lease->addrs; ap; ap = ap->next) {
				if (!ni_sockaddr_is_specified(&ap->local_addr))
					continue;

				if (!ni_resolve_reverse_timed(&ap->local_addr,
						&name, NI_UPDATER_REVERSE_TIMEOUT))
					break;

				ni_info("Unable to resolve %s to hostname",
					ni_sockaddr_print(&ap->local_addr));

				if (++count >= NI_UPDATER_REVERSE_MAX_CNT)
					break;
			}

			if (ni_string_empty(name)) {
				ni_note("Skipping hostname update, none available");
				goto done;
			}
			ni_string_array_append(&arguments, name);
			ni_string_free(&name);
		}
		break;

	default:
		ni_error("cannot install new %s settings - file format not understood",
				ni_updater_name(updater->kind));
		goto done;
	}

	if (!ni_system_updater_run(updater->proc_install, &arguments)) {
		ni_error("failed to install %s settings", ni_updater_name(updater->kind));
		goto done;
	}

	result = TRUE;

	switch (updater->kind) {
	case NI_ADDRCONF_UPDATER_RESOLVER:
		if (ni_global.other_event)
			ni_global.other_event(NI_EVENT_RESOLVER_UPDATED);
		break;

	case NI_ADDRCONF_UPDATER_HOSTNAME:
		if (ni_global.other_event)
			ni_global.other_event(NI_EVENT_HOSTNAME_UPDATED);
		break;

	case NI_ADDRCONF_UPDATER_GENERIC:
		if (ni_global.other_event)
			ni_global.other_event(NI_EVENT_GENERIC_UPDATED);
		break;

	default:
		break;
	}

done:
	if (file)
		free(file);
	ni_string_array_destroy(&arguments);

	return result;
}
Example #18
0
int
ni_dhcp4_tester_run(ni_dhcp4_tester_t *opts)
{
	ni_netconfig_t *nc;
	ni_netdev_t *ifp = NULL;
	ni_dhcp4_device_t *dev = NULL;
	ni_dhcp4_request_t *req = NULL;
	unsigned int link_timeout = 20;
	int rv;

	if (opts->timeout && opts->timeout != -1U) {
		link_timeout = (opts->timeout * 2) / 3;
		opts->timeout -= link_timeout;
	}

	if (!opts || ni_string_empty(opts->ifname))
		ni_fatal("Invalid start parameters!");

	dhcp4_tester_opts   = *opts;
	dhcp4_tester_status = NI_WICKED_RC_ERROR;

	if (!(nc = ni_global_state_handle(1)))
		ni_fatal("Cannot refresh interface list!");

	if (!(ifp = ni_netdev_by_name(nc, opts->ifname)))
		ni_fatal("Cannot find interface with name '%s'", opts->ifname);

	if (!ni_dhcp4_supported(ifp))
		ni_fatal("DHCPv4 not supported on '%s'", opts->ifname);

	if (!(dev = ni_dhcp4_device_new(ifp->name, &ifp->link)))
		ni_fatal("Cannot allocate dhcp4 client for '%s'", opts->ifname);

	ni_dhcp4_set_event_handler(ni_dhcp4_tester_protocol_event);

	if (!(req = ni_dhcp4_request_new())) {
		ni_error("Cannot allocate dhcp4 request");
		goto failure;
	}

	if (!ni_dhcp4_tester_req_init(req, opts->request))
		goto failure;

	if (!ni_netdev_link_is_up(ifp)) {
		ni_netdev_req_t *ifreq;
		ni_debug_dhcp("%s: Link is not up, trying to bring it up",
				ifp->name);

		ifreq = ni_netdev_req_new();
		ifreq->ifflags = NI_IFF_LINK_UP | NI_IFF_NETWORK_UP;
		if ((rv = ni_system_interface_link_change(ifp, ifreq)) < 0) {
			ni_error("%s: Unable to set up link", ifp->name);
			ni_netdev_req_free(ifreq);
			goto failure;
		}
		ni_netdev_req_free(ifreq);

		do {
			sleep(1);

			if (!(nc = ni_global_state_handle(1)))
				goto failure;

			if (!(ifp = ni_netdev_by_index(nc, dev->link.ifindex)))
				break;

			if (ni_netdev_link_is_up(ifp))
				break;

			ni_debug_dhcp("%s: Link is not (yet) up", ifp->name);
		} while (link_timeout-- > 1);

		if (!ifp || !ni_netdev_link_is_up(ifp) || !link_timeout) {
			ni_error("%s: Unable to bring link up",
				ifp && ifp->name ? ifp->name : dev->ifname);
			goto failure;
		}

		/* Do not try to send too early, even link is reported up now */
		sleep(1);
	}

	if (opts->timeout && opts->timeout != -1U)
		req->acquire_timeout = opts->timeout;

	req->broadcast = opts->broadcast;

	if ((rv = ni_dhcp4_acquire(dev, req)) < 0) {
		ni_error("%s: DHCP4v6 acquire request %s failed: %s",
				dev->ifname, ni_uuid_print(&req->uuid),
				ni_strerror(rv));
		goto failure;
	}

	dhcp4_tester_status = NI_WICKED_RC_IN_PROGRESS;
	while (!ni_caught_terminal_signal()) {
		long timeout;

		timeout = ni_timer_next_timeout();

		if (ni_socket_wait(timeout) != 0)
			break;
	}
	ni_server_deactivate_interface_events();
	ni_socket_deactivate_all();

failure:
	if (dev)
		ni_dhcp4_device_put(dev);
	if (req)
		ni_dhcp4_request_free(req);
	return dhcp4_tester_status;
}
Example #19
0
static ni_netdev_t *
__ni_objectmodel_macvlan_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *dev_ifp = NULL;
	const ni_macvlan_t *macvlan;
	const char *err;
	const char *cfg_ifp_iftype = NULL;
	int rv;

	cfg_ifp_iftype = ni_linktype_type_to_name(cfg_ifp->link.type);

	if (ni_string_empty(cfg_ifp->link.lowerdev.name)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Incomplete arguments: need a lower device name");
		return NULL;
	} else
	if (!ni_netdev_ref_bind_ifindex(&cfg_ifp->link.lowerdev, nc)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
			"Unable to find %s lower device %s by name",
			cfg_ifp_iftype,
			cfg_ifp->link.lowerdev.name);
		return NULL;
	}

	macvlan = ni_netdev_get_macvlan(cfg_ifp);
	if ((err = ni_macvlan_validate(macvlan))) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err);
		goto out;
	}

	if (ni_string_empty(ifname)) {
		if (ni_string_empty(cfg_ifp->name) &&
			(ifname = ni_netdev_make_name(
				nc,
				cfg_ifp_iftype,
				0))) {
			ni_string_dup(&cfg_ifp->name, ifname);
		} else {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Unable to create %s interface: "
				"name argument missed",
				cfg_ifp_iftype);
			goto out;
		}
		ifname = NULL;
	} else if(!ni_string_eq(cfg_ifp->name, ifname)) {
		ni_string_dup(&cfg_ifp->name, ifname);
	}
	if (ni_string_eq(cfg_ifp->name, cfg_ifp->link.lowerdev.name)) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
			"Cannot create %s interface: "
			"macvlan name %s equal with lower device name",
			cfg_ifp_iftype,
			cfg_ifp->name);
		return NULL;
	}

	if (cfg_ifp->link.hwaddr.len) {
		if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID)
			cfg_ifp->link.hwaddr.type = ARPHRD_ETHER;
		if (cfg_ifp->link.hwaddr.type != ARPHRD_ETHER ||
		    cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_ETHER)) {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Cannot create %s interface: "
				"invalid ethernet address '%s'",
				cfg_ifp_iftype,
				ni_link_address_print(&cfg_ifp->link.hwaddr));
			return NULL;
		}
	}

	if ((rv = ni_system_macvlan_create(nc, cfg_ifp, &dev_ifp)) < 0) {
		if (rv != -NI_ERROR_DEVICE_EXISTS || dev_ifp == NULL
		|| (ifname && dev_ifp && !ni_string_eq(dev_ifp->name, ifname))) {
			dbus_set_error(error, DBUS_ERROR_FAILED,
					"Unable to create %s interface: %s",
				cfg_ifp_iftype,
				ni_strerror(rv));
			dev_ifp = NULL;
			goto out;
		}
		ni_debug_dbus("%s interface exists (and name matches)",
			cfg_ifp_iftype);
	}

	if (dev_ifp->link.type != cfg_ifp->link.type) {
		dbus_set_error(error, DBUS_ERROR_FAILED,
				"Unable to create %s interface: "
				"new interface is of type %s",
			cfg_ifp_iftype,
			ni_linktype_type_to_name(dev_ifp->link.type));
		dev_ifp = NULL;
	}

out:
	if (cfg_ifp)
		ni_netdev_put(cfg_ifp);
	return dev_ifp;
}