예제 #1
0
파일: ethtool.c 프로젝트: openSUSE/wicked
static int
set_ethtool_ring(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args)
{
	ni_ethtool_ring_t *ring;
	char *key = NULL, *val = NULL;
	int ret = -1, n;

	if (!(ring = ni_ethtool_ring_new()))
		return ret;

	for (n = 0; n < args->argc && args->argv[n]; ++n) {
		key = args->argv[n++];
		if (n < args->argc)
			val = args->argv[n];
		else
			break;
		if (ni_string_eq(key, "tx")) {
			ni_parse_uint(val, &ring->tx, 10);
		} else
		if (ni_string_eq(key, "rx")) {
			ni_parse_uint(val, &ring->rx, 10);
		} else
		if (ni_string_eq(key, "rx-jumbo") ||
				ni_string_eq(key, "rx_jumbo")) {
			ni_parse_uint(val, &ring->rx_jumbo, 10);
		} else
		if (ni_string_eq(key, "rx-mini") ||
				ni_string_eq(key, "rx_mini")) {
			ni_parse_uint(val, &ring->rx_mini, 10);
		} else {
			val = key;
			key = NULL;
			break;
		}

		key = NULL;
		val = NULL;
	}

	if (key) {
		if (val)
			fprintf(stderr, "%s: cannot parse ring '%s' argument '%s'\n",
					ref->name, key, val);
		else
			fprintf(stderr, "%s: missing ring '%s' value argument\n",
					ref->name, key);
	} else {
		if (val)
			fprintf(stderr, "%s: unknown ring setting name '%s'\n",
					ref->name, val);
		else
			ret = ni_ethtool_set_ring(ref, ethtool, ring);
	}
	ni_ethtool_ring_free(ring);
	return ret;
}
예제 #2
0
파일: lease.c 프로젝트: nirmoy/wicked
static int
__ni_dhcp6_lease_ia_data_from_xml(ni_dhcp6_ia_t *ia, const xml_node_t *node)
{
	const char *iadr_name;
	const xml_node_t *child;
	ni_dhcp6_ia_addr_t *iadr;
	int ret;

	if (ia->type == NI_DHCP6_OPTION_IA_PD) {
		iadr_name = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_PREFIX);
	} else {
		iadr_name = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_ADDRESS);
	}

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "interface-id")) {
			if (ni_parse_uint(child->cdata, &ia->iaid, 10) !=  0)
				return -1;
		} else
		if (ni_string_eq(child->name, "acquired")) {
			int64_t acquired;

			if (ni_parse_int64(child->cdata, &acquired, 10))
				return -1;

			ia->acquired.tv_sec = acquired;
			ia->acquired.tv_usec = 0;
		} else
		if (ni_string_eq(child->name, "renewal-time") &&
		    ia->type != NI_DHCP6_OPTION_IA_TA) {
			if (ni_parse_uint(child->cdata, &ia->renewal_time, 10) != 0)
				return -1;
		} else
		if (ni_string_eq(child->name, "rebind-time") &&
		    ia->type != NI_DHCP6_OPTION_IA_TA) {
			if (ni_parse_uint(child->cdata, &ia->rebind_time, 10) != 0)
				return -1;
		} else
		if (ni_string_eq(child->name, iadr_name)) {
			iadr = ni_dhcp6_ia_addr_new(in6addr_any, 0);
			ret = __ni_dhcp6_lease_ia_addr_from_xml(iadr, ia->type, child);
			if (ret) {
				ni_dhcp6_ia_addr_free(iadr);
				if (ret < 0)
					return ret;
			} else {
				ni_dhcp6_ia_addr_list_append(&ia->addrs, iadr);
			}
		} else
		if (ni_string_eq(child->name, "status")) {
			if (__ni_dhcp6_lease_status_from_xml(&ia->status, child) < 0)
				return -1;
		}
	}
	return 0;
}
예제 #3
0
파일: ethtool.c 프로젝트: openSUSE/wicked
static int
set_ethtool_channels(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args)
{
	ni_ethtool_channels_t *channels;
	char *key = NULL, *val = NULL;
	int ret = -1, n;

	if (!(channels = ni_ethtool_channels_new()))
		return ret;

	for (n = 0; n < args->argc && args->argv[n]; ++n) {
		key = args->argv[n++];
		if (n < args->argc)
			val = args->argv[n];
		else
			break;
		if (ni_string_eq(key, "tx")) {
			ni_parse_uint(val, &channels->tx, 10);
		} else
		if (ni_string_eq(key, "rx")) {
			ni_parse_uint(val, &channels->rx, 10);
		} else
		if (ni_string_eq(key, "other")) {
			ni_parse_uint(val, &channels->other, 10);
		} else
		if (ni_string_eq(key, "combined")) {
			ni_parse_uint(val, &channels->combined, 10);
		} else {
			val = key;
			key = NULL;
			break;
		}

		key = NULL;
		val = NULL;
	}

	if (key) {
		if (val)
			fprintf(stderr, "%s: cannot parse channels '%s' argument '%s'\n",
					ref->name, key, val);
		else
			fprintf(stderr, "%s: missing channels '%s' value argument\n",
					ref->name, key);
	} else {
		if (val)
			fprintf(stderr, "%s: unknown channels setting name '%s'\n",
					ref->name, val);
		else
			ret = ni_ethtool_set_channels(ref, ethtool, channels);
	}
	ni_ethtool_channels_free(channels);
	return ret;
}
예제 #4
0
파일: lease.c 프로젝트: nirmoy/wicked
static int
__ni_dhcp6_lease_ia_addr_from_xml(ni_dhcp6_ia_addr_t *iadr, unsigned int type,
					const xml_node_t *node)
{
	const xml_node_t *child;
	const char *name;
	ni_sockaddr_t addr;
	unsigned int value;

	name = (type == NI_DHCP6_OPTION_IA_PD) ? "prefix" : "address";
	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, name) && child->cdata) {
			if (type == NI_DHCP6_OPTION_IA_PD) {
				if (!ni_sockaddr_prefix_parse(child->cdata,
							&addr, &value)
					|| value == 0 || value > 128
					|| addr.ss_family != AF_INET6)
					return -1;
				iadr->addr = addr.six.sin6_addr;
				iadr->plen = value;
			} else {
				if (ni_sockaddr_parse(&addr, child->cdata,
							AF_INET6) != 0)
					return -1;
				iadr->addr = addr.six.sin6_addr;
				iadr->plen = 0;
			}
		} else
		if (ni_string_eq(child->name, "preferred-lft") && child->cdata) {
			if (ni_parse_uint(child->cdata, &value, 10) != 0)
				return -1;
			iadr->preferred_lft = value;
		} else
		if (ni_string_eq(child->name, "valid-lft") && child->cdata) {
			if (ni_parse_uint(child->cdata, &value, 10) != 0)
				return -1;
			iadr->valid_lft = value;
		} else
		if (ni_string_eq(child->name, "status")) {
			if (__ni_dhcp6_lease_status_from_xml(&iadr->status, child) < 0)
				return -1;
		}
	}

	ni_sockaddr_set_ipv6(&addr, iadr->addr, 0);
	if (ni_sockaddr_is_ipv6_specified(&addr))
		return 0;
	else
		return 1;
}
예제 #5
0
/*
 * Extract interface index from object path.
 * Path names must be NI_OBJECTMODEL_OBJECT_PATH "/" <something> "/Interface/" <index>
 */
static ni_netdev_t *
ni_objectmodel_addrconf_path_to_device(const char *path)
{
	unsigned int ifindex;
	ni_netconfig_t *nc;
	char cc;

	if (strncmp(path, NI_OBJECTMODEL_OBJECT_PATH, strlen(NI_OBJECTMODEL_OBJECT_PATH)))
		return NULL;
	path += strlen(NI_OBJECTMODEL_OBJECT_PATH);

	if (*path++ != '/')
		return NULL;
	while ((cc = *path++) != '/') {
		if (cc == '\0')
			return NULL;
	}

	if (strncmp(path, "Interface/", 10))
		return NULL;
	path += 10;

	if (ni_parse_uint(path, &ifindex, 10) < 0)
		return NULL;

	nc = ni_global_state_handle(1);
	if (nc == NULL) {
		ni_error("%s: unable to refresh interfaces", __func__);
		return NULL;
	}

	return ni_netdev_by_index(nc, ifindex);
}
예제 #6
0
파일: ethtool.c 프로젝트: openSUSE/wicked
static int
set_ethtool_eee(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args)
{
	ni_ethtool_eee_t *eee;
	char *key = NULL, *val = NULL;
	ni_bool_t enabled;
	int ret = -1, n;

	if (!(eee = ni_ethtool_eee_new()))
		return ret;

	for (n = 0; n < args->argc && args->argv[n]; ++n) {
		key = args->argv[n++];
		if (n < args->argc)
			val = args->argv[n];
		else
			break;
		if (ni_string_eq(key, "eee")) {
			if (ni_parse_boolean(val, &enabled) != 0)
				break;
			ni_tristate_set(&eee->status.enabled, enabled);
		} else
		if (ni_string_eq(key, "tx-lpi")) {
			if (ni_parse_boolean(val, &enabled) != 0)
				break;
			ni_tristate_set(&eee->tx_lpi.enabled, enabled);
		} else
		if (ni_string_eq(key, "tx-timer")) {
			ni_parse_uint(val, &eee->tx_lpi.timer, 10);
		} else
		if (ni_string_eq(key, "advertise")) {
			if (!set_ethtool_link_advertise(val, &eee->speed.advertising))
				break;
		} else {
			val = key;
			key = NULL;
			break;
		}

		key = NULL;
		val = NULL;
	}

	if (key) {
		if (val)
			fprintf(stderr, "%s: cannot parse eee '%s' argument '%s'\n",
					ref->name, key, val);
		else
			fprintf(stderr, "%s: missing eee '%s' value argument\n",
					ref->name, key);
	} else {
		if (val)
			fprintf(stderr, "%s: unknown eee setting name '%s'\n",
					ref->name, val);
		else
			ret = ni_ethtool_set_eee(ref, ethtool, eee);
	}
	ni_ethtool_eee_free(eee);
	return ret;
}
예제 #7
0
파일: iaid.c 프로젝트: mtomaschewski/wicked
static ni_bool_t
ni_iaid_map_node_to_iaid(const xml_node_t *node, unsigned int *iaid)
{
	if (!node || !iaid)
		return FALSE;

	return ni_parse_uint(node->cdata, iaid, 0) == 0;
}
예제 #8
0
파일: naming.c 프로젝트: gsanso/wicked
static ni_bool_t
__match_uint(unsigned int device_value, const char *query_string)
{
	unsigned int query_value;

	if (ni_parse_uint(query_string, &query_value, 0) < 0)
		return FALSE;
	return device_value == query_value;
}
예제 #9
0
파일: leasefile.c 프로젝트: gsanso/wicked
/*
 * utils to parse lease or a lease data group from xml
 */
static int
__ni_addrconf_lease_info_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node)
{
	ni_bool_t update = FALSE;
	xml_node_t *child;
	int value;

	if (!lease || !node)
		return -1;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "family")) {
			if ((value = ni_addrfamily_name_to_type(child->cdata)) == -1)
				return -1;
			lease->family = value;
		} else
		if (ni_string_eq(child->name, "type")) {
			if ((value = ni_addrconf_name_to_type(child->cdata)) == -1)
				return -1;
			lease->type = value;
		} else
		if (ni_string_eq(child->name, "owner")) {
			if (!ni_string_empty(child->cdata))
				ni_string_dup(&lease->owner, child->cdata);
		} else
		if (ni_string_eq(child->name, "uuid")) {
			if (ni_uuid_parse(&lease->uuid, child->cdata) != 0)
				return -1;
		} else
		if (ni_string_eq(child->name, "update")) {
			if (ni_parse_uint(child->cdata, &lease->update, 16) != 0)
				return -1;
			update = TRUE;
		}
		if (ni_string_eq(child->name, "acquired")) {
			if (ni_parse_uint(child->cdata, &lease->time_acquired, 10) != 0)
				return -1;
		}
	}
	if (!update)
		lease->update = ni_config_addrconf_update_mask(lease->type, lease->family);

	return 0;
}
예제 #10
0
파일: config.c 프로젝트: mijos/wicked
void
ni_config_parse_fslocation(ni_config_fslocation_t *fsloc, xml_node_t *node)
{
	const char *attrval;

	if ((attrval = xml_node_get_attr(node, "path")) != NULL)
		ni_string_dup(&fsloc->path, attrval);
	if ((attrval = xml_node_get_attr(node, "mode")) != NULL)
		ni_parse_uint(attrval, &fsloc->mode, 8);
}
예제 #11
0
ni_bool_t
xml_node_get_attr_uint(const xml_node_t *node, const char *name, unsigned int *valp)
{
	const char *value;

	if (!valp || !(value = xml_node_get_attr(node, name)))
		return FALSE;

	if (ni_parse_uint(value, valp, 10) < 0)
		return FALSE;

	return TRUE;
}
예제 #12
0
파일: util.c 프로젝트: okirch/testbus
int
ni_parse_uint_maybe_mapped(const char *input, const ni_intmap_t *map, unsigned int *result, int base)
{
	if (!map || !input || !result)
		return -1;

	if (ni_parse_uint_mapped(input, map, result) == 0)
		return 0;

	if (ni_parse_uint(input, result, base) < 0)
		return -1;

	if (ni_format_uint_mapped(*result, map) == NULL)
		return 1;

	return 0;
}
예제 #13
0
파일: lease.c 프로젝트: nirmoy/wicked
/*
 * dhcp6 lease data from xml
 */
static int
__ni_dhcp6_lease_status_from_xml(ni_dhcp6_status_t *status, const xml_node_t *node)
{
	const xml_node_t *child;
	unsigned int value;

	ni_dhcp6_status_clear(status);
	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "code")) {
			if (ni_parse_uint(child->cdata, &value, 10) != 0
					|| value > 0xffff)
				return -1;
			status->code = value;
		} else
		if (ni_string_eq(child->name, "message") && child->cdata) {
			ni_string_dup(&status->message, child->cdata);
		}
	}
	return 0;
}
예제 #14
0
파일: ethtool.c 프로젝트: openSUSE/wicked
static int
set_ethtool_link_settings(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args)
{
	ni_ethtool_link_settings_t *link;
	char *key = NULL, *val = NULL;
	unsigned int value;
	ni_bool_t enabled;
	int ret = -1, n;

	if (!(link = ni_ethtool_link_settings_new()))
		return ret;

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

		if (ni_string_eq(key, "autoneg")) {
			if (ni_parse_boolean(val, &enabled) != 0)
				break;
			ni_tristate_set(&link->autoneg, enabled);
		} else
		if (ni_string_eq(key, "speed")) {
			if (ni_parse_uint(val, &value, 10) != 0)
				break;
			link->speed = value;
		} else
		if (ni_string_eq(key, "duplex")) {
			if (!ni_ethtool_link_duplex_type(val, &value))
				break;
			link->duplex = value;
		} else
		if (ni_string_eq(key, "port")) {
			if (!ni_ethtool_link_port_type(val, &value))
				break;
			link->port = value;
		} else
		if (ni_string_eq(key, "mdix")) {
			if (!ni_ethtool_link_mdix_type(val, &value))
				break;
			link->tp_mdix = value;
		} else
		if (ni_string_eq(key, "phy-address")) {
			if (ni_parse_uint(val, &value, 10) != 0)
				break;
			link->phy_address = value;
		} else
		if (ni_string_eq(key, "transceiver")) {
			if (!ni_ethtool_link_xcvr_type(val, &value))
				break;
			link->transceiver = value;
		} else
		if (ni_string_eq(key, "advertise")) {
			if (!set_ethtool_link_advertise(val, &link->advertising))
				break;
		} else {
			val = key;
			key = NULL;
			break;
		}

		key = NULL;
		val = NULL;
	}

	if (key) {
		if (val)
			fprintf(stderr, "%s: cannot parse link '%s' argument '%s'\n",
					ref->name, key, val);
		else
			fprintf(stderr, "%s: missing link '%s' value argument\n",
					ref->name, key);
	} else {
		if (val)
			fprintf(stderr, "%s: unknown link setting name '%s'\n",
					ref->name, val);
		else
			ret = ni_ethtool_set_link_settings(ref, ethtool, link);
	}
	ni_ethtool_link_settings_free(link);
	return ret;
}
예제 #15
0
파일: lease.c 프로젝트: nirmoy/wicked
int
ni_dhcp6_lease_data_from_xml(ni_addrconf_lease_t *lease, const xml_node_t *node, const char *ifname)
{
	const char *ia_na_name = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_NA);
	const char *ia_ta_name = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_TA);
	const char *ia_pd_name = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_PD);
	unsigned int value;
	ni_sockaddr_t addr;
	xml_node_t *child;

	if (!lease || !node)
		return -1;

	lease->dhcp6.rapid_commit = FALSE;
	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "client-id") && child->cdata) {
			if (!ni_duid_parse_hex(&lease->dhcp6.client_id, child->cdata))
				return -1;
		} else
		if (ni_string_eq(child->name, "server-id") && child->cdata) {
			if (!ni_duid_parse_hex(&lease->dhcp6.server_id, child->cdata))
				return -1;
		} else
		if (ni_string_eq(child->name, "server-address") && child->cdata) {
			if (ni_sockaddr_parse(&addr, child->cdata, AF_INET6) < 0)
				return -1;
			lease->dhcp6.server_addr = addr.six.sin6_addr;
		} else
		if (ni_string_eq(child->name, "server-preference") && child->cdata) {
			if (ni_parse_uint(child->cdata, &value, 10) != 0 || value > 255)
				return -1;
			lease->dhcp6.server_pref = value;
		} else
		if (ni_string_eq(child->name, "rapid-commit")) {
			lease->dhcp6.rapid_commit = TRUE;
		} else
		if (ni_string_eq(child->name, "hostname") && child->cdata) {
			ni_string_dup(&lease->hostname, child->cdata);
		}

		if (ni_string_eq(child->name, ia_na_name)) {
			if (__ni_dhcp6_lease_ia_type_from_xml(&lease->dhcp6.ia_list,
						NI_DHCP6_OPTION_IA_NA, child) < 0)
				return -1;
		} else
		if (ni_string_eq(child->name, ia_ta_name)) {
			if (__ni_dhcp6_lease_ia_type_from_xml(&lease->dhcp6.ia_list,
						NI_DHCP6_OPTION_IA_TA, child) < 0)
				return -1;
		} else
		if (ni_string_eq(child->name, ia_pd_name)) {
			if (__ni_dhcp6_lease_ia_type_from_xml(&lease->dhcp6.ia_list,
						NI_DHCP6_OPTION_IA_PD, child) < 0)
				return -1;
		} else

		if (ni_string_eq(child->name, "boot")) {
			if (__ni_dhcp6_lease_boot_from_xml(lease, child) < 0)
				return -1;
		} else

		if (ni_string_eq(child->name, NI_ADDRCONF_LEASE_XML_DNS_DATA_NODE)) {
			if (ni_addrconf_lease_dns_data_from_xml(lease, child, ifname) < 0)
				return -1;
		} else
		if (ni_string_eq(child->name, NI_ADDRCONF_LEASE_XML_NTP_DATA_NODE)) {
			if (ni_addrconf_lease_ntp_data_from_xml(lease, child, ifname) < 0)
				return -1;
		} else
		if (ni_string_eq(child->name, NI_ADDRCONF_LEASE_XML_SIP_DATA_NODE)) {
			if (ni_addrconf_lease_sip_data_from_xml(lease, child, ifname) < 0)
				return -1;
		} else
		if (ni_string_eq(child->name, NI_ADDRCONF_LEASE_XML_PTZ_DATA_NODE)) {
			if (ni_addrconf_lease_ptz_data_from_xml(lease, child, ifname) < 0)
				return -1;
		} else
		if (ni_string_eq(child->name, NI_ADDRCONF_LEASE_XML_OPTS_DATA_NODE)) {
			if (ni_addrconf_lease_opts_data_from_xml(lease, child, ifname) < 0)
				return -1;
		}
	}
	return 0;
}
예제 #16
0
파일: tester.c 프로젝트: kmroz/wicked
static ni_bool_t
dhcp4_tester_req_xml_init(ni_dhcp4_request_t *req, xml_document_t *doc)
{
	xml_node_t *xml, *child;
	const char *type;

	xml = xml_document_root(doc);
	if (xml && !xml->name && xml->children)
		xml = xml->children;

	if (!xml || !ni_string_eq(xml->name, "request")) {
		ni_error("Invalid dhcp4 request xml '%s'",
				xml ? xml_node_location(xml) : NULL);
		return FALSE;
	}

	type = xml_node_get_attr(xml, "type");
	if (ni_string_eq(type, "offer")) {
		req->dry_run = NI_DHCP4_RUN_OFFER;
	} else
	if (ni_string_eq(type, "lease")) {
		req->dry_run = NI_DHCP4_RUN_LEASE;
	}

	for (child = xml->children; child; child = child->next) {
		if (ni_string_eq(child->name, "uuid")) {
			if (ni_uuid_parse(&req->uuid, child->cdata) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "acquire-timeout")) {
			if (ni_parse_uint(child->cdata, &req->acquire_timeout, 10) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "hostname")) {
			if (!ni_check_domain_name(child->cdata, ni_string_len(child->cdata), 0))
				goto failure;
			ni_string_dup(&req->hostname, child->cdata);
		} else
		if (ni_string_eq(child->name, "clientid")) {
			ni_opaque_t duid;

			if (ni_parse_hex(child->cdata, duid.data, sizeof(duid.data)) <= 0)
				goto failure;
			ni_string_dup(&req->clientid, child->cdata);
		} else
		if(ni_string_eq(child->name, "start-delay")) {
			if (ni_parse_uint(child->cdata, &req->start_delay, 10) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "lease-time")) {
			if (ni_parse_uint(child->cdata, &req->lease_time, 10) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "recover-lease")) {
			if (ni_parse_boolean(child->cdata, &req->recover_lease) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "release-lease")) {
			if (ni_parse_boolean(child->cdata, &req->release_lease) != 0)
				goto failure;
		}
	}

	return TRUE;
failure:
	if (child) {
		ni_error("Cannot parse dhcp4 request '%s': %s",
				child->name, xml_node_location(child));
	}
	return FALSE;
}
예제 #17
0
int
ni_do_ifreload(int argc, char **argv)
{
	enum  { OPT_HELP, OPT_IFCONFIG, OPT_PERSISTENT, OPT_TRANSIENT,
#ifdef NI_TEST_HACKS
		OPT_IGNORE_PRIO, OPT_IGNORE_STARTMODE,
#endif
	};

	static struct option ifreload_options[] = {
		{ "help",	no_argument,       NULL, OPT_HELP       },
		{ "transient", 	no_argument,       NULL, OPT_TRANSIENT },
		{ "ifconfig",	required_argument, NULL, OPT_IFCONFIG   },
#ifdef NI_TEST_HACKS
		{ "ignore-prio",no_argument, NULL,	OPT_IGNORE_PRIO },
		{ "ignore-startmode",no_argument, NULL, OPT_IGNORE_STARTMODE },
#endif
		{ "persistent",	no_argument,       NULL, OPT_PERSISTENT },

		{ NULL,		no_argument,	   NULL, 0              }
	};
	ni_string_array_t opt_ifconfig = NI_STRING_ARRAY_INIT;
	ni_ifworker_array_t marked = { 0, NULL };
	ni_ifmatcher_t ifmatch;
	ni_bool_t check_prio = TRUE;
	ni_bool_t opt_persistent = FALSE;
	ni_bool_t opt_transient = FALSE;
	int c, status = NI_WICKED_RC_USAGE;
	unsigned int nmarked, i;
	const ni_uint_range_t up_range = {
		.min = NI_FSM_STATE_ADDRCONF_UP,
		.max = __NI_FSM_STATE_MAX
	};
	const char *ptr;
	ni_fsm_t *fsm;

	/* Allow ifreload on all interfaces with a changed config */
	memset(&ifmatch, 0, sizeof(ifmatch));
	ifmatch.require_configured = FALSE;
	ifmatch.allow_persistent = TRUE;
	ifmatch.require_config = FALSE;

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

	/*
	 * Workaround to consider WAIT_FOR_INTERFACES variable
	 * in network/config (bnc#863371, bnc#862530 timeouts).
	 * Correct would be to get it from compat layer, but
	 * the network/config is sourced in systemd service...
	 */
	if ((ptr = getenv("WAIT_FOR_INTERFACES"))) {
		unsigned int sec;

		if (ni_parse_uint(ptr, &sec, 10) == 0 &&
		    (sec * 1000 > fsm->worker_timeout)) {
			ni_debug_application("wait %u sec for interfaces", sec);
			fsm->worker_timeout = sec * 1000;
		}
	}

	optind = 1;
	while ((c = getopt_long(argc, argv, "", ifreload_options, NULL)) != EOF) {
		switch (c) {
		case OPT_IFCONFIG:
			ni_string_array_append(&opt_ifconfig, optarg);
			break;

#ifdef NI_TEST_HACKS
		case OPT_IGNORE_PRIO:
			check_prio = FALSE;
			break;

		case OPT_IGNORE_STARTMODE:
			ifmatch.ignore_startmode = TRUE;
			break;
#endif

		case OPT_PERSISTENT:
			opt_persistent = TRUE;
			break;

		case OPT_TRANSIENT:
			opt_transient = TRUE;
			break;

		default:
		case OPT_HELP:
usage:
			fprintf(stderr,
				"wicked [options] ifreload [ifreload-options] <ifname ...>|all\n"
				"\nSupported ifreload-options:\n"
				"  --help\n"
				"      Show this help text.\n"
				"  --transient\n"
				"      Enable transient interface return codes\n"
				"  --ifconfig <filename>\n"
				"      Read interface configuration(s) from file\n"
#ifdef NI_TEST_HACKS
				"  --ignore-prio\n"
				"      Ignore checking the config origin priorities\n"
				"  --ignore-startmode\n"
				"      Ignore checking the STARTMODE=off and STARTMODE=manual configs\n"
#endif
				"  --persistent\n"
				"      Set interface into persistent mode (no regular ifdown allowed)\n"
				);
			goto cleanup;
		}
	}

	/* at least one argument is required */
	if (optind >= argc) {
		fprintf(stderr, "Missing interface argument\n");
		goto usage;
	} else for (c = optind; c < argc; ++c) {
			if (ni_string_empty(argv[c])) {
				printf("ARG: %s\n", argv[c]);
				goto usage;
			}
	}

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

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

	if (opt_ifconfig.count == 0) {
		const ni_string_array_t *sources = ni_config_sources("ifconfig");

		if (sources && sources->count)
			ni_string_array_copy(&opt_ifconfig, sources);

		if (opt_ifconfig.count == 0) {
			ni_error("ifreload: unable to load interface config source list");
			status = NI_WICKED_RC_NOT_CONFIGURED;
			goto cleanup;
		}
	}

	if (!ni_ifconfig_load(fsm, opt_global_rootdir, &opt_ifconfig, check_prio, TRUE)) {
		status = NI_WICKED_RC_NOT_CONFIGURED;
		goto cleanup;
	}

	status = NI_WICKED_RC_SUCCESS;
	nmarked = 0;
	for (c = optind; c < argc; ++c) {
		ni_ifworker_array_t temp = { 0, NULL };

		/* Getting an array of ifworkers matching argument */
		ifmatch.name = argv[c];
		if (!ni_fsm_get_matching_workers(fsm, &ifmatch, &temp))
			continue;

		for (i = 0; i < temp.count; ++i) {
			ni_ifworker_t *w = temp.data[i];
			ni_netdev_t *dev = w->device;

			/* skip duplicate matches */
			if (ni_ifworker_array_index(&marked, w) != -1)
				continue;

			/* skip unused devices without config */
			if (!ni_ifcheck_worker_config_exists(w) &&
			    !ni_ifcheck_device_configured(dev))
				continue;

			/* skip if config changed somehow */
			if (ni_ifcheck_worker_config_matches(w))
				continue;

			/* Mark persistend when requested */
			if (opt_persistent)
				w->client_state.persistent = TRUE;

			/* Remember all changed devices */
			ni_ifworker_array_append(&marked, w);

			/* Persistent do not go down but up only */
			if (!dev || ni_ifcheck_device_is_persistent(dev))
				continue;

			/* Decide how much down we go */
			if (ni_ifcheck_worker_config_exists(w)) {
				if (!ni_ifcheck_device_configured(dev))
					continue;
				w->target_range.min = NI_FSM_STATE_NONE;
				w->target_range.max = NI_FSM_STATE_DEVICE_READY;
				nmarked++;
			} else
			if (ni_ifcheck_device_configured(dev)) {
				w->target_range.min = NI_FSM_STATE_NONE;
				w->target_range.max = NI_FSM_STATE_DEVICE_DOWN;
				nmarked++;
			}
		}
		ni_ifworker_array_destroy(&temp);
	}

	if (nmarked) {
		/* Run ifdown part of the reload */
		ni_debug_application("Shutting down unneeded devices");
		ni_fsm_start_matching_workers(fsm, &marked);

		/* Execute the down run */
		if (ni_fsm_schedule(fsm) != 0)
			ni_fsm_mainloop(fsm);

	}

	if (marked.count) {

		/* Drop deleted or apply the up range */
		ni_fsm_reset_matching_workers(fsm, &marked, &up_range, FALSE);

		/* And trigger up */
		ni_debug_application("Reloading all changed devices");
		ni_ifup_pull_in_children(&marked);
		nmarked = ni_fsm_start_matching_workers(fsm, &marked);

		ni_ifworker_array_destroy(&marked);
	}

	if (nmarked) {
		/* Build the up tree */
		if (ni_fsm_build_hierarchy(fsm) < 0) {
			ni_error("ifreload: unable to build device hierarchy");
			/* Severe error we always explicitly return */
			status = NI_WICKED_RC_ERROR;
			goto cleanup;
		}

		/* Execute the up run */
		if (ni_fsm_schedule(fsm) != 0)
			ni_fsm_mainloop(fsm);

		/* No error if all interfaces were good */
		status = ni_fsm_fail_count(fsm) ?
			NI_WICKED_RC_ERROR : NI_WICKED_RC_SUCCESS;

		/* Do not report any transient errors to systemd (e.g. dhcp
		 * or whatever not ready in time) -- returning an error may
		 * cause to stop the network completely.
		 */
		if (!opt_transient)
			status = NI_LSB_RC_SUCCESS;
	}

cleanup:
	ni_string_array_destroy(&opt_ifconfig);
	ni_ifworker_array_destroy(&marked);
	return status;
}
예제 #18
0
파일: arputil.c 프로젝트: gsanso/wicked
int
ni_do_arp(int argc, char **argv)
{
	static struct option      options[] = {
		{ "help",         no_argument,       NULL, OPT_HELP        },
		{ "quiet",        no_argument,       NULL, OPT_QUIET       },
		{ "verbose",      no_argument,       NULL, OPT_VERBOSE     },

		{ "verify",       required_argument, NULL, OPT_VERIFY      },
		{ "notify",       required_argument, NULL, OPT_NOTIFY      },
		{ "interval",     required_argument, NULL, OPT_TIMEOUT     },

		{ NULL,           no_argument,       NULL, 0               }
	};
	int               c, status = NI_WICKED_RC_USAGE;
	unsigned int      opt_verbose = OPT_VERBOSE;
	unsigned int      opt_nprobes;
	unsigned int      opt_nclaims;
	struct arp_handle handle;

	memset(&handle, 0, sizeof(handle));
	handle.nprobes = opt_nprobes = 3;
	handle.nclaims = opt_nclaims = 0;
	handle.timeout = 200;

	optind = 1;
	while ((c = getopt_long(argc, argv, "", options, NULL)) != EOF) {
		switch (c) {
		case OPT_HELP:
			status = NI_WICKED_RC_SUCCESS;
		default:
		usage:
			fprintf(stderr,
				"wicked %s [options ...] <ifname> <IP address>\n"
				"\n"
				"Supported options:\n"
				"  --help\n"
				"      Show this help text.\n"
				"  --quiet\n"
				"      Return exit status only\n"
				"  --verbose\n"
				"      Show a result info (default)\n"
				"\n"
				"  --verify <count>\n"
				"      Verify IP for duplicates on the network (DAD);\n"
				"      Returns 4, when duplicate IP address exists.\n"
				"  --notify <count>\n"
				"      Notify about IP address use (gratuitous ARP)\n"
				"  --interval <msec>\n"
				"      Packet sending interval in msec\n"
				, argv[0]
			);
			goto cleanup;

		case OPT_QUIET:
		case OPT_VERBOSE:
			opt_verbose = c;
			break;

		case OPT_VERIFY:
			if (ni_parse_uint(optarg, &opt_nprobes, 10)) {
				ni_error("%s: Cannot parse verify count '%s'",
						argv[0], optarg);
				goto cleanup;
			}
			handle.nprobes = opt_nprobes;
			break;

		case OPT_NOTIFY:
			if (ni_parse_uint(optarg, &opt_nclaims, 10)) {
				ni_error("%s: Cannot parse notify count '%s'",
						argv[0], optarg);
				goto cleanup;
			}
			handle.nclaims = opt_nclaims;
			break;

		case OPT_TIMEOUT:
			if (ni_parse_uint(optarg, &handle.timeout, 10)) {
				ni_error("%s %s: Cannot parse interval '%s'",
						argv[0], argv[1], optarg);
				goto cleanup;
			}
			break;
		}
	}

	if (optind + 2 != argc)
		goto usage;

	if (!handle.nprobes && !handle.nclaims) {
		ni_error("%s: nothing to send", argv[0]);
		goto cleanup;
	}

	handle.ifname = argv[optind++];
	if (ni_string_empty(handle.ifname))
		goto cleanup;

	if (ni_sockaddr_parse(&handle.ipaddr, argv[optind], AF_INET) != 0) {
		ni_error("%s: cannot parse '%s' as IPv4 address",
			argv[0], argv[optind]);
		goto cleanup;
	}

	status = __do_arp_validate(&handle);
	if (opt_verbose) {
		if (handle.hwaddr.len) {
			printf("%s: IP address %s is in use by %s\n",
					handle.ifname,
					ni_sockaddr_print(&handle.ipaddr),
					ni_link_address_print(&handle.hwaddr));
		} else {
			if (opt_nprobes) {
				printf("%s: No duplicates for IP address %s detected\n",
					handle.ifname,
					ni_sockaddr_print(&handle.ipaddr));
			}
			if (opt_nclaims) {
				printf("%s: Notified neighbours about IP address %s\n",
					handle.ifname,
					ni_sockaddr_print(&handle.ipaddr));
			}
		}
	}

cleanup:
	return status;
}
예제 #19
0
파일: ifdown.c 프로젝트: mijos/wicked
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;
}
예제 #20
0
파일: ethtool.c 프로젝트: openSUSE/wicked
static int
set_ethtool_coalesce(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args)
{
	ni_ethtool_coalesce_t *coalesce;
	char *key = NULL, *val = NULL;
	ni_bool_t enabled;
	int ret = -1, n;

	if (!(coalesce = ni_ethtool_coalesce_new()))
		return ret;

	for (n = 0; n < args->argc && args->argv[n]; ++n) {
		key = args->argv[n++];
		if (n < args->argc)
			val = args->argv[n];
		else
			break;
		if (ni_string_eq(key, "adaptive-rx")) {
			if (ni_parse_boolean(val, &enabled) != 0)
				break;
			ni_tristate_set(&coalesce->adaptive_rx, enabled);
		} else
		if (ni_string_eq(key, "adaptive-tx")) {
			if (ni_parse_boolean(val, &enabled) != 0)
				break;
			ni_tristate_set(&coalesce->adaptive_tx, enabled);
		} else
		if (ni_string_eq(key, "rx-usecs")) {
			ni_parse_uint(val, &coalesce->rx_usecs, 10);
		} else
		if (ni_string_eq(key, "rx-frames")) {
			ni_parse_uint(val, &coalesce->rx_frames, 10);
		} else
		if (ni_string_eq(key, "rx-usecs-irq")) {
			ni_parse_uint(val, &coalesce->rx_usecs_irq, 10);
		} else
		if (ni_string_eq(key, "rx-frames-irq")) {
			ni_parse_uint(val, &coalesce->rx_frames_irq, 10);
		} else
		if (ni_string_eq(key, "tx-usecs")) {
			ni_parse_uint(val, &coalesce->tx_usecs, 10);
		} else
		if (ni_string_eq(key, "tx-frames")) {
			ni_parse_uint(val, &coalesce->tx_frames, 10);
		} else
		if (ni_string_eq(key, "tx-usecs-irq")) {
			ni_parse_uint(val, &coalesce->tx_usecs_irq, 10);
		} else
		if (ni_string_eq(key, "tx-frames-irq")) {
			ni_parse_uint(val, &coalesce->rx_frames_irq, 10);
		} else
		if (ni_string_eq(key, "stats-block-usecs")) {
			ni_parse_uint(val, &coalesce->stats_block_usecs, 10);
		} else
		if (ni_string_eq(key, "pkt-rate-low")) {
			ni_parse_uint(val, &coalesce->pkt_rate_low, 10);
		} else
		if (ni_string_eq(key, "rx-usecs-low")) {
			ni_parse_uint(val, &coalesce->rx_usecs_low, 10);
		} else
		if (ni_string_eq(key, "rx-frames-low")) {
			ni_parse_uint(val, &coalesce->rx_frames_low, 10);
		} else
		if (ni_string_eq(key, "tx-usecs-low")) {
			ni_parse_uint(val, &coalesce->tx_usecs_low, 10);
		} else
		if (ni_string_eq(key, "tx-frames-low")) {
			ni_parse_uint(val, &coalesce->tx_frames_low, 10);
		} else
		if (ni_string_eq(key, "pkt-rate-high")) {
			ni_parse_uint(val, &coalesce->pkt_rate_high, 10);
		} else
		if (ni_string_eq(key, "rx-usecs-high")) {
			ni_parse_uint(val, &coalesce->rx_usecs_high, 10);
		} else
		if (ni_string_eq(key, "rx-frames-high")) {
			ni_parse_uint(val, &coalesce->rx_frames_high, 10);
		} else
		if (ni_string_eq(key, "tx-usecs-high")) {
			ni_parse_uint(val, &coalesce->tx_usecs_high, 10);
		} else
		if (ni_string_eq(key, "tx-frames-high")) {
			ni_parse_uint(val, &coalesce->tx_frames_high, 10);
		} else
		if (ni_string_eq(key, "sample_interval")) {
			ni_parse_uint(val, &coalesce->sample_interval, 10);
		} else {
			val = key;
			key = NULL;
			break;
		}

		key = NULL;
		val = NULL;
	}

	if (key) {
		if (val)
			fprintf(stderr, "%s: cannot parse coalesce '%s' argument '%s'\n",
					ref->name, key, val);
		else
			fprintf(stderr, "%s: missing coalesce '%s' value argument\n",
					ref->name, key);
	} else {
		if (val)
			fprintf(stderr, "%s: unknown coalesce setting name '%s'\n",
					ref->name, val);
		else
			ret = ni_ethtool_set_coalesce(ref, ethtool, coalesce);
	}
	ni_ethtool_coalesce_free(coalesce);
	return ret;
}
예제 #21
0
파일: leasefile.c 프로젝트: gsanso/wicked
static int
__ni_addrconf_lease_addr_from_xml(ni_address_t **ap_list, unsigned int family,
					const xml_node_t *node)
{
	const xml_node_t *child;
	ni_sockaddr_t addr;
	unsigned int plen;
	ni_address_t *ap;

	if (!(child = xml_node_get_child(node, "local")))
		return 1;

	if (ni_sockaddr_prefix_parse(child->cdata, &addr, &plen))
		return -1;

	if (family != addr.ss_family ||
	    (family == AF_INET  && plen > 32) ||
	    (family == AF_INET6 && plen > 128))
		return -1;

	if (!(ap = ni_address_new(family, plen, &addr, NULL)))
		return -1;

	if ((child = xml_node_get_child(node, "peer"))) {
		if (ni_sockaddr_parse(&ap->peer_addr, child->cdata, family) != 0)
			goto failure;
	}
	if ((child = xml_node_get_child(node, "anycast"))) {
		if (ni_sockaddr_parse(&ap->anycast_addr, child->cdata, family) != 0)
			goto failure;
	}
	if ((child = xml_node_get_child(node, "broadcast"))) {
		if (ni_sockaddr_parse(&ap->bcast_addr, child->cdata, family) != 0)
			goto failure;
	}

	if (family == AF_INET && (child = xml_node_get_child(node, "label"))) {
		ni_string_dup(&ap->label, child->cdata);
	}

	if ((child = xml_node_get_child(node, "cache-info"))) {
		xml_node_t *cnode;
		unsigned int lft;

		if ((cnode = xml_node_get_child(child, "preferred-lifetime"))) {
			if (ni_parse_uint(child->cdata, &lft, 10) != 0)
				goto failure;
			ap->ipv6_cache_info.preferred_lft = lft;
		}
		if ((cnode = xml_node_get_child(child, "valid-lifetime"))) {
			if (ni_parse_uint(child->cdata, &lft, 10) != 0)
				goto failure;
			ap->ipv6_cache_info.valid_lft = lft;
		}
	}

	ni_address_list_append(ap_list, ap);
	return 0;

failure:
	ni_address_free(ap);
	return -1;
}
예제 #22
0
파일: tester.c 프로젝트: nirmoy/wicked
static ni_bool_t
ni_dhcp4_tester_req_xml_init(ni_dhcp4_request_t *req, xml_document_t *doc)
{
	xml_node_t *xml, *child;
	const char *type;

	xml = xml_document_root(doc);
	if (xml && !xml->name && xml->children)
		xml = xml->children;

	if (!xml || !ni_string_eq(xml->name, "request")) {
		ni_error("Invalid dhcp4 request xml '%s'",
				xml ? xml_node_location(xml) : NULL);
		return FALSE;
	}

	type = xml_node_get_attr(xml, "type");
	if (ni_string_eq(type, "offer")) {
		req->dry_run = NI_DHCP4_RUN_OFFER;
	} else
	if (ni_string_eq(type, "lease")) {
		req->dry_run = NI_DHCP4_RUN_LEASE;
	}

	for (child = xml->children; child; child = child->next) {
		if (ni_string_eq(child->name, "uuid")) {
			if (ni_uuid_parse(&req->uuid, child->cdata) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "acquire-timeout")) {
			if (ni_parse_uint(child->cdata, &req->acquire_timeout, 10) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "hostname")) {
			if (!ni_check_domain_name(child->cdata, ni_string_len(child->cdata), 0))
				goto failure;
			ni_string_dup(&req->hostname, child->cdata);
		} else
		if (ni_string_eq(child->name, "fqdn")) {
			const xml_node_t *ptr;

			for (ptr = child->children; ptr; ptr = ptr->next) {
				if (ni_string_eq(ptr->name, "enabled")) {
					ni_bool_t b;
					if (ni_parse_boolean(ptr->cdata, &b) == 0)
						ni_tristate_set(&req->fqdn.enabled, b);
					else
					if (ni_string_eq(ptr->cdata, "default"))
						req->fqdn.enabled = NI_TRISTATE_DEFAULT;
					else
						goto failure;
				} else
				if (ni_string_eq(ptr->name, "update")) {
					if (!ni_dhcp_fqdn_update_name_to_mode(ptr->cdata, &req->fqdn.update))
						goto failure;
				} else
				if (ni_string_eq(ptr->name, "encode")) {
					if (ni_parse_boolean(ptr->cdata, &req->fqdn.encode) != 0)
						goto failure;
				} else
				if (ni_string_eq(ptr->name, "qualify")) {
					if (ni_parse_boolean(ptr->cdata, &req->fqdn.qualify) != 0)
						goto failure;
				}
			}
		} else
		if (ni_string_eq(child->name, "clientid")) {
			ni_opaque_t duid;

			if (ni_parse_hex(child->cdata, duid.data, sizeof(duid.data)) <= 0)
				goto failure;
			ni_string_dup(&req->clientid, child->cdata);
		} else
		if(ni_string_eq(child->name, "start-delay")) {
			if (ni_parse_uint(child->cdata, &req->start_delay, 10) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "lease-time")) {
			if (ni_parse_uint(child->cdata, &req->lease_time, 10) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "recover-lease")) {
			if (ni_parse_boolean(child->cdata, &req->recover_lease) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "release-lease")) {
			if (ni_parse_boolean(child->cdata, &req->release_lease) != 0)
				goto failure;
		} else
		if (ni_string_eq(child->name, "request-options")) {
			xml_node_t *opt;
			for (opt = child->children; opt; opt = opt->next) {
				if (ni_string_empty(opt->cdata))
					continue;
				ni_string_array_append(&req->request_options, opt->cdata);
			}
		}
	}

	return TRUE;
failure:
	if (child) {
		ni_error("Cannot parse dhcp4 request '%s': %s",
				child->name, xml_node_location(child));
	}
	return FALSE;
}
예제 #23
0
static int
ni_do_ifup_direct(int argc, char **argv)
{
	enum  { OPT_HELP, OPT_IFCONFIG, OPT_CONTROL_MODE, OPT_STAGE, OPT_TIMEOUT,
		OPT_SKIP_ACTIVE, OPT_SKIP_ORIGIN, OPT_PERSISTENT, OPT_TRANSIENT,
#ifdef NI_TEST_HACKS
		OPT_IGNORE_PRIO, OPT_IGNORE_STARTMODE,
#endif
	};

	static struct option ifup_options[] = {
		{ "help",	no_argument,       NULL,	OPT_HELP },
		{ "ifconfig",	required_argument, NULL,	OPT_IFCONFIG },
		{ "mode",	required_argument, NULL,	OPT_CONTROL_MODE },
		{ "boot-stage",	required_argument, NULL,	OPT_STAGE },
		{ "skip-active",required_argument, NULL,	OPT_SKIP_ACTIVE },
		{ "skip-origin",required_argument, NULL,	OPT_SKIP_ORIGIN },
		{ "timeout",	required_argument, NULL,	OPT_TIMEOUT },
		{ "transient", 	no_argument,		NULL,	OPT_TRANSIENT },
#ifdef NI_TEST_HACKS
		{ "ignore-prio",no_argument, NULL,	OPT_IGNORE_PRIO },
		{ "ignore-startmode",no_argument, NULL,	OPT_IGNORE_STARTMODE },
#endif
		{ "persistent",	no_argument, NULL,	OPT_PERSISTENT },
		{ NULL }
	};

	ni_ifmatcher_t ifmatch;
	ni_ifmarker_t ifmarker;
	ni_ifworker_array_t ifmarked;
	ni_string_array_t opt_ifconfig = NI_STRING_ARRAY_INIT;
	ni_bool_t check_prio = TRUE;
	ni_bool_t opt_transient = FALSE;
	unsigned int nmarked;
	ni_fsm_t *fsm;
	int c, status = NI_WICKED_RC_USAGE;
	unsigned int timeout = 0;
	const char *ptr;

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

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

	/* Allow ifup on all interfaces we have config for */
	ifmatch.require_configured = FALSE;
	ifmatch.allow_persistent = TRUE;
	ifmatch.require_config = TRUE;

	ifmarker.target_range.min = NI_FSM_STATE_ADDRCONF_UP;
	ifmarker.target_range.max = __NI_FSM_STATE_MAX;

	/*
	 * Workaround to consider WAIT_FOR_INTERFACES variable
	 * in network/config (bnc#863371, bnc#862530 timeouts).
	 * Correct would be to get it from compat layer, but
	 * the network/config is sourced in systemd service...
	 */
	if ((ptr = getenv("WAIT_FOR_INTERFACES"))) {
		unsigned int sec;

		if (ni_parse_uint(ptr, &sec, 10) == 0 &&
		    (sec * 1000 > fsm->worker_timeout)) {
			ni_debug_application("wait %u sec for interfaces", sec);
			timeout = sec * 1000;
		}
	}

	optind = 1;
	while ((c = getopt_long(argc, argv, "", ifup_options, NULL)) != EOF) {
		switch (c) {
		case OPT_IFCONFIG:
			ni_string_array_append(&opt_ifconfig, optarg);
			break;

		case OPT_CONTROL_MODE:
			ifmatch.mode = optarg;
			break;

		case OPT_STAGE:
			ifmatch.boot_stage= optarg;
			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("ifup: cannot parse timeout option \"%s\"", optarg);
				goto usage;
			}
			break;

		case OPT_SKIP_ORIGIN:
			ifmatch.skip_origin = optarg;
			break;

		case OPT_SKIP_ACTIVE:
			ifmatch.skip_active = TRUE;
			break;

#ifdef NI_TEST_HACKS
		case OPT_IGNORE_PRIO:
			check_prio = FALSE;
			break;

		case OPT_IGNORE_STARTMODE:
			ifmatch.ignore_startmode = TRUE;
			break;
#endif

		case OPT_PERSISTENT:
			ifmarker.persistent = TRUE;
			break;

		case OPT_TRANSIENT:
			opt_transient = TRUE;
			break;

		default:
		case OPT_HELP:
usage:
			fprintf(stderr,
				"wicked [options] ifup [ifup-options] <ifname ...>|all\n"
				"\nSupported ifup-options:\n"
				"  --help\n"
				"      Show this help text.\n"
				"  --transient\n"
				"      Enable transient interface return codes\n"
				"  --ifconfig <pathname>\n"
				"      Read interface configuration(s) from file/directory rather than using system config\n"
				"  --mode <label>\n"
				"      Only touch interfaces with matching control <mode>\n"
				"  --boot-stage <label>\n"
				"      Only touch interfaces with matching <boot-stage>\n"
				"  --skip-active\n"
				"      Do not touch running interfaces\n"
				"  --skip-origin <name>\n"
				"      Skip interfaces that have a configuration origin of <name>\n"
				"      Usually, you would use this with the name \"firmware\" to avoid\n"
				"      touching interfaces that have been set up via firmware (like iBFT) previously\n"
				"  --timeout <nsec>\n"
				"      Timeout after <nsec> seconds\n"
#ifdef NI_TEST_HACKS
				"  --ignore-prio\n"
				"      Ignore checking the config origin priorities\n"
				"  --ignore-startmode\n"
				"      Ignore checking the STARTMODE=off and STARTMODE=manual configs\n"
#endif
				"  --persistent\n"
				"      Set interface into persistent mode (no regular ifdown allowed)\n"
				);
			goto cleanup;
		}
	}

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

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

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

	if (opt_ifconfig.count == 0) {
		const ni_string_array_t *sources = ni_config_sources("ifconfig");

		if (sources && sources->count)
			ni_string_array_copy(&opt_ifconfig, sources);

		if (opt_ifconfig.count == 0) {
			ni_error("ifup: unable to load interface config source list");
			status = NI_WICKED_RC_NOT_CONFIGURED;
			goto cleanup;
		}
	}

	if (!ni_ifconfig_load(fsm, opt_global_rootdir, &opt_ifconfig, check_prio, TRUE)) {
		status = NI_WICKED_RC_NOT_CONFIGURED;
		goto cleanup;
	}

	/* Client waits for device-up events for WAIT_FOR_INTERFACES */
	if (timeout)
		ni_wait_for_interfaces = timeout; /* One set by user */
	else
		ni_wait_for_interfaces *= 1000;   /* in msec */

	if (ni_fsm_build_hierarchy(fsm) < 0) {
		ni_error("ifup: unable to build device hierarchy");
		/* Severe error we always explicitly return */
		status = NI_WICKED_RC_ERROR;
		goto cleanup;
	}

	/* Get workers that match given criteria */
	nmarked = 0;
	while (optind < argc) {
		ifmatch.name = argv[optind++];

		if (!strcmp(ifmatch.name, "boot")) {
			ifmatch.name = "all";
			ifmatch.mode = "boot";
		}

		ni_fsm_get_matching_workers(fsm, &ifmatch, &ifmarked);
	}

	ni_ifup_pull_in_children(&ifmarked);

	/* Mark and start selected workers */
	if (ifmarked.count)
		nmarked = ni_fsm_mark_matching_workers(fsm, &ifmarked, &ifmarker);

	if (nmarked == 0) {
		printf("ifup: no matching interfaces\n");
		status = NI_WICKED_RC_SUCCESS;
	} else {
		if (ni_fsm_schedule(fsm) != 0)
			ni_fsm_mainloop(fsm);

		/* No error if all interfaces were good */
		status = ni_fsm_fail_count(fsm) ?
			NI_WICKED_RC_ERROR : NI_WICKED_RC_SUCCESS;

		/* Do not report any transient errors to systemd (e.g. dhcp
		 * or whatever not ready in time) -- returning an error may
		 * cause to stop the network completely.
		 */
		if (!opt_transient)
			status = NI_LSB_RC_SUCCESS;
	}

cleanup:
	ni_ifworker_array_destroy(&ifmarked);
	ni_string_array_destroy(&opt_ifconfig);
	return status;
}
예제 #24
0
파일: main.c 프로젝트: kmroz/wicked
int
main(int argc, char **argv)
{
	dhcp4_tester_t * tester = NULL;
	int c, status = NI_WICKED_RC_USAGE;

	ni_log_init();
	program_name = ni_basename(argv[0]);

	while ((c = getopt_long(argc, argv, "+", options, NULL)) != EOF) {
		switch (c) {
		/* common */
		case OPT_HELP:
			status = NI_WICKED_RC_SUCCESS;
		default:
		usage:
			fprintf(stderr,
				"%s [options]\n"
				"This command understands the following options\n"
				"  --help\n"
				"  --version\n"
				"  --config filename\n"
				"        Read configuration file <filename> instead of system default.\n"
				"  --log-level level\n"
				"        Set log level to <error|warning|notice|info|debug>.\n"
				"  --log-target target\n"
				"        Set log destination to <stderr|syslog>.\n"
				"  --debug facility\n"
				"        Enable debugging for debug <facility>.\n"
				"        Use '--debug help' for a list of facilities.\n"
				"  --foreground\n"
				"        Do not background the service.\n"
				"  --recover\n"
				"        Enable automatic recovery of daemon's state.\n"
				"  --systemd\n"
				"        Enables behavior required by systemd service\n"
				"\n"
				"  --test [test-options] <ifname>\n"
				"    test-options:\n"
				"       --test-request <request.xml>\n"
				"       --test-timeout <timeout in sec> (default: 20+10)\n"
				"       --test-output  <output file name>\n"
				"       --test-format  <leaseinfo|lease-xml>\n"
				, program_name);
			return status;

		case OPT_VERSION:
			printf("%s %s\n", program_name, PACKAGE_VERSION);
			return NI_WICKED_RC_SUCCESS;

		case OPT_CONFIGFILE:
			if (!ni_set_global_config_path(optarg)) {
				fprintf(stderr, "Unable to set config file '%s': %m\n",
						optarg);
				return NI_WICKED_RC_ERROR;
			}
			break;

		case OPT_DEBUG:
			if (!strcmp(optarg, "help")) {
				printf("Supported debug facilities:\n");
				ni_debug_help();
				return NI_WICKED_RC_SUCCESS;
			}
			if (ni_enable_debug(optarg) < 0) {
				fprintf(stderr, "Bad debug facility \"%s\"\n", optarg);
				goto usage;
			}
			break;

		case OPT_LOG_LEVEL:
			if (!ni_log_level_set(optarg)) {
				fprintf(stderr, "Bad log level \%s\"\n", optarg);
				goto usage;
			}
			break;

		case OPT_LOG_TARGET:
			opt_log_target = optarg;
			break;

		/* daemon */
		case OPT_FOREGROUND:
			opt_foreground = TRUE;
			break;

		/* specific */
		case OPT_RECOVER:
			opt_recover_state = TRUE;
			break;

		case OPT_SYSTEMD:
			opt_systemd = TRUE;
			break;

		/* test run */
		case OPT_TEST:
			opt_foreground = TRUE;
			tester = dhcp4_tester_init();
			break;

		case OPT_TEST_REQUEST:
			if (!tester || ni_string_empty(optarg))
				goto usage;
			tester->request = optarg;
			break;

		case OPT_TEST_TIMEOUT:
			if (!tester || ni_parse_uint(optarg,
						&tester->timeout, 0) < 0)
				goto usage;
			break;

		case OPT_TEST_OUTPUT:
			if (!tester || ni_string_empty(optarg))
				goto usage;
			tester->output = optarg;
			break;

		case OPT_TEST_OUTFMT:
			if (!tester || !dhcp4_tester_set_outfmt(optarg,
						&tester->outfmt))
				goto usage;
			break;
		}
	}
예제 #25
0
파일: tester.c 프로젝트: gsanso/wicked
int
ni_do_test_dhcp4(const char *caller, int argc, char **argv)
{
	enum {
		OPT_HELP 	 = 'h',
		OPT_TEST_TIMEOUT = 't',
		OPT_TEST_REQUEST = 'r',
		OPT_TEST_OUTPUT	 = 'o',
		OPT_TEST_OUTFMT	 = 'F',
	};
	static struct option	options[] = {
		{ "help",	no_argument,		NULL,	OPT_HELP	},
		{ "request",	required_argument,	NULL,	OPT_TEST_REQUEST},
		{ "timeout",	required_argument,	NULL,	OPT_TEST_TIMEOUT},
		{ "output",	required_argument,	NULL,	OPT_TEST_OUTPUT	},
		{ "format",	required_argument,	NULL,	OPT_TEST_OUTFMT	},
		{ NULL,		no_argument,		NULL,	0		}
	};
	int opt = 0, status = NI_WICKED_RC_USAGE;
	char *program = NULL;
	ni_dhcp4_tester_t *tester;

	ni_string_printf(&program, "%s %s",	caller  ? caller  : "wicked",
						argv[0] ? argv[0] : "test");
	argv[0] = program;

	tester = ni_dhcp4_tester_init();
	if (tester == NULL) {
		fprintf(stderr, "Error: %s: unable to initialize dhcp4 tester\n", program);
		status = NI_WICKED_RC_ERROR;
		goto cleanup;
	}

	optind = 1;
	while ((opt = getopt_long(argc, argv, "+hr:t:o:F:", options, NULL)) != EOF) {
		switch (opt) {
		case OPT_HELP:
			status = NI_WICKED_RC_SUCCESS;
		default:
		usage:
			fprintf(stderr,
				"\nUsage:\n"
				"  %s [options] <ifname>\n"
				"\n"
				"Options:\n"
				"  --help, -h      show this help text and exit.\n"
				"\n"
				"  --timeout, -t   <timeout in sec> (default: 20+10)\n"
				"  --request, -r   <request.xml>\n"
				"  --output, -o    <output file name>\n"
				"  --format, -F    <leaseinfo|lease-xml>\n"
				"\n", program);
			goto cleanup;

		case OPT_TEST_TIMEOUT:
			if (ni_string_empty(optarg))
				goto usage;
			if (ni_parse_uint(optarg, &tester->timeout, 0) < 0) {
				fprintf(stderr, "%s: unable to parse timeout option '%s'\n",
						program, optarg);
				status = NI_WICKED_RC_ERROR;
				goto cleanup;
			}
			break;

		case OPT_TEST_REQUEST:
			if (ni_string_empty(optarg))
				goto usage;
			tester->request = optarg;
			break;

		case OPT_TEST_OUTPUT:
			if (ni_string_empty(optarg))
				goto usage;
			tester->output = optarg;
			break;

		case OPT_TEST_OUTFMT:
			if (ni_string_empty(optarg))
				goto usage;
			if (!ni_dhcp4_tester_set_outfmt(optarg, &tester->outfmt)) {
				fprintf(stderr, "%s: unable to parse output format option '%s'\n",
						program, optarg);
				status = NI_WICKED_RC_ERROR;
				goto cleanup;
			}
			break;
		}
	}

	if (optind >= argc || ni_string_empty(argv[optind])) {
		fprintf(stderr, "Error: %s: missing interface name argument\n", program);
		goto usage;
	} else
	if (optind + 1 != argc) {
		fprintf(stderr, "Error: %s: multiple interface names not supported\n", program);
		goto cleanup;
	}

	ni_netconfig_set_family_filter(ni_global_state_handle(0), AF_INET);
	ni_netconfig_set_discover_filter(ni_global_state_handle(0),
					NI_NETCONFIG_DISCOVER_LINK_EXTERN);

	tester->ifname = argv[optind];
	status = ni_dhcp4_tester_run(tester);

cleanup:
	ni_string_free(&program);
	return status;
}