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