xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision 9ecf9d1c1d4888d341a6eac72112c72d1ae3a4cb)
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 	put_device_interface(interface->device_interface);
161 
162 	free(interface->address);
163 	free(interface->destination);
164 	free(interface->mask);
165 
166 	delete interface;
167 
168 	// Release reference of the stack - at this point, our stack may be unloaded
169 	// if no other interfaces or sockets are left
170 	put_module(NET_STARTER_MODULE_NAME);
171 }
172 
173 
174 void
175 put_interface(struct net_interface_private *interface)
176 {
177 	// TODO: reference counting
178 	// TODO: better locking scheme
179 	benaphore_unlock(&((net_domain_private *)interface->domain)->lock);
180 }
181 
182 
183 struct net_interface_private *
184 get_interface(net_domain *_domain, const char *name)
185 {
186 	net_domain_private *domain = (net_domain_private *)_domain;
187 	benaphore_lock(&domain->lock);
188 
189 	net_interface_private *interface = NULL;
190 	while (true) {
191 		interface = (net_interface_private *)list_get_next_item(
192 			&domain->interfaces, interface);
193 		if (interface == NULL)
194 			break;
195 
196 		if (!strcmp(interface->name, name))
197 			return interface;
198 	}
199 
200 	benaphore_unlock(&domain->lock);
201 	return NULL;
202 }
203 
204 
205 //	#pragma mark - device interfaces
206 
207 
208 void
209 get_device_interface_address(net_device_interface *interface, sockaddr *_address)
210 {
211 	sockaddr_dl &address = *(sockaddr_dl *)_address;
212 
213 	address.sdl_family = AF_LINK;
214 	address.sdl_index = interface->device->index;
215 	address.sdl_type = interface->device->type;
216 	address.sdl_nlen = strlen(interface->name);
217 	address.sdl_slen = 0;
218 	memcpy(address.sdl_data, interface->name, address.sdl_nlen);
219 
220 	address.sdl_alen = interface->device->address.length;
221 	memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
222 
223 	address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
224 		+ address.sdl_nlen + address.sdl_alen;
225 }
226 
227 
228 uint32
229 count_device_interfaces()
230 {
231 	BenaphoreLocker locker(sInterfaceLock);
232 
233 	net_device_interface *interface = NULL;
234 	uint32 count = 0;
235 
236 	while (true) {
237 		interface = (net_device_interface *)list_get_next_item(&sInterfaces,
238 			interface);
239 		if (interface == NULL)
240 			break;
241 
242 		count++;
243 	}
244 
245 	return count;
246 }
247 
248 
249 /*!
250 	Dumps a list of all interfaces into the supplied userland buffer.
251 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
252 	returned.
253 */
254 status_t
255 list_device_interfaces(void *buffer, size_t size)
256 {
257 	BenaphoreLocker locker(sInterfaceLock);
258 
259 	net_device_interface *interface = NULL;
260 	size_t spaceLeft = size;
261 
262 	while (true) {
263 		interface = (net_device_interface *)list_get_next_item(&sInterfaces,
264 			interface);
265 		if (interface == NULL)
266 			break;
267 
268 		ifreq request;
269 		strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
270 		get_device_interface_address(interface, &request.ifr_addr);
271 
272 		size = IF_NAMESIZE + request.ifr_addr.sa_len;
273 		if (spaceLeft < size)
274 			return ENOBUFS;
275 
276 		if (user_memcpy(buffer, &request, size) < B_OK)
277 			return B_BAD_ADDRESS;
278 
279 		buffer = (void *)((addr_t)buffer + size);
280 		spaceLeft -= size;
281 	}
282 
283 	return B_OK;
284 }
285 
286 
287 /*!
288 	Releases the reference for the interface. When all references are
289 	released, the interface is removed.
290 */
291 void
292 put_device_interface(struct net_device_interface *interface)
293 {
294 	if (atomic_add(&interface->ref_count, -1) != 1)
295 		return;
296 
297 	// we need to remove this interface!
298 
299 	{
300 		BenaphoreLocker locker(sInterfaceLock);
301 		list_remove_item(&sInterfaces, interface);
302 	}
303 
304 	interface->module->uninit_device(interface->device);
305 	put_module(interface->module->info.name);
306 }
307 
308 
309 /*!
310 	Finds an interface by the specified index and grabs a reference to it.
311 */
312 struct net_device_interface *
313 get_device_interface(uint32 index)
314 {
315 	BenaphoreLocker locker(sInterfaceLock);
316 	net_device_interface *interface = NULL;
317 
318 	while (true) {
319 		interface = (net_device_interface *)list_get_next_item(&sInterfaces, interface);
320 		if (interface == NULL)
321 			break;
322 
323 		if (interface->device->index == index) {
324 			if (atomic_add(&interface->ref_count, 1) != 0)
325 				return interface;
326 		}
327 	}
328 
329 	return NULL;
330 }
331 
332 
333 /*!
334 	Finds an interface by the specified name and grabs a reference to it.
335 	If the interface does not yet exist, a new one is created.
336 */
337 struct net_device_interface *
338 get_device_interface(const char *name)
339 {
340 	BenaphoreLocker locker(sInterfaceLock);
341 
342 	net_device_interface *interface = find_device_interface(name);
343 	if (interface != NULL) {
344 		if (atomic_add(&interface->ref_count, 1) != 0)
345 			return interface;
346 
347 		// try to recreate interface - it just got removed
348 	}
349 
350 	void *cookie = open_module_list("network/devices");
351 	if (cookie == NULL)
352 		return NULL;
353 
354 	while (true) {
355 		char moduleName[B_FILE_NAME_LENGTH];
356 		size_t length = sizeof(moduleName);
357 		if (read_next_module_name(cookie, moduleName, &length) != B_OK)
358 			break;
359 
360 		TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name));
361 
362 		net_device_module_info *module;
363 		if (get_module(moduleName, (module_info **)&module) == B_OK) {
364 			net_device *device;
365 			status_t status = module->init_device(name, &device);
366 			if (status == B_OK) {
367 				// create new module interface for this
368 				interface = new (std::nothrow) net_device_interface;
369 				if (interface != NULL) {
370 					interface->name = device->name;
371 					interface->module = module;
372 					interface->device = device;
373 					interface->up_count = 0;
374 					interface->ref_count = 1;
375 					interface->deframe_func = NULL;
376 					interface->deframe_ref_count = 0;
377 
378 					device->index = ++sDeviceIndex;
379 					device->module = module;
380 
381 					list_add_item(&sInterfaces, interface);
382 					return interface;
383 				} else
384 					module->uninit_device(device);
385 			}
386 
387 			put_module(moduleName);
388 		}
389 	}
390 
391 	return NULL;
392 }
393 
394 
395 //	#pragma mark - devices
396 
397 
398 /*!
399 	Unregisters a previously registered deframer function.
400 	This function is part of the net_manager_module_info API.
401 */
402 status_t
403 unregister_device_deframer(net_device *device)
404 {
405 	BenaphoreLocker locker(sInterfaceLock);
406 
407 	// find device interface for this device
408 	net_device_interface *interface = find_device_interface(device->name);
409 	if (interface == NULL)
410 		return ENODEV;
411 
412 	if (--interface->deframe_ref_count == 0)
413 		interface->deframe_func = NULL;
414 
415 	return B_OK;
416 }
417 
418 
419 /*!
420 	Registers the deframer function for the specified \a device.
421 	Note, however, that right now, you can only register one single
422 	deframer function per device.
423 
424 	If the need arises, we might want to lift that limitation at a
425 	later time (which would require a slight API change, though).
426 
427 	This function is part of the net_manager_module_info API.
428 */
429 status_t
430 register_device_deframer(net_device *device, net_deframe_func deframeFunc)
431 {
432 	BenaphoreLocker locker(sInterfaceLock);
433 
434 	// find device interface for this device
435 	net_device_interface *interface = find_device_interface(device->name);
436 	if (interface == NULL)
437 		return ENODEV;
438 
439 	if (interface->deframe_func != NULL && interface->deframe_func != deframeFunc)
440 		return B_ERROR;
441 
442 	interface->deframe_func = deframeFunc;
443 	interface->deframe_ref_count++;
444 	return B_OK;
445 }
446 
447 
448 status_t
449 register_domain_device_handler(struct net_device *device, int32 type,
450 	struct net_domain *_domain)
451 {
452 	net_domain_private *domain = (net_domain_private *)_domain;
453 	if (domain->module == NULL || domain->module->receive_data == NULL)
454 		return B_BAD_VALUE;
455 
456 	return register_device_handler(device, type, &domain_receive_adapter, domain);
457 }
458 
459 
460 status_t
461 register_device_handler(struct net_device *device, int32 type,
462 	net_receive_func receiveFunc, void *cookie)
463 {
464 	BenaphoreLocker locker(sInterfaceLock);
465 
466 	// find device interface for this device
467 	net_device_interface *interface = find_device_interface(device->name);
468 	if (interface == NULL)
469 		return ENODEV;
470 
471 	// see if such a handler already for this device
472 
473 	DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
474 	while (iterator.HasNext()) {
475 		net_device_handler *handler = iterator.Next();
476 
477 		if (handler->type == type)
478 			return B_ERROR;
479 	}
480 
481 	// Add new handler
482 
483 	net_device_handler *handler = new (std::nothrow) net_device_handler;
484 	if (handler == NULL)
485 		return B_NO_MEMORY;
486 
487 	handler->func = receiveFunc;
488 	handler->type = type;
489 	handler->cookie = cookie;
490 	interface->receive_funcs.Add(handler);
491 	return B_OK;
492 }
493 
494 
495 status_t
496 unregister_device_handler(struct net_device *device, int32 type)
497 {
498 	BenaphoreLocker locker(sInterfaceLock);
499 
500 	// find device interface for this device
501 	net_device_interface *interface = find_device_interface(device->name);
502 	if (interface == NULL)
503 		return ENODEV;
504 
505 	// search for the handler
506 
507 	DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
508 	while (iterator.HasNext()) {
509 		net_device_handler *handler = iterator.Next();
510 
511 		if (handler->type == type) {
512 			// found it
513 			iterator.Remove();
514 			delete handler;
515 			return B_OK;
516 		}
517 	}
518 
519 	return B_BAD_VALUE;
520 }
521 
522 
523 status_t
524 register_device_monitor(struct net_device *device,
525 	net_receive_func receiveFunc, void *cookie)
526 {
527 	BenaphoreLocker locker(sInterfaceLock);
528 
529 	// find device interface for this device
530 	net_device_interface *interface = find_device_interface(device->name);
531 	if (interface == NULL)
532 		return ENODEV;
533 
534 	// Add new monitor
535 
536 	net_device_monitor *monitor = new (std::nothrow) net_device_monitor;
537 	if (monitor == NULL)
538 		return B_NO_MEMORY;
539 
540 	monitor->func = receiveFunc;
541 	monitor->cookie = cookie;
542 	interface->monitor_funcs.Add(monitor);
543 	return B_OK;
544 }
545 
546 
547 status_t
548 unregister_device_monitor(struct net_device *device,
549 	net_receive_func receiveFunc, void *cookie)
550 {
551 	BenaphoreLocker locker(sInterfaceLock);
552 
553 	// find device interface for this device
554 	net_device_interface *interface = find_device_interface(device->name);
555 	if (interface == NULL)
556 		return ENODEV;
557 
558 	// search for the monitor
559 
560 	DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
561 	while (iterator.HasNext()) {
562 		net_device_monitor *monitor = iterator.Next();
563 
564 		if (monitor->cookie == cookie && monitor->func == receiveFunc) {
565 			// found it
566 			iterator.Remove();
567 			delete monitor;
568 			return B_OK;
569 		}
570 	}
571 
572 	return B_BAD_VALUE;
573 }
574 
575 
576 /*!
577 	This function is called by device modules once their device got
578 	physically removed, ie. a USB networking card is unplugged.
579 	It is part of the net_manager_module_info API.
580 */
581 status_t
582 device_removed(net_device *device)
583 {
584 	BenaphoreLocker locker(sInterfaceLock);
585 	// TODO: all what this function should do is to clear the IFF_UP flag of the interfaces.
586 	return B_OK;
587 }
588 
589 
590 //	#pragma mark -
591 
592 
593 status_t
594 init_interfaces()
595 {
596 	if (benaphore_init(&sInterfaceLock, "net interfaces") < B_OK)
597 		return B_ERROR;
598 
599 	list_init(&sInterfaces);
600 	return B_OK;
601 }
602 
603 
604 status_t
605 uninit_interfaces()
606 {
607 	benaphore_destroy(&sInterfaceLock);
608 	return B_OK;
609 }
610 
611