Beispiel #1
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;
}
Beispiel #2
0
/*
 * Decode a CIDR list option.
 */
static int
ni_dhcp_decode_csr(ni_buffer_t *bp, ni_route_array_t *routes)
{
	while (ni_buffer_count(bp) && !bp->underflow) {
		ni_sockaddr_t destination, gateway;
		struct in_addr prefix = { 0 };
		unsigned int prefix_len;
		ni_route_t *rp;

		prefix_len = ni_buffer_getc(bp);
		if (prefix_len > 32) {
			ni_error("invalid prefix len of %u in classless static route", prefix_len);
			return -1;
		}

		if (prefix_len)
			ni_buffer_get(bp, &prefix, (prefix_len + 7) / 8);
		ni_sockaddr_set_ipv4(&destination, prefix, 0);

		if (ni_dhcp_option_get_sockaddr(bp, &gateway) < 0)
			return -1;

		rp = ni_route_create(prefix_len, &destination, &gateway, 0, NULL);
		ni_route_array_append(routes, rp);
	}

	if (bp->underflow)
		return -1;

	return 0;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
0
static ni_bool_t
__ni_dhcp4_address_on_device(const ni_netdev_t *ifp, struct in_addr ipv4)
{
	const ni_address_t *ap;
	ni_sockaddr_t addr;

	ni_sockaddr_set_ipv4(&addr, ipv4, 0);
	for (ap = ifp->addrs; ap; ap = ap->next) {
		if (ap->family != AF_INET)
			continue;

		if (ni_sockaddr_equal(&ap->local_addr, &addr))
			return TRUE;
	}
	return FALSE;
}
Beispiel #7
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;
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #10
0
static void
__do_arp_validate_process(ni_arp_socket_t *sock, const ni_arp_packet_t *pkt,
		void *user_data)
{
	struct arp_handle *handle = user_data;
	ni_netconfig_t *nc = ni_global_state_handle(0);
	const ni_netdev_t *ifp;
	ni_bool_t false_alarm = FALSE;
	ni_bool_t found_addr = FALSE;
	const ni_address_t *ap;
	ni_sockaddr_t addr;

	if (!pkt || pkt->op != ARPOP_REPLY || !handle->replies)
		return;

	/* Is it about the address we're validating at all? */
	if (pkt->sip.s_addr != handle->ipaddr.sin.sin_addr.s_addr) {
		ni_debug_application("%s: report about different address",
				handle->ifname);
		return;
	}

	/* Ignore any ARP replies that seem to come from our own
	 * MAC address. Some helpful switches seem to generate
	 * these. */
	if (ni_link_address_equal(&sock->dev_info.hwaddr, &pkt->sha)) {
		ni_debug_application("%s: adress in use by ourself",
				handle->ifname);
		return;
	}

	/* As well as ARP replies that seem to come from our own
	 * host: dup if same address, not a dup if there are two
	 * interfaces connected to the same broadcast domain.
	 */
	ni_sockaddr_set_ipv4(&addr, pkt->sip, 0);
	for (ifp = ni_netconfig_devlist(nc); ifp; ifp = ifp->next) {
		if (ifp->link.ifindex == sock->dev_info.ifindex)
			continue;

		if (!ni_netdev_link_is_up(ifp))
			continue;

		if (!ni_link_address_equal(&ifp->link.hwaddr, &pkt->sha))
			continue;

		/* OK, we have an interface matching the hwaddr,
		 * which will answer arp requests when it is on
		 * the same broadcast domain and causes a false
		 * alarm, except it really has the IP assigned.
		 */
		false_alarm = TRUE;
		for (ap = ifp->addrs; !found_addr && ap; ap = ap->next) {
			if (ap->family != AF_INET)
				continue;
			if (ni_sockaddr_equal(&ap->local_addr, &addr))
				found_addr = TRUE;
		}
	}
	if (false_alarm && !found_addr) {
		ni_debug_application("%s: reply from one of our interfaces",
				handle->ifname);
		return;
	}

	ni_info("%s: adress %s in use by %s reported",
			handle->ifname,
			inet_ntoa(pkt->sip),
			ni_link_address_print(&pkt->sha));
	handle->hwaddr = pkt->sha;
}