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