1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/*
2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon
3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved
5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without
7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions
8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met:
9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright
10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    notice, this list of conditions and the following disclaimer.
11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright
12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    notice, this list of conditions and the following disclaimer in the
13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    documentation and/or other materials provided with the distribution.
14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *
15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE.
26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */
27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/socket.h>
29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/types.h>
30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <net/if.h>
32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/in.h>
33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <netinet/if_ether.h>
34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h>
36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <signal.h>
37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h>
38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h>
39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h>
40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ELOOP_QUEUE 5
42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h"
43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "arp.h"
44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h"
45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv4.h"
46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h"
47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h"
48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcpcd.h"
49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "eloop.h"
50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h"
51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if-options.h"
52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv4ll.h"
53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ARP_LEN								      \
55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic ssize_t
58f20514bf582d08567217a3b06171bab5a11458eaSamuel Tanarp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip,
59f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	    const uint8_t *dest_hw_addr)
60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	uint8_t arp_buffer[ARP_LEN];
62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arphdr ar;
63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	size_t len;
64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	uint8_t *p;
65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ar.ar_hrd = htons(ifp->family);
67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ar.ar_pro = htons(ETHERTYPE_IP);
68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ar.ar_hln = ifp->hwlen;
69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ar.ar_pln = sizeof(sip);
70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ar.ar_op = htons(ARPOP_REQUEST);
71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	p = arp_buffer;
73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	len = 0;
74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define CHECK(fun, b, l)						\
76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	do {								\
77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (len + (l) > sizeof(arp_buffer))			\
78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			goto eexit;					\
79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		fun(p, (b), (l));					\
80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		p += (l);						\
81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		len += (l);						\
82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} while (/* CONSTCOND */ 0)
83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define APPEND(b, l)	CHECK(memcpy, b, l)
84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ZERO(l)		CHECK(memset, 0, l)
85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	APPEND(&ar, sizeof(ar));
87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	APPEND(ifp->hwaddr, ifp->hwlen);
88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	APPEND(&sip, sizeof(sip));
89f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	if (dest_hw_addr)
90f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan		APPEND(dest_hw_addr, ifp->hwlen);
91f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	else
92f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan		ZERO(ifp->hwlen);
93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	APPEND(&tip, sizeof(tip));
94f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	return if_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len,
95f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan				dest_hw_addr);
96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneexit:
98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	errno = ENOBUFS;
99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return -1;
100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_report_conflicted(const struct arp_state *astate, const struct arp_msg *amsg)
104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (amsg) {
107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		char buf[HWADDR_LEN * 3];
108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(astate->iface->ctx, LOG_ERR,
110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    "%s: hardware address %s claims %s",
111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    astate->iface->name,
112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    hwaddr_ntoa(amsg->sha, astate->iface->hwlen,
113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    buf, sizeof(buf)),
114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    inet_ntoa(astate->failed));
115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else
116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(astate->iface->ctx, LOG_ERR,
117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    "%s: DAD detected %s",
118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    astate->iface->name, inet_ntoa(astate->failed));
119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_packet(void *arg)
123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct interface *ifp = arg;
125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct interface *ifn;
126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	uint8_t arp_buffer[ARP_LEN];
127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arphdr ar;
128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_msg arm;
129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ssize_t bytes;
130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state;
131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate, *astaten;
132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	unsigned char *hw_s, *hw_t;
133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	int flags;
134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state = D_STATE(ifp);
1365158c9dfe576a285663b4ba16828fd6e9b35779cSamuel Tan	state->failed.s_addr = 0;
137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	flags = 0;
138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	while (!(flags & RAW_EOF)) {
139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    arp_buffer, sizeof(arp_buffer), &flags);
141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (bytes == -1) {
142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(ifp->ctx, LOG_ERR,
143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    "%s: arp if_readrawpacket: %m", ifp->name);
144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			dhcp_close(ifp);
145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			return;
146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* We must have a full ARP header */
148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if ((size_t)bytes < sizeof(ar))
149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		memcpy(&ar, arp_buffer, sizeof(ar));
151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Families must match */
152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ar.ar_hrd != htons(ifp->family))
153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Protocol must be IP. */
155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ar.ar_pro != htons(ETHERTYPE_IP))
156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ar.ar_pln != sizeof(arm.sip.s_addr))
158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Only these types are recognised */
160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ar.ar_op != htons(ARPOP_REPLY) &&
161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    ar.ar_op != htons(ARPOP_REQUEST))
162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Get pointers to the hardware addreses */
165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		hw_s = arp_buffer + sizeof(ar);
166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		hw_t = hw_s + ar.ar_hln + ar.ar_pln;
167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Ensure we got all the data */
168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Ignore messages from ourself */
171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (ar.ar_hln == ifn->hwlen &&
173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				break;
175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ifn)
177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Copy out the HW and IP addresses */
179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		memcpy(&arm.sha, hw_s, ar.ar_hln);
180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		memcpy(&arm.tha, hw_t, ar.ar_hln);
182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Run the conflicts */
185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (astate->conflicted_cb)
187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				astate->conflicted_cb(astate, &arm);
188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_open(struct interface *ifp)
194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state;
196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state = D_STATE(ifp);
198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->arp_fd == -1) {
199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (state->arp_fd == -1) {
201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    __func__, ifp->name);
203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			return;
204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		eloop_event_add(ifp->ctx->eloop, state->arp_fd,
206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    arp_packet, ifp, NULL, NULL);
207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_announced(void *arg)
212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate = arg;
214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (astate->announced_cb) {
216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->announced_cb(astate);
217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Nothing more to do, so free us */
221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_free(astate);
222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_announce1(void *arg)
226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate = arg;
228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct interface *ifp = astate->iface;
229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (++astate->claims < ANNOUNCE_NUM)
231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_DEBUG,
232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    "%s: ARP announcing %s (%d of %d), "
233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    "next in %d.0 seconds",
234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    ifp->name, inet_ntoa(astate->addr),
235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    astate->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT);
236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	else
237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_DEBUG,
238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    "%s: ARP announcing %s (%d of %d)",
239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    ifp->name, inet_ntoa(astate->addr),
240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    astate->claims, ANNOUNCE_NUM);
241f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr,
242f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan			NULL) == -1)
243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_ERR, "send_arp: %m");
244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    astate);
247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_announce(struct arp_state *astate)
251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_open(astate->iface);
254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->claims = 0;
255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_announce1(astate);
256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_probed(void *arg)
260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate = arg;
262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->probed_cb(astate);
264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_probe1(void *arg)
268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate = arg;
270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct interface *ifp = astate->iface;
271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct timespec tv;
272f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	uint8_t *dest_hwaddr = NULL;
273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (++astate->probes < PROBE_NUM) {
275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		tv.tv_sec = PROBE_MIN;
276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		tv.tv_nsec = (suseconds_t)arc4random_uniform(
277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    (PROBE_MAX - PROBE_MIN) * NSEC_PER_SEC);
278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		timespecnorm(&tv);
279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate);
280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else {
281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		tv.tv_sec = ANNOUNCE_WAIT;
282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		tv.tv_nsec = 0;
283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
28524aa62eefd9284fb94820093f6088607d42c4249Samuel Tan	logger(ifp->ctx, LOG_INFO,
286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    ifp->name, inet_ntoa(astate->addr),
288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    timespec_to_double(&tv));
290f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan	if (astate->dest_hwlen == ifp->hwlen)
291f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan		dest_hwaddr = astate->dest_hwaddr;
2921c4088e958ed0fded0040bcb1d67b73159acfe8cSamuel Tan	if (arp_request(ifp, astate->src_addr.s_addr,
293f20514bf582d08567217a3b06171bab5a11458eaSamuel Tan			astate->addr.s_addr, dest_hwaddr) == -1)
294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_ERR, "send_arp: %m");
295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_probe(struct arp_state *astate)
299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_open(astate->iface);
302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->probes = 0;
303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	logger(astate->iface->ctx, LOG_DEBUG, "%s: probing for %s",
304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    astate->iface->name, inet_ntoa(astate->addr));
305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_probe1(astate);
306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic struct arp_state *
309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_find(struct interface *ifp, const struct in_addr *addr)
310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate;
312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state;
313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state = D_STATE(ifp);
315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_FOREACH(astate, &state->arp_states, next) {
316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp)
317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			return astate;
318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	errno = ESRCH;
320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return NULL;
321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct arp_state *
324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_new(struct interface *ifp, const struct in_addr *addr)
325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate;
327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state;
328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (addr && (astate = arp_find(ifp, addr)))
330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return astate;
331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if ((astate = calloc(1, sizeof(*astate))) == NULL) {
333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return NULL;
335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state = D_STATE(ifp);
337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->iface = ifp;
338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (addr)
339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->addr = *addr;
340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return astate;
342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_cancel(struct arp_state *astate)
346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate);
349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_free(struct arp_state *astate)
353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state;
355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (astate) {
357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate);
358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state = D_STATE(astate->iface);
359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		TAILQ_REMOVE(&state->arp_states, astate, next);
360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (state->arp_ipv4ll == astate) {
361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			ipv4ll_stop(astate->iface);
362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			state->arp_ipv4ll = NULL;
363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(astate);
365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_free_but(struct arp_state *astate)
370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *p, *n;
372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state;
373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state = D_STATE(astate->iface);
375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_FOREACH_SAFE(p, &state->arp_states, next, n) {
376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (p != astate)
377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			arp_free(p);
378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_close(struct interface *ifp)
383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(ifp);
385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate;
386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state == NULL)
388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->arp_fd != -1) {
391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0);
392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		close(state->arp_fd);
393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state->arp_fd = -1;
394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	while ((astate = TAILQ_FIRST(&state->arp_states))) {
397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifndef __clang_analyzer__
398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* clang guard needed for a more compex variant on this bug:
399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		 * http://llvm.org/bugs/show_bug.cgi?id=18222 */
400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		arp_free(astate);
401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanarp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan    int flags)
408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IN_IFF_DUPLICATED
410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(ifp);
411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate, *asn;
412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (cmd != RTM_NEWADDR || (state = D_STATE(ifp)) == NULL)
414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, asn) {
417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (astate->addr.s_addr == addr->s_addr) {
418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (flags & IN_IFF_DUPLICATED) {
419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				if (astate->conflicted_cb)
420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan					astate->conflicted_cb(astate, NULL);
421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			} else if (!(flags & IN_IFF_NOTUSEABLE)) {
422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				if (astate->probed_cb)
423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan					astate->probed_cb(astate);
424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			}
425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else
428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	UNUSED(cmd);
429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	UNUSED(ifp);
430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	UNUSED(addr);
431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	UNUSED(flags);
432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
434