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