Beispiel #1
0
int
__ni_process_run(ni_process_t *pi, int *pfd)
{
	const char *arg0 = pi->argv.data[0];
	pid_t pid;

	if (pi->pid != 0) {
		ni_error("Cannot execute process instance twice (%s)", pi->process->command);
		return NI_PROCESS_FAILURE;
	}

	if (!ni_file_executable(arg0)) {
		ni_error("Unable to run %s; does not exist or is not executable", arg0);
		return NI_PROCESS_COMMAND;
	}

	signal(SIGCHLD, ni_process_sigchild);

	if ((pid = fork()) < 0) {
		ni_error("%s: unable to fork child process: %m", __func__);
		return NI_PROCESS_FAILURE;
	}
	pi->pid = pid;
	pi->status = -1;

	if (pid == 0) {
		int maxfd;
		int fd;

		if (chdir("/") < 0)
			ni_warn("%s: unable to chdir to /: %m", __func__);

		close(0);
		if ((fd = open("/dev/null", O_RDONLY)) < 0)
			ni_warn("%s: unable to open /dev/null: %m", __func__);
		else if (dup2(fd, 0) < 0)
			ni_warn("%s: cannot dup null descriptor: %m", __func__);

		if (pfd) {
			if (dup2(pfd[1], 1) < 0 || dup2(pfd[1], 2) < 0)
				ni_warn("%s: cannot dup pipe out descriptor: %m", __func__);
		}

		maxfd = getdtablesize();
		for (fd = 3; fd < maxfd; ++fd)
			close(fd);

		/* NULL terminate argv and env lists */
		ni_string_array_append(&pi->argv, NULL);
		ni_string_array_append(&pi->environ, NULL);

		arg0 = pi->argv.data[0];
		execve(arg0, pi->argv.data, pi->environ.data);

		ni_error("%s: cannot execute %s: %m", __func__, arg0);
		exit(127);
	}

	return NI_PROCESS_SUCCESS;
}
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
static int
set_ethtool_priv_flags(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args)
{
	ni_ethtool_priv_flags_t *pflags;
	ni_bool_t enabled;
	char *key, *val;
	int ret = -1, n;

	if (!(pflags = ni_ethtool_priv_flags_new()))
		return ret;

	for (n = 0; n + 1 < args->argc && args->argv[n]; ++n) {
		key = args->argv[n++];
		val = args->argv[n];

		if (ni_parse_boolean(val, &enabled) ||
		    ni_string_array_append(&pflags->names, key))
			goto cleanup;

		if (enabled)
			pflags->bitmap |= NI_BIT(pflags->names.count - 1);
	}

	ret = ni_ethtool_set_priv_flags(ref, ethtool, pflags);

cleanup:
	ni_ethtool_priv_flags_free(pflags);
	return ret;
}
Beispiel #4
0
int
__ni_addrconf_lease_nis_domain_from_xml(ni_nis_info_t *nis, const xml_node_t *node)
{
	const xml_node_t *child;
	ni_nis_domain_t *dom = NULL;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "domain") && child->cdata) {
			if (!(dom = ni_nis_domain_find(nis, child->cdata)))
				dom = ni_nis_domain_new(nis, child->cdata);
			else
				return -1;
		}
	}
	if (dom) {
		for (child = node->children; child; child = child->next) {
			if (ni_string_eq(child->name, "binding") &&
				!ni_string_empty(child->cdata)) {
				int b = ni_nis_binding_name_to_type(child->cdata);
				if (b != -1) {
					dom->binding = (unsigned int)b;
				}
			}
			if (ni_string_eq(child->name, "server")) {
				if (!ni_string_empty(child->cdata)) {
					ni_string_array_append(&dom->servers,
								child->cdata);
				}
			}
		}
	}
	return dom ? 0 : 1;
}
Beispiel #5
0
/*
 * Create a process description
 */
ni_shellcmd_t *
ni_shellcmd_new(const ni_string_array_t *argv)
{
	ni_shellcmd_t *cmd;
	unsigned int i;

	cmd = xcalloc(1, sizeof(*cmd));
	cmd->refcount = 1;
	if (!argv)
		return cmd;

	for (i = 0; i < argv->count; ++i) {
		const char *arg = argv->data[i];

		if (ni_string_empty(arg)) {
			__ni_shellcmd_free(cmd);
			return NULL;
		}

		if (ni_string_array_append(&cmd->argv, arg) < 0) {
			__ni_shellcmd_free(cmd);
			return NULL;
		}
	}

	if (__ni_shellcmd_format(&cmd->command, &cmd->argv) == NULL) {
		__ni_shellcmd_free(cmd);
		return NULL;
	}
	if (ni_string_array_copy(&cmd->environ, __ni_default_environment()) < 0) {
		__ni_shellcmd_free(cmd);
		return NULL;
	}
	return cmd;
}
Beispiel #6
0
/*
 * Scan directory and return all file names matching the given prefix.
 */
int
ni_scandir(const char *dirname, const char *pattern, ni_string_array_t *res)
{
	struct dirent *dp;
	char *copy = NULL;
	const char *match_prefix = NULL;
	const char *match_suffix = NULL;
	unsigned int pfxlen, sfxlen;
	unsigned int count, rv = 0;
	DIR *dir;

	dir = opendir(dirname);
	if (dir == NULL) {
		ni_debug_readwrite("Unable to open directory '%s': %m",
				dirname);
		return 0;
	}

	if (pattern) {
		char *s;

		copy = xstrdup(pattern);
		if ((s = strchr(copy, '*')) == NULL) {
			ni_error("%s: bad pattern \"%s\"", __func__, pattern);
			goto out;
		}
		if (s != copy)
			match_prefix = copy;
		*s++ = '\0';
		if (*s != '\0')
			match_suffix = s;
	}

	count  = res->count;
	pfxlen = match_prefix? strlen(match_prefix) : 0;
	sfxlen = match_suffix? strlen(match_suffix) : 0;
	while ((dp = readdir(dir)) != NULL) {
		const char *name = dp->d_name;

		if (name[0] == '.')
			continue;
		if (pfxlen && strncmp(name, match_prefix, pfxlen))
			continue;
		if (sfxlen != 0) {
			unsigned int namelen = strlen(name);

			if (namelen < pfxlen + sfxlen)
				continue;
			if (strcmp(name + namelen - sfxlen, match_suffix))
				continue;
		}
		ni_string_array_append(res, name);
	}
	rv = res->count - count;

out:
	closedir(dir);
	free(copy);
	return rv;
}
Beispiel #7
0
int
ni_addrconf_lease_nds_data_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node)
{
	const xml_node_t *child;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "tree") && !ni_string_empty(child->cdata)) {
			ni_string_dup(&lease->nds_tree, child->cdata);
		} else
		if (ni_string_eq(child->name, "server") && !ni_string_empty(child->cdata)) {
			ni_string_array_append(&lease->nds_servers, child->cdata);
		} else
		if (ni_string_eq(child->name, "context") && !ni_string_empty(child->cdata)) {
			ni_string_array_append(&lease->nds_context, child->cdata);
		}
	}
	return 0;
}
Beispiel #8
0
ni_bool_t
ni_config_parse_addrconf_dhcp4(struct ni_config_dhcp4 *dhcp4, xml_node_t *node)
{
	xml_node_t *child;

	for (child = node->children; child; child = child->next) {
		const char *attrval;

		if (!strcmp(child->name, "vendor-class"))
			ni_string_dup(&dhcp4->vendor_class, child->cdata);
		if (!strcmp(child->name, "lease-time") && child->cdata)
			dhcp4->lease_time = strtoul(child->cdata, NULL, 0);
		if (!strcmp(child->name, "ignore-server")
		 && (attrval = xml_node_get_attr(child, "ip")) != NULL)
			ni_string_array_append(&dhcp4->ignore_servers, attrval);
		if (!strcmp(child->name, "prefer-server")
		 && (attrval = xml_node_get_attr(child, "ip")) != NULL) {
			ni_server_preference_t *pref;

			if (dhcp4->num_preferred_servers >= NI_DHCP_SERVER_PREFERENCES_MAX) {
				ni_warn("config: too many <prefer-server> elements");
				continue;
			}

			pref = &dhcp4->preferred_server[dhcp4->num_preferred_servers++];
			if (ni_sockaddr_parse(&pref->address, attrval, AF_INET) < 0) {
				ni_error("config: unable to parse <prefer-server ip=\"%s\"",
						attrval);
				return FALSE;
			}

			pref->weight = 100;
			if ((attrval = xml_node_get_attr(child, "weight")) != NULL) {
				if (!strcmp(attrval, "always")) {
					pref->weight = 100;
				} else if (!strcmp(attrval, "never")) {
					pref->weight = -1;
				} else {
					pref->weight = strtol(attrval, NULL, 0);
					if (pref->weight > 100) {
						pref->weight = 100;
						ni_warn("preferred dhcp server weight exceeds max, "
							"clamping to %d",
							pref->weight);
					}
				}
			}
		}
		if (!strcmp(child->name, "allow-update"))
			ni_config_parse_update_targets(&dhcp4->allow_update, child);
	}
	return TRUE;
}
Beispiel #9
0
int
ni_string_array_copy(ni_string_array_t *dst, const ni_string_array_t *src)
{
	unsigned int i;

	ni_string_array_destroy(dst);
	for (i = 0; i < src->count; ++i) {
		if (ni_string_array_append(dst, src->data[i]) < 0)
			return -1;
	}
	return 0;
}
Beispiel #10
0
static int
__ni_string_array_from_xml(ni_string_array_t *array, const char *name, const xml_node_t *node)
{
	const xml_node_t *child;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, name) && !ni_string_empty(child->cdata)) {
			ni_string_array_append(array, child->cdata);
		}
	}
	return 0;
}
Beispiel #11
0
int
ni_addrconf_lease_smb_data_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node)
{
	const xml_node_t *child;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "type") && child->cdata) {
			if (!ni_netbios_node_type_to_code(child->cdata, &lease->netbios_type))
				return -1;
		} else
		if (ni_string_eq(child->name, "scope") && !ni_string_empty(child->cdata)) {
			ni_string_dup(&lease->netbios_scope, child->cdata);
		} else
		if (ni_string_eq(child->name, "name-server") && !ni_string_empty(child->cdata)) {
			ni_string_array_append(&lease->netbios_name_servers, child->cdata);
		} else
		if (ni_string_eq(child->name, "dd-server") && !ni_string_empty(child->cdata)) {
			ni_string_array_append(&lease->netbios_dd_servers, child->cdata);
		}
	}
	return 0;
}
Beispiel #12
0
void
ni_bridge_get_port_names(const ni_bridge_t *bridge, ni_string_array_t *names)
{
	unsigned int i;

	if (!bridge || !names)
		return;
	for (i = 0; i < bridge->ports.count; ++i) {
		ni_bridge_port_t *port = bridge->ports.data[i];
		if (port && port->ifname && *port->ifname)
			ni_string_array_append(names, port->ifname);
	}
}
Beispiel #13
0
int
ni_addrconf_lease_dns_data_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node)
{
	ni_resolver_info_t *dns;
	const xml_node_t *child;

	if (!(dns = ni_resolver_info_new()))
		return -1;

	if (lease->resolver) {
		ni_resolver_info_free(lease->resolver);
		lease->resolver = NULL;
	}

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "domain") &&
				!ni_string_empty(child->cdata)) {
			ni_string_dup(&dns->default_domain, child->cdata);
		} else
		if (ni_string_eq(child->name, "server") &&
				!ni_string_empty(child->cdata)) {
			ni_string_array_append(&dns->dns_servers, child->cdata);
		} else
		if (ni_string_eq(child->name, "search") &&
				!ni_string_empty(child->cdata)) {
			ni_string_array_append(&dns->dns_search, child->cdata);
		}
	}

	if (ni_string_empty(dns->default_domain) &&
			dns->dns_servers.count == 0 &&
			dns->dns_search.count == 0) {
		ni_resolver_info_free(dns);
		return 1;
	}
	lease->resolver = dns;
	return 0;
}
Beispiel #14
0
unsigned int
ni_team_tx_hash_get_bit_names(ni_team_tx_hash_bit_t mask, ni_string_array_t *names)
{
	const ni_intmap_t *map;
	unsigned int n = 0;

	for (map = ni_team_tx_hash_bit_names; map->name; ++map) {
		if (mask & (1 << map->value)) {
			ni_string_array_append(names, map->name);
			n++;
		}
	}
	return n;
}
Beispiel #15
0
ni_bool_t
ni_shellcmd_add_arg(ni_shellcmd_t *cmd, const char *arg)
{
	if (!cmd || ni_string_empty(arg))
		return FALSE;

	if (ni_string_array_append(&cmd->argv, arg) < 0)
		return FALSE;

	if (__ni_shellcmd_format(&cmd->command, &cmd->argv) == NULL)
		return FALSE;

	return TRUE;
}
Beispiel #16
0
int
ni_addrconf_lease_nis_data_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node)
{
	const xml_node_t *child, *gc;
	ni_nis_info_t *nis;

	if (!(nis = ni_nis_info_new()))
		return -1;

	if (lease->nis) {
		ni_nis_info_free(lease->nis);
		lease->nis = NULL;
	}

	nis->default_binding = NI_NISCONF_STATIC;
	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "default")) {
			for (gc = child->children; gc; gc = gc->next) {
				if (ni_string_eq(gc->name, "domain") &&
					!ni_string_empty(gc->cdata)) {
					ni_string_dup(&nis->domainname, gc->cdata);
				} else
				if (ni_string_eq(gc->name, "binding") &&
					ni_string_eq(gc->cdata, "broadcast")) {
					nis->default_binding = NI_NISCONF_BROADCAST;
				} else
				if (ni_string_eq(gc->name, "server") &&
					!ni_string_empty(gc->cdata)) {
					ni_string_array_append(&nis->default_servers,
								gc->cdata);
				}
			}
		} else
		if (ni_string_eq(child->name, "domain")) {
			if (__ni_addrconf_lease_nis_domain_from_xml(nis, child) != 0)
				continue;
		}
	}

	if (nis->default_binding == NI_NISCONF_STATIC &&
	    ni_string_empty(nis->domainname) &&
	    nis->default_servers.count == 0 &&
	    nis->domains.count == 0) {
		ni_nis_info_free(nis);
		return 1;
	}
	lease->nis = nis;
	return 0;
}
Beispiel #17
0
static dbus_bool_t
ni_objectmodel_ethtool_set_priv_flags(ni_dbus_object_t *object,
		const ni_dbus_property_t *property,
		const ni_dbus_variant_t *argument,
		DBusError *error)
{
	const ni_dbus_variant_t *dict;
	ni_ethtool_t *ethtool;
	unsigned int i, len;
	dbus_bool_t enabled;
	ni_stringbuf_t buf;
	const char *name;

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

	ni_ethtool_priv_flags_free(ethtool->priv_flags);
	if (!(ethtool->priv_flags = ni_ethtool_priv_flags_new()))
		return FALSE;

	if ((len = argument->array.len) > 32)
		len = 32;

	ni_stringbuf_init(&buf);
	for (i = 0; i < argument->array.len; ++i) {
		dict = &argument->variant_array_value[i];
		if (!ni_dbus_variant_is_dict(dict))
			continue;

		if (!ni_dbus_dict_get_string(dict, "name", &name) ||
		    !ni_dbus_dict_get_bool(dict, "enabled", &enabled))
			continue;

		ni_stringbuf_put(&buf, name, ni_string_len(name));
		ni_stringbuf_trim_head(&buf, " \t\n");
		ni_stringbuf_trim_tail(&buf, " \t\n");
		if (ni_string_empty(buf.string))
			continue;

		if (ni_string_array_append(&ethtool->priv_flags->names, buf.string) == 0) {
			if (enabled)
				ethtool->priv_flags->bitmap |= NI_BIT(i);
		}
		ni_stringbuf_destroy(&buf);
	}
	return TRUE;
}
Beispiel #18
0
const ni_string_array_t *
ni_config_sources(const char *type)
{
	ni_string_array_t *retval = NULL;
	unsigned int i;

	if (ni_string_eq(type, "ifconfig")) {
		retval = &ni_global.config->sources.ifconfig;
		if (retval->count == 0) {
			for (i = 0; __ni_ifconfig_source_types[i]; i++)
				ni_string_array_append(retval, __ni_ifconfig_source_types[i]);
		}
	}
	return retval;
}
Beispiel #19
0
int
__ni_dhcp6_lease_boot_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node)
{
	xml_node_t *child;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "url") && child->cdata) {
			ni_string_dup(&lease->dhcp6.boot_url, child->cdata);
		} else
		if (ni_string_eq(child->name, "param") && child->cdata) {
			ni_string_array_append(&lease->dhcp6.boot_params, child->cdata);
		}
	}
	return 0;
}
Beispiel #20
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;
}
Beispiel #21
0
static int
ni_dhcp_decode_address_list(ni_buffer_t *bp, ni_string_array_t *list)
{
	while (ni_buffer_count(bp) && !bp->underflow) {
		struct in_addr addr;

		if (ni_dhcp_option_get_ipv4(bp, &addr) < 0)
			return -1;
		ni_string_array_append(list, inet_ntoa(addr));
	}

	if (bp->underflow)
		return -1;

	return 0;
}
Beispiel #22
0
static ni_bool_t
__ni_shellcmd_set_argv(ni_shellcmd_t *cmd, const ni_string_array_t *argv)
{
	unsigned int i;

	for (i = 0; i < argv->count; ++i) {
		const char *arg = argv->data[i];

		if (ni_string_empty(arg))
			return FALSE;

		if (ni_string_array_append(&cmd->argv, arg) < 0)
			return FALSE;
	}

	return __ni_shellcmd_format(&cmd->command, &cmd->argv) != NULL;
}
Beispiel #23
0
static inline int
ni_ethtool_get_priv_flags_names(const char *ifname, ni_ethtool_t *ethtool, ni_string_array_t *names)
{
	struct ethtool_gstrings *gstrings;
	unsigned int count, i;
	ni_stringbuf_t buf;
	const char *name;

	count = ni_ethtool_get_gstring_count(ifname, " priv-flags count", ETH_SS_PRIV_FLAGS);
	if (!count) {
		if (errno == EOPNOTSUPP && ethtool->driver_info)
			count = ethtool->driver_info->supports.n_priv_flags;

		if (!count) {
			ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_GET_PRIV_FLAGS, FALSE);
			return -EOPNOTSUPP;
		}
	}
	if (count > 32)
		count = 32;
	gstrings = ni_ethtool_get_gstrings(ifname, " priv-flags names", ETH_SS_PRIV_FLAGS, count);
	if (!gstrings) {
		if (errno == EOPNOTSUPP)
			ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_GET_PRIV_FLAGS, FALSE);
		free(gstrings);
		return errno ? -errno : -1;
	}

	ni_stringbuf_init(&buf);
	for (i = 0; i < gstrings->len; ++i) {
		name = (const char *)(gstrings->data + i * ETH_GSTRING_LEN);
		ni_stringbuf_put(&buf, name, ETH_GSTRING_LEN);
		ni_stringbuf_trim_head(&buf, " \t\n");
		ni_stringbuf_trim_tail(&buf, " \t\n");
		ni_string_array_append(names, buf.string);
		ni_stringbuf_destroy(&buf);
	}
	free(gstrings);

	if (names->count == count)
		return 0;

	ni_string_array_destroy(names);
	return -ENOMEM; /* array append */
}
Beispiel #24
0
/*
 * This specifies sources of client configuration.
 *
 * The ifconfig source specifies the type, location and the
 * priority / load order of the interface configurations.
 *
 * <sources>
 *   <ifconfig location="firmware:" />
 *   <ifconfig location="compat:" />
 *   <ifconfig location="wicked:/etc/wicked/ifconfig" />
 * </sources>
 *
 */
static ni_bool_t
__ni_config_parse_ifconfig_source(ni_string_array_t *sources, xml_node_t *node)
{
	const char *attrval = NULL;
	unsigned int i;

	if ((attrval = xml_node_get_attr(node, "location")) != NULL && *attrval) {
		const char **p = __ni_ifconfig_source_types;
		for (i = 0; p[i]; i++) {
			if (!strncasecmp(attrval, p[i], ni_string_len(p[i]))) {
				ni_debug_readwrite("%s: Adding ifconfig %s", __func__, attrval);
				ni_string_array_append(sources, attrval);
				return TRUE;
			}
		}
	}

	ni_error("Unknown ifconfig location: %s", attrval);
	return FALSE;
}
Beispiel #25
0
/*
 * link-settings
 */
static inline ni_bool_t
get_ethtool_link_adv_name_array(ni_string_array_t *array, ni_bitfield_t *bitfield,
				const char * (*bit_to_name)(unsigned int))
{
	unsigned int bit, bits, count;
	const char *name;

	count = array->count;
	bits = ni_bitfield_bits(bitfield);
	for (bit = 0; bit < bits; ++bit) {
		if (!ni_bitfield_testbit(bitfield, bit))
			continue;

		if (!(name = bit_to_name(bit)))
			continue;

		if (ni_string_array_append(array, name) == 0)
			ni_bitfield_clearbit(bitfield, bit);
	}
	return array->count > count;
}
Beispiel #26
0
static dbus_bool_t
ni_objectmodel_ethtool_link_adv_bitfield_into_array(ni_string_array_t *array,
		ni_bitfield_t *bitfield, const char * (*bit_to_name)(unsigned int))
{
	/* we're using a temporary string array (instead
	 * of direct ni_dbus_variant_append_string_array)
	 * to omit empty dbus dict array entries... */
	unsigned int bit, bits;
	const char *name;

	bits = ni_bitfield_bits(bitfield);
	for (bit = 0; bit < bits; ++bit) {
		if (!ni_bitfield_testbit(bitfield, bit))
			continue;

		if (!(name = bit_to_name(bit)))
			continue;

		if (ni_string_array_append(array, name) == 0)
			ni_bitfield_clearbit(bitfield, bit);
	}
	return array->count > 0;
}
Beispiel #27
0
/*
 * Setting environment variables
 */
static void
__ni_process_setenv(ni_string_array_t *env, const char *name, const char *value)
{
	unsigned int namelen = strlen(name), totlen;
	unsigned int i;
	char *newvar;

	totlen = namelen + strlen(value) + 2;
	newvar = malloc(totlen);
	snprintf(newvar, totlen, "%s=%s", name, value);

	for (i = 0; i < env->count; ++i) {
		char *oldvar = env->data[i];

		if (!strncmp(oldvar, name, namelen) && oldvar[namelen] == '=') {
			env->data[i] = newvar;
			free(oldvar);
			return;
		}
	}

	ni_string_array_append(env, newvar);
	free(newvar);
}
Beispiel #28
0
/*
 * Run an extension script to update resolver, hostname etc.
 */
static ni_bool_t
ni_system_updater_run(ni_shellcmd_t *shellcmd, ni_string_array_t *args)
{
	ni_process_t *pi;
	int rv;

	pi = ni_process_new(shellcmd);
	if (args) {
		unsigned int i;

		for (i = 0; i < args->count; ++i) {
			const char *arg = args->data[i];

			if (arg == NULL)
				arg = "";
			ni_string_array_append(&pi->argv, arg);
		}
	}

	rv = ni_process_run_and_wait(pi);
	ni_process_free(pi);

	return rv >= 0;
}
Beispiel #29
0
unsigned int
ni_string_split(ni_string_array_t *nsa, const char *str, const char *sep,
		unsigned int limit)
{
	unsigned int count;
	char *tmp, *s, *p = NULL;

	if (nsa == NULL || ni_string_len(sep) == 0 || ni_string_len(str) == 0)
		return 0;

	if ((tmp = strdup(str)) == NULL)
		return 0;

	count = nsa->count;

	for (s = strtok_r(tmp, sep, &p); s; s = strtok_r(NULL, sep, &p)) {
		if (limit && (nsa->count - count) >= limit)
			break;
		ni_string_array_append(nsa, s);
	}
	free(tmp);

	return nsa->count - count;
}
Beispiel #30
0
int
ni_do_ifdown(int argc, char **argv)
{
	enum  { OPT_HELP, OPT_FORCE, OPT_DELETE, OPT_NO_DELETE, OPT_TIMEOUT };
	static struct option ifdown_options[] = {
		{ "help",	no_argument, NULL,		OPT_HELP },
		{ "force",	required_argument, NULL,	OPT_FORCE },
		{ "delete",	no_argument, NULL,	OPT_DELETE },
		{ "no-delete",	no_argument, NULL,	OPT_NO_DELETE },
		{ "timeout",	required_argument, NULL,	OPT_TIMEOUT },
		{ NULL }
	};
	ni_ifmatcher_t ifmatch;
	ni_ifmarker_t ifmarker;
	ni_ifworker_array_t ifmarked;
	ni_string_array_t ifnames = NI_STRING_ARRAY_INIT;
	unsigned int nmarked, max_state = NI_FSM_STATE_DEVICE_DOWN;
	unsigned int timeout = NI_IFWORKER_DEFAULT_TIMEOUT;
	ni_stringbuf_t sb = NI_STRINGBUF_INIT_DYNAMIC;
	ni_fsm_t *fsm;
	int c, status = NI_WICKED_RC_USAGE;

	fsm = ni_fsm_new();
	ni_assert(fsm);
	ni_fsm_require_register_type("reachable", ni_ifworker_reachability_check_new);

	/* Allow ifdown only on non-persistent interfaces previously configured by ifup */
	memset(&ifmatch, 0, sizeof(ifmatch));
	memset(&ifmarker, 0, sizeof(ifmarker));
	memset(&ifmarked, 0, sizeof(ifmarked));

	ifmatch.require_configured = TRUE;
	ifmatch.allow_persistent = FALSE;
	ifmatch.require_config = FALSE;

	ifmarker.target_range.min = NI_FSM_STATE_DEVICE_DOWN;
	ifmarker.target_range.max = __NI_FSM_STATE_MAX - 2;

	optind = 1;
	while ((c = getopt_long(argc, argv, "", ifdown_options, NULL)) != EOF) {
		switch (c) {
		case OPT_FORCE:
			if (!ni_ifworker_state_from_name(optarg, &max_state) ||
			    !ni_ifworker_state_in_range(&ifmarker.target_range, max_state)) {
				ni_error("ifdown: wrong force option \"%s\"", optarg);
				goto usage;
			}
			/* Allow ifdown on persistent, unconfigured interfaces */
			ifmatch.require_configured = FALSE;
			ifmatch.allow_persistent = TRUE;
			ifmatch.require_config = FALSE;
			break;

		case OPT_DELETE:
			max_state = NI_FSM_STATE_DEVICE_DOWN;
			/* Allow ifdown on persistent, unconfigured interfaces */
			ifmatch.require_configured = FALSE;
			ifmatch.allow_persistent = TRUE;
			ifmatch.require_config = FALSE;
			break;

		case OPT_NO_DELETE:
			max_state = NI_FSM_STATE_DEVICE_READY;
			/* Allow ifdown only on non-persistent interfaces previously configured by ifup */
			ifmatch.require_configured = TRUE;
			ifmatch.allow_persistent = FALSE;
			ifmatch.require_config = FALSE;
			break;

		case OPT_TIMEOUT:
			if (!strcmp(optarg, "infinite")) {
				timeout = NI_IFWORKER_INFINITE_TIMEOUT;
			} else if (ni_parse_uint(optarg, &timeout, 10) >= 0) {
				timeout *= 1000; /* sec -> msec */
			} else {
				ni_error("ifdown: cannot parse timeout option \"%s\"", optarg);
				goto usage;
			}
			break;

		default:
		case OPT_HELP:
usage:
			ni_client_get_state_strings(&sb, &ifmarker.target_range);
			fprintf(stderr,
				"wicked [options] ifdown [ifdown-options] <ifname ...>|all\n"
				"\nSupported ifdown-options:\n"
				"  --help\n"
				"      Show this help text.\n"
				"  --force <state>\n"
				"      Force putting interface into the <state> state. Despite of persistent mode being set. Possible states:\n"
				"  %s\n"
				"  --delete\n"
				"      Delete device. Despite of persistent mode being set\n"
				"  --no-delete\n"
				"      Do not attempt to delete a device, neither physical nor virtual\n"
				"  --timeout <nsec>\n"
				"      Timeout after <nsec> seconds\n",
				sb.string
				);
			ni_stringbuf_destroy(&sb);
			return status;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing interface argument\n");
		goto usage;
	}

	ifmarker.target_range.min = NI_FSM_STATE_NONE;
	ifmarker.target_range.max = max_state;

	fsm->worker_timeout = ni_fsm_find_max_timeout(fsm, timeout);

	if (!ni_fsm_create_client(fsm)) {
		/* Severe error we always explicitly return */
		return NI_WICKED_RC_ERROR;
	}

	if (!ni_fsm_refresh_state(fsm)) {
		/* Severe error we always explicitly return */
		return NI_WICKED_RC_ERROR;
	}

	/* Get workers that match given criteria */
	nmarked = 0;
	while (optind < argc) {
		ifmatch.name = argv[optind++];
		ifmatch.ifdown = TRUE;
		ni_fsm_get_matching_workers(fsm, &ifmatch, &ifmarked);

		if (ni_string_eq(ifmatch.name, "all") ||
		    ni_string_empty(ifmatch.name)) {
			ni_string_array_destroy(&ifnames);
			break;
		}

		if (ni_string_array_index(&ifnames, ifmatch.name) == -1)
			ni_string_array_append(&ifnames, ifmatch.name);
	}

	/* Mark and start selected workers */
	if (ifmarked.count) {
		if (ni_config_use_nanny()) {
			/* Disable devices and delete all related policies from nanny */
			ni_ifdown_fire_nanny(&ifmarked);
		}

		/* Start workers to perform actual ifdown */
		nmarked = ni_fsm_mark_matching_workers(fsm, &ifmarked, &ifmarker);
	}

	if (nmarked == 0) {
		ni_note("ifdown: no matching interfaces");
		status = NI_WICKED_RC_SUCCESS;
	} else {
		if (ni_fsm_schedule(fsm) != 0)
			ni_fsm_mainloop(fsm);

		status = ni_ifstatus_shutdown_result(fsm, &ifnames, &ifmarked);
	}

	ni_string_array_destroy(&ifnames);
	ni_ifworker_array_destroy(&ifmarked);
	return status;
}