xref: /openbmc/u-boot/net/link_local.c (revision 723806cc5bea9f8b37323dfd7568603f99af6a06)
1d22c338eSJoe Hershberger /*
2d22c338eSJoe Hershberger  * RFC3927 ZeroConf IPv4 Link-Local addressing
3d22c338eSJoe Hershberger  * (see <http://www.zeroconf.org/>)
4d22c338eSJoe Hershberger  *
5d22c338eSJoe Hershberger  * Copied from BusyBox - networking/zcip.c
6d22c338eSJoe Hershberger  *
7d22c338eSJoe Hershberger  * Copyright (C) 2003 by Arthur van Hoff (avh@strangeberry.com)
8d22c338eSJoe Hershberger  * Copyright (C) 2004 by David Brownell
9d22c338eSJoe Hershberger  * Copyright (C) 2010 by Joe Hershberger
10d22c338eSJoe Hershberger  *
11d22c338eSJoe Hershberger  * Licensed under the GPL v2 or later
12d22c338eSJoe Hershberger  */
13d22c338eSJoe Hershberger 
14d22c338eSJoe Hershberger #include <common.h>
15d22c338eSJoe Hershberger #include <net.h>
16d22c338eSJoe Hershberger #include "arp.h"
17d22c338eSJoe Hershberger #include "net_rand.h"
18d22c338eSJoe Hershberger 
19d22c338eSJoe Hershberger /* We don't need more than 32 bits of the counter */
20d22c338eSJoe Hershberger #define MONOTONIC_MS() ((unsigned)get_timer(0) * (1000 / CONFIG_SYS_HZ))
21d22c338eSJoe Hershberger 
22d22c338eSJoe Hershberger enum {
23d22c338eSJoe Hershberger /* 169.254.0.0 */
24d22c338eSJoe Hershberger 	LINKLOCAL_ADDR = 0xa9fe0000,
25d22c338eSJoe Hershberger 
26d22c338eSJoe Hershberger 	IN_CLASSB_NET = 0xffff0000,
27d22c338eSJoe Hershberger 	IN_CLASSB_HOST = 0x0000ffff,
28d22c338eSJoe Hershberger 
29d22c338eSJoe Hershberger /* protocol timeout parameters, specified in seconds */
30d22c338eSJoe Hershberger 	PROBE_WAIT = 1,
31d22c338eSJoe Hershberger 	PROBE_MIN = 1,
32d22c338eSJoe Hershberger 	PROBE_MAX = 2,
33d22c338eSJoe Hershberger 	PROBE_NUM = 3,
34d22c338eSJoe Hershberger 	MAX_CONFLICTS = 10,
35d22c338eSJoe Hershberger 	RATE_LIMIT_INTERVAL = 60,
36d22c338eSJoe Hershberger 	ANNOUNCE_WAIT = 2,
37d22c338eSJoe Hershberger 	ANNOUNCE_NUM = 2,
38d22c338eSJoe Hershberger 	ANNOUNCE_INTERVAL = 2,
39d22c338eSJoe Hershberger 	DEFEND_INTERVAL = 10
40d22c338eSJoe Hershberger };
41d22c338eSJoe Hershberger 
42d22c338eSJoe Hershberger /* States during the configuration process. */
43d22c338eSJoe Hershberger static enum ll_state_t {
44d22c338eSJoe Hershberger 	PROBE = 0,
45d22c338eSJoe Hershberger 	RATE_LIMIT_PROBE,
46d22c338eSJoe Hershberger 	ANNOUNCE,
47d22c338eSJoe Hershberger 	MONITOR,
48d22c338eSJoe Hershberger 	DEFEND,
49d22c338eSJoe Hershberger 	DISABLED
50d22c338eSJoe Hershberger } state = DISABLED;
51d22c338eSJoe Hershberger 
52049a95a7SJoe Hershberger static struct in_addr ip;
53d22c338eSJoe Hershberger static int timeout_ms = -1;
54d22c338eSJoe Hershberger static unsigned deadline_ms;
55d22c338eSJoe Hershberger static unsigned conflicts;
56d22c338eSJoe Hershberger static unsigned nprobes;
57d22c338eSJoe Hershberger static unsigned nclaims;
58d22c338eSJoe Hershberger static int ready;
5999e139d5SMichael Walle static unsigned int seed;
60d22c338eSJoe Hershberger 
61d22c338eSJoe Hershberger static void link_local_timeout(void);
62d22c338eSJoe Hershberger 
63d22c338eSJoe Hershberger /**
64d22c338eSJoe Hershberger  * Pick a random link local IP address on 169.254/16, except that
65d22c338eSJoe Hershberger  * the first and last 256 addresses are reserved.
66d22c338eSJoe Hershberger  */
pick(void)67049a95a7SJoe Hershberger static struct in_addr pick(void)
68d22c338eSJoe Hershberger {
69d22c338eSJoe Hershberger 	unsigned tmp;
70049a95a7SJoe Hershberger 	struct in_addr ip;
71d22c338eSJoe Hershberger 
72d22c338eSJoe Hershberger 	do {
7399e139d5SMichael Walle 		tmp = rand_r(&seed) & IN_CLASSB_HOST;
74d22c338eSJoe Hershberger 	} while (tmp > (IN_CLASSB_HOST - 0x0200));
75049a95a7SJoe Hershberger 	ip.s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
76049a95a7SJoe Hershberger 	return ip;
77d22c338eSJoe Hershberger }
78d22c338eSJoe Hershberger 
79d22c338eSJoe Hershberger /**
80d22c338eSJoe Hershberger  * Return milliseconds of random delay, up to "secs" seconds.
81d22c338eSJoe Hershberger  */
random_delay_ms(unsigned secs)82d22c338eSJoe Hershberger static inline unsigned random_delay_ms(unsigned secs)
83d22c338eSJoe Hershberger {
8499e139d5SMichael Walle 	return rand_r(&seed) % (secs * 1000);
85d22c338eSJoe Hershberger }
86d22c338eSJoe Hershberger 
configure_wait(void)87d22c338eSJoe Hershberger static void configure_wait(void)
88d22c338eSJoe Hershberger {
89d22c338eSJoe Hershberger 	if (timeout_ms == -1)
90d22c338eSJoe Hershberger 		return;
91d22c338eSJoe Hershberger 
92d22c338eSJoe Hershberger 	/* poll, being ready to adjust current timeout */
93d22c338eSJoe Hershberger 	if (!timeout_ms)
94d22c338eSJoe Hershberger 		timeout_ms = random_delay_ms(PROBE_WAIT);
95d22c338eSJoe Hershberger 
96d22c338eSJoe Hershberger 	/* set deadline_ms to the point in time when we timeout */
97d22c338eSJoe Hershberger 	deadline_ms = MONOTONIC_MS() + timeout_ms;
98d22c338eSJoe Hershberger 
994ef8d53cSJoe Hershberger 	debug_cond(DEBUG_DEV_PKT, "...wait %d %s nprobes=%u, nclaims=%u\n",
100d22c338eSJoe Hershberger 		   timeout_ms, eth_get_name(), nprobes, nclaims);
101d22c338eSJoe Hershberger 
102bc0571fcSJoe Hershberger 	net_set_timeout_handler(timeout_ms, link_local_timeout);
103d22c338eSJoe Hershberger }
104d22c338eSJoe Hershberger 
link_local_start(void)105d22c338eSJoe Hershberger void link_local_start(void)
106d22c338eSJoe Hershberger {
107*723806ccSSimon Glass 	ip = env_get_ip("llipaddr");
108049a95a7SJoe Hershberger 	if (ip.s_addr != 0 &&
109049a95a7SJoe Hershberger 	    (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR) {
110d22c338eSJoe Hershberger 		puts("invalid link address");
111d22c338eSJoe Hershberger 		net_set_state(NETLOOP_FAIL);
112d22c338eSJoe Hershberger 		return;
113d22c338eSJoe Hershberger 	}
11427a0f038SAlexandre Messier 	net_netmask.s_addr = htonl(IN_CLASSB_NET);
115d22c338eSJoe Hershberger 
11699e139d5SMichael Walle 	seed = seed_mac();
117049a95a7SJoe Hershberger 	if (ip.s_addr == 0)
118d22c338eSJoe Hershberger 		ip = pick();
119d22c338eSJoe Hershberger 
120d22c338eSJoe Hershberger 	state = PROBE;
121d22c338eSJoe Hershberger 	timeout_ms = 0;
122d22c338eSJoe Hershberger 	conflicts = 0;
123d22c338eSJoe Hershberger 	nprobes = 0;
124d22c338eSJoe Hershberger 	nclaims = 0;
125d22c338eSJoe Hershberger 	ready = 0;
126d22c338eSJoe Hershberger 
127d22c338eSJoe Hershberger 	configure_wait();
128d22c338eSJoe Hershberger }
129d22c338eSJoe Hershberger 
link_local_timeout(void)130d22c338eSJoe Hershberger static void link_local_timeout(void)
131d22c338eSJoe Hershberger {
132d22c338eSJoe Hershberger 	switch (state) {
133d22c338eSJoe Hershberger 	case PROBE:
134d22c338eSJoe Hershberger 		/* timeouts in the PROBE state mean no conflicting ARP packets
135d22c338eSJoe Hershberger 		   have been received, so we can progress through the states */
136d22c338eSJoe Hershberger 		if (nprobes < PROBE_NUM) {
137049a95a7SJoe Hershberger 			struct in_addr zero_ip = {.s_addr = 0};
138049a95a7SJoe Hershberger 
139d22c338eSJoe Hershberger 			nprobes++;
1404ef8d53cSJoe Hershberger 			debug_cond(DEBUG_LL_STATE, "probe/%u %s@%pI4\n",
141d22c338eSJoe Hershberger 				   nprobes, eth_get_name(), &ip);
1420adb5b76SJoe Hershberger 			arp_raw_request(zero_ip, net_null_ethaddr, ip);
143d22c338eSJoe Hershberger 			timeout_ms = PROBE_MIN * 1000;
144d22c338eSJoe Hershberger 			timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
145d22c338eSJoe Hershberger 		} else {
146d22c338eSJoe Hershberger 			/* Switch to announce state */
147d22c338eSJoe Hershberger 			state = ANNOUNCE;
148d22c338eSJoe Hershberger 			nclaims = 0;
1494ef8d53cSJoe Hershberger 			debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n",
150d22c338eSJoe Hershberger 				   nclaims, eth_get_name(), &ip);
1510adb5b76SJoe Hershberger 			arp_raw_request(ip, net_ethaddr, ip);
152d22c338eSJoe Hershberger 			timeout_ms = ANNOUNCE_INTERVAL * 1000;
153d22c338eSJoe Hershberger 		}
154d22c338eSJoe Hershberger 		break;
155d22c338eSJoe Hershberger 	case RATE_LIMIT_PROBE:
156d22c338eSJoe Hershberger 		/* timeouts in the RATE_LIMIT_PROBE state mean no conflicting
157d22c338eSJoe Hershberger 		   ARP packets have been received, so we can move immediately
158d22c338eSJoe Hershberger 		   to the announce state */
159d22c338eSJoe Hershberger 		state = ANNOUNCE;
160d22c338eSJoe Hershberger 		nclaims = 0;
1614ef8d53cSJoe Hershberger 		debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n",
162d22c338eSJoe Hershberger 			   nclaims, eth_get_name(), &ip);
1630adb5b76SJoe Hershberger 		arp_raw_request(ip, net_ethaddr, ip);
164d22c338eSJoe Hershberger 		timeout_ms = ANNOUNCE_INTERVAL * 1000;
165d22c338eSJoe Hershberger 		break;
166d22c338eSJoe Hershberger 	case ANNOUNCE:
167d22c338eSJoe Hershberger 		/* timeouts in the ANNOUNCE state mean no conflicting ARP
168d22c338eSJoe Hershberger 		   packets have been received, so we can progress through
169d22c338eSJoe Hershberger 		   the states */
170d22c338eSJoe Hershberger 		if (nclaims < ANNOUNCE_NUM) {
171d22c338eSJoe Hershberger 			nclaims++;
1724ef8d53cSJoe Hershberger 			debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n",
173d22c338eSJoe Hershberger 				   nclaims, eth_get_name(), &ip);
1740adb5b76SJoe Hershberger 			arp_raw_request(ip, net_ethaddr, ip);
175d22c338eSJoe Hershberger 			timeout_ms = ANNOUNCE_INTERVAL * 1000;
176d22c338eSJoe Hershberger 		} else {
177d22c338eSJoe Hershberger 			/* Switch to monitor state */
178d22c338eSJoe Hershberger 			state = MONITOR;
179d22c338eSJoe Hershberger 			printf("Successfully assigned %pI4\n", &ip);
180049a95a7SJoe Hershberger 			net_copy_ip(&net_ip, &ip);
181d22c338eSJoe Hershberger 			ready = 1;
182d22c338eSJoe Hershberger 			conflicts = 0;
183d22c338eSJoe Hershberger 			timeout_ms = -1;
184d22c338eSJoe Hershberger 			/* Never timeout in the monitor state */
185bc0571fcSJoe Hershberger 			net_set_timeout_handler(0, NULL);
186d22c338eSJoe Hershberger 
187d22c338eSJoe Hershberger 			/* NOTE: all other exit paths should deconfig ... */
188d22c338eSJoe Hershberger 			net_set_state(NETLOOP_SUCCESS);
189d22c338eSJoe Hershberger 			return;
190d22c338eSJoe Hershberger 		}
191d22c338eSJoe Hershberger 		break;
192d22c338eSJoe Hershberger 	case DEFEND:
193d22c338eSJoe Hershberger 		/* We won!  No ARP replies, so just go back to monitor */
194d22c338eSJoe Hershberger 		state = MONITOR;
195d22c338eSJoe Hershberger 		timeout_ms = -1;
196d22c338eSJoe Hershberger 		conflicts = 0;
197d22c338eSJoe Hershberger 		break;
198d22c338eSJoe Hershberger 	default:
199d22c338eSJoe Hershberger 		/* Invalid, should never happen.  Restart the whole protocol */
200d22c338eSJoe Hershberger 		state = PROBE;
201d22c338eSJoe Hershberger 		ip = pick();
202d22c338eSJoe Hershberger 		timeout_ms = 0;
203d22c338eSJoe Hershberger 		nprobes = 0;
204d22c338eSJoe Hershberger 		nclaims = 0;
205d22c338eSJoe Hershberger 		break;
206d22c338eSJoe Hershberger 	}
207d22c338eSJoe Hershberger 	configure_wait();
208d22c338eSJoe Hershberger }
209d22c338eSJoe Hershberger 
link_local_receive_arp(struct arp_hdr * arp,int len)210d22c338eSJoe Hershberger void link_local_receive_arp(struct arp_hdr *arp, int len)
211d22c338eSJoe Hershberger {
212d22c338eSJoe Hershberger 	int source_ip_conflict;
213d22c338eSJoe Hershberger 	int target_ip_conflict;
214049a95a7SJoe Hershberger 	struct in_addr null_ip = {.s_addr = 0};
215d22c338eSJoe Hershberger 
216d22c338eSJoe Hershberger 	if (state == DISABLED)
217d22c338eSJoe Hershberger 		return;
218d22c338eSJoe Hershberger 
219d22c338eSJoe Hershberger 	/* We need to adjust the timeout in case we didn't receive a
220d22c338eSJoe Hershberger 	   conflicting packet. */
221d22c338eSJoe Hershberger 	if (timeout_ms > 0) {
222d22c338eSJoe Hershberger 		unsigned diff = deadline_ms - MONOTONIC_MS();
223d22c338eSJoe Hershberger 		if ((int)(diff) < 0) {
224d22c338eSJoe Hershberger 			/* Current time is greater than the expected timeout
225d22c338eSJoe Hershberger 			   time. This should never happen */
2264ef8d53cSJoe Hershberger 			debug_cond(DEBUG_LL_STATE,
2274ef8d53cSJoe Hershberger 				   "missed an expected timeout\n");
228d22c338eSJoe Hershberger 			timeout_ms = 0;
229d22c338eSJoe Hershberger 		} else {
2304ef8d53cSJoe Hershberger 			debug_cond(DEBUG_INT_STATE, "adjusting timeout\n");
231d22c338eSJoe Hershberger 			timeout_ms = diff | 1; /* never 0 */
232d22c338eSJoe Hershberger 		}
233d22c338eSJoe Hershberger 	}
234b6841157Sbenoit.thebaudeau@advans #if 0
235b6841157Sbenoit.thebaudeau@advans  /* XXX Don't bother with ethernet link just yet */
236d22c338eSJoe Hershberger 	if ((fds[0].revents & POLLIN) == 0) {
237d22c338eSJoe Hershberger 		if (fds[0].revents & POLLERR) {
2383fe63839SWolfgang Denk 			/*
2393fe63839SWolfgang Denk 			 * FIXME: links routinely go down;
2403fe63839SWolfgang Denk 			 */
241d22c338eSJoe Hershberger 			bb_error_msg("iface %s is down", eth_get_name());
2428e7ff677SJoe Hershberger 			if (ready)
243d22c338eSJoe Hershberger 				run(argv, "deconfig", &ip);
244d22c338eSJoe Hershberger 			return EXIT_FAILURE;
245d22c338eSJoe Hershberger 		}
246d22c338eSJoe Hershberger 		continue;
247d22c338eSJoe Hershberger 	}
248b6841157Sbenoit.thebaudeau@advans #endif
249d22c338eSJoe Hershberger 
2504ef8d53cSJoe Hershberger 	debug_cond(DEBUG_INT_STATE, "%s recv arp type=%d, op=%d,\n",
251d22c338eSJoe Hershberger 		   eth_get_name(), ntohs(arp->ar_pro),
252d22c338eSJoe Hershberger 		   ntohs(arp->ar_op));
2534ef8d53cSJoe Hershberger 	debug_cond(DEBUG_INT_STATE, "\tsource=%pM %pI4\n",
254d22c338eSJoe Hershberger 		   &arp->ar_sha,
255d22c338eSJoe Hershberger 		   &arp->ar_spa);
2564ef8d53cSJoe Hershberger 	debug_cond(DEBUG_INT_STATE, "\ttarget=%pM %pI4\n",
257d22c338eSJoe Hershberger 		   &arp->ar_tha,
258d22c338eSJoe Hershberger 		   &arp->ar_tpa);
259d22c338eSJoe Hershberger 
2608e7ff677SJoe Hershberger 	if (arp->ar_op != htons(ARPOP_REQUEST) &&
2618e7ff677SJoe Hershberger 	    arp->ar_op != htons(ARPOP_REPLY)) {
262d22c338eSJoe Hershberger 		configure_wait();
263d22c338eSJoe Hershberger 		return;
264d22c338eSJoe Hershberger 	}
265d22c338eSJoe Hershberger 
266d22c338eSJoe Hershberger 	source_ip_conflict = 0;
267d22c338eSJoe Hershberger 	target_ip_conflict = 0;
268d22c338eSJoe Hershberger 
2690adb5b76SJoe Hershberger 	if (memcmp(&arp->ar_spa, &ip, ARP_PLEN) == 0 &&
2700adb5b76SJoe Hershberger 	    memcmp(&arp->ar_sha, net_ethaddr, ARP_HLEN) != 0)
271d22c338eSJoe Hershberger 		source_ip_conflict = 1;
2725da7cf81SJoe Hershberger 
2735da7cf81SJoe Hershberger 	/*
2745da7cf81SJoe Hershberger 	 * According to RFC 3927, section 2.2.1:
2755da7cf81SJoe Hershberger 	 * Check if packet is an ARP probe by checking for a null source IP
2765da7cf81SJoe Hershberger 	 * then check that target IP is equal to ours and source hw addr
2775da7cf81SJoe Hershberger 	 * is not equal to ours. This condition should cause a conflict only
2785da7cf81SJoe Hershberger 	 * during probe.
2795da7cf81SJoe Hershberger 	 */
2805da7cf81SJoe Hershberger 	if (arp->ar_op == htons(ARPOP_REQUEST) &&
2815da7cf81SJoe Hershberger 	    memcmp(&arp->ar_spa, &null_ip, ARP_PLEN) == 0 &&
2825da7cf81SJoe Hershberger 	    memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0 &&
2830adb5b76SJoe Hershberger 	    memcmp(&arp->ar_sha, net_ethaddr, ARP_HLEN) != 0) {
284d22c338eSJoe Hershberger 		target_ip_conflict = 1;
285d22c338eSJoe Hershberger 	}
286d22c338eSJoe Hershberger 
2874ef8d53cSJoe Hershberger 	debug_cond(DEBUG_NET_PKT,
2884ef8d53cSJoe Hershberger 		   "state = %d, source ip conflict = %d, target ip conflict = "
2894ef8d53cSJoe Hershberger 		   "%d\n", state, source_ip_conflict, target_ip_conflict);
290d22c338eSJoe Hershberger 	switch (state) {
291d22c338eSJoe Hershberger 	case PROBE:
292d22c338eSJoe Hershberger 	case ANNOUNCE:
293d22c338eSJoe Hershberger 		/* When probing or announcing, check for source IP conflicts
294d22c338eSJoe Hershberger 		   and other hosts doing ARP probes (target IP conflicts). */
295d22c338eSJoe Hershberger 		if (source_ip_conflict || target_ip_conflict) {
296d22c338eSJoe Hershberger 			conflicts++;
297d22c338eSJoe Hershberger 			state = PROBE;
298d22c338eSJoe Hershberger 			if (conflicts >= MAX_CONFLICTS) {
299d22c338eSJoe Hershberger 				debug("%s ratelimit\n", eth_get_name());
300d22c338eSJoe Hershberger 				timeout_ms = RATE_LIMIT_INTERVAL * 1000;
301d22c338eSJoe Hershberger 				state = RATE_LIMIT_PROBE;
302d22c338eSJoe Hershberger 			}
303d22c338eSJoe Hershberger 
304d22c338eSJoe Hershberger 			/* restart the whole protocol */
305d22c338eSJoe Hershberger 			ip = pick();
306d22c338eSJoe Hershberger 			timeout_ms = 0;
307d22c338eSJoe Hershberger 			nprobes = 0;
308d22c338eSJoe Hershberger 			nclaims = 0;
309d22c338eSJoe Hershberger 		}
310d22c338eSJoe Hershberger 		break;
311d22c338eSJoe Hershberger 	case MONITOR:
312d22c338eSJoe Hershberger 		/* If a conflict, we try to defend with a single ARP probe */
313d22c338eSJoe Hershberger 		if (source_ip_conflict) {
314d22c338eSJoe Hershberger 			debug("monitor conflict -- defending\n");
315d22c338eSJoe Hershberger 			state = DEFEND;
316d22c338eSJoe Hershberger 			timeout_ms = DEFEND_INTERVAL * 1000;
3170adb5b76SJoe Hershberger 			arp_raw_request(ip, net_ethaddr, ip);
318d22c338eSJoe Hershberger 		}
319d22c338eSJoe Hershberger 		break;
320d22c338eSJoe Hershberger 	case DEFEND:
321d22c338eSJoe Hershberger 		/* Well, we tried.  Start over (on conflict) */
322d22c338eSJoe Hershberger 		if (source_ip_conflict) {
323d22c338eSJoe Hershberger 			state = PROBE;
324d22c338eSJoe Hershberger 			debug("defend conflict -- starting over\n");
325d22c338eSJoe Hershberger 			ready = 0;
326049a95a7SJoe Hershberger 			net_ip.s_addr = 0;
327d22c338eSJoe Hershberger 
328d22c338eSJoe Hershberger 			/* restart the whole protocol */
329d22c338eSJoe Hershberger 			ip = pick();
330d22c338eSJoe Hershberger 			timeout_ms = 0;
331d22c338eSJoe Hershberger 			nprobes = 0;
332d22c338eSJoe Hershberger 			nclaims = 0;
333d22c338eSJoe Hershberger 		}
334d22c338eSJoe Hershberger 		break;
335d22c338eSJoe Hershberger 	default:
336d22c338eSJoe Hershberger 		/* Invalid, should never happen.  Restart the whole protocol */
337d22c338eSJoe Hershberger 		debug("invalid state -- starting over\n");
338d22c338eSJoe Hershberger 		state = PROBE;
339d22c338eSJoe Hershberger 		ip = pick();
340d22c338eSJoe Hershberger 		timeout_ms = 0;
341d22c338eSJoe Hershberger 		nprobes = 0;
342d22c338eSJoe Hershberger 		nclaims = 0;
343d22c338eSJoe Hershberger 		break;
344d22c338eSJoe Hershberger 	}
345d22c338eSJoe Hershberger 	configure_wait();
346d22c338eSJoe Hershberger }
347