Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
static int
__ni_addrconf_lease_route_nh_from_xml(ni_route_t *rp, const xml_node_t *node)
{
	const xml_node_t *child;
	ni_route_nexthop_t *nh = NULL;
	ni_sockaddr_t addr;

	for (child = node->children; child; child = child->next) {
		if (ni_string_eq(child->name, "gateway") && child->cdata) {
			if (ni_sockaddr_parse(&addr, child->cdata, AF_UNSPEC) != 0)
				return -1;
			if (rp->family != addr.ss_family)
				return -1;
			if (nh == NULL) {
				nh = ni_route_nexthop_new();
				ni_route_nexthop_list_append(&rp->nh.next, nh);
			}
			nh->gateway = addr;
			nh = NULL;
		}
	}
	return 0;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
ni_bool_t
ni_config_parse_addrconf_dhcp6(struct ni_config_dhcp6 *dhcp6, xml_node_t *node)
{
	xml_node_t *child;

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

		if (!strcmp(child->name, "default-duid") && !ni_string_empty(child->cdata)) {
			ni_string_dup(&dhcp6->default_duid, child->cdata);
		} else
		if (!strcmp(child->name, "user-class")) {
			ni_string_array_destroy(&dhcp6->user_class_data);

			if (__ni_config_parse_dhcp6_class_data_nodes(child, &dhcp6->user_class_data) < 0) {
				ni_string_array_destroy(&dhcp6->user_class_data);
				return FALSE;
			}

			if (dhcp6->user_class_data.count == 0) {
				ni_warn("config: discarding <user-class> without any <class-data>");
			}
		} else
		if (!strcmp(child->name, "vendor-class") &&
		    (attrval = xml_node_get_attr(child, "enterprise-number")) != NULL) {
			char *      err;
			long        num;
			
			num = strtol(attrval, &err, 0);
			if (*err != '\0' || num < 0 || num >= 0xffffffff) {
				ni_error("config: unable to parse <vendor-class enterprise-number=\"%s\"",
						attrval);
				return FALSE;
			}

			ni_string_array_destroy(&dhcp6->vendor_class_data);
			if (__ni_config_parse_dhcp6_class_data_nodes(child, &dhcp6->vendor_class_data) < 0) {
				ni_string_array_destroy(&dhcp6->vendor_class_data);
				return FALSE;
			}

			if (dhcp6->vendor_class_data.count == 0) {
				ni_warn("config: discarding <vendor-class> without any <class-data>");
			} else {
				dhcp6->vendor_class_en = num;
			}
		} else
		if (!strcmp(child->name, "vendor-opts") &&
		    (attrval = xml_node_get_attr(child, "enterprise-number")) != NULL) {
			char *      err;
			long        num;
			
			num = strtol(attrval, &err, 0);
			if (*err != '\0' || num < 0 || num >= 0xffffffff) {
				ni_error("config: unable to parse <vendor-class enterprise-number=\"%s\"",
						attrval);
				return FALSE;
			}

			ni_var_array_destroy(&dhcp6->vendor_opts_data);
			if (__ni_config_parse_dhcp6_vendor_opts_nodes(child, &dhcp6->vendor_opts_data) < 0) {
				ni_var_array_destroy(&dhcp6->vendor_opts_data);
			}

			if (dhcp6->vendor_opts_data.count == 0) {
				ni_warn("config: discarding <vendor-opts> without any <option>");
			} else {
				dhcp6->vendor_opts_en = num;
			}
		} else
		if (!strcmp(child->name, "lease-time") && child->cdata) {
			dhcp6->lease_time = strtoul(child->cdata, NULL, 0);
		} else
		if (!strcmp(child->name, "ignore-server")
		 && (attrval = xml_node_get_attr(child, "ip")) != NULL) {
			ni_string_array_append(&dhcp6->ignore_servers, attrval);
		} else
		if (!strcmp(child->name, "prefer-server")) {
			ni_server_preference_t *pref;
			const char *id, *ip;

			ip = xml_node_get_attr(child, "ip"); 
			id = xml_node_get_attr(child, "id");

			if (ip == NULL && id == NULL)
				continue;

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

			pref = &dhcp6->preferred_server[dhcp6->num_preferred_servers++];

			if (ip && ni_sockaddr_parse(&pref->address, ip, AF_INET6) < 0) {
				ni_error("config: unable to parse <prefer-server ip=\"%s\"",
						ip);
				return FALSE;
			}

			if (id) {
				int len;

				/* DUID is "opaque", but has 2 bytes type + up to 128 bytes */
				if ((len = sizeof(pref->serverid.data)) > 130)
					len = 130;

				 /* DUID-LL has 2+2 fixed bytes + variable length hwaddress
				  * and seems to be the shortest one I'm aware of ...       */
				if ((len = ni_parse_hex(id, pref->serverid.data, len)) <= 4) {
					ni_error("config: unable to parse <prefer-server id=\"%s\"",
							id);
					return FALSE;
				}
				pref->serverid.len = (size_t)len;
			}

			pref->weight = 255;
			if ((attrval = xml_node_get_attr(child, "weight")) != NULL) {
				if (!strcmp(attrval, "always")) {
					pref->weight = 255;
				} else if (!strcmp(attrval, "never")) {
					pref->weight =  -1;
				} else {
					pref->weight = strtol(attrval, NULL, 0);
					if (pref->weight > 255) {
						pref->weight = 255;
						ni_warn("preferred dhcp server weight exceeds max, "
							"clamping to %d",
							pref->weight);
					}
				}
			}
		} else
		if (!strcmp(child->name, "allow-update")) {
			ni_config_parse_update_targets(&dhcp6->allow_update, child);
		}
	}
	return TRUE;
}