xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision ba499cdc3336fb89429027418871bf263f1f5e14)
1 /*
2  * Copyright 2006, 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 
14 #include <net_device.h>
15 
16 #include <lock.h>
17 #include <util/AutoLock.h>
18 
19 #include <KernelExport.h>
20 
21 #include <net/if_dl.h>
22 #include <new>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 
27 #define TRACE_INTERFACES
28 #ifdef TRACE_INTERFACES
29 #	define TRACE(x) dprintf x
30 #else
31 #	define TRACE(x) ;
32 #endif
33 
34 
35 static benaphore sInterfaceLock;
36 static list sInterfaces;
37 static uint32 sInterfaceIndex;
38 static uint32 sDeviceIndex;
39 
40 
41 static net_device_interface *
42 find_device_interface(const char *name)
43 {
44 	net_device_interface *interface = NULL;
45 
46 	while (true) {
47 		interface = (net_device_interface *)list_get_next_item(&sInterfaces, interface);
48 		if (interface == NULL)
49 			break;
50 
51 		if (!strcmp(interface->name, name))
52 			return interface;
53 	}
54 
55 	return NULL;
56 }
57 
58 
59 static status_t
60 domain_receive_adapter(void *cookie, net_buffer *buffer)
61 {
62 	net_domain_private *domain = (net_domain_private *)cookie;
63 	return domain->module->receive_data(buffer);
64 }
65 
66 
67 //	#pragma mark - interfaces
68 
69 
70 /*!
71 	Searches for a specific interface in a domain by name.
72 	You need to have the domain's lock hold when calling this function.
73 */
74 struct net_interface_private *
75 find_interface(struct net_domain *domain, const char *name)
76 {
77 	net_interface_private *interface = NULL;
78 
79 	while (true) {
80 		interface = (net_interface_private *)list_get_next_item(
81 			&domain->interfaces, interface);
82 		if (interface == NULL)
83 			break;
84 
85 		if (!strcmp(interface->name, name))
86 			return interface;
87 	}
88 
89 	return NULL;
90 }
91 
92 
93 /*!
94 	Searches for a specific interface in a domain by index.
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, uint32 index)
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 (interface->index == index)
109 			return interface;
110 	}
111 
112 	return NULL;
113 }
114 
115 
116 status_t
117 create_interface(net_domain *domain, const char *name, const char *baseName,
118 	net_device_interface *deviceInterface, net_interface_private **_interface)
119 {
120 	net_interface_private *interface =
121 		new (std::nothrow) net_interface_private;
122 	if (interface == NULL)
123 		return B_NO_MEMORY;
124 
125 	strlcpy(interface->name, name, IF_NAMESIZE);
126 	strlcpy(interface->base_name, baseName, IF_NAMESIZE);
127 	interface->domain = domain;
128 	interface->device = deviceInterface->device;
129 
130 	interface->address = NULL;
131 	interface->destination = NULL;
132 	interface->mask = NULL;
133 
134 	interface->index = ++sInterfaceIndex;
135 	interface->flags = deviceInterface->device->flags & ~IFF_UP;
136 	interface->type = 0;
137 	interface->mtu = deviceInterface->device->mtu;
138 	interface->metric = 0;
139 	interface->device_interface = deviceInterface;
140 
141 	status_t status = get_domain_datalink_protocols(interface);
142 	if (status < B_OK) {
143 		delete interface;
144 		return status;
145 	}
146 
147 	// Grab a reference to the networking stack, to make sure it won't be
148 	// unloaded as long as an interface exists
149 	module_info *module;
150 	get_module(NET_STARTER_MODULE_NAME, &module);
151 
152 	*_interface = interface;
153 	return B_OK;
154 }
155 
156 
157 void
158 delete_interface(net_interface_private *interface)
159 {
160 	if ((interface->flags & IFF_UP) != 0) {
161 		// the interface is still up - we need to change that before deleting it
162 		interface->flags &= ~IFF_UP;
163 		interface->device_interface->module->down(interface->device_interface->device);
164 	}
165 
166 	put_device_interface(interface->device_interface);
167 
168 	free(interface->address);
169 	free(interface->destination);
170 	free(interface->mask);
171 
172 	delete interface;
173 
174 	// Release reference of the stack - at this point, our stack may be unloaded
175 	// if no other interfaces or sockets are left
176 	put_module(NET_STARTER_MODULE_NAME);
177 }
178 
179 
180 void
181 put_interface(struct net_interface_private *interface)
182 {
183 	// TODO: reference counting
184 	// TODO: better locking scheme
185 	benaphore_unlock(&((net_domain_private *)interface->domain)->lock);
186 }
187 
188 
189 struct net_interface_private *
190 get_interface(net_domain *_domain, const char *name)
191 {
192 	net_domain_private *domain = (net_domain_private *)_domain;
193 	benaphore_lock(&domain->lock);
194 
195 	net_interface_private *interface = NULL;
196 	while (true) {
197 		interface = (net_interface_private *)list_get_next_item(
198 			&domain->interfaces, interface);
199 		if (interface == NULL)
200 			break;
201 
202 		if (!strcmp(interface->name, name))
203 			return interface;
204 	}
205 
206 	benaphore_unlock(&domain->lock);
207 	return NULL;
208 }
209 
210 
211 //	#pragma mark - device interfaces
212 
213 
214 void
215 get_device_interface_address(net_device_interface *interface, sockaddr *_address)
216 {
217 	sockaddr_dl &address = *(sockaddr_dl *)_address;
218 
219 	address.sdl_family = AF_LINK;
220 	address.sdl_index = interface->device->index;
221 	address.sdl_type = interface->device->type;
222 	address.sdl_nlen = strlen(interface->name);
223 	address.sdl_slen = 0;
224 	memcpy(address.sdl_data, interface->name, address.sdl_nlen);
225 
226 	address.sdl_alen = interface->device->address.length;
227 	memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
228 
229 	address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
230 		+ address.sdl_nlen + address.sdl_alen;
231 }
232 
233 
234 uint32
235 count_device_interfaces()
236 {
237 	BenaphoreLocker locker(sInterfaceLock);
238 
239 	net_device_interface *interface = NULL;
240 	uint32 count = 0;
241 
242 	while (true) {
243 		interface = (net_device_interface *)list_get_next_item(&sInterfaces,
244 			interface);
245 		if (interface == NULL)
246 			break;
247 
248 		count++;
249 	}
250 
251 	return count;
252 }
253 
254 
255 /*!
256 	Dumps a list of all interfaces into the supplied userland buffer.
257 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
258 	returned.
259 */
260 status_t
261 list_device_interfaces(void *buffer, size_t size)
262 {
263 	BenaphoreLocker locker(sInterfaceLock);
264 
265 	net_device_interface *interface = NULL;
266 	size_t spaceLeft = size;
267 
268 	while (true) {
269 		interface = (net_device_interface *)list_get_next_item(&sInterfaces,
270 			interface);
271 		if (interface == NULL)
272 			break;
273 
274 		ifreq request;
275 		strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
276 		get_device_interface_address(interface, &request.ifr_addr);
277 
278 		size = IF_NAMESIZE + request.ifr_addr.sa_len;
279 		if (spaceLeft < size)
280 			return ENOBUFS;
281 
282 		if (user_memcpy(buffer, &request, size) < B_OK)
283 			return B_BAD_ADDRESS;
284 
285 		buffer = (void *)((addr_t)buffer + size);
286 		spaceLeft -= size;
287 	}
288 
289 	return B_OK;
290 }
291 
292 
293 /*!
294 	Releases the reference for the interface. When all references are
295 	released, the interface is removed.
296 */
297 void
298 put_device_interface(struct net_device_interface *interface)
299 {
300 	if (atomic_add(&interface->ref_count, -1) != 1)
301 		return;
302 
303 	// we need to remove this interface!
304 
305 	{
306 		BenaphoreLocker locker(sInterfaceLock);
307 		list_remove_item(&sInterfaces, interface);
308 	}
309 
310 	interface->module->uninit_device(interface->device);
311 	put_module(interface->module->info.name);
312 }
313 
314 
315 /*!
316 	Finds an interface by the specified index and grabs a reference to it.
317 */
318 struct net_device_interface *
319 get_device_interface(uint32 index)
320 {
321 	BenaphoreLocker locker(sInterfaceLock);
322 	net_device_interface *interface = NULL;
323 
324 	while (true) {
325 		interface = (net_device_interface *)list_get_next_item(&sInterfaces, interface);
326 		if (interface == NULL)
327 			break;
328 
329 		if (interface->device->index == index) {
330 			if (atomic_add(&interface->ref_count, 1) != 0)
331 				return interface;
332 		}
333 	}
334 
335 	return NULL;
336 }
337 
338 
339 /*!
340 	Finds an interface by the specified name and grabs a reference to it.
341 	If the interface does not yet exist, a new one is created.
342 */
343 struct net_device_interface *
344 get_device_interface(const char *name)
345 {
346 	BenaphoreLocker locker(sInterfaceLock);
347 
348 	net_device_interface *interface = find_device_interface(name);
349 	if (interface != NULL) {
350 		if (atomic_add(&interface->ref_count, 1) != 0)
351 			return interface;
352 
353 		// try to recreate interface - it just got removed
354 	}
355 
356 	void *cookie = open_module_list("network/devices");
357 	if (cookie == NULL)
358 		return NULL;
359 
360 	while (true) {
361 		char moduleName[B_FILE_NAME_LENGTH];
362 		size_t length = sizeof(moduleName);
363 		if (read_next_module_name(cookie, moduleName, &length) != B_OK)
364 			break;
365 
366 		TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name));
367 
368 		net_device_module_info *module;
369 		if (get_module(moduleName, (module_info **)&module) == B_OK) {
370 			net_device *device;
371 			status_t status = module->init_device(name, &device);
372 			if (status == B_OK) {
373 				// create new module interface for this
374 				interface = new (std::nothrow) net_device_interface;
375 				if (interface != NULL) {
376 					interface->name = device->name;
377 					interface->module = module;
378 					interface->device = device;
379 					interface->up_count = 0;
380 					interface->ref_count = 1;
381 					interface->deframe_func = NULL;
382 					interface->deframe_ref_count = 0;
383 
384 					device->index = ++sDeviceIndex;
385 					device->module = module;
386 
387 					list_add_item(&sInterfaces, interface);
388 					return interface;
389 				} else
390 					module->uninit_device(device);
391 			}
392 
393 			put_module(moduleName);
394 		}
395 	}
396 
397 	return NULL;
398 }
399 
400 
401 //	#pragma mark - devices
402 
403 
404 /*!
405 	Unregisters a previously registered deframer function.
406 	This function is part of the net_manager_module_info API.
407 */
408 status_t
409 unregister_device_deframer(net_device *device)
410 {
411 	BenaphoreLocker locker(sInterfaceLock);
412 
413 	// find device interface for this device
414 	net_device_interface *interface = find_device_interface(device->name);
415 	if (interface == NULL)
416 		return ENODEV;
417 
418 	if (--interface->deframe_ref_count == 0)
419 		interface->deframe_func = NULL;
420 
421 	return B_OK;
422 }
423 
424 
425 /*!
426 	Registers the deframer function for the specified \a device.
427 	Note, however, that right now, you can only register one single
428 	deframer function per device.
429 
430 	If the need arises, we might want to lift that limitation at a
431 	later time (which would require a slight API change, though).
432 
433 	This function is part of the net_manager_module_info API.
434 */
435 status_t
436 register_device_deframer(net_device *device, net_deframe_func deframeFunc)
437 {
438 	BenaphoreLocker locker(sInterfaceLock);
439 
440 	// find device interface for this device
441 	net_device_interface *interface = find_device_interface(device->name);
442 	if (interface == NULL)
443 		return ENODEV;
444 
445 	if (interface->deframe_func != NULL && interface->deframe_func != deframeFunc)
446 		return B_ERROR;
447 
448 	interface->deframe_func = deframeFunc;
449 	interface->deframe_ref_count++;
450 	return B_OK;
451 }
452 
453 
454 status_t
455 register_domain_device_handler(struct net_device *device, int32 type,
456 	struct net_domain *_domain)
457 {
458 	net_domain_private *domain = (net_domain_private *)_domain;
459 	if (domain->module == NULL || domain->module->receive_data == NULL)
460 		return B_BAD_VALUE;
461 
462 	return register_device_handler(device, type, &domain_receive_adapter, domain);
463 }
464 
465 
466 status_t
467 register_device_handler(struct net_device *device, int32 type,
468 	net_receive_func receiveFunc, void *cookie)
469 {
470 	BenaphoreLocker locker(sInterfaceLock);
471 
472 	// find device interface for this device
473 	net_device_interface *interface = find_device_interface(device->name);
474 	if (interface == NULL)
475 		return ENODEV;
476 
477 	// see if such a handler already for this device
478 
479 	DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
480 	while (iterator.HasNext()) {
481 		net_device_handler *handler = iterator.Next();
482 
483 		if (handler->type == type)
484 			return B_ERROR;
485 	}
486 
487 	// Add new handler
488 
489 	net_device_handler *handler = new (std::nothrow) net_device_handler;
490 	if (handler == NULL)
491 		return B_NO_MEMORY;
492 
493 	handler->func = receiveFunc;
494 	handler->type = type;
495 	handler->cookie = cookie;
496 	interface->receive_funcs.Add(handler);
497 	return B_OK;
498 }
499 
500 
501 status_t
502 unregister_device_handler(struct net_device *device, int32 type)
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 	// search for the handler
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 			// found it
519 			iterator.Remove();
520 			delete handler;
521 			return B_OK;
522 		}
523 	}
524 
525 	return B_BAD_VALUE;
526 }
527 
528 
529 status_t
530 register_device_monitor(struct net_device *device,
531 	net_receive_func receiveFunc, void *cookie)
532 {
533 	BenaphoreLocker locker(sInterfaceLock);
534 
535 	// find device interface for this device
536 	net_device_interface *interface = find_device_interface(device->name);
537 	if (interface == NULL)
538 		return ENODEV;
539 
540 	// Add new monitor
541 
542 	net_device_monitor *monitor = new (std::nothrow) net_device_monitor;
543 	if (monitor == NULL)
544 		return B_NO_MEMORY;
545 
546 	monitor->func = receiveFunc;
547 	monitor->cookie = cookie;
548 	interface->monitor_funcs.Add(monitor);
549 	return B_OK;
550 }
551 
552 
553 status_t
554 unregister_device_monitor(struct net_device *device,
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 	// search for the monitor
565 
566 	DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
567 	while (iterator.HasNext()) {
568 		net_device_monitor *monitor = iterator.Next();
569 
570 		if (monitor->cookie == cookie && monitor->func == receiveFunc) {
571 			// found it
572 			iterator.Remove();
573 			delete monitor;
574 			return B_OK;
575 		}
576 	}
577 
578 	return B_BAD_VALUE;
579 }
580 
581 
582 /*!
583 	This function is called by device modules once their device got
584 	physically removed, ie. a USB networking card is unplugged.
585 	It is part of the net_manager_module_info API.
586 */
587 status_t
588 device_removed(net_device *device)
589 {
590 	BenaphoreLocker locker(sInterfaceLock);
591 	// TODO: all what this function should do is to clear the IFF_UP flag of the interfaces.
592 	return B_OK;
593 }
594 
595 
596 //	#pragma mark -
597 
598 
599 status_t
600 init_interfaces()
601 {
602 	if (benaphore_init(&sInterfaceLock, "net interfaces") < B_OK)
603 		return B_ERROR;
604 
605 	list_init(&sInterfaces);
606 	return B_OK;
607 }
608 
609 
610 status_t
611 uninit_interfaces()
612 {
613 	benaphore_destroy(&sInterfaceLock);
614 	return B_OK;
615 }
616 
617