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
27BNetworkRoster BNetworkRoster::sDefault;
28
29
30/*static*/ BNetworkRoster&
31BNetworkRoster::Default()
32{
33	return sDefault;
34}
35
36
37size_t
38BNetworkRoster::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
55status_t
56BNetworkRoster::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
110status_t
111BNetworkRoster::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
128status_t
129BNetworkRoster::AddInterface(const BNetworkInterface& interface)
130{
131	return AddInterface(interface.Name());
132}
133
134
135status_t
136BNetworkRoster::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
154status_t
155BNetworkRoster::RemoveInterface(const BNetworkInterface& interface)
156{
157	return RemoveInterface(interface.Name());
158}
159
160
161int32
162BNetworkRoster::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
178status_t
179BNetworkRoster::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
235status_t
236BNetworkRoster::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
273status_t
274BNetworkRoster::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
291status_t
292BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask)
293{
294	return start_watching_network(eventMask, target);
295}
296
297
298void
299BNetworkRoster::StopWatching(const BMessenger& target)
300{
301	stop_watching_network(target);
302}
303
304
305// #pragma mark - private
306
307
308BNetworkRoster::BNetworkRoster()
309{
310}
311
312
313BNetworkRoster::~BNetworkRoster()
314{
315}
316