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