Example #1
0
void
ni_dhcp4_fsm_process_arp_packet(ni_arp_socket_t *arph, const ni_arp_packet_t *pkt, void *user_data)
{
	ni_dhcp4_device_t *dev = 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;

	if (!pkt || pkt->op != ARPOP_REPLY || !dev || !dev->lease)
		return;

	/* Is it about the address we're validating at all? */
	if (pkt->sip.s_addr != dev->lease->dhcp4.address.s_addr)
		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(&dev->system.hwaddr, &pkt->sha))
		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.
	 */
	for (ifp = ni_netconfig_devlist(nc); ifp; ifp = ifp->next) {
		if (ifp->link.ifindex == dev->link.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;
		if (__ni_dhcp4_address_on_device(ifp, pkt->sip))
			found_addr = TRUE;
	}
	if (false_alarm && !found_addr)
		return;

	ni_debug_dhcp("%s: address %s already in use by %s",
			dev->ifname, inet_ntoa(pkt->sip),
			ni_link_address_print(&pkt->sha));
	ni_dhcp4_device_arp_close(dev);
	ni_dhcp4_fsm_decline(dev);
}
Example #2
0
/*
 * Helper functions for matching naming attributes
 */
static ni_bool_t
__match_hwaddr(const ni_hwaddr_t *hwaddr, const char *string)
{
	ni_hwaddr_t match;

	if (!string)
		return FALSE;

	if (ni_link_address_parse(&match, hwaddr->type, string) < 0)
		return FALSE;

	return ni_link_address_equal(hwaddr, &match);
}
Example #3
0
/*
 * Find interface by its LL address
 */
ni_netdev_t *
ni_netdev_by_hwaddr(ni_netconfig_t *nc, const ni_hwaddr_t *lla)
{
	ni_netdev_t *dev;

	if (!lla || !lla->len)
		return NULL;

	for (dev = nc->interfaces; dev; dev = dev->next) {
		if (ni_link_address_equal(&dev->link.hwaddr, lla))
			return dev;
	}

	return NULL;
}
Example #4
0
File: compat.c Project: mchf/wicked
ni_compat_netdev_t *
ni_compat_netdev_by_hwaddr(ni_compat_netdev_array_t *array, const ni_hwaddr_t *hwaddr)
{
	unsigned int i;

	if (array == NULL || hwaddr == NULL || hwaddr->type == 0)
		return NULL;
	for (i = 0; i < array->count; ++i) {
		ni_compat_netdev_t *compat = array->data[i];

		if (ni_link_address_equal(hwaddr, &compat->identify.hwaddr))
			return compat;
	}
	return NULL;
}
Example #5
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;
}