xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision c7509fce9db782326f159843f1b028b5f5dcb1d2)
1 /*
2  * Copyright 2006-2007, 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 "domains.h"
11 #include "interfaces.h"
12 #include "stack_private.h"
13 #include "utility.h"
14 
15 #include <net_device.h>
16 
17 #include <lock.h>
18 #include <util/AutoLock.h>
19 
20 #include <KernelExport.h>
21 
22 #include <net/if_dl.h>
23 #include <new>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 
28 #define TRACE_INTERFACES
29 #ifdef TRACE_INTERFACES
30 #	define TRACE(x) dprintf x
31 #else
32 #	define TRACE(x) ;
33 #endif
34 
35 
36 static benaphore sInterfaceLock;
37 static DeviceInterfaceList sInterfaces;
38 static uint32 sInterfaceIndex;
39 static uint32 sDeviceIndex;
40 
41 
42 static net_device_interface *
43 find_device_interface(const char *name)
44 {
45 	DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
46 
47 	while (iterator.HasNext()) {
48 		net_device_interface *interface = iterator.Next();
49 
50 		if (!strcmp(interface->name, name))
51 			return interface;
52 	}
53 
54 	return NULL;
55 }
56 
57 
58 static status_t
59 domain_receive_adapter(void *cookie, net_buffer *buffer)
60 {
61 	net_domain_private *domain = (net_domain_private *)cookie;
62 	return domain->module->receive_data(buffer);
63 }
64 
65 
66 net_device_interface *
67 grab_device_interface(net_device_interface *interface)
68 {
69 	if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0)
70 		return NULL;
71 
72 	return interface;
73 }
74 
75 
76 static void
77 notify_device_monitors(net_device_interface *interface, int32 event)
78 {
79 	DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
80 	while (iterator.HasNext()) {
81 		// when we call Next() the next item in the list is obtained
82 		// so it's safe for the "current" item to remove itself.
83 		net_device_monitor *monitor = iterator.Next();
84 
85 		monitor->event(monitor, event);
86 	}
87 }
88 
89 
90 //	#pragma mark - interfaces
91 
92 
93 /*!
94 	Searches for a specific interface in a domain by name.
95 	You need to have the domain's lock hold when calling this function.
96 */
97 struct net_interface_private *
98 find_interface(struct net_domain *domain, const char *name)
99 {
100 	net_interface_private *interface = NULL;
101 
102 	while (true) {
103 		interface = (net_interface_private *)list_get_next_item(
104 			&domain->interfaces, interface);
105 		if (interface == NULL)
106 			break;
107 
108 		if (!strcmp(interface->name, name))
109 			return interface;
110 	}
111 
112 	return NULL;
113 }
114 
115 
116 /*!
117 	Searches for a specific interface in a domain by index.
118 	You need to have the domain's lock hold when calling this function.
119 */
120 struct net_interface_private *
121 find_interface(struct net_domain *domain, uint32 index)
122 {
123 	net_interface_private *interface = NULL;
124 
125 	while (true) {
126 		interface = (net_interface_private *)list_get_next_item(
127 			&domain->interfaces, interface);
128 		if (interface == NULL)
129 			break;
130 
131 		if (interface->index == index)
132 			return interface;
133 	}
134 
135 	return NULL;
136 }
137 
138 
139 status_t
140 create_interface(net_domain *domain, const char *name, const char *baseName,
141 	net_device_interface *deviceInterface, net_interface_private **_interface)
142 {
143 	net_interface_private *interface =
144 		new (std::nothrow) net_interface_private;
145 	if (interface == NULL)
146 		return B_NO_MEMORY;
147 
148 	strlcpy(interface->name, name, IF_NAMESIZE);
149 	strlcpy(interface->base_name, baseName, IF_NAMESIZE);
150 	interface->domain = domain;
151 	interface->device = deviceInterface->device;
152 
153 	interface->address = NULL;
154 	interface->destination = NULL;
155 	interface->mask = NULL;
156 
157 	interface->index = ++sInterfaceIndex;
158 	interface->flags = 0;
159 	interface->type = 0;
160 	interface->mtu = deviceInterface->device->mtu;
161 	interface->metric = 0;
162 	interface->device_interface = grab_device_interface(deviceInterface);
163 
164 	status_t status = get_domain_datalink_protocols(interface);
165 	if (status < B_OK) {
166 		delete interface;
167 		return status;
168 	}
169 
170 	// Grab a reference to the networking stack, to make sure it won't be
171 	// unloaded as long as an interface exists
172 	module_info *module;
173 	get_module(NET_STARTER_MODULE_NAME, &module);
174 
175 	*_interface = interface;
176 	return B_OK;
177 }
178 
179 
180 void
181 interface_set_down(net_interface *interface)
182 {
183 	if ((interface->flags & IFF_UP) == 0)
184 		return;
185 
186 	interface->flags &= ~IFF_UP;
187 	interface->first_info->interface_down(interface->first_protocol);
188 }
189 
190 
191 void
192 delete_interface(net_interface_private *interface)
193 {
194 	// deleting an interface is fairly complex as we need
195 	// to clear all references to it throughout the stack
196 
197 	// this will possibly call (if IFF_UP):
198 	//  interface_protocol_down()
199 	//   domain_interface_went_down()
200 	//    invalidate_routes()
201 	//     remove_route()
202 	//      update_route_infos()
203 	//       get_route_internal()
204 	//   down_device_interface() -- if upcount reaches 0
205 	interface_set_down(interface);
206 
207 	// This call requires the RX Lock to be a recursive
208 	// lock since each uninit_protocol() call may call
209 	// again into the stack to unregister a reader for
210 	// instance, which tries to obtain the RX lock again.
211 	put_domain_datalink_protocols(interface);
212 
213 	put_device_interface(interface->device_interface);
214 
215 	free(interface->address);
216 	free(interface->destination);
217 	free(interface->mask);
218 
219 	delete interface;
220 
221 	// Release reference of the stack - at this point, our stack may be unloaded
222 	// if no other interfaces or sockets are left
223 	put_module(NET_STARTER_MODULE_NAME);
224 }
225 
226 
227 void
228 put_interface(struct net_interface_private *interface)
229 {
230 	// TODO: reference counting
231 	// TODO: better locking scheme
232 	benaphore_unlock(&((net_domain_private *)interface->domain)->lock);
233 }
234 
235 
236 struct net_interface_private *
237 get_interface(net_domain *_domain, const char *name)
238 {
239 	net_domain_private *domain = (net_domain_private *)_domain;
240 	benaphore_lock(&domain->lock);
241 
242 	net_interface_private *interface = NULL;
243 	while (true) {
244 		interface = (net_interface_private *)list_get_next_item(
245 			&domain->interfaces, interface);
246 		if (interface == NULL)
247 			break;
248 
249 		if (!strcmp(interface->name, name))
250 			return interface;
251 	}
252 
253 	benaphore_unlock(&domain->lock);
254 	return NULL;
255 }
256 
257 
258 //	#pragma mark - device interfaces
259 
260 
261 void
262 get_device_interface_address(net_device_interface *interface, sockaddr *_address)
263 {
264 	sockaddr_dl &address = *(sockaddr_dl *)_address;
265 
266 	address.sdl_family = AF_LINK;
267 	address.sdl_index = interface->device->index;
268 	address.sdl_type = interface->device->type;
269 	address.sdl_nlen = strlen(interface->name);
270 	address.sdl_slen = 0;
271 	memcpy(address.sdl_data, interface->name, address.sdl_nlen);
272 
273 	address.sdl_alen = interface->device->address.length;
274 	memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
275 
276 	address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
277 		+ address.sdl_nlen + address.sdl_alen;
278 }
279 
280 
281 uint32
282 count_device_interfaces()
283 {
284 	BenaphoreLocker locker(sInterfaceLock);
285 
286 	DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
287 	uint32 count = 0;
288 
289 	while (iterator.HasNext()) {
290 		iterator.Next();
291 		count++;
292 	}
293 
294 	return count;
295 }
296 
297 
298 /*!
299 	Dumps a list of all interfaces into the supplied userland buffer.
300 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
301 	returned.
302 */
303 status_t
304 list_device_interfaces(void *_buffer, size_t *bufferSize)
305 {
306 	BenaphoreLocker locker(sInterfaceLock);
307 
308 	DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
309 	UserBuffer buffer(_buffer, *bufferSize);
310 
311 	while (iterator.HasNext()) {
312 		net_device_interface *interface = iterator.Next();
313 
314 		ifreq request;
315 		strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
316 		get_device_interface_address(interface, &request.ifr_addr);
317 
318 		if (buffer.Copy(&request, IF_NAMESIZE
319 				+ request.ifr_addr.sa_len) == NULL)
320 			return buffer.Status();
321 	}
322 
323 	*bufferSize = buffer.ConsumedAmount();
324 	return B_OK;
325 }
326 
327 
328 /*!
329 	Releases the reference for the interface. When all references are
330 	released, the interface is removed.
331 */
332 void
333 put_device_interface(struct net_device_interface *interface)
334 {
335 	if (atomic_add(&interface->ref_count, -1) != 1)
336 		return;
337 
338 	// we need to remove this interface!
339 
340 	{
341 		BenaphoreLocker locker(sInterfaceLock);
342 		sInterfaces.Remove(interface);
343 	}
344 
345 	interface->module->uninit_device(interface->device);
346 	put_module(interface->module->info.name);
347 
348 	recursive_lock_destroy(&interface->rx_lock);
349 	delete interface;
350 }
351 
352 
353 /*!
354 	Finds an interface by the specified index and grabs a reference to it.
355 */
356 struct net_device_interface *
357 get_device_interface(uint32 index)
358 {
359 	BenaphoreLocker locker(sInterfaceLock);
360 	DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
361 
362 	while (iterator.HasNext()) {
363 		net_device_interface *interface = iterator.Next();
364 
365 		if (interface->device->index == index) {
366 			if (atomic_add(&interface->ref_count, 1) != 0)
367 				return interface;
368 		}
369 	}
370 
371 	return NULL;
372 }
373 
374 
375 /*!
376 	Finds an interface by the specified name and grabs a reference to it.
377 	If the interface does not yet exist, a new one is created.
378 */
379 struct net_device_interface *
380 get_device_interface(const char *name, bool create)
381 {
382 	BenaphoreLocker locker(sInterfaceLock);
383 
384 	net_device_interface *interface = find_device_interface(name);
385 	if (interface != NULL) {
386 		if (atomic_add(&interface->ref_count, 1) != 0)
387 			return interface;
388 
389 		// try to recreate interface - it just got removed
390 	}
391 
392 	if (!create)
393 		return NULL;
394 
395 	void *cookie = open_module_list("network/devices");
396 	if (cookie == NULL)
397 		return NULL;
398 
399 	while (true) {
400 		char moduleName[B_FILE_NAME_LENGTH];
401 		size_t length = sizeof(moduleName);
402 		if (read_next_module_name(cookie, moduleName, &length) != B_OK)
403 			break;
404 
405 		TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name));
406 
407 		net_device_module_info *module;
408 		if (get_module(moduleName, (module_info **)&module) == B_OK) {
409 			net_device *device;
410 			status_t status = module->init_device(name, &device);
411 			if (status == B_OK) {
412 				// create new module interface for this
413 				interface = new (std::nothrow) net_device_interface;
414 				if (interface != NULL) {
415 					if (recursive_lock_init(&interface->rx_lock,
416 							"rx lock") >= B_OK) {
417 						interface->name = device->name;
418 						interface->module = module;
419 						interface->device = device;
420 						interface->up_count = 0;
421 						interface->ref_count = 1;
422 						interface->deframe_func = NULL;
423 						interface->deframe_ref_count = 0;
424 
425 						device->index = ++sDeviceIndex;
426 						device->module = module;
427 
428 						sInterfaces.Add(interface);
429 						return interface;
430 					}
431 					delete interface;
432 				}
433 				module->uninit_device(device);
434 			}
435 			put_module(moduleName);
436 		}
437 	}
438 
439 	return NULL;
440 }
441 
442 
443 void
444 down_device_interface(net_device_interface *interface)
445 {
446 	// RX lock must be held when calling down_device_interface.
447 	// Known callers are `interface_protocol_down' which gets
448 	// here via one of the following paths:
449 	//
450 	// - domain_interface_control() [rx lock held, domain lock held]
451 	//    interface_set_down()
452 	//     interface_protocol_down()
453 	//
454 	// - domain_interface_control() [rx lock held, domain lock held]
455 	//    remove_interface_from_domain()
456 	//     delete_interface()
457 	//      interface_set_down()
458 
459 	net_device *device = interface->device;
460 
461 	dprintf("down_device_interface(%s)\n", interface->name);
462 
463 	device->flags &= ~IFF_UP;
464 	interface->module->down(device);
465 
466 	notify_device_monitors(interface, B_DEVICE_GOING_DOWN);
467 
468 	thread_id reader_thread = interface->reader_thread;
469 
470 	// one of the callers must hold a reference to the net_device_interface
471 	// usually it is one of the net_interfaces.
472 	recursive_lock_unlock(&interface->rx_lock);
473 
474 	// make sure the reader thread is gone before shutting down the interface
475 	status_t status;
476 	wait_for_thread(reader_thread, &status);
477 
478 	recursive_lock_lock(&interface->rx_lock);
479 }
480 
481 
482 //	#pragma mark - devices
483 
484 
485 /*!
486 	Unregisters a previously registered deframer function.
487 	This function is part of the net_manager_module_info API.
488 */
489 status_t
490 unregister_device_deframer(net_device *device)
491 {
492 	BenaphoreLocker locker(sInterfaceLock);
493 
494 	// find device interface for this device
495 	net_device_interface *interface = find_device_interface(device->name);
496 	if (interface == NULL)
497 		return ENODEV;
498 
499 	RecursiveLocker _(interface->rx_lock);
500 
501 	if (--interface->deframe_ref_count == 0)
502 		interface->deframe_func = NULL;
503 
504 	return B_OK;
505 }
506 
507 
508 /*!
509 	Registers the deframer function for the specified \a device.
510 	Note, however, that right now, you can only register one single
511 	deframer function per device.
512 
513 	If the need arises, we might want to lift that limitation at a
514 	later time (which would require a slight API change, though).
515 
516 	This function is part of the net_manager_module_info API.
517 */
518 status_t
519 register_device_deframer(net_device *device, net_deframe_func deframeFunc)
520 {
521 	BenaphoreLocker locker(sInterfaceLock);
522 
523 	// find device interface for this device
524 	net_device_interface *interface = find_device_interface(device->name);
525 	if (interface == NULL)
526 		return ENODEV;
527 
528 	RecursiveLocker _(interface->rx_lock);
529 
530 	if (interface->deframe_func != NULL && interface->deframe_func != deframeFunc)
531 		return B_ERROR;
532 
533 	interface->deframe_func = deframeFunc;
534 	interface->deframe_ref_count++;
535 	return B_OK;
536 }
537 
538 
539 status_t
540 register_domain_device_handler(struct net_device *device, int32 type,
541 	struct net_domain *_domain)
542 {
543 	net_domain_private *domain = (net_domain_private *)_domain;
544 	if (domain->module == NULL || domain->module->receive_data == NULL)
545 		return B_BAD_VALUE;
546 
547 	return register_device_handler(device, type, &domain_receive_adapter, domain);
548 }
549 
550 
551 status_t
552 register_device_handler(struct net_device *device, int32 type,
553 	net_receive_func receiveFunc, void *cookie)
554 {
555 	BenaphoreLocker locker(sInterfaceLock);
556 
557 	// find device interface for this device
558 	net_device_interface *interface = find_device_interface(device->name);
559 	if (interface == NULL)
560 		return ENODEV;
561 
562 	RecursiveLocker _(interface->rx_lock);
563 
564 	// see if such a handler already for this device
565 
566 	DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
567 	while (iterator.HasNext()) {
568 		net_device_handler *handler = iterator.Next();
569 
570 		if (handler->type == type)
571 			return B_ERROR;
572 	}
573 
574 	// Add new handler
575 
576 	net_device_handler *handler = new (std::nothrow) net_device_handler;
577 	if (handler == NULL)
578 		return B_NO_MEMORY;
579 
580 	handler->func = receiveFunc;
581 	handler->type = type;
582 	handler->cookie = cookie;
583 	interface->receive_funcs.Add(handler);
584 	return B_OK;
585 }
586 
587 
588 status_t
589 unregister_device_handler(struct net_device *device, int32 type)
590 {
591 	BenaphoreLocker locker(sInterfaceLock);
592 
593 	// find device interface for this device
594 	net_device_interface *interface = find_device_interface(device->name);
595 	if (interface == NULL)
596 		return ENODEV;
597 
598 	RecursiveLocker _(interface->rx_lock);
599 
600 	// search for the handler
601 
602 	DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
603 	while (iterator.HasNext()) {
604 		net_device_handler *handler = iterator.Next();
605 
606 		if (handler->type == type) {
607 			// found it
608 			iterator.Remove();
609 			delete handler;
610 			return B_OK;
611 		}
612 	}
613 
614 	return B_BAD_VALUE;
615 }
616 
617 
618 status_t
619 register_device_monitor(net_device *device, net_device_monitor *monitor)
620 {
621 	if (monitor->receive == NULL || monitor->event == NULL)
622 		return B_BAD_VALUE;
623 
624 	BenaphoreLocker locker(sInterfaceLock);
625 
626 	// find device interface for this device
627 	net_device_interface *interface = find_device_interface(device->name);
628 	if (interface == NULL)
629 		return ENODEV;
630 
631 	RecursiveLocker _(interface->rx_lock);
632 	interface->monitor_funcs.Add(monitor);
633 	return B_OK;
634 }
635 
636 
637 status_t
638 unregister_device_monitor(net_device *device, net_device_monitor *monitor)
639 {
640 	BenaphoreLocker locker(sInterfaceLock);
641 
642 	// find device interface for this device
643 	net_device_interface *interface = find_device_interface(device->name);
644 	if (interface == NULL)
645 		return ENODEV;
646 
647 	RecursiveLocker _(interface->rx_lock);
648 
649 	// search for the monitor
650 
651 	DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
652 	while (iterator.HasNext()) {
653 		if (iterator.Next() == monitor) {
654 			iterator.Remove();
655 			return B_OK;
656 		}
657 	}
658 
659 	return B_BAD_VALUE;
660 }
661 
662 
663 /*!
664 	This function is called by device modules in case their link
665 	state changed, ie. if an ethernet cable was plugged in or
666 	removed.
667 */
668 status_t
669 device_link_changed(net_device *device)
670 {
671 	return B_OK;
672 }
673 
674 
675 /*!
676 	This function is called by device modules once their device got
677 	physically removed, ie. a USB networking card is unplugged.
678 	It is part of the net_manager_module_info API.
679 */
680 status_t
681 device_removed(net_device *device)
682 {
683 	BenaphoreLocker locker(sInterfaceLock);
684 
685 	// hold a reference to the device interface being removed
686 	// so our put_() will (eventually) do the final cleanup
687 	net_device_interface *interface = get_device_interface(device->name, false);
688 	if (interface == NULL)
689 		return ENODEV;
690 
691 	// Propagate the loss of the device throughout the stack.
692 	// This is very complex, refer to delete_interface() for
693 	// further details.
694 
695 	RecursiveLocker _(interface->rx_lock);
696 
697 	// this will possibly call:
698 	//  remove_interface_from_domain() [domain gets locked]
699 	//   delete_interface()
700 	//    ... [see delete_interface()]
701 	domain_removed_device_interface(interface);
702 
703 	notify_device_monitors(interface, B_DEVICE_BEING_REMOVED);
704 
705 	// By now all of the monitors must have removed themselves. If they
706 	// didn't, they'll probably wait forever to be callback'ed again.
707 	interface->monitor_funcs.RemoveAll();
708 
709 	// All of the readers should be gone as well since we are out of
710 	// interfaces and `put_domain_datalink_protocols' is called for
711 	// each delete_interface().
712 
713 	put_device_interface(interface);
714 
715 	return B_OK;
716 }
717 
718 
719 //	#pragma mark -
720 
721 
722 status_t
723 init_interfaces()
724 {
725 	if (benaphore_init(&sInterfaceLock, "net interfaces") < B_OK)
726 		return B_ERROR;
727 
728 	new (&sInterfaces) DeviceInterfaceList;
729 		// static C++ objects are not initialized in the module startup
730 	return B_OK;
731 }
732 
733 
734 status_t
735 uninit_interfaces()
736 {
737 	benaphore_destroy(&sInterfaceLock);
738 	return B_OK;
739 }
740 
741