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