Beispiel #1
0
/*
 * A lease has changed, and we are asked to update the system configuration.
 * When we get here, the old lease has already been removed from the interface,
 * and the new one has been added.
 */
int
ni_system_update_from_lease(const ni_addrconf_lease_t *lease, const unsigned int ifindex, const char *ifname)
{
	ni_bool_t res = TRUE;
	int ret;
	unsigned int kind;

	ni_debug_ifconfig("%s()", __func__);
	ni_system_updaters_init();

	for (kind = 0; kind < __NI_ADDRCONF_UPDATER_MAX; ++kind) {
		if (can_update_type(lease, kind)) {
			ni_updater_t *updater = &updaters[kind];
			ni_updater_source_array_t sources = NI_UPDATER_SOURCE_ARRAY_INIT;

			if (!updater->enabled)
				continue;

			switch(lease->state) {
			case NI_ADDRCONF_STATE_GRANTED:
				if(!ni_system_update_remove_matching_leases(updater, lease, ifindex, ifname)) {
					ni_error("Failed to remove any matching leases. Storing new lease anyway.");
					res = FALSE;
				}
				/* Remove matching leases before we install a new lease.
				 * This is important for hostname updates in the case
				 * where the interface name has changed. If we don't process
				 * the resulting remove before we install, we will remove
				 * the newly installed (or already present) hostname file
				 * and thus restore the hostname to /etc/HOSTNAME.
				 */
				if(!ni_system_updater_install(updater, lease, ifname)) {
					res = FALSE;
				}
				ni_objectmodel_updater_add_source(kind, lease, ifindex, ifname);
				break;
			default:
				if(!ni_system_update_remove_matching_leases(updater, lease, ifindex, ifname)) {
					ni_error("Failed to remove any matching leases. Storing new lease anyway.");
					res = FALSE;
				}
				/* If we no longer have any lease data for this resource, restore
				 * the system default.
				 */
				if (!ni_objectmodel_updater_select_sources(updater, &sources)) {
					if (!ni_system_updater_restore(updater, ifname))
						res = FALSE;
				}

				ni_updater_source_array_destroy(&sources);
				break;
			}
		}
	}

	return ret = res ? 0 : -1;
}
Beispiel #2
0
/*
 * Run all the netif firmware discovery scripts and return their output
 * as one large buffer.
 */
static ni_buffer_t *
__ni_netconfig_firmware_discovery(const char *root, const char *type, const char *path)
{
	ni_buffer_t *result;
	ni_config_t *config = ni_global.config;
	ni_extension_t *ex;

	ni_assert(config);

	result = ni_buffer_new_dynamic(1024);

	for (ex = config->fw_extensions; ex; ex = ex->next) {
		ni_script_action_t *script;

		if (ex->c_bindings)
			ni_warn("builtins specified in a netif-firmware-discovery element: not supported");

		for (script = ex->actions; script; script = script->next) {
			ni_process_t *process;
			int rv;

			/* Check if requested to use specific type/name only (e.g. "ibft") */
			if (type && !ni_string_eq_nocase(type, script->name))
				continue;

			ni_debug_ifconfig("trying to discover netif config via firmware service \"%s\"", script->name);

			/* Create an instance of this command */
			process = ni_process_new(script->process);

			/* Add root directory argument if given */
			if (root) {
				ni_string_array_append(&process->argv, "-r");
				ni_string_array_append(&process->argv, root);
			}

			/* Add firmware type specific path argument if given */
			if (type && path) {
				ni_string_array_append(&process->argv, "-p");
				ni_string_array_append(&process->argv, path);
			}

			rv = ni_process_run_and_capture_output(process, result);
			ni_process_free(process);
			if (rv) {
				ni_error("unable to discover firmware (script \"%s\")",
						script->name);
				ni_buffer_free(result);
				return NULL;
			}
		}
	}

	return result;
}
Beispiel #3
0
ni_bool_t
ni_netdev_load_client_state(ni_netdev_t *dev)
{
	ni_client_state_t cs;

	ni_client_state_init(&cs);
	if (dev && ni_client_state_load(&cs, dev->link.ifindex)) {
		ni_netdev_set_client_state(dev, ni_client_state_clone(&cs));
		ni_debug_ifconfig("loading %s structure from a file for %s",
			NI_CLIENT_STATE_XML_NODE, dev->name);
		return TRUE;
	}

	return FALSE;
}
Beispiel #4
0
/*
 * Run the netif firmware discovery scripts and return their output
 * as an XML document.
 * The optional from parameter allow to specify the firmware extension
 * type (e.g. ibft) and a firmware type specific path (e.g. ethernet0),
 * passed as last argument to the discovery script.
 */
xml_document_t *
ni_netconfig_firmware_discovery(const char *root, const char *from)
{
	ni_buffer_t *buffer;
	xml_document_t *doc;
	char *path = NULL;
	char *type = NULL;

	/* sanity adjustments... */
	if (ni_string_empty(root))
		root = NULL;

	if (ni_string_empty(from))
		from = NULL;
	else {
		ni_string_dup(&type, from);

		if ((path = strchr(type, ':')))
			*path++ = '\0';

		if (ni_string_empty(path))
			path = NULL;
	}

	buffer = __ni_netconfig_firmware_discovery(root, type, path);
	if (buffer == NULL) {
		ni_string_free(&type);
		return NULL;
	}

	ni_debug_ifconfig("%s: %s%sbuffer has %u bytes", __func__,
			(from ? from : ""), (from ? " ": ""),
			ni_buffer_count(buffer));
	doc = xml_document_from_buffer(buffer, from);
	ni_buffer_free(buffer);
	ni_string_free(&type);

	if (doc == NULL)
		ni_error("%s: error processing document", __func__);

	return doc;
}
Beispiel #5
0
static inline int
__ni_wireless_process_wpa1(ni_wireless_network_t *net, void *ptr, size_t len)
{
	static unsigned char wpa1_oui[] = {0x00, 0x50, 0xf2};
	unsigned char buffer[3];
	ni_buffer_t data;

	ni_buffer_init_reader(&data, ptr, len);
	if (ni_buffer_get(&data, buffer, 3) < 0)
		return -1;

	if (memcmp(buffer, wpa1_oui, 3)) {
		ni_debug_ifconfig("skipping non-WPA1 IE (OUI=%02x:%02x:%02x)",
				buffer[0], buffer[1], buffer[0]);
		return 0;
	}

	if (ni_buffer_get(&data, buffer, 1) < 0)
		return -1;
	if (buffer[0] != 0x01)
		return 0;

	return __ni_wireless_process_wpa_common(net, &data, NI_WIRELESS_AUTH_WPA1, wpa1_oui);
}
Beispiel #6
0
/*
 * Remove information from a lease which has been released and already detached
 * from a device.
 */
static ni_bool_t
ni_system_updater_remove(ni_updater_t *updater, const ni_addrconf_lease_t *lease, const char *ifname)
{
	ni_string_array_t arguments = NI_STRING_ARRAY_INIT;
	ni_bool_t result = FALSE;

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

	if (!updater->proc_remove)
		return TRUE;

	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_remove(ifname, lease->type, lease->family);
			break;
		default:
			ni_error("Unsupported %s updater data format.",
				ni_updater_name(updater->kind));
			break;
		}
		break;

	case NI_ADDRCONF_UPDATER_RESOLVER:
	case NI_ADDRCONF_UPDATER_HOSTNAME:
		break;

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

	if (!ni_system_updater_run(updater->proc_remove, &arguments)) {
		ni_error("failed to remove %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:
	ni_string_array_destroy(&arguments);
	return result;
}
Beispiel #7
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;
}