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