Exemplo n.º 1
0
ni_bool_t
ni_objectmodel_save_state(const char *filename)
{
	xml_document_t *doc;
	ni_bool_t rv = FALSE;
	FILE *fp = NULL;

	ni_debug_objectmodel("saving server state to %s", filename);

	doc = xml_document_new();
	if (!ni_objectmodel_save_state_xml(doc->root, __ni_objectmodel_server))
		goto done;

	fp = ni_file_open(filename, "w", 0600);
	if (xml_document_print(doc, fp) < 0) {
		ni_error("%s: unable to write server state to %s", __func__, filename);
		goto done;
	}

	rv = TRUE;

done:
	if (fp)
		fclose(fp);
	xml_document_free(doc);
	return rv;
}
Exemplo n.º 2
0
/*
 * Forward an addrconf drop call to a supplicant service, such as DHCP or zeroconf
 */
static dbus_bool_t
ni_objectmodel_addrconf_forward_release(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;
	dbus_bool_t rv;

	/* If we have no lease, neither pending nor granted, there's nothing we need to do.
	 */
	if ((lease = ni_netdev_get_lease(dev, forwarder->addrfamily, forwarder->addrconf)) == NULL)
		return TRUE;

	rv = ni_objectmodel_addrconf_forwarder_call(forwarder, dev, "drop", &lease->uuid, NULL, error);
	if (!rv) {
		switch (ni_dbus_get_error(error, NULL)) {
		case -NI_ERROR_ADDRCONF_NO_LEASE:
			ni_debug_objectmodel("%s: no %s/%s lease", dev->name,
				ni_addrconf_type_to_name(forwarder->addrconf),
				ni_addrfamily_type_to_name(forwarder->addrfamily));
			rv = TRUE;
			break;
		default:
			ni_debug_objectmodel("%s: service returned %s (%s)", forwarder->supplicant.interface,
				error->name, error->message);
		}
		return rv;
	}

	/* Check again whether we still have a lease for this. The addrconf supplicant may
	 * actually be fast, so that the callback has arrived before the reply to our original
	 * release() call. In that case, we would tell the client to wait for a release event
	 * that has already been broadcast (and ignored).
	 */
	if ((lease = ni_netdev_get_lease(dev, forwarder->addrfamily, forwarder->addrconf)) != NULL) {
		/* Tell the client to wait for an addressReleased event with the given uuid */
		ni_debug_objectmodel("%s/%s: found lease, waiting for drop notification from supplicant",
				ni_addrconf_type_to_name(forwarder->addrconf),
				ni_addrfamily_type_to_name(forwarder->addrfamily));
		rv =  __ni_objectmodel_return_callback_info(reply, NI_EVENT_ADDRESS_RELEASED, &lease->uuid, error);
	}
	return rv;
}
Exemplo n.º 3
0
static dbus_bool_t
ni_objectmodel_gre_change(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_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *dev, *cfg;
	ni_gre_t *gre;
	const char *err;

	/* we've already checked that argv matches our signature */
	ni_assert(argc == 1);

	if (!(dev = ni_objectmodel_unwrap_netif(object, error)) ||
		!(cfg = __ni_objectmodel_gre_device_arg(&argv[0])) ||
		!(ni_netdev_get_gre(dev))) {
		ni_dbus_error_invalid_args(error, object->path, method->name);
		return FALSE;
	}

	gre = ni_netdev_get_gre(cfg);
	if ((err = ni_gre_validate(gre))) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err);
		return FALSE;
	}

	cfg->link.ifindex = dev->link.ifindex;
	if (ni_string_empty(cfg->name))
		ni_string_dup(&cfg->name, dev->name);

	if (ni_netdev_device_is_up(dev)) {
		ni_debug_objectmodel("Skipping gre changeDevice call on %s: "
				"device is up", dev->name);
		return TRUE;
	}

	if (!ni_string_empty(cfg->link.lowerdev.name) &&
	    !ni_objectmodel_bind_netdev_ref_index(cfg->name, "gre tunnel",
					&cfg->link.lowerdev, nc, error))
		return FALSE;

	if (ni_system_tunnel_change(nc, dev, cfg) < 0) {
		dbus_set_error(error,
			DBUS_ERROR_FAILED,
			"Unable to change gre properties on interface %s",
			dev->name);
		return FALSE;
	}

	return TRUE;
}
Exemplo n.º 4
0
static dbus_bool_t
ni_objectmodel_dummy_change(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_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *dev, *cfg;

	/* we've already checked that argv matches our signature */
	ni_assert(argc == 1);

	if (!(dev = ni_objectmodel_unwrap_netif(object, error)) ||
	    !(cfg = __ni_objectmodel_dummy_device_arg(&argv[0]))) {
		ni_dbus_error_invalid_args(error, object->path, method->name);
		return FALSE;
	}

	cfg->link.ifindex = dev->link.ifindex;
	if (ni_string_empty(cfg->name))
		ni_string_dup(&cfg->name, dev->name);

	if (ni_netdev_device_is_up(dev)) {
		ni_debug_objectmodel("Skipping dummy changeDevice call on %s: "
				"device is up", dev->name);
		return TRUE;
	}

	if (ni_system_dummy_change(nc, dev, cfg) < 0) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to change dummy properties on interface %s",
				dev->name);
		return FALSE;
	}

	if (cfg->link.hwaddr.type == ARPHRD_VOID)
		cfg->link.hwaddr.type = ARPHRD_ETHER;
	if (!ni_link_address_is_invalid(&cfg->link.hwaddr) &&
	    ni_system_hwaddr_change(nc, dev, &cfg->link.hwaddr) < 0) {
		ni_error("Unable to change hwaddr on dummy interface %s",
				dev->name);
		/* fail? */
	}

	return TRUE;
}
Exemplo n.º 5
0
/*
 * Register all naming services specified in the config file.
 * These naming services are supposed to be provided by shared libraries.
 * The symbol specified by the C binding element must refer to a
 * ni_objectmodel_ns struct.
 */
void
ni_objectmodel_register_ns_dynamic(void)
{
	ni_config_t *config = ni_global.config;
	ni_extension_t *ex;

	ni_assert(config);
	for (ex = config->ns_extensions; ex; ex = ex->next) {
		ni_c_binding_t *binding;
		void *addr;

		for (binding = ex->c_bindings; binding; binding = binding->next) {
			if ((addr = ni_c_binding_get_address(binding)) == NULL) {
				ni_error("cannot bind %s name service - invalid C binding",
						binding->name);
				continue;
			}

			ni_debug_objectmodel("trying to bind netif naming service \"%s\"", binding->name);
			ni_objectmodel_register_ns((ni_objectmodel_ns_t *) addr);
		}
	}
}
Exemplo n.º 6
0
/*
 * Change a macvlan/macvtap interface
 */
static dbus_bool_t
__ni_objectmodel_macvlan_change(ni_netdev_t *cfg, ni_netdev_t *dev, DBusError *error)
{
	ni_netconfig_t *nc = ni_global_state_handle(0);
	const char *err;
	ni_macvlan_t *macvlan;
	const char *dev_iftype = NULL;

	macvlan = ni_netdev_get_macvlan(cfg);
	if ((err = ni_macvlan_validate(macvlan))) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err);
		return FALSE;
	}

	if ((cfg->link.lowerdev.index &&
	     (cfg->link.lowerdev.index != dev->link.lowerdev.index)) ||
	    (cfg->link.lowerdev.name &&
	     !ni_string_eq(cfg->link.lowerdev.name, dev->link.lowerdev.name))) {
		const char *cfg_iftype = ni_linktype_type_to_name(cfg->link.type);

		if (cfg->link.lowerdev.name) {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Cannot change %s lower device to %s",
				cfg_iftype, cfg->link.lowerdev.name);
		} else {
			dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Cannot change %s lower device to %u",
				cfg_iftype, cfg->link.lowerdev.index);
		}
		return FALSE;
	}
	cfg->link.lowerdev.index = dev->link.lowerdev.index;
	ni_string_dup(&cfg->link.lowerdev.name, dev->link.lowerdev.name);

	cfg->link.ifindex = dev->link.ifindex;
	if (ni_string_empty(cfg->name))
		ni_string_dup(&cfg->name, dev->name);

	dev_iftype = ni_linktype_type_to_name(dev->link.type);

	if (!macvlan->mode) {
		macvlan->mode = dev->macvlan->mode;
	} else
	if ((macvlan->mode == NI_MACVLAN_MODE_PASSTHRU) !=
	    (dev->macvlan->mode == NI_MACVLAN_MODE_PASSTHRU)) {
		/* Passthrough mode can't be set or cleared dynamically */
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
				"Cannot change %s mode to %s",
			dev_iftype,
			ni_macvlan_mode_to_name(macvlan->mode));
		return FALSE;
	}

	if (ni_netdev_device_is_up(dev)) {
		ni_debug_objectmodel("Skipping %s changeDevice call on %s: "
				"device is up", dev_iftype, dev->name);
		return TRUE;
	}

	if (ni_system_macvlan_change(nc, dev, cfg) < 0) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to change %s properties on interface %s",
			dev_iftype, dev->name);
		return FALSE;
	}

	if (cfg->link.hwaddr.type == ARPHRD_VOID)
		cfg->link.hwaddr.type = ARPHRD_ETHER;
	if (!ni_link_address_is_invalid(&cfg->link.hwaddr) &&
	    ni_system_hwaddr_change(nc, dev, &cfg->link.hwaddr) < 0) {
		ni_error("Unable to change hwaddr on %s interface %s",
			dev_iftype, dev->name);
		/* fail? */
	}

	return TRUE;
}
Exemplo n.º 7
0
static dbus_bool_t
ni_objectmodel_tuntap_change(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_netconfig_t *nc = ni_global_state_handle(0);
	ni_netdev_t *dev, *cfg;
	ni_tuntap_t *tuntap;
	const char *err;
	const char *iftype_name;

	/* we've already checked that argv matches our signature */
	ni_assert(argc == 1);

	if (!(dev = ni_objectmodel_unwrap_netif(object, error)) ||
	    !(cfg = __ni_objectmodel_tuntap_device_arg(&argv[0], dev->link.type)) ||
	    !(ni_netdev_get_tuntap(dev))) {
		ni_dbus_error_invalid_args(error, object->path, method->name);
		return FALSE;
	}

	/* changeDevice method is only needed in case of TAP devices */
	if (dev->link.type != NI_IFTYPE_TAP)
		return TRUE;

	iftype_name = ni_linktype_type_to_name(dev->link.type);

	tuntap = ni_netdev_get_tuntap(cfg);
	if ((err = ni_tuntap_validate(tuntap))) {
		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err);
		return FALSE;
	}

	cfg->link.ifindex = dev->link.ifindex;
	if (ni_string_empty(cfg->name))
		ni_string_dup(&cfg->name, dev->name);

	if (ni_netdev_device_is_up(dev)) {
		ni_debug_objectmodel("Skipping %s changeDevice call on %s: "
				"device is up", iftype_name, dev->name);
		return TRUE;
	}

	if (ni_system_tap_change(nc, dev, cfg) < 0) {
		dbus_set_error(error,
				DBUS_ERROR_FAILED,
				"Unable to change %s properties on interface %s",
				iftype_name, dev->name);
		return FALSE;
	}

	if (cfg->link.hwaddr.type == ARPHRD_VOID)
		cfg->link.hwaddr.type = ARPHRD_ETHER;
	if (ni_system_hwaddr_change(nc, dev, &cfg->link.hwaddr) < 0) {
		ni_error("Unable to change hwaddr on %s interface %s",
				iftype_name, dev->name);
		/* fail? */
	}

	return TRUE;
}