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