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