xref: /haiku/src/add-ons/kernel/network/stack/domains.cpp (revision c22d69bf1f5f60f7ebddd79108a53c8f97f300fe)
1*c22d69bfSAxel Dörfler /*
2*c22d69bfSAxel Dörfler  * Copyright 2006, Haiku, Inc. All Rights Reserved.
3*c22d69bfSAxel Dörfler  * Distributed under the terms of the MIT License.
4*c22d69bfSAxel Dörfler  *
5*c22d69bfSAxel Dörfler  * Authors:
6*c22d69bfSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
7*c22d69bfSAxel Dörfler  */
8*c22d69bfSAxel Dörfler 
9*c22d69bfSAxel Dörfler 
10*c22d69bfSAxel Dörfler #include "domains.h"
11*c22d69bfSAxel Dörfler #include "interfaces.h"
12*c22d69bfSAxel Dörfler 
13*c22d69bfSAxel Dörfler #include <KernelExport.h>
14*c22d69bfSAxel Dörfler 
15*c22d69bfSAxel Dörfler #include <lock.h>
16*c22d69bfSAxel Dörfler #include <util/AutoLock.h>
17*c22d69bfSAxel Dörfler 
18*c22d69bfSAxel Dörfler #include <new>
19*c22d69bfSAxel Dörfler #include <string.h>
20*c22d69bfSAxel Dörfler 
21*c22d69bfSAxel Dörfler 
22*c22d69bfSAxel Dörfler #define TRACE_DOMAINS
23*c22d69bfSAxel Dörfler #ifdef TRACE_DOMAINS
24*c22d69bfSAxel Dörfler #	define TRACE(x) dprintf x
25*c22d69bfSAxel Dörfler #else
26*c22d69bfSAxel Dörfler #	define TRACE(x) ;
27*c22d69bfSAxel Dörfler #endif
28*c22d69bfSAxel Dörfler 
29*c22d69bfSAxel Dörfler 
30*c22d69bfSAxel Dörfler static benaphore sDomainLock;
31*c22d69bfSAxel Dörfler static list sDomains;
32*c22d69bfSAxel Dörfler 
33*c22d69bfSAxel Dörfler 
34*c22d69bfSAxel Dörfler /*!
35*c22d69bfSAxel Dörfler 	Scans the domain list for the specified family.
36*c22d69bfSAxel Dörfler 	You need to hold the sDomainLock when calling this function.
37*c22d69bfSAxel Dörfler */
38*c22d69bfSAxel Dörfler static net_domain_private *
39*c22d69bfSAxel Dörfler lookup_domain(int family)
40*c22d69bfSAxel Dörfler {
41*c22d69bfSAxel Dörfler 	net_domain_private *domain = NULL;
42*c22d69bfSAxel Dörfler 	while (true) {
43*c22d69bfSAxel Dörfler 		domain = (net_domain_private *)list_get_next_item(&sDomains, domain);
44*c22d69bfSAxel Dörfler 		if (domain == NULL)
45*c22d69bfSAxel Dörfler 			break;
46*c22d69bfSAxel Dörfler 
47*c22d69bfSAxel Dörfler 		if (domain->family == family)
48*c22d69bfSAxel Dörfler 			return domain;
49*c22d69bfSAxel Dörfler 	}
50*c22d69bfSAxel Dörfler 
51*c22d69bfSAxel Dörfler 	return NULL;
52*c22d69bfSAxel Dörfler }
53*c22d69bfSAxel Dörfler 
54*c22d69bfSAxel Dörfler 
55*c22d69bfSAxel Dörfler //	#pragma mark -
56*c22d69bfSAxel Dörfler 
57*c22d69bfSAxel Dörfler 
58*c22d69bfSAxel Dörfler /*!
59*c22d69bfSAxel Dörfler 	Gets the domain of the specified family.
60*c22d69bfSAxel Dörfler */
61*c22d69bfSAxel Dörfler net_domain *
62*c22d69bfSAxel Dörfler get_domain(int family)
63*c22d69bfSAxel Dörfler {
64*c22d69bfSAxel Dörfler 	BenaphoreLocker locker(sDomainLock);
65*c22d69bfSAxel Dörfler 	return lookup_domain(family);
66*c22d69bfSAxel Dörfler }
67*c22d69bfSAxel Dörfler 
68*c22d69bfSAxel Dörfler 
69*c22d69bfSAxel Dörfler uint32
70*c22d69bfSAxel Dörfler count_domain_interfaces()
71*c22d69bfSAxel Dörfler {
72*c22d69bfSAxel Dörfler 	BenaphoreLocker locker(sDomainLock);
73*c22d69bfSAxel Dörfler 
74*c22d69bfSAxel Dörfler 	net_domain_private *domain = NULL;
75*c22d69bfSAxel Dörfler 	uint32 count = 0;
76*c22d69bfSAxel Dörfler 
77*c22d69bfSAxel Dörfler 	while (true) {
78*c22d69bfSAxel Dörfler 		domain = (net_domain_private *)list_get_next_item(&sDomains, domain);
79*c22d69bfSAxel Dörfler 		if (domain == NULL)
80*c22d69bfSAxel Dörfler 			break;
81*c22d69bfSAxel Dörfler 
82*c22d69bfSAxel Dörfler 		net_interface *interface = NULL;
83*c22d69bfSAxel Dörfler 		while (true) {
84*c22d69bfSAxel Dörfler 			interface = (net_interface *)list_get_next_item(&domain->interfaces,
85*c22d69bfSAxel Dörfler 				interface);
86*c22d69bfSAxel Dörfler 			if (interface == NULL)
87*c22d69bfSAxel Dörfler 				break;
88*c22d69bfSAxel Dörfler 
89*c22d69bfSAxel Dörfler 			count++;
90*c22d69bfSAxel Dörfler 		}
91*c22d69bfSAxel Dörfler 	}
92*c22d69bfSAxel Dörfler 
93*c22d69bfSAxel Dörfler 	return count;
94*c22d69bfSAxel Dörfler }
95*c22d69bfSAxel Dörfler 
96*c22d69bfSAxel Dörfler 
97*c22d69bfSAxel Dörfler /*!
98*c22d69bfSAxel Dörfler 	Dumps a list of all interfaces into the supplied userland buffer.
99*c22d69bfSAxel Dörfler 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
100*c22d69bfSAxel Dörfler 	returned.
101*c22d69bfSAxel Dörfler */
102*c22d69bfSAxel Dörfler status_t
103*c22d69bfSAxel Dörfler list_domain_interfaces(void *buffer, size_t size)
104*c22d69bfSAxel Dörfler {
105*c22d69bfSAxel Dörfler 	BenaphoreLocker locker(sDomainLock);
106*c22d69bfSAxel Dörfler 
107*c22d69bfSAxel Dörfler 	net_domain_private *domain = NULL;
108*c22d69bfSAxel Dörfler 	size_t spaceLeft = size;
109*c22d69bfSAxel Dörfler 
110*c22d69bfSAxel Dörfler 	while (true) {
111*c22d69bfSAxel Dörfler 		domain = (net_domain_private *)list_get_next_item(&sDomains, domain);
112*c22d69bfSAxel Dörfler 		if (domain == NULL)
113*c22d69bfSAxel Dörfler 			break;
114*c22d69bfSAxel Dörfler 
115*c22d69bfSAxel Dörfler 		net_interface *interface = NULL;
116*c22d69bfSAxel Dörfler 		while (true) {
117*c22d69bfSAxel Dörfler 			interface = (net_interface *)list_get_next_item(&domain->interfaces,
118*c22d69bfSAxel Dörfler 				interface);
119*c22d69bfSAxel Dörfler 			if (interface == NULL)
120*c22d69bfSAxel Dörfler 				break;
121*c22d69bfSAxel Dörfler 
122*c22d69bfSAxel Dörfler 			size = IF_NAMESIZE + (interface->address ? interface->address->sa_len : 1);
123*c22d69bfSAxel Dörfler 			if (spaceLeft < size)
124*c22d69bfSAxel Dörfler 				return ENOBUFS;
125*c22d69bfSAxel Dörfler 
126*c22d69bfSAxel Dörfler 			ifreq request;
127*c22d69bfSAxel Dörfler 			strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
128*c22d69bfSAxel Dörfler 			if (interface->address != NULL)
129*c22d69bfSAxel Dörfler 				memcpy(&request.ifr_addr, interface->address, interface->address->sa_len);
130*c22d69bfSAxel Dörfler 			else {
131*c22d69bfSAxel Dörfler 				// empty address
132*c22d69bfSAxel Dörfler 				request.ifr_addr.sa_len = 2;
133*c22d69bfSAxel Dörfler 				request.ifr_addr.sa_family = AF_UNSPEC;
134*c22d69bfSAxel Dörfler 			}
135*c22d69bfSAxel Dörfler 
136*c22d69bfSAxel Dörfler 			if (user_memcpy(buffer, &request, size) < B_OK)
137*c22d69bfSAxel Dörfler 				return B_BAD_ADDRESS;
138*c22d69bfSAxel Dörfler 
139*c22d69bfSAxel Dörfler 			buffer = (void *)((addr_t)buffer + size);
140*c22d69bfSAxel Dörfler 			spaceLeft -= size;
141*c22d69bfSAxel Dörfler 		}
142*c22d69bfSAxel Dörfler 	}
143*c22d69bfSAxel Dörfler 
144*c22d69bfSAxel Dörfler 	return B_OK;
145*c22d69bfSAxel Dörfler }
146*c22d69bfSAxel Dörfler 
147*c22d69bfSAxel Dörfler 
148*c22d69bfSAxel Dörfler status_t
149*c22d69bfSAxel Dörfler add_interface_to_domain(net_domain *_domain,
150*c22d69bfSAxel Dörfler 	struct ifreq& request)
151*c22d69bfSAxel Dörfler {
152*c22d69bfSAxel Dörfler 	net_domain_private *domain = (net_domain_private *)_domain;
153*c22d69bfSAxel Dörfler 
154*c22d69bfSAxel Dörfler 	const char *deviceName = request.ifr_parameter.device[0]
155*c22d69bfSAxel Dörfler 		? request.ifr_parameter.device : request.ifr_name;
156*c22d69bfSAxel Dörfler 	net_device_interface *deviceInterface = get_device_interface(deviceName);
157*c22d69bfSAxel Dörfler 	if (deviceInterface == NULL)
158*c22d69bfSAxel Dörfler 		return ENODEV;
159*c22d69bfSAxel Dörfler 
160*c22d69bfSAxel Dörfler 	BenaphoreLocker locker(domain->lock);
161*c22d69bfSAxel Dörfler 
162*c22d69bfSAxel Dörfler 	if (find_interface(domain, request.ifr_name) != NULL)
163*c22d69bfSAxel Dörfler 		return B_NAME_IN_USE;
164*c22d69bfSAxel Dörfler 
165*c22d69bfSAxel Dörfler 	net_interface_private *interface;
166*c22d69bfSAxel Dörfler 	status_t status = create_interface(domain,
167*c22d69bfSAxel Dörfler 		request.ifr_name, request.ifr_parameter.base_name[0]
168*c22d69bfSAxel Dörfler 			? request.ifr_parameter.base_name : request.ifr_name,
169*c22d69bfSAxel Dörfler 		deviceInterface, &interface);
170*c22d69bfSAxel Dörfler 	if (status < B_OK) {
171*c22d69bfSAxel Dörfler 		put_device_interface(deviceInterface);
172*c22d69bfSAxel Dörfler 		return status;
173*c22d69bfSAxel Dörfler 	}
174*c22d69bfSAxel Dörfler 
175*c22d69bfSAxel Dörfler 	list_add_item(&domain->interfaces, interface);
176*c22d69bfSAxel Dörfler 	return B_OK;
177*c22d69bfSAxel Dörfler }
178*c22d69bfSAxel Dörfler 
179*c22d69bfSAxel Dörfler 
180*c22d69bfSAxel Dörfler /*!
181*c22d69bfSAxel Dörfler 	Removes the interface from its domain, and deletes it.
182*c22d69bfSAxel Dörfler 	You need to hold the domain's lock when calling this function.
183*c22d69bfSAxel Dörfler */
184*c22d69bfSAxel Dörfler status_t
185*c22d69bfSAxel Dörfler remove_interface_from_domain(net_interface *interface)
186*c22d69bfSAxel Dörfler {
187*c22d69bfSAxel Dörfler 	net_domain_private *domain = (net_domain_private *)interface->domain;
188*c22d69bfSAxel Dörfler 
189*c22d69bfSAxel Dörfler 	list_remove_item(&domain->interfaces, interface);
190*c22d69bfSAxel Dörfler 	delete_interface((net_interface_private *)interface);
191*c22d69bfSAxel Dörfler 	return B_OK;
192*c22d69bfSAxel Dörfler }
193*c22d69bfSAxel Dörfler 
194*c22d69bfSAxel Dörfler 
195*c22d69bfSAxel Dörfler status_t
196*c22d69bfSAxel Dörfler register_domain(int family, const char *name,
197*c22d69bfSAxel Dörfler 	struct net_protocol_module_info *module,
198*c22d69bfSAxel Dörfler 	struct net_address_module_info *addressModule,
199*c22d69bfSAxel Dörfler 	net_domain **_domain)
200*c22d69bfSAxel Dörfler {
201*c22d69bfSAxel Dörfler 	TRACE(("register_domain(%d, %s)\n", family, name));
202*c22d69bfSAxel Dörfler 	BenaphoreLocker locker(sDomainLock);
203*c22d69bfSAxel Dörfler 
204*c22d69bfSAxel Dörfler 	struct net_domain_private *domain = lookup_domain(family);
205*c22d69bfSAxel Dörfler 	if (domain != NULL)
206*c22d69bfSAxel Dörfler 		return B_NAME_IN_USE;
207*c22d69bfSAxel Dörfler 
208*c22d69bfSAxel Dörfler 	domain = new (std::nothrow) net_domain_private;
209*c22d69bfSAxel Dörfler 	if (domain == NULL)
210*c22d69bfSAxel Dörfler 		return B_NO_MEMORY;
211*c22d69bfSAxel Dörfler 
212*c22d69bfSAxel Dörfler 	status_t status = benaphore_init(&domain->lock, name);
213*c22d69bfSAxel Dörfler 	if (status < B_OK) {
214*c22d69bfSAxel Dörfler 		delete domain;
215*c22d69bfSAxel Dörfler 		return status;
216*c22d69bfSAxel Dörfler 	}
217*c22d69bfSAxel Dörfler 
218*c22d69bfSAxel Dörfler 	domain->family = family;
219*c22d69bfSAxel Dörfler 	domain->name = name;
220*c22d69bfSAxel Dörfler 	domain->module = module;
221*c22d69bfSAxel Dörfler 	domain->address_module = addressModule;
222*c22d69bfSAxel Dörfler 
223*c22d69bfSAxel Dörfler 	list_init(&domain->interfaces);
224*c22d69bfSAxel Dörfler 
225*c22d69bfSAxel Dörfler 	list_add_item(&sDomains, domain);
226*c22d69bfSAxel Dörfler 
227*c22d69bfSAxel Dörfler 	*_domain = domain;
228*c22d69bfSAxel Dörfler 	return B_OK;
229*c22d69bfSAxel Dörfler }
230*c22d69bfSAxel Dörfler 
231*c22d69bfSAxel Dörfler 
232*c22d69bfSAxel Dörfler status_t
233*c22d69bfSAxel Dörfler unregister_domain(net_domain *_domain)
234*c22d69bfSAxel Dörfler {
235*c22d69bfSAxel Dörfler 	TRACE(("unregister_domain(%p, %d, %s)\n", _domain, _domain->family, _domain->name));
236*c22d69bfSAxel Dörfler 
237*c22d69bfSAxel Dörfler 	net_domain_private *domain = (net_domain_private *)_domain;
238*c22d69bfSAxel Dörfler 	BenaphoreLocker locker(sDomainLock);
239*c22d69bfSAxel Dörfler 
240*c22d69bfSAxel Dörfler 	list_remove_item(&sDomains, domain);
241*c22d69bfSAxel Dörfler 
242*c22d69bfSAxel Dörfler 	net_interface_private *interface = NULL;
243*c22d69bfSAxel Dörfler 	while (true) {
244*c22d69bfSAxel Dörfler 		interface = (net_interface_private *)list_remove_head_item(&domain->interfaces);
245*c22d69bfSAxel Dörfler 		if (interface == NULL)
246*c22d69bfSAxel Dörfler 			break;
247*c22d69bfSAxel Dörfler 
248*c22d69bfSAxel Dörfler 		delete_interface(interface);
249*c22d69bfSAxel Dörfler 	}
250*c22d69bfSAxel Dörfler 
251*c22d69bfSAxel Dörfler 	benaphore_destroy(&domain->lock);
252*c22d69bfSAxel Dörfler 	delete domain;
253*c22d69bfSAxel Dörfler 	return B_OK;
254*c22d69bfSAxel Dörfler }
255*c22d69bfSAxel Dörfler 
256*c22d69bfSAxel Dörfler 
257*c22d69bfSAxel Dörfler status_t
258*c22d69bfSAxel Dörfler init_domains()
259*c22d69bfSAxel Dörfler {
260*c22d69bfSAxel Dörfler 	if (benaphore_init(&sDomainLock, "net domains") < B_OK)
261*c22d69bfSAxel Dörfler 		return B_ERROR;
262*c22d69bfSAxel Dörfler 
263*c22d69bfSAxel Dörfler 	list_init_etc(&sDomains, offsetof(struct net_domain_private, link));
264*c22d69bfSAxel Dörfler 	return B_OK;
265*c22d69bfSAxel Dörfler }
266*c22d69bfSAxel Dörfler 
267*c22d69bfSAxel Dörfler 
268*c22d69bfSAxel Dörfler status_t
269*c22d69bfSAxel Dörfler uninit_domains()
270*c22d69bfSAxel Dörfler {
271*c22d69bfSAxel Dörfler 	benaphore_destroy(&sDomainLock);
272*c22d69bfSAxel Dörfler 	return B_OK;
273*c22d69bfSAxel Dörfler }
274*c22d69bfSAxel Dörfler 
275