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
47struct 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
67struct 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
110struct arp_protocol : net_datalink_protocol {
111	sockaddr_dl	hardware_address;
112	in_addr_t	local_address;
113};
114
115
116static const net_buffer* kDeletedBuffer = (net_buffer*)~0;
117
118static void arp_timer(struct net_timer *timer, void *data);
119
120net_buffer_module_info* gBufferModule;
121static net_stack_module_info* sStackModule;
122static net_datalink_module_info* sDatalinkModule;
123static mutex sCacheLock;
124static bool sIgnoreReplies;
125
126
127struct 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
153typedef BOpenHashTable<arpHash> AddressCache;
154static AddressCache* sCache;
155
156
157#ifdef TRACE_ARP
158
159
160const char*
161mac_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
170const char*
171inet_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
186static net_buffer*
187get_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
202static void
203put_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
214static void
215delete_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
224static void
225ipv4_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 *
252arp_entry::Lookup(in_addr_t address)
253{
254	return sCache->Lookup(address);
255}
256
257
258/*static*/ arp_entry *
259arp_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
300arp_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
310void
311arp_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
322void
323arp_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
332void
333arp_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
354void
355arp_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*/
375static status_t
376arp_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
430static status_t
431arp_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
472static void
473arp_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*/
523static void
524arp_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*/
541static status_t
542arp_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
568static status_t
569handle_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
617static void
618handle_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
628static status_t
629arp_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
683static void
684arp_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*/
769static status_t
770arp_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
836static status_t
837arp_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
944static status_t
945arp_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
960static status_t
961arp_uninit()
962{
963	unregister_generic_syscall(ARP_SYSCALLS, 1);
964	return B_OK;
965}
966
967
968//	#pragma mark - net_datalink_protocol
969
970
971status_t
972arp_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
1002status_t
1003arp_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
1015status_t
1016arp_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
1070status_t
1071arp_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
1090void
1091arp_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
1100status_t
1101arp_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
1137status_t
1138arp_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
1147static status_t
1148arp_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
1161static status_t
1162arp_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
1175static status_t
1176arp_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
1190static 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
1208module_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
1215module_info* modules[] = {
1216	(module_info*)&sARPModule,
1217	NULL
1218};
1219