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