xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 /*
2  * Copyright 2006-2011, 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 
10 #include "interfaces.h"
11 
12 #include <net/if_dl.h>
13 #include <new>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/sockio.h>
18 
19 #include <KernelExport.h>
20 
21 #include <net_device.h>
22 #include <NetUtilities.h>
23 
24 #include "device_interfaces.h"
25 #include "domains.h"
26 #include "stack_private.h"
27 #include "utility.h"
28 
29 
30 //#define TRACE_INTERFACES
31 #ifdef TRACE_INTERFACES
32 #	define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
33 #else
34 #	define TRACE(x...) ;
35 #endif
36 
37 
38 struct AddressHashDefinition {
39 	typedef const sockaddr* KeyType;
40 	typedef InterfaceAddress ValueType;
41 
42 	AddressHashDefinition()
43 	{
44 	}
45 
46 	size_t HashKey(const KeyType& key) const
47 	{
48 		net_domain* domain = get_domain(key->sa_family);
49 		if (domain == NULL)
50 			return 0;
51 
52 		return domain->address_module->hash_address(key, false);
53 	}
54 
55 	size_t Hash(InterfaceAddress* address) const
56 	{
57 		return address->domain->address_module->hash_address(address->local,
58 			false);
59 	}
60 
61 	bool Compare(const KeyType& key, InterfaceAddress* address) const
62 	{
63 		if (address->local == NULL)
64 			return key->sa_family == AF_UNSPEC;
65 
66 		if (address->local->sa_family != key->sa_family)
67 			return false;
68 
69 		return address->domain->address_module->equal_addresses(key,
70 			address->local);
71 	}
72 
73 	InterfaceAddress*& GetLink(InterfaceAddress* address) const
74 	{
75 		return address->HashTableLink();
76 	}
77 };
78 
79 typedef BOpenHashTable<AddressHashDefinition, true, false> AddressTable;
80 
81 
82 static mutex sLock;
83 static InterfaceList sInterfaces;
84 static mutex sHashLock;
85 static AddressTable sAddressTable;
86 static uint32 sInterfaceIndex;
87 
88 
89 #if 0
90 //! For debugging purposes only
91 void
92 dump_interface_refs(void)
93 {
94 	MutexLocker locker(sLock);
95 
96 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
97 	while (Interface* interface = iterator.Next()) {
98 		dprintf("%p: %s, %ld\n", interface, interface->name,
99 			interface->CountReferences());
100 	}
101 }
102 #endif
103 
104 
105 #if ENABLE_DEBUGGER_COMMANDS
106 
107 
108 static int
109 dump_interface(int argc, char** argv)
110 {
111 	if (argc != 2) {
112 		kprintf("usage: %s [name|address]\n", argv[0]);
113 		return 0;
114 	}
115 
116 	Interface* interface = NULL;
117 
118 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
119 	while ((interface = iterator.Next()) != NULL) {
120 		if (!strcmp(argv[1], interface->name))
121 			break;
122 	}
123 
124 	if (interface == NULL)
125 		interface = (Interface*)parse_expression(argv[1]);
126 
127 	interface->Dump();
128 
129 	return 0;
130 }
131 
132 
133 static int
134 dump_interfaces(int argc, char** argv)
135 {
136 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
137 	while (Interface* interface = iterator.Next()) {
138 		kprintf("%p  %s\n", interface, interface->name);
139 	}
140 	return 0;
141 }
142 
143 
144 static int
145 dump_local(int argc, char** argv)
146 {
147 	AddressTable::Iterator iterator = sAddressTable.GetIterator();
148 	size_t i = 0;
149 	while (InterfaceAddress* address = iterator.Next()) {
150 		address->Dump(++i);
151 		dprintf("    hash:          %lu\n",
152 			address->domain->address_module->hash_address(address->local,
153 				false));
154 	}
155 	return 0;
156 }
157 
158 
159 static int
160 dump_route(int argc, char** argv)
161 {
162 	if (argc != 2) {
163 		kprintf("usage: %s [address]\n", argv[0]);
164 		return 0;
165 	}
166 
167 	net_route* route = (net_route*)parse_expression(argv[1]);
168 	kprintf("destination:       %p\n", route->destination);
169 	kprintf("mask:              %p\n", route->mask);
170 	kprintf("gateway:           %p\n", route->gateway);
171 	kprintf("flags:             %" B_PRIx32 "\n", route->flags);
172 	kprintf("mtu:               %" B_PRIu32 "\n", route->mtu);
173 	kprintf("interface address: %p\n", route->interface_address);
174 
175 	if (route->interface_address != NULL) {
176 		((InterfaceAddress*)route->interface_address)->Dump();
177 	}
178 
179 	return 0;
180 }
181 
182 
183 #endif	// ENABLE_DEBUGGER_COMMANDS
184 
185 
186 InterfaceAddress::InterfaceAddress()
187 {
188 	_Init(NULL, NULL);
189 }
190 
191 
192 InterfaceAddress::InterfaceAddress(net_interface* netInterface,
193 	net_domain* netDomain)
194 {
195 	_Init(netInterface, netDomain);
196 }
197 
198 
199 InterfaceAddress::~InterfaceAddress()
200 {
201 	TRACE("InterfaceAddress %p: destructor\n", this);
202 
203 	if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
204 		((Interface*)interface)->ReleaseReference();
205 }
206 
207 
208 status_t
209 InterfaceAddress::SetTo(const ifaliasreq& request)
210 {
211 	status_t status = SetLocal((const sockaddr*)&request.ifra_addr);
212 	if (status == B_OK)
213 		status = SetDestination((const sockaddr*)&request.ifra_broadaddr);
214 	if (status == B_OK)
215 		status = SetMask((const sockaddr*)&request.ifra_mask);
216 
217 	return status;
218 }
219 
220 
221 status_t
222 InterfaceAddress::SetLocal(const sockaddr* to)
223 {
224 	return Set(&local, to);
225 }
226 
227 
228 status_t
229 InterfaceAddress::SetDestination(const sockaddr* to)
230 {
231 	return Set(&destination, to);
232 }
233 
234 
235 status_t
236 InterfaceAddress::SetMask(const sockaddr* to)
237 {
238 	return Set(&mask, to);
239 }
240 
241 
242 sockaddr**
243 InterfaceAddress::AddressFor(int32 option)
244 {
245 	switch (option) {
246 		case SIOCSIFADDR:
247 		case SIOCGIFADDR:
248 		case SIOCDIFADDR:
249 			return &local;
250 
251 		case SIOCSIFNETMASK:
252 		case SIOCGIFNETMASK:
253 			return &mask;
254 
255 		case SIOCSIFBRDADDR:
256 		case SIOCSIFDSTADDR:
257 		case SIOCGIFBRDADDR:
258 		case SIOCGIFDSTADDR:
259 			return &destination;
260 
261 		default:
262 			return NULL;
263 	}
264 }
265 
266 
267 /*!	Adds the default routes that every interface address needs, ie. the local
268 	host route, and one for the subnet (if set).
269 */
270 void
271 InterfaceAddress::AddDefaultRoutes(int32 option)
272 {
273 	net_route route;
274 	route.destination = local;
275 	route.gateway = NULL;
276 	route.interface_address = this;
277 
278 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
279 		route.mask = mask;
280 		route.flags = 0;
281 		add_route(domain, &route);
282 	}
283 
284 	if (option == SIOCSIFADDR) {
285 		route.mask = NULL;
286 		route.flags = RTF_LOCAL | RTF_HOST;
287 		add_route(domain, &route);
288 	}
289 }
290 
291 
292 /*!	Removes the default routes as set by AddDefaultRoutes() again. */
293 void
294 InterfaceAddress::RemoveDefaultRoutes(int32 option)
295 {
296 	net_route route;
297 	route.destination = local;
298 	route.gateway = NULL;
299 	route.interface_address = this;
300 
301 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
302 		route.mask = mask;
303 		route.flags = 0;
304 		remove_route(domain, &route);
305 	}
306 
307 	if (option == SIOCSIFADDR) {
308 		route.mask = NULL;
309 		route.flags = RTF_LOCAL | RTF_HOST;
310 		remove_route(domain, &route);
311 	}
312 }
313 
314 
315 bool
316 InterfaceAddress::LocalIsDefined() const
317 {
318 	return local != NULL && local->sa_family != AF_UNSPEC;
319 }
320 
321 
322 #if ENABLE_DEBUGGER_COMMANDS
323 
324 
325 void
326 InterfaceAddress::Dump(size_t index, bool hideInterface)
327 {
328 	if (index)
329 		kprintf("%2zu. ", index);
330 	else
331 		kprintf("    ");
332 
333 	if (!hideInterface) {
334 		kprintf("interface:   %p (%s)\n    ", interface,
335 			interface != NULL ? interface->name : "-");
336 	}
337 
338 	kprintf("domain:      %p (family %u)\n", domain,
339 		domain != NULL ? domain->family : AF_UNSPEC);
340 
341 	char buffer[64];
342 	if (local != NULL && domain != NULL) {
343 		domain->address_module->print_address_buffer(local, buffer,
344 			sizeof(buffer), false);
345 	} else
346 		strcpy(buffer, "-");
347 	kprintf("    local:       %s\n", buffer);
348 
349 	if (mask != NULL && domain != NULL) {
350 		domain->address_module->print_address_buffer(mask, buffer,
351 			sizeof(buffer), false);
352 	} else
353 		strcpy(buffer, "-");
354 	kprintf("    mask:        %s\n", buffer);
355 
356 	if (destination != NULL && domain != NULL) {
357 		domain->address_module->print_address_buffer(destination, buffer,
358 			sizeof(buffer), false);
359 	} else
360 		strcpy(buffer, "-");
361 	kprintf("    destination: %s\n", buffer);
362 
363 	kprintf("    ref count:   %" B_PRId32 "\n", CountReferences());
364 }
365 
366 
367 #endif	// ENABLE_DEBUGGER_COMMANDS
368 
369 
370 /*static*/ status_t
371 InterfaceAddress::Set(sockaddr** _address, const sockaddr* to)
372 {
373 	sockaddr* address = *_address;
374 
375 	if (to == NULL || to->sa_family == AF_UNSPEC) {
376 		// Clear address
377 		free(address);
378 		*_address = NULL;
379 		return B_OK;
380 	}
381 
382 	// Set address
383 
384 	size_t size = max_c(to->sa_len, sizeof(sockaddr));
385 	if (size > sizeof(sockaddr_storage))
386 		size = sizeof(sockaddr_storage);
387 
388 	address = Prepare(_address, size);
389 	if (address == NULL)
390 		return B_NO_MEMORY;
391 
392 	memcpy(address, to, size);
393 	address->sa_len = size;
394 
395 	return B_OK;
396 }
397 
398 
399 /*!	Makes sure that the sockaddr object pointed to by \a _address is large
400 	enough to hold \a size bytes.
401 	\a _address may point to NULL when calling this method.
402 */
403 /*static*/ sockaddr*
404 InterfaceAddress::Prepare(sockaddr** _address, size_t size)
405 {
406 	size = max_c(size, sizeof(sockaddr));
407 	if (size > sizeof(sockaddr_storage))
408 		size = sizeof(sockaddr_storage);
409 
410 	sockaddr* address = *_address;
411 
412 	if (address == NULL || size > address->sa_len) {
413 		address = (sockaddr*)realloc(address, size);
414 		if (address == NULL)
415 			return NULL;
416 	}
417 
418 	address->sa_len = size;
419 
420 	*_address = address;
421 	return address;
422 }
423 
424 
425 void
426 InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
427 {
428 	TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
429 		netInterface, netDomain);
430 
431 	interface = netInterface;
432 	domain = netDomain;
433 	local = NULL;
434 	destination = NULL;
435 	mask = NULL;
436 	flags = 0;
437 
438 	if (interface != NULL)
439 		((Interface*)interface)->AcquireReference();
440 }
441 
442 
443 // #pragma mark -
444 
445 
446 Interface::Interface(const char* interfaceName,
447 	net_device_interface* deviceInterface)
448 {
449 	TRACE("Interface %p: new \"%s\", device interface %p\n", this,
450 		interfaceName, deviceInterface);
451 
452 	int written = strlcpy(name, interfaceName, IF_NAMESIZE);
453 	memset(name + written, 0, IF_NAMESIZE - written);
454 		// Clear remaining space
455 
456 	device = deviceInterface->device;
457 
458 	index = ++sInterfaceIndex;
459 	flags = 0;
460 	type = 0;
461 	mtu = deviceInterface->device->mtu;
462 	metric = 0;
463 
464 	fDeviceInterface = acquire_device_interface(deviceInterface);
465 
466 	recursive_lock_init(&fLock, name);
467 
468 	// Grab a reference to the networking stack, to make sure it won't be
469 	// unloaded as long as an interface exists
470 	module_info* module;
471 	get_module(gNetStackInterfaceModule.info.name, &module);
472 }
473 
474 
475 Interface::~Interface()
476 {
477 	TRACE("Interface %p: destructor\n", this);
478 
479 	put_device_interface(fDeviceInterface);
480 
481 	// Uninitialize the domain datalink protocols
482 
483 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
484 	while (domain_datalink* datalink = iterator.Next()) {
485 		put_domain_datalink_protocols(this, datalink->domain);
486 	}
487 
488 	// Free domain datalink objects
489 
490 	domain_datalink* next = fDatalinkTable.Clear(true);
491 	while (next != NULL) {
492 		domain_datalink* datalink = next;
493 		next = next->hash_link;
494 
495 		delete datalink;
496 	}
497 
498 	recursive_lock_destroy(&fLock);
499 
500 	// Release reference of the stack - at this point, our stack may be unloaded
501 	// if no other interfaces or sockets are left
502 	put_module(gNetStackInterfaceModule.info.name);
503 }
504 
505 
506 /*!	Returns a reference to the first InterfaceAddress that is from the same
507 	as the specified \a family.
508 */
509 InterfaceAddress*
510 Interface::FirstForFamily(int family)
511 {
512 	RecursiveLocker locker(fLock);
513 
514 	InterfaceAddress* address = _FirstForFamily(family);
515 	if (address != NULL) {
516 		address->AcquireReference();
517 		return address;
518 	}
519 
520 	return NULL;
521 }
522 
523 
524 /*!	Returns a reference to the first unconfigured address of this interface
525 	for the specified \a family.
526 */
527 InterfaceAddress*
528 Interface::FirstUnconfiguredForFamily(int family)
529 {
530 	RecursiveLocker locker(fLock);
531 
532 	AddressList::Iterator iterator = fAddresses.GetIterator();
533 	while (InterfaceAddress* address = iterator.Next()) {
534 		if (address->domain->family == family
535 			&& (address->local == NULL
536 				// TODO: this has to be solved differently!!
537 				|| (flags & IFF_CONFIGURING) != 0)) {
538 			address->AcquireReference();
539 			return address;
540 		}
541 	}
542 
543 	return NULL;
544 }
545 
546 
547 /*!	Returns a reference to the InterfaceAddress that has the specified
548 	\a destination address.
549 */
550 InterfaceAddress*
551 Interface::AddressForDestination(net_domain* domain,
552 	const sockaddr* destination)
553 {
554 	RecursiveLocker locker(fLock);
555 
556 	if ((device->flags & IFF_BROADCAST) == 0) {
557 		// The device does not support broadcasting
558 		return NULL;
559 	}
560 
561 	AddressList::Iterator iterator = fAddresses.GetIterator();
562 	while (InterfaceAddress* address = iterator.Next()) {
563 		if (address->domain == domain
564 			&& address->destination != NULL
565 			&& domain->address_module->equal_addresses(address->destination,
566 					destination)) {
567 			address->AcquireReference();
568 			return address;
569 		}
570 	}
571 
572 	return NULL;
573 }
574 
575 
576 /*!	Returns a reference to the InterfaceAddress that has the specified
577 	\a local address.
578 */
579 InterfaceAddress*
580 Interface::AddressForLocal(net_domain* domain, const sockaddr* local)
581 {
582 	RecursiveLocker locker(fLock);
583 
584 	AddressList::Iterator iterator = fAddresses.GetIterator();
585 	while (InterfaceAddress* address = iterator.Next()) {
586 		if (address->domain == domain
587 			&& address->local != NULL
588 			&& domain->address_module->equal_addresses(address->local, local)) {
589 			address->AcquireReference();
590 			return address;
591 		}
592 	}
593 
594 	return NULL;
595 }
596 
597 
598 status_t
599 Interface::AddAddress(InterfaceAddress* address)
600 {
601 	net_domain* domain = address->domain;
602 	if (domain == NULL)
603 		return B_BAD_VALUE;
604 
605 	RecursiveLocker locker(fLock);
606 	fAddresses.Add(address);
607 	locker.Unlock();
608 
609 	if (address->LocalIsDefined()) {
610 		MutexLocker hashLocker(sHashLock);
611 		sAddressTable.Insert(address);
612 	}
613 	return B_OK;
614 }
615 
616 
617 void
618 Interface::RemoveAddress(InterfaceAddress* address)
619 {
620 	net_domain* domain = address->domain;
621 	if (domain == NULL)
622 		return;
623 
624 	RecursiveLocker locker(fLock);
625 
626 	fAddresses.Remove(address);
627 	address->GetDoublyLinkedListLink()->next = NULL;
628 
629 	locker.Unlock();
630 
631 	if (address->LocalIsDefined()) {
632 		MutexLocker hashLocker(sHashLock);
633 		sAddressTable.Remove(address);
634 	}
635 }
636 
637 
638 bool
639 Interface::GetNextAddress(InterfaceAddress** _address)
640 {
641 	RecursiveLocker locker(fLock);
642 
643 	InterfaceAddress* address = *_address;
644 	if (address == NULL) {
645 		// get first address
646 		address = fAddresses.First();
647 	} else {
648 		// get next, if possible
649 		InterfaceAddress* next = fAddresses.GetNext(address);
650 		address->ReleaseReference();
651 		address = next;
652 	}
653 
654 	*_address = address;
655 
656 	if (address == NULL)
657 		return false;
658 
659 	address->AcquireReference();
660 	return true;
661 }
662 
663 
664 InterfaceAddress*
665 Interface::AddressAt(size_t index)
666 {
667 	RecursiveLocker locker(fLock);
668 
669 	AddressList::Iterator iterator = fAddresses.GetIterator();
670 	size_t i = 0;
671 
672 	while (InterfaceAddress* address = iterator.Next()) {
673 		if (i++ == index) {
674 			address->AcquireReference();
675 			return address;
676 		}
677 	}
678 
679 	return NULL;
680 }
681 
682 
683 int32
684 Interface::IndexOfAddress(InterfaceAddress* address)
685 {
686 	if (address == NULL)
687 		return -1;
688 
689 	RecursiveLocker locker(fLock);
690 
691 	AddressList::Iterator iterator = fAddresses.GetIterator();
692 	int32 index = 0;
693 
694 	while (iterator.HasNext()) {
695 		if (address == iterator.Next())
696 			return index;
697 
698 		index++;
699 	}
700 
701 	return -1;
702 }
703 
704 
705 size_t
706 Interface::CountAddresses()
707 {
708 	RecursiveLocker locker(fLock);
709 	return fAddresses.Count();
710 }
711 
712 
713 void
714 Interface::RemoveAddresses()
715 {
716 	RecursiveLocker locker(fLock);
717 
718 	while (InterfaceAddress* address = fAddresses.RemoveHead()) {
719 		locker.Unlock();
720 
721 		if (address->LocalIsDefined()) {
722 			MutexLocker hashLocker(sHashLock);
723 			sAddressTable.Remove(address);
724 		}
725 		address->ReleaseReference();
726 
727 		locker.Lock();
728 	}
729 }
730 
731 
732 /*!	This is called in order to call the correct methods of the datalink
733 	protocols, ie. it will translate address changes to
734 	net_datalink_protocol::change_address(), and IFF_UP changes to
735 	net_datalink_protocol::interface_up(), and interface_down().
736 
737 	Everything else is passed unchanged to net_datalink_protocol::control().
738 */
739 status_t
740 Interface::Control(net_domain* domain, int32 option, ifreq& request,
741 	ifreq* userRequest, size_t length)
742 {
743 	switch (option) {
744 		case SIOCSIFFLAGS:
745 		{
746 			if (length != sizeof(ifreq))
747 				return B_BAD_VALUE;
748 
749 			uint32 requestFlags = request.ifr_flags;
750 			uint32 oldFlags = flags;
751 			status_t status = B_OK;
752 
753 			request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
754 
755 			if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
756 				if ((requestFlags & IFF_UP) != 0)
757 					status = _SetUp();
758 				else
759 					SetDown();
760 			}
761 
762 			if (status == B_OK) {
763 				// TODO: maybe allow deleting IFF_BROADCAST on the interface
764 				// level?
765 				flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
766 				flags |= request.ifr_flags;
767 			}
768 
769 			if (oldFlags != flags) {
770 				TRACE("Interface %p: flags changed from %" B_PRIx32 " to %"
771 					B_PRIx32 "\n", this, oldFlags, flags);
772 				notify_interface_changed(this, oldFlags, flags);
773 			}
774 
775 			return status;
776 		}
777 
778 		case B_SOCKET_SET_ALIAS:
779 		{
780 			if (length != sizeof(ifaliasreq))
781 				return B_BAD_VALUE;
782 
783 			RecursiveLocker locker(fLock);
784 
785 			ifaliasreq aliasRequest;
786 			if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
787 					!= B_OK)
788 				return B_BAD_ADDRESS;
789 
790 			InterfaceAddress* address = NULL;
791 			if (aliasRequest.ifra_index < 0) {
792 				if (!domain->address_module->is_empty_address(
793 						(const sockaddr*)&aliasRequest.ifra_addr, false)) {
794 					// Find first address that matches the local address
795 					address = AddressForLocal(domain,
796 						(const sockaddr*)&aliasRequest.ifra_addr);
797 				}
798 				if (address == NULL) {
799 					// Find first address for family
800 					address = FirstForFamily(domain->family);
801 				}
802 				if (address == NULL) {
803 					// Create new on the fly
804 					address = new(std::nothrow) InterfaceAddress(this, domain);
805 					if (address == NULL)
806 						return B_NO_MEMORY;
807 
808 					status_t status = AddAddress(address);
809 					if (status != B_OK) {
810 						delete address;
811 						return status;
812 					}
813 
814 					// Note, even if setting the address failed, the empty
815 					// address added here will still be added to the interface.
816 					address->AcquireReference();
817 				}
818 			} else
819 				address = AddressAt(aliasRequest.ifra_index);
820 
821 			if (address == NULL)
822 				return B_BAD_VALUE;
823 
824 			status_t status = B_OK;
825 
826 			if (!domain->address_module->equal_addresses(
827 					(sockaddr*)&aliasRequest.ifra_addr, address->local)) {
828 				status = _ChangeAddress(locker, address, SIOCSIFADDR,
829 					address->local, (sockaddr*)&aliasRequest.ifra_addr);
830 			}
831 
832 			if (status == B_OK && !domain->address_module->equal_addresses(
833 					(sockaddr*)&aliasRequest.ifra_mask, address->mask)
834 				&& !domain->address_module->is_empty_address(
835 					(sockaddr*)&aliasRequest.ifra_mask, false)) {
836 				status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
837 					address->mask, (sockaddr*)&aliasRequest.ifra_mask);
838 			}
839 
840 			if (status == B_OK && !domain->address_module->equal_addresses(
841 					(sockaddr*)&aliasRequest.ifra_destination,
842 					address->destination)
843 				&& !domain->address_module->is_empty_address(
844 					(sockaddr*)&aliasRequest.ifra_destination, false)) {
845 				status = _ChangeAddress(locker, address,
846 					(domain->address_module->flags
847 						& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
848 							? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
849 					address->destination,
850 					(sockaddr*)&aliasRequest.ifra_destination);
851 			}
852 
853 			address->ReleaseReference();
854 			return status;
855 		}
856 
857 		case SIOCSIFADDR:
858 		case SIOCSIFNETMASK:
859 		case SIOCSIFBRDADDR:
860 		case SIOCSIFDSTADDR:
861 		case SIOCDIFADDR:
862 		{
863 			if (length != sizeof(ifreq))
864 				return B_BAD_VALUE;
865 
866 			RecursiveLocker locker(fLock);
867 
868 			InterfaceAddress* address = NULL;
869 			sockaddr_storage newAddress;
870 
871 			size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
872 			if (size > sizeof(sockaddr_storage))
873 				size = sizeof(sockaddr_storage);
874 
875 			if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
876 				return B_BAD_ADDRESS;
877 
878 			if (option == SIOCDIFADDR) {
879 				// Find referring address - we can't use the hash, as another
880 				// interface might use the same address.
881 				AddressList::Iterator iterator = fAddresses.GetIterator();
882 				while ((address = iterator.Next()) != NULL) {
883 					if (address->domain == domain
884 						&& domain->address_module->equal_addresses(
885 							address->local, (sockaddr*)&newAddress))
886 						break;
887 				}
888 
889 				if (address == NULL)
890 					return B_BAD_VALUE;
891 			} else {
892 				// Just use the first address for this family
893 				address = _FirstForFamily(domain->family);
894 				if (address == NULL) {
895 					// Create new on the fly
896 					address = new(std::nothrow) InterfaceAddress(this, domain);
897 					if (address == NULL)
898 						return B_NO_MEMORY;
899 
900 					status_t status = AddAddress(address);
901 					if (status != B_OK) {
902 						delete address;
903 						return status;
904 					}
905 
906 					// Note, even if setting the address failed, the empty
907 					// address added here will still be added to the interface.
908 				}
909 			}
910 
911 			return _ChangeAddress(locker, address, option,
912 				*address->AddressFor(option),
913 				option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
914 		}
915 
916 		default:
917 			// pass the request into the datalink protocol stack
918 			domain_datalink* datalink = DomainDatalink(domain->family);
919 			if (datalink->first_info != NULL) {
920 				return datalink->first_info->control(
921 					datalink->first_protocol, option, userRequest, length);
922 			}
923 			break;
924 	}
925 
926 	return B_BAD_VALUE;
927 }
928 
929 
930 void
931 Interface::SetDown()
932 {
933 	if ((flags & IFF_UP) == 0)
934 		return;
935 
936 	RecursiveLocker locker(fLock);
937 
938 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
939 	while (domain_datalink* datalink = iterator.Next()) {
940 		datalink->first_info->interface_down(datalink->first_protocol);
941 	}
942 
943 	flags &= ~IFF_UP;
944 }
945 
946 
947 /*!	Called when a device lost its IFF_UP status. We will invalidate all
948 	interface routes here.
949 */
950 void
951 Interface::WentDown()
952 {
953 	TRACE("Interface %p: went down\n", this);
954 
955 	RecursiveLocker locker(fLock);
956 
957 	AddressList::Iterator iterator = fAddresses.GetIterator();
958 	while (InterfaceAddress* address = iterator.Next()) {
959 		if (address->domain != NULL)
960 			invalidate_routes(address->domain, this);
961 	}
962 }
963 
964 
965 status_t
966 Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
967 {
968 	RecursiveLocker locker(fLock);
969 
970 	if (fDatalinkTable.Lookup(domain->family) != NULL)
971 		return B_OK;
972 
973 	TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
974 
975 	domain_datalink* datalink = new(std::nothrow) domain_datalink;
976 	if (datalink == NULL)
977 		return B_NO_MEMORY;
978 
979 	datalink->first_protocol = NULL;
980 	datalink->first_info = NULL;
981 	datalink->domain = domain;
982 
983 	// setup direct route for bound devices
984 	datalink->direct_route.destination = NULL;
985 	datalink->direct_route.mask = NULL;
986 	datalink->direct_route.gateway = NULL;
987 	datalink->direct_route.flags = 0;
988 	datalink->direct_route.mtu = 0;
989 	datalink->direct_route.interface_address = &datalink->direct_address;
990 	datalink->direct_route.ref_count = 1;
991 		// make sure this doesn't get deleted accidently
992 
993 	// provide its link back to the interface
994 	datalink->direct_address.local = NULL;
995 	datalink->direct_address.destination = NULL;
996 	datalink->direct_address.mask = NULL;
997 	datalink->direct_address.domain = domain;
998 	datalink->direct_address.interface = this;
999 	datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
1000 
1001 	fDatalinkTable.Insert(datalink);
1002 
1003 	status_t status = get_domain_datalink_protocols(this, domain);
1004 	if (status == B_OK)
1005 		return B_OK;
1006 
1007 	fDatalinkTable.Remove(datalink);
1008 	delete datalink;
1009 
1010 	return status;
1011 }
1012 
1013 
1014 domain_datalink*
1015 Interface::DomainDatalink(uint8 family)
1016 {
1017 	// Note: domain datalinks cannot be removed while the interface is alive,
1018 	// since this would require us either to hold the lock while calling this
1019 	// function, or introduce reference counting for the domain_datalink
1020 	// structure.
1021 	RecursiveLocker locker(fLock);
1022 	return fDatalinkTable.Lookup(family);
1023 }
1024 
1025 
1026 #if ENABLE_DEBUGGER_COMMANDS
1027 
1028 
1029 void
1030 Interface::Dump() const
1031 {
1032 	kprintf("name:                %s\n", name);
1033 	kprintf("device:              %p\n", device);
1034 	kprintf("device_interface:    %p\n", fDeviceInterface);
1035 	kprintf("index:               %" B_PRIu32 "\n", index);
1036 	kprintf("flags:               %#" B_PRIx32 "\n", flags);
1037 	kprintf("type:                %u\n", type);
1038 	kprintf("mtu:                 %" B_PRIu32 "\n", mtu);
1039 	kprintf("metric:              %" B_PRIu32 "\n", metric);
1040 	kprintf("ref count:           %" B_PRId32 "\n", CountReferences());
1041 
1042 	kprintf("datalink protocols:\n");
1043 
1044 	DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
1045 	size_t i = 0;
1046 	while (domain_datalink* datalink = datalinkIterator.Next()) {
1047 		kprintf("%2zu. domain:          %p\n", ++i, datalink->domain);
1048 		kprintf("    first_protocol:  %p\n", datalink->first_protocol);
1049 		kprintf("    first_info:      %p\n", datalink->first_info);
1050 		kprintf("    direct_route:    %p\n", &datalink->direct_route);
1051 	}
1052 
1053 	kprintf("addresses:\n");
1054 
1055 	AddressList::ConstIterator iterator = fAddresses.GetIterator();
1056 	i = 0;
1057 	while (InterfaceAddress* address = iterator.Next()) {
1058 		address->Dump(++i, true);
1059 	}
1060 }
1061 
1062 
1063 #endif	// ENABLE_DEBUGGER_COMMANDS
1064 
1065 
1066 status_t
1067 Interface::_SetUp()
1068 {
1069 	status_t status = up_device_interface(fDeviceInterface);
1070 	if (status != B_OK)
1071 		return status;
1072 
1073 	// Propagate flag to all datalink protocols
1074 
1075 	RecursiveLocker locker(fLock);
1076 
1077 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
1078 	while (domain_datalink* datalink = iterator.Next()) {
1079 		status = datalink->first_info->interface_up(datalink->first_protocol);
1080 		if (status != B_OK) {
1081 			// Revert "up" status
1082 			DatalinkTable::Iterator secondIterator
1083 				= fDatalinkTable.GetIterator();
1084 			while (secondIterator.HasNext()) {
1085 				domain_datalink* secondDatalink = secondIterator.Next();
1086 				if (secondDatalink == NULL || secondDatalink == datalink)
1087 					break;
1088 
1089 				secondDatalink->first_info->interface_down(
1090 					secondDatalink->first_protocol);
1091 			}
1092 
1093 			down_device_interface(fDeviceInterface);
1094 			return status;
1095 		}
1096 	}
1097 
1098 	// Add default routes for the existing addresses
1099 
1100 	AddressList::Iterator addressIterator = fAddresses.GetIterator();
1101 	while (InterfaceAddress* address = addressIterator.Next()) {
1102 		address->AddDefaultRoutes(SIOCSIFADDR);
1103 	}
1104 
1105 	flags |= IFF_UP;
1106 	return B_OK;
1107 }
1108 
1109 
1110 InterfaceAddress*
1111 Interface::_FirstForFamily(int family)
1112 {
1113 	ASSERT_LOCKED_RECURSIVE(&fLock);
1114 
1115 	AddressList::Iterator iterator = fAddresses.GetIterator();
1116 	while (InterfaceAddress* address = iterator.Next()) {
1117 		if (address->domain != NULL && address->domain->family == family)
1118 			return address;
1119 	}
1120 
1121 	return NULL;
1122 }
1123 
1124 
1125 status_t
1126 Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
1127 	int32 option, const sockaddr* originalAddress,
1128 	const sockaddr* requestedAddress)
1129 {
1130 	// Copy old address
1131 	sockaddr_storage oldAddress;
1132 	if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
1133 			originalAddress) != B_OK)
1134 		oldAddress.ss_family = AF_UNSPEC;
1135 
1136 	// Copy new address (this also makes sure that sockaddr::sa_len is set
1137 	// correctly)
1138 	sockaddr_storage newAddress;
1139 	if (address->domain->address_module->set_to((sockaddr*)&newAddress,
1140 			requestedAddress) != B_OK)
1141 		newAddress.ss_family = AF_UNSPEC;
1142 
1143 	// Test if anything changed for real
1144 	if (address->domain->address_module->equal_addresses(
1145 			(sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
1146 		// Nothing to do
1147 		TRACE("  option %" B_PRId32 " addresses are equal!\n", option);
1148 		return B_OK;
1149 	}
1150 
1151 	// TODO: mark this address busy or call while holding the lock!
1152 	address->AcquireReference();
1153 	locker.Unlock();
1154 
1155 	domain_datalink* datalink = DomainDatalink(address->domain);
1156 	status_t status = datalink->first_protocol->module->change_address(
1157 		datalink->first_protocol, address, option,
1158 		oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1159 		newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
1160 
1161 	locker.Lock();
1162 	address->ReleaseReference();
1163 	return status;
1164 }
1165 
1166 
1167 // #pragma mark -
1168 
1169 
1170 /*!	Searches for a specific interface by name.
1171 	You need to have the interface list's lock hold when calling this function.
1172 */
1173 static struct Interface*
1174 find_interface(const char* name)
1175 {
1176 	ASSERT_LOCKED_MUTEX(&sLock);
1177 
1178 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1179 	while (Interface* interface = iterator.Next()) {
1180 		if (!strcmp(interface->name, name))
1181 			return interface;
1182 	}
1183 
1184 	return NULL;
1185 }
1186 
1187 
1188 /*!	Searches for a specific interface by index.
1189 	You need to have the interface list's lock hold when calling this function.
1190 */
1191 static struct Interface*
1192 find_interface(uint32 index)
1193 {
1194 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1195 	while (Interface* interface = iterator.Next()) {
1196 		if (interface->index == index)
1197 			return interface;
1198 	}
1199 
1200 	return NULL;
1201 }
1202 
1203 
1204 // #pragma mark -
1205 
1206 
1207 status_t
1208 add_interface(const char* name, net_domain_private* domain,
1209 	const ifaliasreq& request, net_device_interface* deviceInterface)
1210 {
1211 	MutexLocker locker(sLock);
1212 
1213 	if (find_interface(name) != NULL)
1214 		return B_NAME_IN_USE;
1215 
1216 	Interface* interface
1217 		= new(std::nothrow) Interface(name, deviceInterface);
1218 	if (interface == NULL)
1219 		return B_NO_MEMORY;
1220 
1221 	sInterfaces.Add(interface);
1222 	interface->AcquireReference();
1223 		// We need another reference to be able to use the interface without
1224 		// holding sLock.
1225 
1226 	locker.Unlock();
1227 
1228 	status_t status = add_interface_address(interface, domain, request);
1229 	if (status == B_OK)
1230 		notify_interface_added(interface);
1231 	else {
1232 		locker.Lock();
1233 		sInterfaces.Remove(interface);
1234 		locker.Unlock();
1235 		interface->ReleaseReference();
1236 	}
1237 
1238 	interface->ReleaseReference();
1239 
1240 	return status;
1241 }
1242 
1243 
1244 /*!	Removes the interface from the list, and puts the stack's reference to it.
1245 */
1246 void
1247 remove_interface(Interface* interface)
1248 {
1249 	interface->SetDown();
1250 	interface->RemoveAddresses();
1251 
1252 	MutexLocker locker(sLock);
1253 	sInterfaces.Remove(interface);
1254 	locker.Unlock();
1255 
1256 	notify_interface_removed(interface);
1257 
1258 	interface->ReleaseReference();
1259 }
1260 
1261 
1262 /*!	This is called whenever a device interface is being removed. We will get
1263 	the corresponding Interface, and remove it.
1264 */
1265 void
1266 interface_removed_device_interface(net_device_interface* deviceInterface)
1267 {
1268 	MutexLocker locker(sLock);
1269 
1270 	Interface* interface = find_interface(deviceInterface->device->name);
1271 	if (interface != NULL)
1272 		remove_interface(interface);
1273 }
1274 
1275 
1276 status_t
1277 add_interface_address(Interface* interface, net_domain_private* domain,
1278 	const ifaliasreq& request)
1279 {
1280 	// Make sure the family of the provided addresses is valid
1281 	if ((request.ifra_addr.ss_family != domain->family
1282 			&& request.ifra_addr.ss_family != AF_UNSPEC)
1283 		|| (request.ifra_mask.ss_family != domain->family
1284 			&& request.ifra_mask.ss_family != AF_UNSPEC)
1285 		|| (request.ifra_broadaddr.ss_family != domain->family
1286 			&& request.ifra_broadaddr.ss_family != AF_UNSPEC))
1287 		return B_BAD_VALUE;
1288 
1289 	RecursiveLocker locker(interface->Lock());
1290 
1291 	InterfaceAddress* address
1292 		= new(std::nothrow) InterfaceAddress(interface, domain);
1293 	if (address == NULL)
1294 		return B_NO_MEMORY;
1295 
1296 	status_t status = address->SetTo(request);
1297 	if (status == B_OK)
1298 		status = interface->CreateDomainDatalinkIfNeeded(domain);
1299 	if (status == B_OK)
1300 		status = interface->AddAddress(address);
1301 
1302 	if (status == B_OK && address->local != NULL) {
1303 		// update the datalink protocols
1304 		domain_datalink* datalink = interface->DomainDatalink(domain->family);
1305 
1306 		status = datalink->first_protocol->module->change_address(
1307 			datalink->first_protocol, address, SIOCAIFADDR, NULL,
1308 			address->local);
1309 		if (status != B_OK)
1310 			interface->RemoveAddress(address);
1311 	}
1312 	if (status == B_OK)
1313 		notify_interface_changed(interface);
1314 	else
1315 		delete address;
1316 
1317 	return status;
1318 }
1319 
1320 
1321 status_t
1322 update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
1323 	const sockaddr* oldAddress, const sockaddr* newAddress)
1324 {
1325 	TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1326 		"%s)\n", __FUNCTION__, interfaceAddress, option,
1327 		AddressString(interfaceAddress->domain, oldAddress).Data(),
1328 		AddressString(interfaceAddress->domain, newAddress).Data());
1329 
1330 	MutexLocker locker(sHashLock);
1331 
1332 	// set logical interface address
1333 	sockaddr** _address = interfaceAddress->AddressFor(option);
1334 	if (_address == NULL)
1335 		return B_BAD_VALUE;
1336 
1337 	Interface* interface = (Interface*)interfaceAddress->interface;
1338 
1339 	interfaceAddress->RemoveDefaultRoutes(option);
1340 
1341 	if (option == SIOCDIFADDR) {
1342 		// Remove address, and release its reference (causing our caller to
1343 		// delete it)
1344 		locker.Unlock();
1345 
1346 		invalidate_routes(interfaceAddress);
1347 
1348 		interface->RemoveAddress(interfaceAddress);
1349 		interfaceAddress->ReleaseReference();
1350 		return B_OK;
1351 	}
1352 
1353 	if (interfaceAddress->LocalIsDefined())
1354 		sAddressTable.Remove(interfaceAddress);
1355 
1356 	// Copy new address over
1357 	status_t status = InterfaceAddress::Set(_address, newAddress);
1358 	if (status == B_OK) {
1359 		sockaddr* address = *_address;
1360 
1361 		if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
1362 			// Reset netmask and broadcast addresses to defaults
1363 			net_domain* domain = interfaceAddress->domain;
1364 			sockaddr* defaultNetmask = NULL;
1365 			const sockaddr* netmask = NULL;
1366 			if (option == SIOCSIFADDR) {
1367 				defaultNetmask = InterfaceAddress::Prepare(
1368 					&interfaceAddress->mask, address->sa_len);
1369 			} else
1370 				netmask = newAddress;
1371 
1372 			// Reset the broadcast address if the address family has
1373 			// such
1374 			sockaddr* defaultBroadcast = NULL;
1375 			if ((domain->address_module->flags
1376 					& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
1377 				defaultBroadcast = InterfaceAddress::Prepare(
1378 					&interfaceAddress->destination, address->sa_len);
1379 			} else
1380 				InterfaceAddress::Set(&interfaceAddress->destination, NULL);
1381 
1382 			domain->address_module->set_to_defaults(defaultNetmask,
1383 				defaultBroadcast, interfaceAddress->local, netmask);
1384 		}
1385 
1386 		interfaceAddress->AddDefaultRoutes(option);
1387 		notify_interface_changed(interface);
1388 	}
1389 
1390 	if (interfaceAddress->LocalIsDefined())
1391 		sAddressTable.Insert(interfaceAddress);
1392 	return status;
1393 }
1394 
1395 
1396 Interface*
1397 get_interface(net_domain* domain, uint32 index)
1398 {
1399 	MutexLocker locker(sLock);
1400 
1401 	Interface* interface;
1402 	if (index == 0)
1403 		interface = sInterfaces.First();
1404 	else
1405 		interface = find_interface(index);
1406 	if (interface == NULL)
1407 		return NULL;
1408 
1409 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1410 		return NULL;
1411 
1412 	interface->AcquireReference();
1413 	return interface;
1414 }
1415 
1416 
1417 Interface*
1418 get_interface(net_domain* domain, const char* name)
1419 {
1420 	MutexLocker locker(sLock);
1421 
1422 	Interface* interface = find_interface(name);
1423 	if (interface == NULL)
1424 		return NULL;
1425 
1426 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1427 		return NULL;
1428 
1429 	interface->AcquireReference();
1430 	return interface;
1431 }
1432 
1433 
1434 Interface*
1435 get_interface_for_device(net_domain* domain, uint32 index)
1436 {
1437 	MutexLocker locker(sLock);
1438 
1439 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1440 	while (Interface* interface = iterator.Next()) {
1441 		if (interface->device->index == index) {
1442 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1443 				return NULL;
1444 
1445 			interface->AcquireReference();
1446 			return interface;
1447 		}
1448 	}
1449 
1450 	return NULL;
1451 }
1452 
1453 
1454 /*!	Returns a reference to an Interface that matches the given \a linkAddress.
1455 	The link address is checked against its hardware address, or its interface
1456 	name, or finally the interface index.
1457 */
1458 Interface*
1459 get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1460 {
1461 	sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1462 
1463 	MutexLocker locker(sLock);
1464 
1465 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1466 	while (Interface* interface = iterator.Next()) {
1467 		// Test if the hardware address matches, or if the given interface
1468 		// matches, or if at least the index matches.
1469 		if ((linkAddress.sdl_alen == interface->device->address.length
1470 				&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1471 					linkAddress.sdl_alen) == 0)
1472 			|| (linkAddress.sdl_nlen > 0
1473 				&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1474 			|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1475 				&& linkAddress.sdl_index == interface->index)) {
1476 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1477 				return NULL;
1478 
1479 			interface->AcquireReference();
1480 			return interface;
1481 		}
1482 	}
1483 
1484 	return NULL;
1485 }
1486 
1487 
1488 InterfaceAddress*
1489 get_interface_address(const sockaddr* local)
1490 {
1491 	if (local->sa_family == AF_UNSPEC)
1492 		return NULL;
1493 
1494 	MutexLocker locker(sHashLock);
1495 
1496 	InterfaceAddress* address = sAddressTable.Lookup(local);
1497 	if (address == NULL)
1498 		return NULL;
1499 
1500 	address->AcquireReference();
1501 	return address;
1502 }
1503 
1504 
1505 InterfaceAddress*
1506 get_interface_address_for_destination(net_domain* domain,
1507 	const sockaddr* destination)
1508 {
1509 	MutexLocker locker(sLock);
1510 
1511 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1512 	while (Interface* interface = iterator.Next()) {
1513 		InterfaceAddress* address
1514 			= interface->AddressForDestination(domain, destination);
1515 		if (address != NULL)
1516 			return address;
1517 	}
1518 
1519 	return NULL;
1520 }
1521 
1522 
1523 /*!	Returns a reference to an InterfaceAddress of the specified \a domain that
1524 	belongs to the interface identified via \a linkAddress. Only the hardware
1525 	address is matched.
1526 
1527 	If \a unconfiguredOnly is set, the interface address must not yet be
1528 	configured, or must currently be in the process of being configured.
1529 */
1530 InterfaceAddress*
1531 get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1532 	bool unconfiguredOnly)
1533 {
1534 	sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
1535 
1536 	MutexLocker locker(sLock);
1537 
1538 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1539 	while (Interface* interface = iterator.Next()) {
1540 		// Test if the hardware address matches, or if the given interface
1541 		// matches, or if at least the index matches.
1542 		if (linkAddress.sdl_alen == interface->device->address.length
1543 			&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1544 				linkAddress.sdl_alen) == 0) {
1545 			TRACE("  %s matches\n", interface->name);
1546 			// link address matches
1547 			if (unconfiguredOnly)
1548 				return interface->FirstUnconfiguredForFamily(domain->family);
1549 
1550 			return interface->FirstForFamily(domain->family);
1551 		}
1552 	}
1553 
1554 	return NULL;
1555 }
1556 
1557 
1558 uint32
1559 count_interfaces()
1560 {
1561 	MutexLocker locker(sLock);
1562 
1563 	return sInterfaces.Count();
1564 }
1565 
1566 
1567 /*!	Dumps a list of all interfaces into the supplied userland buffer.
1568 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1569 	returned.
1570 */
1571 status_t
1572 list_interfaces(int family, void* _buffer, size_t* bufferSize)
1573 {
1574 	MutexLocker locker(sLock);
1575 
1576 	UserBuffer buffer(_buffer, *bufferSize);
1577 
1578 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1579 	while (Interface* interface = iterator.Next()) {
1580 		// Copy name
1581 		buffer.Push(interface->name, IF_NAMESIZE);
1582 
1583 		// Copy address
1584 		InterfaceAddress* address = interface->FirstForFamily(family);
1585 		size_t length = 0;
1586 
1587 		if (address != NULL && address->local != NULL) {
1588 			// Actual address
1589 			buffer.Push(address->local, length = address->local->sa_len);
1590 		} else {
1591 			// Empty address
1592 			sockaddr empty;
1593 			empty.sa_len = 2;
1594 			empty.sa_family = AF_UNSPEC;
1595 			buffer.Push(&empty, length = empty.sa_len);
1596 		}
1597 
1598 		if (address != NULL)
1599 			address->ReleaseReference();
1600 
1601 		if (IF_NAMESIZE + length < sizeof(ifreq)) {
1602 			// Make sure at least sizeof(ifreq) bytes are written for each
1603 			// interface for compatibility with other platforms
1604 			buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
1605 		}
1606 
1607 		if (buffer.Status() != B_OK)
1608 			return buffer.Status();
1609 	}
1610 
1611 	*bufferSize = buffer.BytesConsumed();
1612 	return B_OK;
1613 }
1614 
1615 
1616 //	#pragma mark -
1617 
1618 
1619 status_t
1620 init_interfaces()
1621 {
1622 	mutex_init(&sLock, "net interfaces");
1623 	mutex_init(&sHashLock, "net local addresses");
1624 
1625 	new (&sInterfaces) InterfaceList;
1626 	new (&sAddressTable) AddressTable;
1627 		// static C++ objects are not initialized in the module startup
1628 
1629 #if ENABLE_DEBUGGER_COMMANDS
1630 	add_debugger_command("net_interface", &dump_interface,
1631 		"Dump the given network interface");
1632 	add_debugger_command("net_interfaces", &dump_interfaces,
1633 		"Dump all network interfaces");
1634 	add_debugger_command("net_local", &dump_local,
1635 		"Dump all local interface addresses");
1636 	add_debugger_command("net_route", &dump_route,
1637 		"Dump the given network route");
1638 #endif
1639 	return B_OK;
1640 }
1641 
1642 
1643 status_t
1644 uninit_interfaces()
1645 {
1646 #if ENABLE_DEBUGGER_COMMANDS
1647 	remove_debugger_command("net_interface", &dump_interface);
1648 	remove_debugger_command("net_interfaces", &dump_interfaces);
1649 	remove_debugger_command("net_local", &dump_local);
1650 	remove_debugger_command("net_route", &dump_route);
1651 #endif
1652 
1653 	mutex_destroy(&sLock);
1654 	mutex_destroy(&sHashLock);
1655 	return B_OK;
1656 }
1657 
1658