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