xref: /haiku/src/kits/network/libnetapi/NetworkRoster.cpp (revision 22e92014f0dd38c0b621a94af3453a9e15b95609)
1 /*
2  * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <NetworkRoster.h>
8 
9 #include <errno.h>
10 #include <sys/sockio.h>
11 
12 #include <NetworkDevice.h>
13 #include <NetworkInterface.h>
14 
15 #include <net_notifications.h>
16 #include <AutoDeleter.h>
17 #include <NetServer.h>
18 #include <RouteSupport.h>
19 
20 
21 // TODO: using AF_INET for the socket isn't really a smart idea, as one
22 // could completely remove IPv4 support from the stack easily.
23 // Since in the stack, device_interfaces are pretty much interfaces now, we
24 // could get rid of them more or less, and make AF_LINK provide the same
25 // information as AF_INET for the interface functions mostly.
26 
27 
28 BNetworkRoster BNetworkRoster::sDefault;
29 
30 
31 /*static*/ BNetworkRoster&
32 BNetworkRoster::Default()
33 {
34 	return sDefault;
35 }
36 
37 
38 size_t
39 BNetworkRoster::CountInterfaces() const
40 {
41 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
42 	if (socket < 0)
43 		return 0;
44 
45 	FileDescriptorCloser closer(socket);
46 
47 	ifconf config;
48 	config.ifc_len = sizeof(config.ifc_value);
49 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) != 0)
50 		return 0;
51 
52 	return (size_t)config.ifc_value;
53 }
54 
55 
56 status_t
57 BNetworkRoster::GetNextInterface(uint32* cookie,
58 	BNetworkInterface& interface) const
59 {
60 	// TODO: think about caching the interfaces!
61 
62 	if (cookie == NULL)
63 		return B_BAD_VALUE;
64 
65 	// get a list of all interfaces
66 
67 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
68 	if (socket < 0)
69 		return errno;
70 
71 	FileDescriptorCloser closer(socket);
72 
73 	ifconf config;
74 	config.ifc_len = sizeof(config.ifc_value);
75 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
76 		return errno;
77 
78 	size_t count = (size_t)config.ifc_value;
79 	if (count == 0)
80 		return B_BAD_VALUE;
81 
82 	char* buffer = (char*)malloc(count * sizeof(struct ifreq));
83 	if (buffer == NULL)
84 		return B_NO_MEMORY;
85 
86 	MemoryDeleter deleter(buffer);
87 
88 	config.ifc_len = count * sizeof(struct ifreq);
89 	config.ifc_buf = buffer;
90 	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
91 		return errno;
92 
93 	ifreq* interfaces = (ifreq*)buffer;
94 	ifreq* end = (ifreq*)(buffer + config.ifc_len);
95 
96 	for (uint32 i = 0; interfaces < end; i++) {
97 		interface.SetTo(interfaces[0].ifr_name);
98 		if (i == *cookie) {
99 			(*cookie)++;
100 			return B_OK;
101 		}
102 
103 		interfaces = (ifreq*)((uint8*)interfaces
104 			+ _SIZEOF_ADDR_IFREQ(interfaces[0]));
105 	}
106 
107 	return B_BAD_VALUE;
108 }
109 
110 
111 status_t
112 BNetworkRoster::AddInterface(const char* name)
113 {
114 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
115 	if (socket < 0)
116 		return errno;
117 
118 	FileDescriptorCloser closer(socket);
119 
120 	ifaliasreq request;
121 	memset(&request, 0, sizeof(ifaliasreq));
122 	strlcpy(request.ifra_name, name, IF_NAMESIZE);
123 
124 	if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) != 0)
125 		return errno;
126 
127 	return B_OK;
128 }
129 
130 
131 status_t
132 BNetworkRoster::AddInterface(const BNetworkInterface& interface)
133 {
134 	return AddInterface(interface.Name());
135 }
136 
137 
138 status_t
139 BNetworkRoster::RemoveInterface(const char* name)
140 {
141 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
142 	if (socket < 0)
143 		return errno;
144 
145 	FileDescriptorCloser closer(socket);
146 
147 	ifreq request;
148 	strlcpy(request.ifr_name, name, IF_NAMESIZE);
149 
150 	request.ifr_addr.sa_family = AF_UNSPEC;
151 
152 	if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) != 0)
153 		return errno;
154 
155 	return B_OK;
156 }
157 
158 
159 status_t
160 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface)
161 {
162 	return RemoveInterface(interface.Name());
163 }
164 
165 
166 status_t
167 BNetworkRoster::GetRoutes(int family, BObjectList<route_entry>& routes) const
168 {
169 	return BPrivate::get_routes(NULL, family, routes);
170 }
171 
172 
173 int32
174 BNetworkRoster::CountPersistentNetworks() const
175 {
176 	BMessenger networkServer(kNetServerSignature);
177 	BMessage message(kMsgCountPersistentNetworks);
178 	BMessage reply;
179 	if (networkServer.SendMessage(&message, &reply) != B_OK)
180 		return 0;
181 
182 	int32 count = 0;
183 	if (reply.FindInt32("count", &count) != B_OK)
184 		return 0;
185 
186 	return count;
187 }
188 
189 
190 status_t
191 BNetworkRoster::GetNextPersistentNetwork(uint32* cookie,
192 	wireless_network& network) const
193 {
194 	BMessenger networkServer(kNetServerSignature);
195 	BMessage message(kMsgGetPersistentNetwork);
196 	message.AddInt32("index", (int32)*cookie);
197 
198 	BMessage reply;
199 	status_t result = networkServer.SendMessage(&message, &reply);
200 	if (result != B_OK)
201 		return result;
202 
203 	status_t status;
204 	if (reply.FindInt32("status", &status) != B_OK)
205 		return B_ERROR;
206 	if (status != B_OK)
207 		return status;
208 
209 	BMessage networkMessage;
210 	if (reply.FindMessage("network", &networkMessage) != B_OK)
211 		return B_ERROR;
212 
213 	BString networkName;
214 	if (networkMessage.FindString("name", &networkName) != B_OK)
215 		return B_ERROR;
216 
217 	memset(network.name, 0, sizeof(network.name));
218 	strncpy(network.name, networkName.String(), sizeof(network.name));
219 
220 	BNetworkAddress address;
221 	if (networkMessage.FindFlat("address", &network.address) != B_OK)
222 		network.address.Unset();
223 
224 	if (networkMessage.FindUInt32("flags", &network.flags) != B_OK)
225 		network.flags = 0;
226 
227 	if (networkMessage.FindUInt32("authentication_mode",
228 			&network.authentication_mode) != B_OK) {
229 		network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE;
230 	}
231 
232 	if (networkMessage.FindUInt32("cipher", &network.cipher) != B_OK)
233 		network.cipher = B_NETWORK_CIPHER_NONE;
234 
235 	if (networkMessage.FindUInt32("group_cipher", &network.group_cipher)
236 			!= B_OK) {
237 		network.group_cipher = B_NETWORK_CIPHER_NONE;
238 	}
239 
240 	if (networkMessage.FindUInt32("key_mode", &network.key_mode) != B_OK)
241 		network.key_mode = B_KEY_MODE_NONE;
242 
243 	return B_OK;
244 }
245 
246 
247 status_t
248 BNetworkRoster::AddPersistentNetwork(const wireless_network& network)
249 {
250 	BMessage message(kMsgAddPersistentNetwork);
251 	BString networkName;
252 	networkName.SetTo(network.name, sizeof(network.name));
253 	status_t status = message.AddString("name", networkName);
254 	if (status == B_OK) {
255 		BNetworkAddress address = network.address;
256 		status = message.AddFlat("address", &address);
257 	}
258 
259 	if (status == B_OK)
260 		status = message.AddUInt32("flags", network.flags);
261 	if (status == B_OK) {
262 		status = message.AddUInt32("authentication_mode",
263 			network.authentication_mode);
264 	}
265 	if (status == B_OK)
266 		status = message.AddUInt32("cipher", network.cipher);
267 	if (status == B_OK)
268 		status = message.AddUInt32("group_cipher", network.group_cipher);
269 	if (status == B_OK)
270 		status = message.AddUInt32("key_mode", network.key_mode);
271 
272 	if (status != B_OK)
273 		return status;
274 
275 	BMessenger networkServer(kNetServerSignature);
276 	BMessage reply;
277 	status = networkServer.SendMessage(&message, &reply);
278 	if (status == B_OK)
279 		reply.FindInt32("status", &status);
280 
281 	return status;
282 }
283 
284 
285 status_t
286 BNetworkRoster::RemovePersistentNetwork(const char* name)
287 {
288 	BMessage message(kMsgRemovePersistentNetwork);
289 	status_t status = message.AddString("name", name);
290 	if (status != B_OK)
291 		return status;
292 
293 	BMessenger networkServer(kNetServerSignature);
294 	BMessage reply;
295 	status = networkServer.SendMessage(&message, &reply);
296 	if (status == B_OK)
297 		reply.FindInt32("status", &status);
298 
299 	return status;
300 }
301 
302 
303 status_t
304 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask)
305 {
306 	return start_watching_network(eventMask, target);
307 }
308 
309 
310 void
311 BNetworkRoster::StopWatching(const BMessenger& target)
312 {
313 	stop_watching_network(target);
314 }
315 
316 
317 // #pragma mark - private
318 
319 
320 BNetworkRoster::BNetworkRoster()
321 {
322 }
323 
324 
325 BNetworkRoster::~BNetworkRoster()
326 {
327 }
328