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