xref: /haiku/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp (revision 93a78ecaa45114d68952d08c4778f073515102f2)
1 /*
2  * Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  *		Hugo Santos, hugosantos@gmail.com
8  */
9 
10 //! Ethernet Address Resolution Protocol, see RFC 826.
11 
12 
13 #include <arp_control.h>
14 #include <net_datalink_protocol.h>
15 #include <net_device.h>
16 #include <net_datalink.h>
17 #include <net_stack.h>
18 #include <NetBufferUtilities.h>
19 
20 #include <generic_syscall.h>
21 #include <util/AutoLock.h>
22 #include <util/DoublyLinkedList.h>
23 #include <util/khash.h>
24 
25 #include <ByteOrder.h>
26 #include <KernelExport.h>
27 
28 #include <net/if.h>
29 #include <net/if_dl.h>
30 #include <net/if_types.h>
31 #include <new>
32 #include <stdio.h>
33 #include <string.h>
34 #include <sys/sockio.h>
35 
36 
37 //#define TRACE_ARP
38 #ifdef TRACE_ARP
39 #	define TRACE(x) dprintf x
40 #else
41 #	define TRACE(x) ;
42 #endif
43 
44 
45 struct arp_header {
46 	uint16		hardware_type;
47 	uint16		protocol_type;
48 	uint8		hardware_length;
49 	uint8		protocol_length;
50 	uint16		opcode;
51 
52 	// TODO: this should be a variable length header, but for our current
53 	//	usage (Ethernet/IPv4), this should work fine.
54 	uint8		hardware_sender[6];
55 	in_addr_t	protocol_sender;
56 	uint8		hardware_target[6];
57 	in_addr_t	protocol_target;
58 } _PACKED;
59 
60 #define ARP_OPCODE_REQUEST	1
61 #define ARP_OPCODE_REPLY	2
62 
63 #define ARP_HARDWARE_TYPE_ETHER	1
64 
65 struct arp_entry {
66 	arp_entry	*next;
67 	in_addr_t	protocol_address;
68 	sockaddr_dl	hardware_address;
69 	uint32		flags;
70 	net_buffer	*request_buffer;
71 	net_timer	timer;
72 	uint32		timer_state;
73 	bigtime_t	timestamp;
74 	net_datalink_protocol *protocol;
75 
76 	typedef DoublyLinkedListCLink<net_buffer> NetBufferLink;
77 	typedef DoublyLinkedList<net_buffer, NetBufferLink> BufferList;
78 
79 	BufferList  queue;
80 
81 	static int Compare(void *_entry, const void *_key);
82 	static uint32 Hash(void *_entry, const void *_key, uint32 range);
83 	static arp_entry *Lookup(in_addr_t protocolAddress);
84 	static arp_entry *Add(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
85 		uint32 flags);
86 
87 	~arp_entry();
88 
89 	void ClearQueue();
90 	void MarkFailed();
91 	void MarkValid();
92 };
93 
94 // see arp_control.h for flags
95 
96 #define ARP_NO_STATE				0
97 #define ARP_STATE_REQUEST			1
98 #define ARP_STATE_LAST_REQUEST		5
99 #define ARP_STATE_REQUEST_FAILED	6
100 #define ARP_STATE_REMOVE_FAILED		7
101 #define ARP_STATE_STALE				8
102 
103 #define ARP_STALE_TIMEOUT	30 * 60000000LL		// 30 minutes
104 #define ARP_REJECT_TIMEOUT	20000000LL			// 20 seconds
105 #define ARP_REQUEST_TIMEOUT	1000000LL			// 1 second
106 
107 struct arp_protocol : net_datalink_protocol {
108 };
109 
110 
111 static void arp_timer(struct net_timer *timer, void *data);
112 
113 net_buffer_module_info *gBufferModule;
114 static net_stack_module_info *sStackModule;
115 static hash_table *sCache;
116 static benaphore sCacheLock;
117 static bool sIgnoreReplies;
118 
119 
120 /*static*/ int
121 arp_entry::Compare(void *_entry, const void *_key)
122 {
123 	arp_entry *entry = (arp_entry *)_entry;
124 	in_addr_t *key = (in_addr_t *)_key;
125 
126 	if (entry->protocol_address == *key)
127 		return 0;
128 
129 	return 1;
130 }
131 
132 
133 /*static*/ uint32
134 arp_entry::Hash(void *_entry, const void *_key, uint32 range)
135 {
136 	arp_entry *entry = (arp_entry *)_entry;
137 	const in_addr_t *key = (const in_addr_t *)_key;
138 
139 // TODO: check if this makes a good hash...
140 #define HASH(o) ((((o) >> 24) ^ ((o) >> 16) ^ ((o) >> 8) ^ (o)) % range)
141 
142 #ifdef TRACE_ARP
143 	in_addr_t a = entry ? entry->protocol_address : *key;
144 	dprintf("%ld.%ld.%ld.%ld: Hash: %lu\n", a >> 24, (a >> 16) & 0xff,
145 		(a >> 8) & 0xff, a & 0xff, HASH(a));
146 #endif
147 
148 	if (entry != NULL)
149 		return HASH(entry->protocol_address);
150 
151 	return HASH(*key);
152 #undef HASH
153 }
154 
155 
156 /*static*/ arp_entry *
157 arp_entry::Lookup(in_addr_t address)
158 {
159 	return (arp_entry *)hash_lookup(sCache, &address);
160 }
161 
162 
163 /*static*/ arp_entry *
164 arp_entry::Add(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
165 	uint32 flags)
166 {
167 	arp_entry *entry = new (std::nothrow) arp_entry;
168 	if (entry == NULL)
169 		return NULL;
170 
171 	entry->protocol_address = protocolAddress;
172 	entry->flags = flags;
173 	entry->timestamp = system_time();
174 	entry->protocol = NULL;
175 	entry->request_buffer = NULL;
176 	entry->timer_state = ARP_NO_STATE;
177 	sStackModule->init_timer(&entry->timer, arp_timer, entry);
178 
179 	if (hardwareAddress != NULL) {
180 		// this entry is already resolved
181 		entry->hardware_address = *hardwareAddress;
182 		entry->hardware_address.sdl_e_type = ETHER_TYPE_IP;
183 	} else {
184 		// this entry still needs to be resolved
185 		entry->hardware_address.sdl_alen = 0;
186 	}
187 	if (entry->hardware_address.sdl_len != sizeof(sockaddr_dl)) {
188 		// explicitly set correct length in case our caller hasn't...
189 		entry->hardware_address.sdl_len = sizeof(sockaddr_dl);
190 	}
191 
192 	if (hash_insert(sCache, entry) != B_OK) {
193 		delete entry;
194 		return NULL;
195 	}
196 
197 	return entry;
198 }
199 
200 
201 arp_entry::~arp_entry()
202 {
203 	ClearQueue();
204 }
205 
206 
207 void
208 arp_entry::ClearQueue()
209 {
210 	BufferList::Iterator iterator = queue.GetIterator();
211 	while (iterator.HasNext()) {
212 		net_buffer *buffer = iterator.Next();
213 		iterator.Remove();
214 		gBufferModule->free(buffer);
215 	}
216 }
217 
218 
219 void
220 arp_entry::MarkFailed()
221 {
222 	TRACE(("ARP entry %p Marked as FAILED\n", this));
223 
224 	flags = (flags & ~ARP_FLAG_VALID) | ARP_FLAG_REJECT;
225 	ClearQueue();
226 }
227 
228 
229 void
230 arp_entry::MarkValid()
231 {
232 	TRACE(("ARP entry %p Marked as VALID, have %li packets queued.\n", this,
233 		queue.Size()));
234 
235 	flags = (flags & ~ARP_FLAG_REJECT) | ARP_FLAG_VALID;
236 
237 	BufferList::Iterator iterator = queue.GetIterator();
238 	while (iterator.HasNext()) {
239 		net_buffer *buffer = iterator.Next();
240 		iterator.Remove();
241 
242 		TRACE(("  ARP Dequeing packet %p...\n", buffer));
243 
244 		memcpy(buffer->destination, &hardware_address,
245 			hardware_address.sdl_len);
246 		protocol->next->module->send_data(protocol->next, buffer);
247 	}
248 }
249 
250 
251 static void
252 ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
253 {
254 	// RFC 1112 - Host extensions for IP multicasting
255 	//
256 	//   ``An IP host group address is mapped to an Ethernet multicast
257 	//   address by placing the low-order 23-bits of the IP address into
258 	//   the low-order 23 bits of the Ethernet multicast address
259 	//   01-00-5E-00-00-00 (hex).''
260 
261 	destination->sdl_len = sizeof(sockaddr_dl);
262 	destination->sdl_family = AF_DLI;
263 	destination->sdl_index = 0;
264 	destination->sdl_type = IFT_ETHER;
265 	destination->sdl_e_type = ETHER_TYPE_IP;
266 	destination->sdl_nlen = destination->sdl_slen = 0;
267 	destination->sdl_alen = ETHER_ADDRESS_LENGTH;
268 
269 	memcpy(LLADDR(destination) + 2, &source->sin_addr, sizeof(in_addr));
270 	uint32 *data = (uint32 *)LLADDR(destination);
271 	data[0] = (data[0] & htonl(0x7f)) | htonl(0x01005e00);
272 }
273 
274 
275 //	#pragma mark -
276 
277 
278 /*!
279 	Updates the entry determined by \a protocolAddress with the specified
280 	\a hardwareAddress.
281 	If such an entry does not exist yet, a new entry is added. If you try
282 	to update a local existing entry but didn't ask for it (by setting
283 	\a flags to ARP_FLAG_LOCAL), an error is returned.
284 
285 	This function does not lock the cache - you have to do it yourself
286 	before calling it.
287 */
288 status_t
289 arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
290 	uint32 flags, arp_entry **_entry = NULL)
291 {
292 	arp_entry *entry = arp_entry::Lookup(protocolAddress);
293 	if (entry != NULL) {
294 		// We disallow updating of entries that had been resolved before,
295 		// but to a different address.
296 		// Right now, you have to manually purge the ARP entries (or wait some
297 		// time) to let us switch to the new address.
298 		if (entry->hardware_address.sdl_alen != 0
299 			&& memcmp(LLADDR(&entry->hardware_address),
300 				LLADDR(hardwareAddress), ETHER_ADDRESS_LENGTH)) {
301 			dprintf("ARP host %08lx updated with different hardware address %02x:%02x:%02x:%02x:%02x:%02x.\n",
302 				protocolAddress,
303 				hardwareAddress->sdl_data[0], hardwareAddress->sdl_data[1],
304 				hardwareAddress->sdl_data[2], hardwareAddress->sdl_data[3],
305 				hardwareAddress->sdl_data[4], hardwareAddress->sdl_data[5]);
306 			return B_ERROR;
307 		}
308 
309 		entry->hardware_address = *hardwareAddress;
310 		entry->timestamp = system_time();
311 	} else {
312 		entry = arp_entry::Add(protocolAddress, hardwareAddress, flags);
313 		if (entry == NULL)
314 			return B_NO_MEMORY;
315 	}
316 
317 	if (entry->request_buffer != NULL) {
318 		gBufferModule->free(entry->request_buffer);
319 		entry->request_buffer = NULL;
320 	}
321 
322 	if ((entry->flags & ARP_FLAG_PERMANENT) == 0) {
323 		// (re)start the stale timer
324 		entry->timer_state = ARP_STATE_STALE;
325 		sStackModule->set_timer(&entry->timer, ARP_STALE_TIMEOUT);
326 	}
327 
328 	if (entry->flags & ARP_FLAG_REJECT)
329 		entry->MarkFailed();
330 	else
331 		entry->MarkValid();
332 
333 	if (_entry)
334 		*_entry = entry;
335 
336 	return B_OK;
337 }
338 
339 
340 static status_t
341 arp_update_local(net_datalink_protocol *protocol)
342 {
343 	net_interface *interface = protocol->interface;
344 	in_addr_t inetAddress;
345 
346 	if (interface->address == NULL) {
347 		// interface has not yet been set
348 		inetAddress = INADDR_ANY;
349 	} else
350 		inetAddress = ((sockaddr_in *)interface->address)->sin_addr.s_addr;
351 
352 	sockaddr_dl address;
353 	address.sdl_len = sizeof(sockaddr_dl);
354 	address.sdl_family = AF_DLI;
355 	address.sdl_type = IFT_ETHER;
356 	address.sdl_e_type = ETHER_TYPE_IP;
357 	address.sdl_nlen = 0;
358 	address.sdl_slen = 0;
359 	address.sdl_alen = interface->device->address.length;
360 	memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
361 
362 	arp_entry *entry;
363 	status_t status = arp_update_entry(inetAddress, &address,
364 		ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
365 	if (status == B_OK)
366 		entry->protocol = protocol;
367 
368 	return status;
369 }
370 
371 
372 static status_t
373 handle_arp_request(net_buffer *buffer, arp_header &header)
374 {
375 	BenaphoreLocker locker(sCacheLock);
376 
377 	if (!sIgnoreReplies) {
378 		arp_update_entry(header.protocol_sender, (sockaddr_dl *)buffer->source, 0);
379 			// remember the address of the sender as we might need it later
380 	}
381 
382 	// check if this request is for us
383 
384 	arp_entry *entry = arp_entry::Lookup(header.protocol_target);
385 	if (entry == NULL || (entry->flags & (ARP_FLAG_LOCAL | ARP_FLAG_PUBLISH)) == 0) {
386 		// We're not the one to answer this request
387 		// TODO: instead of letting the other's request time-out, can we reply
388 		//	failure somehow?
389 		TRACE(("  not for us\n"));
390 		return B_ERROR;
391 	}
392 
393 	// send a reply (by reusing the buffer we got)
394 
395 	TRACE(("  send reply!\n"));
396 	header.opcode = htons(ARP_OPCODE_REPLY);
397 
398 	memcpy(header.hardware_target, header.hardware_sender, ETHER_ADDRESS_LENGTH);
399 	header.protocol_target = header.protocol_sender;
400 	memcpy(header.hardware_sender, LLADDR(&entry->hardware_address), ETHER_ADDRESS_LENGTH);
401 	header.protocol_sender = entry->protocol_address;
402 
403 	// exchange source and destination address
404 	memcpy(LLADDR((sockaddr_dl *)buffer->source), header.hardware_sender,
405 		ETHER_ADDRESS_LENGTH);
406 	memcpy(LLADDR((sockaddr_dl *)buffer->destination), header.hardware_target,
407 		ETHER_ADDRESS_LENGTH);
408 
409 	buffer->flags = 0;
410 		// make sure this won't be a broadcast message
411 
412 	return entry->protocol->next->module->send_data(entry->protocol->next, buffer);
413 }
414 
415 
416 static void
417 handle_arp_reply(net_buffer *buffer, arp_header &header)
418 {
419 	if (sIgnoreReplies)
420 		return;
421 
422 	BenaphoreLocker locker(sCacheLock);
423 	arp_update_entry(header.protocol_sender, (sockaddr_dl *)buffer->source, 0);
424 }
425 
426 
427 static status_t
428 arp_receive(void *cookie, net_device *device, net_buffer *buffer)
429 {
430 	TRACE(("ARP receive\n"));
431 
432 	NetBufferHeaderReader<arp_header> bufferHeader(buffer);
433 	if (bufferHeader.Status() < B_OK)
434 		return bufferHeader.Status();
435 
436 	arp_header &header = bufferHeader.Data();
437 	uint16 opcode = ntohs(header.opcode);
438 
439 #ifdef TRACE_ARP
440 	dprintf("  hw sender: %02x:%02x:%02x:%02x:%02x:%02x\n",
441 		header.hardware_sender[0], header.hardware_sender[1], header.hardware_sender[2],
442 		header.hardware_sender[3], header.hardware_sender[4], header.hardware_sender[5]);
443 	dprintf("  proto sender: %ld.%ld.%ld.%ld\n", header.protocol_sender >> 24, (header.protocol_sender >> 16) & 0xff,
444 		(header.protocol_sender >> 8) & 0xff, header.protocol_sender & 0xff);
445 	dprintf("  hw target: %02x:%02x:%02x:%02x:%02x:%02x\n",
446 		header.hardware_target[0], header.hardware_target[1], header.hardware_target[2],
447 		header.hardware_target[3], header.hardware_target[4], header.hardware_target[5]);
448 	dprintf("  proto target: %ld.%ld.%ld.%ld\n", header.protocol_target >> 24, (header.protocol_target >> 16) & 0xff,
449 		(header.protocol_target >> 8) & 0xff, header.protocol_target & 0xff);
450 #endif
451 
452 	if (ntohs(header.protocol_type) != ETHER_TYPE_IP
453 		|| ntohs(header.hardware_type) != ARP_HARDWARE_TYPE_ETHER)
454 		return B_BAD_TYPE;
455 
456 	// check if the packet is okay
457 
458 	if (header.hardware_length != ETHER_ADDRESS_LENGTH
459 		|| header.protocol_length != sizeof(in_addr_t))
460 		return B_BAD_DATA;
461 
462 	// handle packet
463 
464 	switch (opcode) {
465 		case ARP_OPCODE_REQUEST:
466 			TRACE(("  got ARP request\n"));
467 			if (handle_arp_request(buffer, header) == B_OK) {
468 				// the function will take care of the buffer if everything went well
469 				return B_OK;
470 			}
471 			break;
472 		case ARP_OPCODE_REPLY:
473 			TRACE(("  got ARP reply\n"));
474 			handle_arp_reply(buffer, header);
475 			break;
476 
477 		default:
478 			dprintf("unknown ARP opcode %d\n", opcode);
479 			return B_ERROR;
480 	}
481 
482 	gBufferModule->free(buffer);
483 	return B_OK;
484 }
485 
486 
487 static void
488 arp_timer(struct net_timer *timer, void *data)
489 {
490 	arp_entry *entry = (arp_entry *)data;
491 	TRACE(("ARP timer %ld, entry %p!\n", entry->timer_state, entry));
492 
493 	switch (entry->timer_state) {
494 		case ARP_NO_STATE:
495 			// who are you kidding?
496 			break;
497 
498 		case ARP_STATE_REQUEST_FAILED:
499 			// requesting the ARP entry failed, we keep it around for a while, though,
500 			// so that we won't try to request the same address again too soon.
501 			TRACE(("  requesting ARP entry %p failed!\n", entry));
502 			entry->timer_state = ARP_STATE_REMOVE_FAILED;
503 			entry->MarkFailed();
504 			sStackModule->set_timer(&entry->timer, ARP_REJECT_TIMEOUT);
505 			break;
506 
507 		case ARP_STATE_REMOVE_FAILED:
508 		case ARP_STATE_STALE:
509 			// the entry has aged so much that we're going to remove it
510 			TRACE(("  remove ARP entry %p!\n", entry));
511 
512 			benaphore_lock(&sCacheLock);
513 			hash_remove(sCache, entry);
514 			benaphore_unlock(&sCacheLock);
515 
516 			delete entry;
517 
518 			break;
519 		default:
520 			if (entry->timer_state > ARP_STATE_LAST_REQUEST)
521 				break;
522 
523 			TRACE(("  send request for ARP entry %p!\n", entry));
524 			net_buffer *request = entry->request_buffer;
525 			if (entry->timer_state < ARP_STATE_LAST_REQUEST) {
526 				// we'll still need our buffer, so in order to prevent it being
527 				// freed by a successful send, we need to clone it
528 				request = gBufferModule->clone(request, true);
529 				if (request == NULL) {
530 					// cloning failed - that means we won't be able to send as
531 					// many requests as originally planned
532 					request = entry->request_buffer;
533 					entry->timer_state = ARP_STATE_LAST_REQUEST;
534 				}
535 			}
536 
537 			// we're trying to resolve the address, so keep sending requests
538 			status_t status = entry->protocol->next->module->send_data(
539 				entry->protocol->next, request);
540 			if (status < B_OK)
541 				gBufferModule->free(request);
542 
543 			if (entry->timer_state == ARP_STATE_LAST_REQUEST) {
544 				// buffer has been freed on send
545 				entry->request_buffer = NULL;
546 			}
547 
548 			entry->timer_state++;
549 			sStackModule->set_timer(&entry->timer, ARP_REQUEST_TIMEOUT);
550 	}
551 }
552 
553 
554 /*!
555 	Address resolver function: prepares and sends the ARP request necessary
556 	to retrieve the hardware address for \a address.
557 	You need to have the sCacheLock held when calling this function - but
558 	note that the lock will be interrupted here if everything goes well.
559 */
560 static status_t
561 arp_start_resolve(net_datalink_protocol *protocol, in_addr_t address, arp_entry **_entry)
562 {
563 	// create an unresolved ARP entry as a placeholder
564 	arp_entry *entry = arp_entry::Add(address, NULL, 0);
565 	if (entry == NULL)
566 		return B_NO_MEMORY;
567 
568 	// prepare ARP request
569 
570 	entry->request_buffer = gBufferModule->create(256);
571 	if (entry->request_buffer == NULL) {
572 		// TODO: do something with the entry
573 		return B_NO_MEMORY;
574 	}
575 
576 	NetBufferPrepend<arp_header> bufferHeader(entry->request_buffer);
577 	status_t status = bufferHeader.Status();
578 	if (status < B_OK) {
579 		// TODO: do something with the entry
580 		return status;
581 	}
582 
583 	// prepare ARP header
584 
585 	net_device *device = protocol->interface->device;
586 	arp_header &header = bufferHeader.Data();
587 
588 	header.hardware_type = htons(ARP_HARDWARE_TYPE_ETHER);
589 	header.protocol_type = htons(ETHER_TYPE_IP);
590 	header.hardware_length = ETHER_ADDRESS_LENGTH;
591 	header.protocol_length = sizeof(in_addr_t);
592 	header.opcode = htons(ARP_OPCODE_REQUEST);
593 
594 	memcpy(header.hardware_sender, device->address.data, ETHER_ADDRESS_LENGTH);
595 	if (protocol->interface->address != NULL)
596 		header.protocol_sender = ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr;
597 	else
598 		header.protocol_sender = 0;
599 			// TODO: test if this actually works - maybe we should use INADDR_BROADCAST instead
600 	memset(header.hardware_target, 0, ETHER_ADDRESS_LENGTH);
601 	header.protocol_target = address;
602 
603 	// prepare source and target addresses
604 
605 	struct sockaddr_dl &source = *(struct sockaddr_dl *)entry->request_buffer->source;
606 	source.sdl_len = sizeof(sockaddr_dl);
607 	source.sdl_family = AF_DLI;
608 	source.sdl_index = device->index;
609 	source.sdl_type = IFT_ETHER;
610 	source.sdl_e_type = ETHER_TYPE_ARP;
611 	source.sdl_nlen = source.sdl_slen = 0;
612 	source.sdl_alen = ETHER_ADDRESS_LENGTH;
613 	memcpy(source.sdl_data, device->address.data, ETHER_ADDRESS_LENGTH);
614 
615 	entry->request_buffer->flags = MSG_BCAST;
616 		// this is a broadcast packet, we don't need to fill in the destination
617 
618 	entry->protocol = protocol;
619 	entry->timer_state = ARP_STATE_REQUEST;
620 	sStackModule->set_timer(&entry->timer, 0);
621 		// start request timer
622 
623 	*_entry = entry;
624 	return B_OK;
625 }
626 
627 
628 static status_t
629 arp_control(const char *subsystem, uint32 function,
630 	void *buffer, size_t bufferSize)
631 {
632 	struct arp_control control;
633 	if (bufferSize != sizeof(struct arp_control))
634 		return B_BAD_VALUE;
635 	if (user_memcpy(&control, buffer, sizeof(struct arp_control)) < B_OK)
636 		return B_BAD_ADDRESS;
637 
638 	BenaphoreLocker locker(sCacheLock);
639 
640 	switch (function) {
641 		case ARP_SET_ENTRY:
642 			sockaddr_dl hardwareAddress;
643 
644 			hardwareAddress.sdl_len = sizeof(sockaddr_dl);
645 			hardwareAddress.sdl_family = AF_DLI;
646 			hardwareAddress.sdl_index = 0;
647 			hardwareAddress.sdl_type = IFT_ETHER;
648 			hardwareAddress.sdl_e_type = ETHER_TYPE_IP;
649 			hardwareAddress.sdl_nlen = hardwareAddress.sdl_slen = 0;
650 			hardwareAddress.sdl_alen = ETHER_ADDRESS_LENGTH;
651 			memcpy(hardwareAddress.sdl_data, control.ethernet_address, ETHER_ADDRESS_LENGTH);
652 
653 			return arp_update_entry(control.address, &hardwareAddress,
654 				control.flags & (ARP_FLAG_PUBLISH | ARP_FLAG_PERMANENT | ARP_FLAG_REJECT));
655 
656 		case ARP_GET_ENTRY:
657 		{
658 			arp_entry *entry = arp_entry::Lookup(control.address);
659 			if (entry == NULL || !(entry->flags & ARP_FLAG_VALID))
660 				return B_ENTRY_NOT_FOUND;
661 
662 			memcpy(control.ethernet_address, entry->hardware_address.sdl_data,
663 				ETHER_ADDRESS_LENGTH);
664 			control.flags = entry->flags;
665 			return user_memcpy(buffer, &control, sizeof(struct arp_control));
666 		}
667 
668 		case ARP_GET_ENTRIES:
669 		{
670 			hash_iterator iterator;
671 			hash_open(sCache, &iterator);
672 
673 			arp_entry *entry;
674 			uint32 i = 0;
675 			while ((entry = (arp_entry *)hash_next(sCache, &iterator)) != NULL
676 				&& i < control.cookie) {
677 				i++;
678 			}
679 			hash_close(sCache, &iterator, false);
680 
681 			if (entry == NULL)
682 				return B_ENTRY_NOT_FOUND;
683 
684 			control.cookie++;
685 			control.address = entry->protocol_address;
686 			memcpy(control.ethernet_address, entry->hardware_address.sdl_data,
687 				ETHER_ADDRESS_LENGTH);
688 			control.flags = entry->flags;
689 
690 			return user_memcpy(buffer, &control, sizeof(struct arp_control));
691 		}
692 
693 		case ARP_DELETE_ENTRY:
694 		{
695 			arp_entry *entry = arp_entry::Lookup(control.address);
696 			if (entry == NULL)
697 				return B_ENTRY_NOT_FOUND;
698 			if ((entry->flags & ARP_FLAG_LOCAL) != 0)
699 				return B_BAD_VALUE;
700 
701 			// schedule a timer to remove this entry
702 			entry->timer_state = ARP_STATE_REMOVE_FAILED;
703 			sStackModule->set_timer(&entry->timer, 0);
704 			return B_OK;
705 		}
706 
707 		case ARP_FLUSH_ENTRIES:
708 		{
709 			hash_iterator iterator;
710 			hash_open(sCache, &iterator);
711 
712 			arp_entry *entry;
713 			while ((entry = (arp_entry *)hash_next(sCache, &iterator)) != NULL) {
714 				// we never flush local ARP entries
715 				if ((entry->flags & ARP_FLAG_LOCAL) != 0)
716 					continue;
717 
718 				// schedule a timer to remove this entry
719 				entry->timer_state = ARP_STATE_REMOVE_FAILED;
720 				sStackModule->set_timer(&entry->timer, 0);
721 			}
722 			hash_close(sCache, &iterator, false);
723 			return B_OK;
724 		}
725 
726 		case ARP_IGNORE_REPLIES:
727 			sIgnoreReplies = control.flags != 0;
728 			return B_OK;
729 	}
730 
731 	return B_BAD_VALUE;
732 }
733 
734 
735 static status_t
736 arp_init()
737 {
738 	status_t status = benaphore_init(&sCacheLock, "arp cache");
739 	if (status < B_OK)
740 		return status;
741 
742 	sCache = hash_init(64, offsetof(struct arp_entry, next),
743 		&arp_entry::Compare, &arp_entry::Hash);
744 	if (sCache == NULL) {
745 		benaphore_destroy(&sCacheLock);
746 		return B_NO_MEMORY;
747 	}
748 
749 	register_generic_syscall(ARP_SYSCALLS, arp_control, 1, 0);
750 	return B_OK;
751 }
752 
753 
754 static status_t
755 arp_uninit()
756 {
757 	unregister_generic_syscall(ARP_SYSCALLS, 1);
758 	return B_OK;
759 }
760 
761 
762 //	#pragma mark -
763 
764 
765 status_t
766 arp_init_protocol(struct net_interface *interface, net_datalink_protocol **_protocol)
767 {
768 	// We currently only support a single family and type!
769 	if (interface->domain->family != AF_INET
770 		|| interface->device->type != IFT_ETHER)
771 		return B_BAD_TYPE;
772 
773 	status_t status = sStackModule->register_device_handler(interface->device,
774 		ETHER_FRAME_TYPE | ETHER_TYPE_ARP, &arp_receive, NULL);
775 
776 	if (status < B_OK)
777 		return status;
778 
779 	arp_protocol *protocol = new (std::nothrow) arp_protocol;
780 	if (protocol == NULL)
781 		return B_NO_MEMORY;
782 
783 	*_protocol = protocol;
784 	return B_OK;
785 }
786 
787 
788 status_t
789 arp_uninit_protocol(net_datalink_protocol *protocol)
790 {
791 	sStackModule->unregister_device_handler(protocol->interface->device,
792 		ETHER_FRAME_TYPE | ETHER_TYPE_ARP);
793 
794 	delete protocol;
795 	return B_OK;
796 }
797 
798 
799 status_t
800 arp_send_data(net_datalink_protocol *protocol,
801 	net_buffer *buffer)
802 {
803 	{
804 		BenaphoreLocker locker(sCacheLock);
805 
806 		// Lookup source (us)
807 		// TODO: this could be cached - the lookup isn't really needed at all
808 
809 		arp_entry *entry = arp_entry::Lookup(
810 			((struct sockaddr_in *)buffer->source)->sin_addr.s_addr);
811 		if (entry == NULL)
812 			return B_ERROR;
813 
814 		memcpy(buffer->source, &entry->hardware_address,
815 			entry->hardware_address.sdl_len);
816 
817 		if (buffer->flags & MSG_MCAST) {
818 			sockaddr_dl multicastDestination;
819 			ipv4_to_ether_multicast(&multicastDestination,
820 				(sockaddr_in *)buffer->destination);
821 			memcpy(buffer->destination, &multicastDestination,
822 				sizeof(multicastDestination));
823 		} else if ((buffer->flags & MSG_BCAST) == 0) {
824 			// Lookup destination (we may need to wait for this)
825 			entry = arp_entry::Lookup(
826 				((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr);
827 			if (entry == NULL) {
828 				status_t status = arp_start_resolve(protocol,
829 					((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr, &entry);
830 				if (status < B_OK)
831 					return status;
832 			}
833 
834 			if (entry->flags & ARP_FLAG_REJECT)
835 				return EHOSTUNREACH;
836 			else if (!(entry->flags & ARP_FLAG_VALID)) {
837 				// entry is still being resolved.
838 				TRACE(("ARP Queuing packet %p, entry still being resolved.\n",
839 					buffer));
840 				entry->queue.Add(buffer);
841 				return B_OK;
842 			}
843 
844 			memcpy(buffer->destination, &entry->hardware_address,
845 				entry->hardware_address.sdl_len);
846 		}
847 	}
848 
849 	return protocol->next->module->send_data(protocol->next, buffer);
850 }
851 
852 
853 status_t
854 arp_up(net_datalink_protocol *_protocol)
855 {
856 	arp_protocol *protocol = (arp_protocol *)_protocol;
857 	status_t status = protocol->next->module->interface_up(protocol->next);
858 	if (status < B_OK)
859 		return status;
860 
861 	// cache this device's address for later use
862 
863 	status = arp_update_local(protocol);
864 	if (status < B_OK) {
865 		protocol->next->module->interface_down(protocol->next);
866 		return status;
867 	}
868 
869 	return B_OK;
870 }
871 
872 
873 void
874 arp_down(net_datalink_protocol *protocol)
875 {
876 	// remove local ARP entry from the cache
877 
878 	if (protocol->interface->address != NULL) {
879 		BenaphoreLocker locker(sCacheLock);
880 
881 		arp_entry *entry = arp_entry::Lookup(
882 			((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr);
883 		if (entry != NULL) {
884 			hash_remove(sCache, entry);
885 			delete entry;
886 		}
887 	}
888 
889 	protocol->next->module->interface_down(protocol->next);
890 }
891 
892 
893 status_t
894 arp_control(net_datalink_protocol *protocol,
895 	int32 op, void *argument, size_t length)
896 {
897 	if (op == SIOCSIFADDR && (protocol->interface->flags & IFF_UP) != 0) {
898 		// The interface may get a new address, so we need to update our
899 		// local entries.
900 		bool hasOldAddress = false;
901 		in_addr_t oldAddress = 0;
902 		if (protocol->interface->address != NULL) {
903 			oldAddress = ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr;
904 			hasOldAddress = true;
905 		}
906 
907 		status_t status = protocol->next->module->control(protocol->next,
908 			SIOCSIFADDR, argument, length);
909 		if (status < B_OK)
910 			return status;
911 
912 		arp_update_local(protocol);
913 
914 		if (oldAddress == ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr
915 			|| !hasOldAddress)
916 			return B_OK;
917 
918 		// remove previous address from cache
919 		// TODO: we should be able to do this (add/remove) in one atomic operation!
920 
921 		BenaphoreLocker locker(sCacheLock);
922 
923 		arp_entry *entry = arp_entry::Lookup(oldAddress);
924 		if (entry != NULL) {
925 			hash_remove(sCache, entry);
926 			delete entry;
927 		}
928 
929 		return B_OK;
930 	}
931 
932 	return protocol->next->module->control(protocol->next,
933 		op, argument, length);
934 }
935 
936 
937 static status_t
938 arp_join_multicast(net_datalink_protocol *protocol, const sockaddr *address)
939 {
940 	if (address->sa_family != AF_INET)
941 		return EINVAL;
942 
943 	sockaddr_dl multicastAddress;
944 	ipv4_to_ether_multicast(&multicastAddress, (const sockaddr_in *)address);
945 
946 	return protocol->next->module->join_multicast(protocol->next,
947 		(sockaddr *)&multicastAddress);
948 }
949 
950 
951 static status_t
952 arp_leave_multicast(net_datalink_protocol *protocol, const sockaddr *address)
953 {
954 	if (address->sa_family != AF_INET)
955 		return EINVAL;
956 
957 	sockaddr_dl multicastAddress;
958 	ipv4_to_ether_multicast(&multicastAddress, (const sockaddr_in *)address);
959 
960 	return protocol->next->module->leave_multicast(protocol->next,
961 		(sockaddr *)&multicastAddress);
962 }
963 
964 
965 static status_t
966 arp_std_ops(int32 op, ...)
967 {
968 	switch (op) {
969 		case B_MODULE_INIT:
970 			return arp_init();
971 		case B_MODULE_UNINIT:
972 			return arp_uninit();
973 
974 		default:
975 			return B_ERROR;
976 	}
977 }
978 
979 
980 static net_datalink_protocol_module_info sARPModule = {
981 	{
982 		"network/datalink_protocols/arp/v1",
983 		0,
984 		arp_std_ops
985 	},
986 	arp_init_protocol,
987 	arp_uninit_protocol,
988 	arp_send_data,
989 	arp_up,
990 	arp_down,
991 	arp_control,
992 	arp_join_multicast,
993 	arp_leave_multicast,
994 };
995 
996 
997 module_dependency module_dependencies[] = {
998 	{NET_STACK_MODULE_NAME, (module_info **)&sStackModule},
999 	{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
1000 	{}
1001 };
1002 
1003 module_info *modules[] = {
1004 	(module_info *)&sARPModule,
1005 	NULL
1006 };
1007