Пример #1
0
static int
__ni_rtevent_process_rdnss_info(ni_netdev_t *dev, const struct nd_opt_hdr *opt,
				size_t len)
{
	const struct ni_nd_opt_rdnss_info_p *ropt;
	char buf[INET6_ADDRSTRLEN+1] = {'\0'};
	const struct in6_addr* addr;
	ni_ipv6_devinfo_t *ipv6;
	unsigned int lifetime;
	struct timeval acquired;
	ni_bool_t emit = FALSE;
	const char *server;

	if (opt == NULL || len < (sizeof(*ropt) + sizeof(*addr))) {
		ni_error("%s: unable to parse ipv6 rdnss info event data -- too short",
				dev->name);
		return -1;
	}

	ipv6 = ni_netdev_get_ipv6(dev);
	if (!ipv6) {
		ni_error("%s: unable to allocate device ipv6 structure: %m",
				dev->name);
		return -1;
	}

	ropt = (const struct ni_nd_opt_rdnss_info_p *)opt;

	ni_timer_get_time(&acquired);
	lifetime = ntohl(ropt->nd_opt_rdnss_lifetime);
	len -= sizeof(*ropt);
	addr = &ropt->nd_opt_rdnss_addr[0];
	for ( ; len >= sizeof(*addr); len -= sizeof(*addr), ++addr) {
		if (IN6_IS_ADDR_LOOPBACK(addr) || IN6_IS_ADDR_UNSPECIFIED(addr)) {
			server = inet_ntop(AF_INET6, addr, buf, sizeof(buf));
			ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS,
					"%s: ignoring invalid rdnss server address %s",
					dev->name, server);
			continue;
		}

		if (!ni_ipv6_ra_rdnss_list_update(&ipv6->radv.rdnss, addr,
					lifetime, &acquired)) {
			server = inet_ntop(AF_INET6, addr, buf, sizeof(buf));
			ni_debug_verbose(NI_LOG_DEBUG, NI_TRACE_IPV6|NI_TRACE_EVENTS,
					"%s: failed to track ipv6 rnssl server %s",
					dev->name, server);
			continue;
		}

		emit = TRUE;
	}

	if (emit)
		__ni_netdev_nduseropt_event(dev, NI_EVENT_RDNSS_UPDATE);
	return 0;
}
Пример #2
0
static int
__ni_dhcp4_build_msg_release(const ni_dhcp4_device_t *dev,
			const ni_addrconf_lease_t *lease,
			ni_buffer_t *msgbuf)
{
	unsigned int msg_code = DHCP4_RELEASE;
	ni_dhcp4_message_t *message;
	ni_sockaddr_t addr;

	/* Release an IP address from a lease we own */
	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0);
	if (!ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_error("%s: cannot release - no ip-address in lease", dev->ifname);
		return -1;
	}

	if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf)))
		return -1;

	message->ciaddr = lease->dhcp4.address.s_addr;
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using release ip-address: %s",
			dev->ifname, ni_sockaddr_print(&addr));

	if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0)
		return -1;

	if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) <  0)
		return -1;

	if (__ni_dhcp4_build_msg_put_server_id(dev, lease, msg_code, msgbuf) <  0)
		return -1;

	return 0;
}
Пример #3
0
static ni_dhcp4_message_t *
__ni_dhcp4_build_msg_init_head(const ni_dhcp4_device_t *dev,
				unsigned int msg_code, ni_buffer_t *msgbuf)
{
	ni_dhcp4_message_t *message;

	/* Build the main message (header) */
	if (!(message = ni_buffer_push_tail(msgbuf, sizeof(*message)))) {
		ni_error("%s: buffer too short for dhcp4 message", dev->ifname);
		return NULL;
	}

	memset(message, 0, sizeof(*message));
	message->op = DHCP4_BOOTREQUEST;
	message->xid = dev->dhcp4.xid;
	message->secs = htons(ni_dhcp4_device_uptime(dev, 0xFFFF));
	message->cookie = htonl(MAGIC_COOKIE);
	message->hwtype = dev->system.hwaddr.type;

	ni_dhcp4_option_put8(msgbuf, DHCP4_MESSAGETYPE, msg_code);
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using message type: %s", dev->ifname,
			ni_dhcp4_message_name(msg_code));

	return message;
}
Пример #4
0
static int
__ni_dhcp4_build_msg_put_client_id(const ni_dhcp4_device_t *dev, unsigned int msg_code,
				ni_dhcp4_message_t *message, ni_buffer_t *msgbuf)
{
	const ni_dhcp4_config_t *options = dev->config;

	if (options->client_id.len) {
		ni_dhcp4_option_put(msgbuf, DHCP4_CLIENTID,
				options->client_id.data,
				options->client_id.len);

		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: using client-id: %s", dev->ifname,
				ni_print_hex(options->client_id.data,
						options->client_id.len));
	} else
	if (!message->hwlen) {
		ni_error("%s: cannot construct %s without usable hw-addr and client-id",
				dev->ifname, ni_dhcp4_message_name(msg_code));
		return -1;
	} else {
		return 1; /* skipped client-id */
	}
	return 0;
}
Пример #5
0
int
__ni_dhcp4_build_msg_request_offer(const ni_dhcp4_device_t *dev,
			const ni_addrconf_lease_t *lease,
			ni_buffer_t *msgbuf)
{
	const ni_dhcp4_config_t *options = dev->config;
	unsigned int msg_code = DHCP4_REQUEST;
	ni_dhcp4_message_t *message;
	ni_sockaddr_t addr;

	/* Request an offer provided by a server (id!) while discover */
	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0);
	if (!ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_error("%s: not requesting this offer - no ip-address in lease",
				dev->ifname);
		return -1;
	}

	if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf)))
		return -1;

	if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0)
		return -1;

	if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) <  0)
		return -1;

	if (__ni_dhcp4_build_msg_put_server_id(dev, lease, msg_code, msgbuf) <  0)
		return -1;

	ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_ADDRESS, lease->dhcp4.address);
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using offered ip-address: %s",
			dev->ifname, ni_sockaddr_print(&addr));

	if (__ni_dhcp4_build_msg_put_our_hostname(dev, msgbuf) < 0)
		return -1;

	if (__ni_dhcp4_build_msg_put_option_request(dev, msg_code, msgbuf) <  0)
		return -1;

	ni_dhcp4_option_put16(msgbuf, DHCP4_MAXMESSAGESIZE, dev->system.mtu);

	if (lease->dhcp4.lease_time != 0) {
		ni_dhcp4_option_put32(msgbuf, DHCP4_LEASETIME,
					lease->dhcp4.lease_time);
	}

	if (options->userclass.len > 0) {
		ni_dhcp4_option_put(msgbuf, DHCP4_USERCLASS,
				options->userclass.data,
				options->userclass.len);
	}

	if (options->classid && options->classid[0]) {
		ni_dhcp4_option_puts(msgbuf, DHCP4_CLASSID, options->classid);
	}

	return 0;
}
Пример #6
0
void
ni_server_trace_interface_nduseropt_events(ni_netdev_t *dev, ni_event_t event)
{
	ni_ipv6_devinfo_t *ipv6 = dev->ipv6;

	if (!ni_debug_guard(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS))
		return;

	switch (event) {
	case NI_EVENT_RDNSS_UPDATE:
		if (ipv6 && ipv6->radv.rdnss) {
			ni_ipv6_ra_rdnss_t *rdnss;
			char buf[32] = {'\0'};
			const char *rainfo;

			rainfo = ipv6->radv.managed_addr ? "managed" :
				 ipv6->radv.other_config ? "config"  : "unmanaged";

			for (rdnss = ipv6->radv.rdnss; rdnss; rdnss = rdnss->next) {
				ni_stringbuf_t lft = NI_STRINGBUF_INIT_BUFFER(buf);

				ni_trace("%s: update IPv6 RA<%s> RDNSS<%s>[%s]",
					dev->name, rainfo,
					ni_sockaddr_print(&rdnss->server),
					ni_lifetime_print_valid(&lft, rdnss->lifetime));
				ni_stringbuf_destroy(&lft);
			}
		}
		break;

	case NI_EVENT_DNSSL_UPDATE:
		if (ipv6 && ipv6->radv.dnssl) {
			ni_ipv6_ra_dnssl_t *dnssl;
			char buf[32] = {'\0'};
			const char *rainfo;

			rainfo = ipv6->radv.managed_addr ? "managed" :
				 ipv6->radv.other_config ? "config"  : "unmanaged";
			for (dnssl = ipv6->radv.dnssl; dnssl; dnssl = dnssl->next) {
				ni_stringbuf_t lft = NI_STRINGBUF_INIT_BUFFER(buf);

				ni_trace("%s: update IPv6 RA<%s> DNSSL<%s>[%s]",
					dev->name, rainfo, dnssl->domain,
					ni_lifetime_print_valid(&lft, dnssl->lifetime));
				ni_stringbuf_destroy(&lft);
			}
		}
		break;

	default:
		ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS,
			"%s: IPv6 RA %s event: ", dev->name, ni_event_type_to_name(event));
		break;
	}
}
Пример #7
0
int
ni_ethtool_set_priv_flags(const char *ifname, ni_ethtool_t *ethtool, const ni_ethtool_priv_flags_t *pflags)
{
	static const ni_ethtool_cmd_info_t NI_ETHTOOL_CMD_SPFLAGS = {
		ETHTOOL_SPFLAGS,	"set priv-flags"
	};
	struct ethtool_value ecmd;
	unsigned int i, bit;
	const char *name;
	ni_bool_t enabled;
	int ret;

	if (!pflags || !pflags->names.count)
		return 1; /* nothing to set */
	if (!ethtool->priv_flags && (ret = ni_ethtool_get_priv_flags(ifname, ethtool)) < 0)
		return ret;
	if (!ethtool->priv_flags || !ethtool->priv_flags->names.count)
		return -EOPNOTSUPP;

	memset(&ecmd, 0, sizeof(ecmd));
	ecmd.data = ethtool->priv_flags->bitmap;
	/* set every single bit separately in case one fails? */
	for (i = 0; i < pflags->names.count; ++i) {
		name = pflags->names.data[i];
		if (ni_string_empty(name))
			continue;

		enabled = !!(pflags->bitmap & NI_BIT(i));
		bit = ni_string_array_index(&ethtool->priv_flags->names, name);
		if (bit == -1U) {
			ni_info("%s: unable to set unknown driver private flag '%s'",
					ifname, name);
			continue;
		}

		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_IFCONFIG,
				"%s: setting driver private flag '%s' to %s",
				ifname, name, ni_format_boolean(enabled));
		if (enabled)
			ecmd.data |= NI_BIT(bit);
		else
			ecmd.data &= ~NI_BIT(bit);
	}
	if (ecmd.data == ethtool->priv_flags->bitmap)
		return 0;

	ret = ni_ethtool_call(ifname, &NI_ETHTOOL_CMD_SPFLAGS, &ecmd, NULL);
	ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_SET_PRIV_FLAGS,
				ret != -EOPNOTSUPP);
	if (ret < 0)
		return ret;

	return 0;
}
Пример #8
0
static int
__ni_dhcp4_build_msg_discover(const ni_dhcp4_device_t *dev,
			const ni_addrconf_lease_t *lease,
			ni_buffer_t *msgbuf)
{
	const ni_dhcp4_config_t *options = dev->config;
	unsigned int msg_code = DHCP4_DISCOVER;
	ni_dhcp4_message_t *message;
	ni_sockaddr_t addr;

	/* Discover server able to provide usable offer */
	if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf)))
		return -1;

	if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0)
		return -1;

	if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) <  0)
		return -1;

	/* An optional hint that we've had this address in the past,
	 * so the server __may__ assign it again to us.
	 */
	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0);
	if (ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_ADDRESS, lease->dhcp4.address);
		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: using ip-address hint: %s",
				dev->ifname, ni_sockaddr_print(&addr));
	}

	if (__ni_dhcp4_build_msg_put_option_request(dev, msg_code, msgbuf) <  0)
		return -1;

	ni_dhcp4_option_put16(msgbuf, DHCP4_MAXMESSAGESIZE, dev->system.mtu);

	if (lease->dhcp4.lease_time != 0) {
		ni_dhcp4_option_put32(msgbuf, DHCP4_LEASETIME,
					lease->dhcp4.lease_time);
	}

	if (options->userclass.len > 0) {
		ni_dhcp4_option_put(msgbuf, DHCP4_USERCLASS,
				options->userclass.data,
				options->userclass.len);
	}

	if (options->classid && options->classid[0]) {
		ni_dhcp4_option_puts(msgbuf, DHCP4_CLASSID, options->classid);
	}

	return 0;
}
Пример #9
0
static int
__ni_dhcp4_build_msg_put_hwspec(const ni_dhcp4_device_t *dev, ni_dhcp4_message_t *message)
{
	switch (dev->system.hwaddr.type) {
	case ARPHRD_ETHER:
	case ARPHRD_IEEE802:
		if (dev->system.hwaddr.len && dev->system.hwaddr.len <= sizeof(message->chaddr)) {
			message->hwlen = dev->system.hwaddr.len;
			memcpy(&message->chaddr, dev->system.hwaddr.data, dev->system.hwaddr.len);
		}
		break;

	case ARPHRD_IEEE1394:
	case ARPHRD_INFINIBAND:
		/* See http://tools.ietf.org/html/rfc4390
		 *
		 * Note: set the ciaddr before if needed.
		 */
		message->hwlen = 0;
		if (message->ciaddr == 0)
			message->flags = htons(BROADCAST_FLAG);
		break;

	default:
		ni_error("%s: dhcp4 unsupported hardware type %s (0x%x)", dev->ifname,
				ni_arphrd_type_to_name(dev->system.hwaddr.type),
				dev->system.hwaddr.type);
		return -1;
	}
	if (message->hwlen) {
		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: using hw-address[%u]: %s", dev->ifname,
				message->hwtype, ni_print_hex(message->chaddr, message->hwlen));
	}
	if (message->flags & htons(BROADCAST_FLAG)) {
		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: using broadcast response flag", dev->ifname);
	}
	return 0;
}
Пример #10
0
static int
__ni_rtevent_process_nd_radv_opts(ni_netdev_t *dev, const struct nd_opt_hdr *opt, size_t len)
{
	while (len > 0) {
		size_t opt_len;

		if (len < 2) {
			ni_error("%s: nd user option length too short", dev->name);
			return -1;
		}

		opt_len = (opt->nd_opt_len << 3);
		if (opt_len == 0) {
			ni_error("%s: zero length nd user option", dev->name);
			return -1;
		}
		else if (opt_len > len) {
			ni_error("%s: nd user option length exceeds total length",
				dev->name);
			return -1;
		}

		switch(opt->nd_opt_type) {
		case NI_ND_OPT_RDNSS_INFORMATION:
			if (__ni_rtevent_process_rdnss_info(dev, opt, opt_len) < 0) {
				ni_error("%s: Cannot process RDNSS info option",
					dev->name);
				return -1;
			}
		break;

		case NI_ND_OPT_DNSSL_INFORMATION:
			if (__ni_rtevent_process_dnssl_info(dev, opt, opt_len) < 0) {
				ni_error("%s: Cannot process DNSSL info option",
					dev->name);
				return -1;
			}
		break;

		default:
			/* kernels up to at least 3.4 do not provide other */
			ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_IPV6|NI_TRACE_EVENTS,
					"%s: unhandled nd user option %d",
					dev->name, opt->nd_opt_type);
		break;
		}

		len -= opt_len;
		opt = (struct nd_opt_hdr *)(((uint8_t *)opt) + opt_len);
	}
	return 0;
}
Пример #11
0
void
ni_server_trace_interface_addr_events(ni_netdev_t *dev, ni_event_t event, const ni_address_t *ap)
{
	ni_stringbuf_t flags = NI_STRINGBUF_INIT_DYNAMIC;

	ni_address_format_flags(&flags, ap->family, ap->flags, NULL);
	ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS,
			"%s: %s event: %s flags[%u] %s",
			dev->name, ni_event_type_to_name(event),
			ni_sockaddr_prefix_print(&ap->local_addr, ap->prefixlen),
			ap->flags, flags.string ? flags.string : "");
	ni_stringbuf_destroy(&flags);
}
Пример #12
0
/*
 * Reload an old lease from file, and see whether we can reuse it.
 * This is used during restart of wickedd.
 */
int
ni_dhcp4_recover_lease(ni_dhcp4_device_t *dev)
{
	ni_addrconf_lease_t *lease;
	ni_sockaddr_t addr;

	if (dev->lease)
		return 1;

	lease = ni_addrconf_lease_file_read(dev->ifname, NI_ADDRCONF_DHCP, AF_INET);
	if (!lease)
		return -1;

	if (!ni_addrconf_lease_is_valid(dev->lease)) {
		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: discarding existing lease, not granted",
				dev->ifname);
		goto discard;
	}

	/* We cannot renew/rebind/reboot without it */
	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.server_id, 0);
	if (!ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: discarding existing lease, no server-id",
				dev->ifname);
		goto discard;
	}

	ni_dhcp4_device_set_lease(dev, lease);
	return 0;

discard:
	ni_addrconf_lease_free(lease);
	return -1;
}
Пример #13
0
int
__ni_dhcp4_build_msg_inform(const ni_dhcp4_device_t *dev,
			const ni_addrconf_lease_t *lease,
			ni_buffer_t *msgbuf)
{
	const ni_dhcp4_config_t *options = dev->config;
	unsigned int msg_code = DHCP4_INFORM;
	ni_dhcp4_message_t *message;
	ni_sockaddr_t addr;

	/* Inform server about IP address we use and request other config */
	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0);
	if (!ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_error("%s: cannot inform - no ip-address set", dev->ifname);
		return -1;
	}

	if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf)))
		return -1;

	message->ciaddr = lease->dhcp4.address.s_addr;
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using inform ip-address: %s",
			dev->ifname, ni_sockaddr_print(&addr));

	if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0)
		return -1;

	if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) <  0)
		return -1;

	if (__ni_dhcp4_build_msg_put_option_request(dev, msg_code, msgbuf) <  0)
		return -1;

	ni_dhcp4_option_put16(msgbuf, DHCP4_MAXMESSAGESIZE, dev->system.mtu);

	if (options->userclass.len > 0) {
		ni_dhcp4_option_put(msgbuf, DHCP4_USERCLASS,
				options->userclass.data,
				options->userclass.len);
	}

	if (options->classid && options->classid[0]) {
		ni_dhcp4_option_puts(msgbuf, DHCP4_CLASSID, options->classid);
	}

	return 0;
}
Пример #14
0
static int
ni_ethtool_call(const char *ifname, const ni_ethtool_cmd_info_t *ioc, void *evp, const char *flag)
{
	int ret;

	ret = __ni_ethtool(ifname, ioc->cmd, evp);
	if (ret < 0) {
		ret = -errno;
		if (errno != EOPNOTSUPP && errno != ENODEV)
			ni_warn("%s: ethtool %s%s failed: %m", ifname, ioc->name, flag ? flag : "");
		else
			ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IFCONFIG,
				"%s: ethtool %s%s failed: %m", ifname, ioc->name, flag ? flag : "");
		errno = -ret;
	}
	return ret;
}
Пример #15
0
static int
__ni_dhcp4_build_msg_put_server_id(const ni_dhcp4_device_t *dev,
				const ni_addrconf_lease_t *lease,
				unsigned int msg_code, ni_buffer_t *msgbuf)
{
	ni_sockaddr_t addr;

	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.server_id, 0);
	if (!ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_error("%s: cannot construct %s without server-id",
				dev->ifname, ni_dhcp4_message_name(msg_code));
		return -1;
	}

	ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_SERVERIDENTIFIER, lease->dhcp4.server_id);
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using server-id: %s", dev->ifname,
			ni_sockaddr_print(&addr));
	return 0;
}
Пример #16
0
void
ni_server_trace_interface_prefix_events(ni_netdev_t *dev, ni_event_t event, const ni_ipv6_ra_pinfo_t *pi)
{
	char vbuf[32] = {'\0'}, pbuf[32] = {'\0'};
	ni_stringbuf_t vlft = NI_STRINGBUF_INIT_BUFFER(vbuf);
	ni_stringbuf_t plft = NI_STRINGBUF_INIT_BUFFER(pbuf);

	ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS,
		"%s: %s IPv6 RA<%s> Prefix<%s/%u %s,%s>[%s,%s]", dev->name,
		(event == NI_EVENT_PREFIX_UPDATE ? "update" : "delete"),
		(dev->ipv6 && dev->ipv6->radv.managed_addr ? "managed" :
		(dev->ipv6 && dev->ipv6->radv.other_config ? "config" : "unmanaged")),
		ni_sockaddr_print(&pi->prefix), pi->length,
		(pi->on_link ? "onlink" : "not-onlink"),
		(pi->autoconf ? "autoconf" : "no-autoconf"),
		ni_lifetime_print_valid(&vlft, pi->valid_lft),
		ni_lifetime_print_preferred(&plft, pi->preferred_lft));
	ni_stringbuf_destroy(&vlft);
	ni_stringbuf_destroy(&plft);
}
Пример #17
0
void
ni_server_trace_rule_events(ni_netconfig_t *nc, ni_event_t event, const ni_rule_t *rule)
{
	ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC;
	unsigned int family_trace;

	switch (rule->family) {
	case AF_INET:
		family_trace = NI_TRACE_IPV4;
		break;
	case AF_INET6:
		family_trace = NI_TRACE_IPV6;
		break;
	default:
		family_trace = 0;
		break;
	}
	ni_debug_verbose(NI_LOG_DEBUG2, family_trace|NI_TRACE_ROUTE|NI_TRACE_EVENTS,
			"%s event: %s", ni_event_type_to_name(event),
			ni_rule_print(&buf, rule));
	ni_stringbuf_destroy(&buf);
}
Пример #18
0
static int
__ni_dhcp4_build_msg_decline(const ni_dhcp4_device_t *dev,
			const ni_addrconf_lease_t *lease,
			ni_buffer_t *msgbuf)
{
	unsigned int msg_code = DHCP4_DECLINE;
	ni_dhcp4_message_t *message;
	ni_sockaddr_t addr;

	/* Decline IP address the server offered to us;
	 * we've found another host using it already.
	 */
	ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0);
	if (!ni_sockaddr_is_ipv4_specified(&addr)) {
		ni_error("%s: cannot decline - no ip-address in lease", dev->ifname);
		return -1;
	}

	if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf)))
		return -1;

	if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0)
		return -1;

	if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) <  0)
		return -1;

	if (__ni_dhcp4_build_msg_put_server_id(dev, lease, msg_code, msgbuf) <  0)
		return -1;

	ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_ADDRESS, lease->dhcp4.address);
	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using decline ip-address: %s",
			dev->ifname, ni_sockaddr_print(&addr));
	return 0;
}
Пример #19
0
static int
__ni_dhcp4_build_msg_put_our_hostname(const ni_dhcp4_device_t *dev,
					ni_buffer_t *msgbuf)
{
	const ni_dhcp4_config_t *options = dev->config;
	size_t len = ni_string_len(options->hostname);

	if (!len)
		return 1; /* skipped hint */

	if (options->fqdn == FQDN_DISABLE) {
		char hname[64] = {'\0'}, *end;

		/*
		 * Truncate the domain part if fqdn to avoid attempts
		 * to update DNS with foo.bar + update-domain.
		 */
		strncat(hname, options->hostname, sizeof(hname)-1);
		if ((end = strchr(hname, '.')))
			*end = '\0';

		len = ni_string_len(hname);
		if (ni_check_domain_name(hname, len, 0)) {
			ni_dhcp4_option_puts(msgbuf, DHCP4_HOSTNAME, hname);
			ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: using hostname: %s", dev->ifname, hname);
		} else {
			ni_info("%s: not sending suspect hostname: '%s'",
				dev->ifname, ni_print_suspect(hname, len));
			return 1;
		}
	} else
	if (ni_check_domain_name(options->hostname, len, 0)) {
		/* IETF DHC-FQDN option(81)
		 * http://tools.ietf.org/html/rfc4702#section-2.1
		 *
		 * Flags: 0000NEOS
		 * S: 1 => Client requests Server to update
		 *         a RR in DNS as well as PTR
		 * O: 1 => Server indicates to client that
		 *         DNS has been updated
		 * E: 1 => Name data is DNS format
		 * N: 1 => Client requests Server to not
		 *         update DNS
		 */
		ni_buffer_putc(msgbuf, DHCP4_FQDN);
		ni_buffer_putc(msgbuf, len + 3);
		ni_buffer_putc(msgbuf, options->fqdn & 0x9);
		ni_buffer_putc(msgbuf, 0);	/* from server for PTR RR */
		ni_buffer_putc(msgbuf, 0);	/* from server for A RR if S=1 */
		ni_buffer_put(msgbuf, options->hostname, len);
		ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
				"%s: using fqdn: %s", dev->ifname,
				options->hostname);
	} else {
		ni_info("%s: not sending suspect fqdn: '%s'",
			dev->ifname, ni_print_suspect(options->hostname, len));
		return 1;
	}

	return 0;
}
Пример #20
0
static int
__ni_rtevent_process_dnssl_info(ni_netdev_t *dev, const struct nd_opt_hdr *opt, size_t len)
{
	const struct ni_nd_opt_dnssl_info_p *dopt;
	ni_ipv6_devinfo_t *ipv6;
	unsigned int lifetime;
	struct timeval acquired;
	size_t length, cnt, off;
	ni_bool_t emit = FALSE;
	char domain[256];

	if (opt == NULL || len < sizeof(*dopt)) {
		ni_error("%s: unable to parse ipv6 dnssl info event data -- too short",
				dev->name);
		return -1;
	}

	ipv6 = ni_netdev_get_ipv6(dev);
	if (!ipv6) {
		ni_error("%s: unable to allocate device ipv6 structure: %m",
				dev->name);
		return -1;
	}

	dopt = (const struct ni_nd_opt_dnssl_info_p *)opt;
	len -= sizeof(*dopt);

	ni_timer_get_time(&acquired);
	lifetime = ntohl(dopt->nd_opt_dnssl_lifetime);

	length = 0;
	domain[length] = '\0';
	for (off = 0; off < len ; ) {
		cnt = dopt->nd_opt_dnssl_list[off++];
		if (cnt == 0) {
			/* just padding */
			if (domain[0] == '\0')
				continue;

			domain[length] = '\0';
			if (!ni_check_domain_name(domain, length, 0)) {
				ni_debug_verbose(NI_LOG_DEBUG, NI_TRACE_IPV6|NI_TRACE_EVENTS,
					"%s: ignoring suspect DNSSL domain: %s",
					dev->name, ni_print_suspect(domain, length));
			} else
			if (!ni_ipv6_ra_dnssl_list_update(&ipv6->radv.dnssl,
						domain, lifetime, &acquired)) {
				ni_debug_verbose(NI_LOG_DEBUG, NI_TRACE_IPV6|NI_TRACE_EVENTS,
						"%s: unable to track ipv6 dnssl domain %s",
						dev->name, domain);
			} else
				emit = TRUE;

			length = 0;
			domain[length] = '\0';
			continue;
		}

		if ((off + cnt >= len) || (length + cnt + 2 > sizeof(domain)))
			break;

		if (length)
			domain[length++] = '.';
		memcpy(&domain[length], &dopt->nd_opt_dnssl_list[off], cnt);
		off += cnt;
		length += cnt;
		domain[length] = '\0';
	}

	if (emit)
		__ni_netdev_nduseropt_event(dev, NI_EVENT_DNSSL_UPDATE);
	return 0;
}
Пример #21
0
static int
__ni_dhcp4_build_msg_put_option_request(const ni_dhcp4_device_t *dev,
					unsigned int msg_code, ni_buffer_t *msgbuf)
{
	const ni_dhcp4_config_t *options = dev->config;
	unsigned int params_begin;

	switch (msg_code) {
	case DHCP4_DISCOVER:
	case DHCP4_REQUEST:
	case DHCP4_INFORM:
		break;
	default:
		return 1; /* skipped hint */
	}

	params_begin = ni_dhcp4_option_begin(msgbuf, DHCP4_PARAMETERREQUESTLIST);
	if (msg_code != DHCP4_INFORM) {
		ni_buffer_putc(msgbuf, DHCP4_RENEWALTIME);
		ni_buffer_putc(msgbuf, DHCP4_REBINDTIME);
	}
	ni_buffer_putc(msgbuf, DHCP4_NETMASK);
	ni_buffer_putc(msgbuf, DHCP4_BROADCAST);
	ni_buffer_putc(msgbuf, DHCP4_MTU);

	/*
	 * RFC 3442 states classless static routes override both,
	 * the (default) router and (class) static routes options.
	 * Keep them in front also on request... just in case.
	 */
	if (options->doflags & DHCP4_DO_CSR) {
		ni_buffer_putc(msgbuf, DHCP4_CSR);
	}
	if (options->doflags & DHCP4_DO_MSCSR) {
		ni_buffer_putc(msgbuf, DHCP4_MSCSR);
	}
	if (options->doflags & DHCP4_DO_GATEWAY) {
		ni_buffer_putc(msgbuf, DHCP4_STATICROUTE);
		ni_buffer_putc(msgbuf, DHCP4_ROUTERS);
	}
	if (options->doflags & DHCP4_DO_HOSTNAME) {
		if (options->fqdn == FQDN_DISABLE) {
			ni_buffer_putc(msgbuf, DHCP4_HOSTNAME);
		} else {
			ni_buffer_putc(msgbuf, DHCP4_FQDN);
		}
	}
	if (options->doflags & DHCP4_DO_DNS) {
		ni_buffer_putc(msgbuf, DHCP4_DNSSEARCH);
		ni_buffer_putc(msgbuf, DHCP4_DNSDOMAIN);
		ni_buffer_putc(msgbuf, DHCP4_DNSSERVER);
	}
	if (options->doflags & DHCP4_DO_NIS) {
		ni_buffer_putc(msgbuf, DHCP4_NISDOMAIN);
		ni_buffer_putc(msgbuf, DHCP4_NISSERVER);
	}
	if (options->doflags & DHCP4_DO_NTP) {
		ni_buffer_putc(msgbuf, DHCP4_NTPSERVER);
	}
	if (options->doflags & DHCP4_DO_ROOT) {
		ni_buffer_putc(msgbuf, DHCP4_ROOTPATH);
	}
	if (options->doflags & DHCP4_DO_LPR) {
		ni_buffer_putc(msgbuf, DHCP4_LPRSERVER);
	}
	if (options->doflags & DHCP4_DO_LOG) {
		ni_buffer_putc(msgbuf, DHCP4_LOGSERVER);
	}
	if (options->doflags & DHCP4_DO_NDS) {
		ni_buffer_putc(msgbuf, DHCP4_NDS_SERVER);
		ni_buffer_putc(msgbuf, DHCP4_NDS_TREE);
		ni_buffer_putc(msgbuf, DHCP4_NDS_CTX);
	}
	if (options->doflags & DHCP4_DO_SIP) {
		ni_buffer_putc(msgbuf, DHCP4_SIPSERVER);
	}
	if (options->doflags & DHCP4_DO_SMB) {
		ni_buffer_putc(msgbuf, DHCP4_NETBIOSNAMESERVER);
		ni_buffer_putc(msgbuf, DHCP4_NETBIOSDDSERVER);
		ni_buffer_putc(msgbuf, DHCP4_NETBIOSNODETYPE);
		ni_buffer_putc(msgbuf, DHCP4_NETBIOSSCOPE);
	}
	if (options->doflags & DHCP4_DO_POSIX_TZ) {
		ni_buffer_putc(msgbuf, DHCP4_POSIX_TZ_STRING);
		ni_buffer_putc(msgbuf, DHCP4_POSIX_TZ_DBNAME);
	}
	ni_dhcp4_option_end(msgbuf, params_begin);

	ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP,
			"%s: using an option request", dev->ifname);

	return 0;
}