xref: /haiku/src/kits/network/libnetapi/NetworkRoster.cpp (revision 0044a8c39ab5721051b6279506d1a8c511e20453)
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 	ifaliasreq request;
118 	memset(&request, 0, sizeof(ifaliasreq));
119 	strlcpy(request.ifra_name, name, IF_NAMESIZE);
120 
121 	if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) != 0)
122 		return errno;
123 
124 	return B_OK;
125 }
126 
127 
128 status_t
129 BNetworkRoster::AddInterface(const BNetworkInterface& interface)
130 {
131 	return AddInterface(interface.Name());
132 }
133 
134 
135 status_t
136 BNetworkRoster::RemoveInterface(const char* name)
137 {
138 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
139 	if (socket < 0)
140 		return errno;
141 
142 	ifreq request;
143 	strlcpy(request.ifr_name, name, IF_NAMESIZE);
144 
145 	request.ifr_addr.sa_family = AF_UNSPEC;
146 
147 	if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) != 0)
148 		return errno;
149 
150 	return B_OK;
151 }
152 
153 
154 status_t
155 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface)
156 {
157 	return RemoveInterface(interface.Name());
158 }
159 
160 
161 int32
162 BNetworkRoster::CountPersistentNetworks() const
163 {
164 	BMessenger networkServer(kNetServerSignature);
165 	BMessage message(kMsgCountPersistentNetworks);
166 	BMessage reply;
167 	if (networkServer.SendMessage(&message, &reply) != B_OK)
168 		return 0;
169 
170 	int32 count = 0;
171 	if (reply.FindInt32("count", &count) != B_OK)
172 		return 0;
173 
174 	return count;
175 }
176 
177 
178 status_t
179 BNetworkRoster::GetNextPersistentNetwork(uint32* cookie,
180 	wireless_network& network) const
181 {
182 	BMessenger networkServer(kNetServerSignature);
183 	BMessage message(kMsgGetPersistentNetwork);
184 	message.AddInt32("index", (int32)*cookie);
185 
186 	BMessage reply;
187 	status_t result = networkServer.SendMessage(&message, &reply);
188 	if (result != B_OK)
189 		return result;
190 
191 	status_t status;
192 	if (reply.FindInt32("status", &status) != B_OK)
193 		return B_ERROR;
194 	if (status != B_OK)
195 		return status;
196 
197 	BMessage networkMessage;
198 	if (reply.FindMessage("network", &networkMessage) != B_OK)
199 		return B_ERROR;
200 
201 	BString networkName;
202 	if (networkMessage.FindString("name", &networkName) != B_OK)
203 		return B_ERROR;
204 
205 	memset(network.name, 0, sizeof(network.name));
206 	strncpy(network.name, networkName.String(), sizeof(network.name));
207 
208 	BNetworkAddress address;
209 	if (networkMessage.FindFlat("address", &network.address) != B_OK)
210 		network.address.Unset();
211 
212 	if (networkMessage.FindUInt32("flags", &network.flags) != B_OK)
213 		network.flags = 0;
214 
215 	if (networkMessage.FindUInt32("authentication_mode",
216 			&network.authentication_mode) != B_OK) {
217 		network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE;
218 	}
219 
220 	if (networkMessage.FindUInt32("cipher", &network.cipher) != B_OK)
221 		network.cipher = B_NETWORK_CIPHER_NONE;
222 
223 	if (networkMessage.FindUInt32("group_cipher", &network.group_cipher)
224 			!= B_OK) {
225 		network.group_cipher = B_NETWORK_CIPHER_NONE;
226 	}
227 
228 	if (networkMessage.FindUInt32("key_mode", &network.key_mode) != B_OK)
229 		network.key_mode = B_KEY_MODE_NONE;
230 
231 	return B_OK;
232 }
233 
234 
235 status_t
236 BNetworkRoster::AddPersistentNetwork(const wireless_network& network)
237 {
238 	BMessage message(kMsgAddPersistentNetwork);
239 	BString networkName;
240 	networkName.SetTo(network.name, sizeof(network.name));
241 	status_t status = message.AddString("name", networkName);
242 	if (status == B_OK) {
243 		BNetworkAddress address = network.address;
244 		status = message.AddFlat("address", &address);
245 	}
246 
247 	if (status == B_OK)
248 		status = message.AddUInt32("flags", network.flags);
249 	if (status == B_OK) {
250 		status = message.AddUInt32("authentication_mode",
251 			network.authentication_mode);
252 	}
253 	if (status == B_OK)
254 		status = message.AddUInt32("cipher", network.cipher);
255 	if (status == B_OK)
256 		status = message.AddUInt32("group_cipher", network.group_cipher);
257 	if (status == B_OK)
258 		status = message.AddUInt32("key_mode", network.key_mode);
259 
260 	if (status != B_OK)
261 		return status;
262 
263 	BMessenger networkServer(kNetServerSignature);
264 	BMessage reply;
265 	status = networkServer.SendMessage(&message, &reply);
266 	if (status == B_OK)
267 		reply.FindInt32("status", &status);
268 
269 	return status;
270 }
271 
272 
273 status_t
274 BNetworkRoster::RemovePersistentNetwork(const char* name)
275 {
276 	BMessage message(kMsgRemovePersistentNetwork);
277 	status_t status = message.AddString("name", name);
278 	if (status != B_OK)
279 		return status;
280 
281 	BMessenger networkServer(kNetServerSignature);
282 	BMessage reply;
283 	status = networkServer.SendMessage(&message, &reply);
284 	if (status == B_OK)
285 		reply.FindInt32("status", &status);
286 
287 	return status;
288 }
289 
290 
291 status_t
292 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask)
293 {
294 	return start_watching_network(eventMask, target);
295 }
296 
297 
298 void
299 BNetworkRoster::StopWatching(const BMessenger& target)
300 {
301 	stop_watching_network(target);
302 }
303 
304 
305 // #pragma mark - private
306 
307 
308 BNetworkRoster::BNetworkRoster()
309 {
310 }
311 
312 
313 BNetworkRoster::~BNetworkRoster()
314 {
315 }
316