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