1/*
2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 * 		Vegard W��rp, vegarwa@online.no
8 *		Alexander von Gluck, kallisti5@unixzen.com
9 */
10
11
12#include "NetServer.h"
13
14#include <errno.h>
15#include <map>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string>
19#include <string.h>
20#include <syslog.h>
21#include <unistd.h>
22
23#include <arpa/inet.h>
24#include <net/if_dl.h>
25#include <net/if_types.h>
26#include <netinet/in.h>
27#include <sys/socket.h>
28#include <sys/sockio.h>
29
30#include <Alert.h>
31#include <Deskbar.h>
32#include <Directory.h>
33#include <Entry.h>
34#include <NetworkDevice.h>
35#include <NetworkInterface.h>
36#include <NetworkRoster.h>
37#include <Path.h>
38#include <PathMonitor.h>
39#include <Roster.h>
40#include <Server.h>
41#include <TextView.h>
42#include <FindDirectory.h>
43
44#include <AutoDeleter.h>
45#include <WPASupplicant.h>
46
47#include "AutoconfigLooper.h"
48#include "Services.h"
49#include "Settings.h"
50
51extern "C" {
52#	include <net80211/ieee80211_ioctl.h>
53}
54
55
56typedef std::map<std::string, AutoconfigLooper*> LooperMap;
57
58
59class NetServer : public BServer {
60public:
61								NetServer(status_t& status);
62	virtual						~NetServer();
63
64	virtual	void				AboutRequested();
65	virtual	void				ReadyToRun();
66	virtual	void				MessageReceived(BMessage* message);
67
68private:
69			bool				_IsValidFamily(uint32 family);
70			bool				_IsValidInterface(BNetworkInterface& interface);
71			void				_RemoveInvalidInterfaces();
72			status_t			_RemoveInterface(const char* name);
73			status_t			_DisableInterface(const char* name);
74			bool				_TestForInterface(const char* name);
75			status_t			_ConfigureInterface(BMessage& interface);
76			status_t			_ConfigureResolver(
77									BMessage& resolverConfiguration);
78			bool				_QuitLooperForDevice(const char* device);
79			AutoconfigLooper*	_LooperForDevice(const char* device);
80			status_t			_ConfigureDevice(const char* path);
81			void				_ConfigureDevices(const char* path,
82									BMessage* suggestedInterface = NULL);
83			void				_ConfigureInterfaces(
84									BMessage* _missingDevice = NULL);
85			void				_ConfigureIPv6LinkLocal(const char* name);
86
87			void				_BringUpInterfaces();
88			void				_StartServices();
89			status_t			_HandleDeviceMonitor(BMessage* message);
90
91			status_t			_AutoJoinNetwork(const char* name);
92			status_t			_JoinNetwork(const BMessage& message,
93									const char* name = NULL);
94			status_t			_LeaveNetwork(const BMessage& message);
95
96			status_t			_ConvertNetworkToSettings(BMessage& message);
97			status_t			_ConvertNetworkFromSettings(BMessage& message);
98
99private:
100			Settings			fSettings;
101			LooperMap			fDeviceMap;
102			BMessenger			fServices;
103};
104
105
106struct address_family {
107	int			family;
108	const char*	name;
109	const char*	identifiers[4];
110};
111
112
113static const address_family kFamilies[] = {
114	{
115		AF_INET,
116		"inet",
117		{"AF_INET", "inet", "ipv4", NULL},
118	},
119	{
120		AF_INET6,
121		"inet6",
122		{"AF_INET6", "inet6", "ipv6", NULL},
123	},
124	{ -1, NULL, {NULL} }
125};
126
127
128// #pragma mark - private functions
129
130
131static status_t
132set_80211(const char* name, int32 type, void* data,
133	int32 length = 0, int32 value = 0)
134{
135	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
136	if (socket < 0)
137		return errno;
138
139	FileDescriptorCloser closer(socket);
140
141	struct ieee80211req ireq;
142	strlcpy(ireq.i_name, name, IF_NAMESIZE);
143	ireq.i_type = type;
144	ireq.i_val = value;
145	ireq.i_len = length;
146	ireq.i_data = data;
147
148	if (ioctl(socket, SIOCS80211, &ireq, sizeof(struct ieee80211req)) < 0)
149		return errno;
150
151	return B_OK;
152}
153
154
155// #pragma mark - exported functions
156
157
158int
159get_address_family(const char* argument)
160{
161	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
162		for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
163			if (!strcmp(argument, kFamilies[i].identifiers[j])) {
164				// found a match
165				return kFamilies[i].family;
166			}
167		}
168	}
169
170	return AF_UNSPEC;
171}
172
173
174/*!	Parses the \a argument as network \a address for the specified \a family.
175	If \a family is \c AF_UNSPEC, \a family will be overwritten with the family
176	of the successfully parsed address.
177*/
178bool
179parse_address(int32& family, const char* argument, BNetworkAddress& address)
180{
181	if (argument == NULL)
182		return false;
183
184	status_t status = address.SetTo(family, argument, (uint16)0,
185		B_NO_ADDRESS_RESOLUTION);
186	if (status != B_OK)
187		return false;
188
189	if (family == AF_UNSPEC) {
190		// Test if we support the resulting address family
191		bool supported = false;
192
193		for (int32 i = 0; kFamilies[i].family >= 0; i++) {
194			if (kFamilies[i].family == address.Family()) {
195				supported = true;
196				break;
197			}
198		}
199		if (!supported)
200			return false;
201
202		// Take over family from address
203		family = address.Family();
204	}
205
206	return true;
207}
208
209
210//	#pragma mark -
211
212
213NetServer::NetServer(status_t& error)
214	:
215	BServer(kNetServerSignature, false, &error)
216{
217}
218
219
220NetServer::~NetServer()
221{
222	BPrivate::BPathMonitor::StopWatching("/dev/net", this);
223}
224
225
226void
227NetServer::AboutRequested()
228{
229	BAlert *alert = new BAlert("about", "Networking Server\n"
230		"\tCopyright " B_UTF8_COPYRIGHT "2006, Haiku.\n", "OK");
231	BTextView *view = alert->TextView();
232	BFont font;
233
234	view->SetStylable(true);
235
236	view->GetFont(&font);
237	font.SetSize(18);
238	font.SetFace(B_BOLD_FACE);
239	view->SetFontAndColor(0, 17, &font);
240
241	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
242	alert->Go(NULL);
243}
244
245
246void
247NetServer::ReadyToRun()
248{
249	fSettings.StartMonitoring(this);
250	_BringUpInterfaces();
251	_StartServices();
252
253	BPrivate::BPathMonitor::StartWatching("/dev/net", B_ENTRY_CREATED
254		| B_ENTRY_REMOVED | B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this);
255}
256
257
258void
259NetServer::MessageReceived(BMessage* message)
260{
261	switch (message->what) {
262		case B_PATH_MONITOR:
263		{
264			fSettings.Update(message);
265			_HandleDeviceMonitor(message);
266			break;
267		}
268
269		case kMsgInterfaceSettingsUpdated:
270		{
271			_ConfigureInterfaces();
272			break;
273		}
274
275		case kMsgServiceSettingsUpdated:
276		{
277			BMessage update = fSettings.Services();
278			update.what = kMsgUpdateServices;
279
280			fServices.SendMessage(&update);
281			break;
282		}
283
284		case kMsgConfigureInterface:
285		{
286			status_t status = _ConfigureInterface(*message);
287
288			BMessage reply(B_REPLY);
289			reply.AddInt32("status", status);
290			message->SendReply(&reply);
291			break;
292		}
293
294		case kMsgConfigureResolver:
295		{
296			status_t status = _ConfigureResolver(*message);
297
298			BMessage reply(B_REPLY);
299			reply.AddInt32("status", status);
300			message->SendReply(&reply);
301			break;
302		}
303
304		case kMsgJoinNetwork:
305		{
306			status_t status = _JoinNetwork(*message);
307
308			BMessage reply(B_REPLY);
309			reply.AddInt32("status", status);
310			message->SendReply(&reply);
311			break;
312		}
313
314		case kMsgLeaveNetwork:
315		{
316			status_t status = _LeaveNetwork(*message);
317
318			BMessage reply(B_REPLY);
319			reply.AddInt32("status", status);
320			message->SendReply(&reply);
321			break;
322		}
323
324		case kMsgCountPersistentNetworks:
325		{
326			BMessage reply(B_REPLY);
327			reply.AddInt32("count", fSettings.CountNetworks());
328			message->SendReply(&reply);
329			break;
330		}
331
332		case kMsgGetPersistentNetwork:
333		{
334			uint32 index = 0;
335			status_t result = message->FindInt32("index", (int32*)&index);
336
337			BMessage reply(B_REPLY);
338			if (result == B_OK) {
339				BMessage network;
340				result = fSettings.GetNextNetwork(index, network);
341				if (result == B_OK)
342					result = _ConvertNetworkFromSettings(network);
343				if (result == B_OK)
344					result = reply.AddMessage("network", &network);
345			}
346
347			reply.AddInt32("status", result);
348			message->SendReply(&reply);
349			break;
350		}
351
352		case kMsgAddPersistentNetwork:
353		{
354			status_t result = _ConvertNetworkToSettings(*message);
355			if (result == B_OK)
356				result = fSettings.AddNetwork(*message);
357
358			BMessage reply(B_REPLY);
359			reply.AddInt32("status", result);
360			message->SendReply(&reply);
361			break;
362		}
363
364		case kMsgRemovePersistentNetwork:
365		{
366			const char* networkName = NULL;
367			status_t result = message->FindString("name", &networkName);
368			if (result == B_OK)
369				result = fSettings.RemoveNetwork(networkName);
370
371			BMessage reply(B_REPLY);
372			reply.AddInt32("status", result);
373			message->SendReply(&reply);
374			break;
375		}
376
377		default:
378			BApplication::MessageReceived(message);
379			return;
380	}
381}
382
383
384/*!	Checks if provided address family is valid.
385	Families include AF_INET, AF_INET6, AF_APPLETALK, etc
386*/
387bool
388NetServer::_IsValidFamily(uint32 family)
389{
390	// Mostly verifies add-on is present
391	int socket = ::socket(family, SOCK_DGRAM, 0);
392	if (socket < 0)
393		return false;
394
395	close(socket);
396	return true;
397}
398
399
400/*!	Checks if an interface is valid, that is, if it has an address in any
401	family, and, in case of ethernet, a hardware MAC address.
402*/
403bool
404NetServer::_IsValidInterface(BNetworkInterface& interface)
405{
406	// check if it has an address
407
408	if (interface.CountAddresses() == 0)
409		return false;
410
411	// check if it has a hardware address, too, in case of ethernet
412
413	BNetworkAddress link;
414	if (interface.GetHardwareAddress(link) != B_OK)
415		return false;
416
417	if (link.LinkLevelType() == IFT_ETHER && link.LinkLevelAddressLength() != 6)
418		return false;
419
420	return true;
421}
422
423
424void
425NetServer::_RemoveInvalidInterfaces()
426{
427	BNetworkRoster& roster = BNetworkRoster::Default();
428	BNetworkInterface interface;
429	uint32 cookie = 0;
430
431	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
432		if (!_IsValidInterface(interface)) {
433			// remove invalid interface
434			_RemoveInterface(interface.Name());
435		}
436	}
437}
438
439
440bool
441NetServer::_TestForInterface(const char* name)
442{
443
444	BNetworkRoster& roster = BNetworkRoster::Default();
445	int32 nameLength = strlen(name);
446	BNetworkInterface interface;
447	uint32 cookie = 0;
448
449	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
450		if (!strncmp(interface.Name(), name, nameLength))
451			return true;
452	}
453
454	return false;
455}
456
457
458status_t
459NetServer::_RemoveInterface(const char* name)
460{
461	BNetworkRoster& roster = BNetworkRoster::Default();
462	status_t status = roster.RemoveInterface(name);
463	if (status != B_OK) {
464		fprintf(stderr, "%s: Could not delete interface %s: %s\n",
465			Name(), name, strerror(status));
466		return status;
467	}
468
469	return B_OK;
470}
471
472
473status_t
474NetServer::_DisableInterface(const char* name)
475{
476	BNetworkInterface interface(name);
477	int32 flags = interface.Flags();
478
479	// Set interface down
480	flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING);
481
482	status_t status = interface.SetFlags(flags);
483	if (status != B_OK) {
484		fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
485			strerror(status));
486		return status;
487	}
488
489	fprintf(stderr, "%s: set %s interface down...\n", Name(), name);
490	return B_OK;
491}
492
493
494status_t
495NetServer::_ConfigureInterface(BMessage& message)
496{
497	const char* name;
498	if (message.FindString("device", &name) != B_OK)
499		return B_BAD_VALUE;
500
501	bool startAutoConfig = false;
502
503	int32 flags;
504	if (message.FindInt32("flags", &flags) != B_OK)
505		flags = IFF_UP;
506
507	bool autoConfigured;
508	if (message.FindBool("auto_configured", &autoConfigured) == B_OK
509			&& autoConfigured) {
510		flags |= IFF_AUTO_CONFIGURED;
511	}
512
513	int32 mtu;
514	if (message.FindInt32("mtu", &mtu) != B_OK)
515		mtu = -1;
516
517	int32 metric;
518	if (message.FindInt32("metric", &metric) != B_OK)
519		metric = -1;
520
521	BNetworkInterface interface(name);
522	if (!interface.Exists()) {
523		// the interface does not exist yet, we have to add it first
524		BNetworkRoster& roster = BNetworkRoster::Default();
525
526		status_t status = roster.AddInterface(interface);
527		if (status != B_OK) {
528			fprintf(stderr, "%s: Could not add interface: %s\n",
529				interface.Name(), strerror(status));
530			return status;
531		}
532	}
533
534	BNetworkDevice device(name);
535	if (device.IsWireless()) {
536		const char* networkName;
537		if (message.FindString("network", &networkName) == B_OK) {
538			// join configured network
539			status_t status = _JoinNetwork(message, networkName);
540			if (status != B_OK) {
541				fprintf(stderr, "%s: joining network \"%s\" failed: %s\n",
542					interface.Name(), networkName, strerror(status));
543			}
544		} else {
545			// auto select network to join
546			status_t status = _AutoJoinNetwork(name);
547			if (status != B_OK) {
548				fprintf(stderr, "%s: auto joining network failed: %s\n",
549					interface.Name(), strerror(status));
550			}
551		}
552	}
553
554	// Set up IPv6 Link Local address (based on MAC, if not loopback)
555	_ConfigureIPv6LinkLocal(name);
556
557	BMessage addressMessage;
558	for (int32 index = 0; message.FindMessage("address", index,
559			&addressMessage) == B_OK; index++) {
560		int32 family;
561		if (addressMessage.FindInt32("family", &family) != B_OK) {
562			const char* familyString;
563			if (addressMessage.FindString("family", &familyString) == B_OK) {
564				if (get_address_family(familyString) == AF_UNSPEC) {
565					// we don't support this family
566					fprintf(stderr, "%s: Ignore unknown family: %s\n", Name(),
567						familyString);
568					continue;
569				}
570			} else
571				family = AF_UNSPEC;
572		}
573
574		// retrieve addresses
575
576		bool autoConfig;
577		if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK)
578			autoConfig = false;
579
580		BNetworkAddress address;
581		BNetworkAddress mask;
582		BNetworkAddress broadcast;
583		BNetworkAddress peer;
584		BNetworkAddress gateway;
585
586		const char* string;
587
588		if (!autoConfig) {
589			if (addressMessage.FindString("address", &string) == B_OK) {
590				parse_address(family, string, address);
591
592				if (addressMessage.FindString("mask", &string) == B_OK)
593					parse_address(family, string, mask);
594			}
595
596			if (addressMessage.FindString("peer", &string) == B_OK)
597				parse_address(family, string, peer);
598
599			if (addressMessage.FindString("broadcast", &string) == B_OK)
600				parse_address(family, string, broadcast);
601		}
602
603		if (autoConfig) {
604			_QuitLooperForDevice(name);
605			startAutoConfig = true;
606		} else if (addressMessage.FindString("gateway", &string) == B_OK
607			&& parse_address(family, string, gateway)) {
608			// add gateway route, if we're asked for it
609			interface.RemoveDefaultRoute(family);
610				// Try to remove a previous default route, doesn't matter
611				// if it fails.
612
613			status_t status = interface.AddDefaultRoute(gateway);
614			if (status != B_OK) {
615				fprintf(stderr, "%s: Could not add route for %s: %s\n",
616					Name(), name, strerror(errno));
617			}
618		}
619
620		// set address/mask/broadcast/peer
621
622		if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) {
623			BNetworkInterfaceAddress interfaceAddress;
624			interfaceAddress.SetAddress(address);
625			interfaceAddress.SetMask(mask);
626			if (!broadcast.IsEmpty())
627				interfaceAddress.SetBroadcast(broadcast);
628			else if (!peer.IsEmpty())
629				interfaceAddress.SetDestination(peer);
630
631			status_t status = interface.SetAddress(interfaceAddress);
632			if (status != B_OK) {
633				fprintf(stderr, "%s: Setting address failed: %s\n", Name(),
634					strerror(status));
635				return status;
636			}
637		}
638
639		// set flags
640
641		if (flags != 0) {
642			int32 newFlags = interface.Flags();
643			newFlags = (newFlags & ~IFF_CONFIGURING) | flags;
644			if (!autoConfigured)
645				newFlags &= ~IFF_AUTO_CONFIGURED;
646
647			status_t status = interface.SetFlags(newFlags);
648			if (status != B_OK) {
649				fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
650					strerror(status));
651			}
652		}
653
654		// set options
655
656		if (mtu != -1) {
657			status_t status = interface.SetMTU(mtu);
658			if (status != B_OK) {
659				fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(),
660					strerror(status));
661			}
662		}
663
664		if (metric != -1) {
665			status_t status = interface.SetMetric(metric);
666			if (status != B_OK) {
667				fprintf(stderr, "%s: Setting metric failed: %s\n", Name(),
668					strerror(status));
669			}
670		}
671	}
672
673	if (startAutoConfig) {
674		// start auto configuration
675		AutoconfigLooper* looper = new AutoconfigLooper(this, name);
676		looper->Run();
677
678		fDeviceMap[name] = looper;
679	} else if (!autoConfigured)
680		_QuitLooperForDevice(name);
681
682	return B_OK;
683}
684
685
686status_t
687NetServer::_ConfigureResolver(BMessage& resolverConfiguration)
688{
689	// TODO: resolv.conf should be parsed, all information should be
690	// maintained and it should be distinguished between user entered
691	// and auto-generated parts of the file, with this method only re-writing
692	// the auto-generated parts of course.
693
694	BPath path;
695	if (find_directory(B_COMMON_SETTINGS_DIRECTORY, &path) != B_OK
696		|| path.Append("network/resolv.conf") != B_OK)
697		return B_ERROR;
698
699	FILE* file = fopen(path.Path(), "w");
700	if (file != NULL) {
701		const char* nameserver;
702		for (int32 i = 0; resolverConfiguration.FindString("nameserver", i,
703				&nameserver) == B_OK; i++) {
704			fprintf(file, "nameserver %s\n", nameserver);
705		}
706
707		const char* domain;
708		if (resolverConfiguration.FindString("domain", &domain) == B_OK)
709			fprintf(file, "domain %s\n", domain);
710
711		fclose(file);
712	}
713	return B_OK;
714}
715
716
717bool
718NetServer::_QuitLooperForDevice(const char* device)
719{
720	LooperMap::iterator iterator = fDeviceMap.find(device);
721	if (iterator == fDeviceMap.end())
722		return false;
723
724	// there is a looper for this device - quit it
725	if (iterator->second->Lock())
726		iterator->second->Quit();
727
728	fDeviceMap.erase(iterator);
729	return true;
730}
731
732
733AutoconfigLooper*
734NetServer::_LooperForDevice(const char* device)
735{
736	LooperMap::const_iterator iterator = fDeviceMap.find(device);
737	if (iterator == fDeviceMap.end())
738		return NULL;
739
740	return iterator->second;
741}
742
743
744status_t
745NetServer::_ConfigureDevice(const char* device)
746{
747	// bring interface up, but don't configure it just yet
748	BMessage interface;
749	interface.AddString("device", device);
750	BMessage address;
751	address.AddString("family", "inet");
752	address.AddBool("auto_config", true);
753	interface.AddMessage("address", &address);
754
755	return _ConfigureInterface(interface);
756}
757
758
759void
760NetServer::_ConfigureDevices(const char* startPath,
761	BMessage* suggestedInterface)
762{
763	BDirectory directory(startPath);
764	BEntry entry;
765	while (directory.GetNextEntry(&entry) == B_OK) {
766		char name[B_FILE_NAME_LENGTH];
767		struct stat stat;
768		BPath path;
769		if (entry.GetName(name) != B_OK
770			|| entry.GetPath(&path) != B_OK
771			|| entry.GetStat(&stat) != B_OK)
772			continue;
773
774		if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) {
775			if (suggestedInterface != NULL
776				&& suggestedInterface->RemoveName("device") == B_OK
777				&& suggestedInterface->AddString("device", path.Path()) == B_OK
778				&& _ConfigureInterface(*suggestedInterface) == B_OK)
779				suggestedInterface = NULL;
780			else
781				_ConfigureDevice(path.Path());
782		} else if (entry.IsDirectory())
783			_ConfigureDevices(path.Path(), suggestedInterface);
784	}
785}
786
787
788void
789NetServer::_ConfigureInterfaces(BMessage* _missingDevice)
790{
791	BMessage interface;
792	uint32 cookie = 0;
793	bool missing = false;
794	while (fSettings.GetNextInterface(cookie, interface) == B_OK) {
795		const char *device;
796		if (interface.FindString("device", &device) != B_OK)
797			continue;
798
799		bool disabled = false;
800		if (interface.FindBool("disabled", &disabled) == B_OK && disabled) {
801			// disabled by user request
802			_DisableInterface(device);
803			continue;
804		}
805
806		if (!strncmp(device, "/dev/net/", 9)) {
807			// it's a kernel device, check if it's present
808			BEntry entry(device);
809			if (!entry.Exists()) {
810				if (!missing && _missingDevice != NULL) {
811					*_missingDevice = interface;
812					missing = true;
813				}
814				continue;
815			}
816		}
817
818		_ConfigureInterface(interface);
819	}
820}
821
822
823void
824NetServer::_BringUpInterfaces()
825{
826	// we need a socket to talk to the networking stack
827	if (!_IsValidFamily(AF_LINK)) {
828		fprintf(stderr, "%s: The networking stack doesn't seem to be "
829			"available.\n", Name());
830		Quit();
831		return;
832	}
833
834	_RemoveInvalidInterfaces();
835
836	// First, we look into the settings, and try to bring everything up from there
837
838	BMessage missingDevice;
839	_ConfigureInterfaces(&missingDevice);
840
841	// check configuration
842
843	if (!_TestForInterface("loop")) {
844		// there is no loopback interface, create one
845		BMessage interface;
846		interface.AddString("device", "loop");
847		BMessage v4address;
848		v4address.AddString("family", "inet");
849		v4address.AddString("address", "127.0.0.1");
850		interface.AddMessage("address", &v4address);
851
852		// Check for IPv6 support and add ::1
853		if (_IsValidFamily(AF_INET6)) {
854			BMessage v6address;
855			v6address.AddString("family", "inet6");
856			v6address.AddString("address", "::1");
857			interface.AddMessage("address", &v6address);
858		}
859		_ConfigureInterface(interface);
860	}
861
862	// TODO: also check if the networking driver is correctly initialized!
863	//	(and check for other devices to take over its configuration)
864
865	if (!_TestForInterface("/dev/net/")) {
866		// there is no driver configured - see if there is one and try to use it
867		_ConfigureDevices("/dev/net",
868			missingDevice.HasString("device") ? &missingDevice : NULL);
869	}
870}
871
872
873/*!	Configure the link local address based on the network card's MAC address
874	if this isn't a loopback device.
875*/
876void
877NetServer::_ConfigureIPv6LinkLocal(const char* name)
878{
879	// Check for IPv6 support
880	if (!_IsValidFamily(AF_INET6))
881		return;
882
883	BNetworkInterface interface(name);
884
885	// Lets make sure this is *not* the loopback interface
886	if ((interface.Flags() & IFF_LOOPBACK) != 0)
887		return;
888
889	BNetworkAddress link;
890	status_t result = interface.GetHardwareAddress(link);
891
892	if (result != B_OK || link.LinkLevelAddressLength() != 6)
893		return;
894
895	const uint8* mac = link.LinkLevelAddress();
896
897	// Check for a few failure situations
898	static const char zeroMac[6] = {0, 0, 0, 0, 0, 0};
899	static const char fullMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
900	if (memcmp(mac, zeroMac, 6) == 0
901		|| memcmp(mac, fullMac, 6) == 0) {
902		// Mac address is all 0 or all FF's
903		syslog(LOG_DEBUG, "%s: MacAddress for interface '%s' is invalid.",
904			__func__, name);
905		return;
906	}
907
908	// Generate a Link Local Scope address
909	// (IPv6 address based on Mac address)
910	in6_addr addressRaw;
911	memset(addressRaw.s6_addr, 0, sizeof(addressRaw.s6_addr));
912	addressRaw.s6_addr[0] = 0xfe;
913	addressRaw.s6_addr[1] = 0x80;
914	addressRaw.s6_addr[8] = mac[0] ^ 0x02;
915	addressRaw.s6_addr[9] = mac[1];
916	addressRaw.s6_addr[10] = mac[2];
917	addressRaw.s6_addr[11] = 0xff;
918	addressRaw.s6_addr[12] = 0xfe;
919	addressRaw.s6_addr[13] = mac[3];
920	addressRaw.s6_addr[14] = mac[4];
921	addressRaw.s6_addr[15] = mac[5];
922
923	BNetworkAddress localLinkAddress(addressRaw, 0);
924	BNetworkAddress localLinkMask("ffff:ffff:ffff:ffff::"); // 64
925	BNetworkAddress localLinkBroadcast("fe80::ffff:ffff:ffff:ffff");
926
927	if (interface.FindAddress(localLinkAddress) >= 0) {
928		// uhoh... already has a local link address
929
930		/*	TODO: Check for any local link scope addresses assigned to card
931			There isn't any flag at the moment though for address scope
932		*/
933		syslog(LOG_DEBUG, "%s: Local Link address already assigned to %s\n",
934			__func__, name);
935		return;
936	}
937
938	BNetworkInterfaceAddress interfaceAddress;
939	interfaceAddress.SetAddress(localLinkAddress);
940	interfaceAddress.SetMask(localLinkMask);
941	interfaceAddress.SetBroadcast(localLinkMask);
942
943	/*	TODO: Duplicate Address Detection.  (DAD)
944		Need to blast an icmp packet over the IPv6 network from :: to ensure
945		there aren't duplicate MAC addresses on the network. (definitely an
946		edge case, but a possible issue)
947	*/
948
949	interface.AddAddress(interfaceAddress);
950}
951
952
953void
954NetServer::_StartServices()
955{
956	BHandler* services = new (std::nothrow) Services(fSettings.Services());
957	if (services != NULL) {
958		AddHandler(services);
959		fServices = BMessenger(services);
960	}
961}
962
963
964status_t
965NetServer::_HandleDeviceMonitor(BMessage* message)
966{
967	int32 opcode;
968	const char* path;
969	if (message->FindInt32("opcode", &opcode) != B_OK
970		|| (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED)
971		|| message->FindString("path", &path) != B_OK)
972		return B_BAD_VALUE;
973
974	if (strncmp(path, "/dev/net", 9)) {
975		// not a device entry, ignore
976		return B_NAME_NOT_FOUND;
977	}
978
979	if (opcode == B_ENTRY_CREATED)
980		_ConfigureDevice(path);
981	else
982		_RemoveInterface(path);
983
984	return B_OK;
985}
986
987
988status_t
989NetServer::_AutoJoinNetwork(const char* name)
990{
991	BNetworkDevice device(name);
992
993	BMessage message;
994	message.AddString("device", name);
995
996	// Choose among configured networks
997
998	uint32 cookie = 0;
999	BMessage networkMessage;
1000	while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) {
1001		status_t status = B_ERROR;
1002		wireless_network network;
1003		const char* networkName;
1004		BNetworkAddress link;
1005
1006		const char* mac;
1007		if (networkMessage.FindString("mac", &mac) == B_OK) {
1008			link.SetTo(AF_LINK, mac);
1009			status = device.GetNetwork(link, network);
1010		} else if (networkMessage.FindString("name", &networkName) == B_OK)
1011			status = device.GetNetwork(networkName, network);
1012
1013		if (status == B_OK) {
1014			status = _JoinNetwork(message, network.name);
1015			printf("auto join network \"%s\": %s\n", network.name,
1016				strerror(status));
1017			if (status == B_OK)
1018				return B_OK;
1019		}
1020	}
1021
1022	return B_NO_INIT;
1023}
1024
1025
1026status_t
1027NetServer::_JoinNetwork(const BMessage& message, const char* name)
1028{
1029	const char* deviceName;
1030	if (message.FindString("device", &deviceName) != B_OK)
1031		return B_BAD_VALUE;
1032
1033	BNetworkAddress address;
1034	message.FindFlat("address", &address);
1035
1036	if (name == NULL)
1037		message.FindString("name", &name);
1038	if (name == NULL) {
1039		// No name specified, we need a network address
1040		if (address.Family() != AF_LINK)
1041			return B_BAD_VALUE;
1042	}
1043
1044	// Search for a network configuration that may override the defaults
1045
1046	bool found = false;
1047	uint32 cookie = 0;
1048	BMessage networkMessage;
1049	while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) {
1050		const char* networkName;
1051		if (networkMessage.FindString("name", &networkName) == B_OK
1052			&& name != NULL && address.Family() != AF_LINK
1053			&& !strcmp(name, networkName)) {
1054			found = true;
1055			break;
1056		}
1057
1058		const char* mac;
1059		if (networkMessage.FindString("mac", &mac) == B_OK
1060			&& address.Family() == AF_LINK) {
1061			BNetworkAddress link(AF_LINK, mac);
1062			if (link == address) {
1063				found = true;
1064				break;
1065			}
1066		}
1067	}
1068
1069	const char* password;
1070	if (message.FindString("password", &password) != B_OK && found)
1071		password = networkMessage.FindString("password");
1072
1073	// Get network
1074	BNetworkDevice device(deviceName);
1075	wireless_network network;
1076
1077	bool askForConfig = false;
1078	if ((address.Family() != AF_LINK
1079			|| device.GetNetwork(address, network) != B_OK)
1080		&& device.GetNetwork(name, network) != B_OK) {
1081		// We did not find a network - just ignore that, and continue
1082		// with some defaults
1083		strlcpy(network.name, name, sizeof(network.name));
1084		network.address = address;
1085		network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE;
1086		network.cipher = 0;
1087		network.group_cipher = 0;
1088		network.key_mode = 0;
1089		askForConfig = true;
1090	}
1091
1092	const char* string;
1093	if (message.FindString("authentication", &string) == B_OK
1094		|| (found && networkMessage.FindString("authentication", &string)
1095				== B_OK)) {
1096		askForConfig = false;
1097		if (!strcasecmp(string, "wpa2")) {
1098			network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2;
1099			network.key_mode = B_KEY_MODE_IEEE802_1X;
1100			network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP;
1101		} else if (!strcasecmp(string, "wpa")) {
1102			network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA;
1103			network.key_mode = B_KEY_MODE_IEEE802_1X;
1104			network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP;
1105		} else if (!strcasecmp(string, "wep")) {
1106			network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP;
1107			network.key_mode = B_KEY_MODE_NONE;
1108			network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40;
1109		} else if (strcasecmp(string, "none") && strcasecmp(string, "open")) {
1110			fprintf(stderr, "%s: invalid authentication mode.\n", name);
1111			askForConfig = true;
1112		}
1113	}
1114
1115	if (!askForConfig
1116		&& network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) {
1117		// we join the network ourselves
1118		status_t status = set_80211(deviceName, IEEE80211_IOC_SSID,
1119			network.name, strlen(network.name));
1120		if (status != B_OK) {
1121			fprintf(stderr, "%s: joining SSID failed: %s\n", name,
1122				strerror(status));
1123			return status;
1124		}
1125
1126		return B_OK;
1127	}
1128
1129	// Join via wpa_supplicant
1130
1131	status_t status = be_roster->Launch(kWPASupplicantSignature);
1132	if (status != B_OK && status != B_ALREADY_RUNNING)
1133		return status;
1134
1135	// TODO: listen to notifications from the supplicant!
1136
1137	BMessage join(kMsgWPAJoinNetwork);
1138	status = join.AddString("device", deviceName);
1139	if (status == B_OK)
1140		status = join.AddString("name", network.name);
1141	if (status == B_OK)
1142		status = join.AddFlat("address", &network.address);
1143	if (status == B_OK && !askForConfig)
1144		status = join.AddUInt32("authentication", network.authentication_mode);
1145	if (status == B_OK && password != NULL)
1146		status = join.AddString("password", password);
1147	if (status != B_OK)
1148		return status;
1149
1150	BMessenger wpaSupplicant(kWPASupplicantSignature);
1151	status = wpaSupplicant.SendMessage(&join);
1152	if (status != B_OK)
1153		return status;
1154
1155	return B_OK;
1156}
1157
1158
1159status_t
1160NetServer::_LeaveNetwork(const BMessage& message)
1161{
1162	// TODO: not yet implemented
1163	return B_NOT_SUPPORTED;
1164}
1165
1166
1167status_t
1168NetServer::_ConvertNetworkToSettings(BMessage& message)
1169{
1170	BNetworkAddress address;
1171	status_t result = message.FindFlat("address", &address);
1172	if (result == B_OK)
1173		message.RemoveName("address");
1174
1175	if (result == B_OK && address.Family() == AF_LINK) {
1176		size_t addressLength = address.LinkLevelAddressLength();
1177		uint8* macAddress = address.LinkLevelAddress();
1178		bool usable = false;
1179		BString formatted;
1180
1181		for (size_t index = 0; index < addressLength; index++) {
1182			if (index > 0)
1183				formatted.Append(":");
1184			char buffer[3];
1185			snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]);
1186			formatted.Append(buffer, sizeof(buffer));
1187
1188			if (macAddress[index] != 0)
1189				usable = true;
1190		}
1191
1192		if (usable)
1193			message.AddString("mac", formatted);
1194	}
1195
1196	uint32 authentication = 0;
1197	result = message.FindUInt32("authentication_mode", &authentication);
1198	if (result == B_OK) {
1199		message.RemoveName("authentication_mode");
1200
1201		const char* authenticationString = NULL;
1202		switch (authentication) {
1203			case B_NETWORK_AUTHENTICATION_NONE:
1204				authenticationString = "none";
1205				break;
1206			case B_NETWORK_AUTHENTICATION_WEP:
1207				authenticationString = "wep";
1208				break;
1209			case B_NETWORK_AUTHENTICATION_WPA:
1210				authenticationString = "wpa";
1211				break;
1212			case B_NETWORK_AUTHENTICATION_WPA2:
1213				authenticationString = "wpa2";
1214				break;
1215		}
1216
1217		if (result == B_OK && authenticationString != NULL)
1218			message.AddString("authentication", authenticationString);
1219	}
1220
1221	uint32 cipher = 0;
1222	result = message.FindUInt32("cipher", &cipher);
1223	if (result == B_OK) {
1224		message.RemoveName("cipher");
1225
1226		if ((cipher & B_NETWORK_CIPHER_NONE) != 0)
1227			message.AddString("cipher", "none");
1228		if ((cipher & B_NETWORK_CIPHER_TKIP) != 0)
1229			message.AddString("cipher", "tkip");
1230		if ((cipher & B_NETWORK_CIPHER_CCMP) != 0)
1231			message.AddString("cipher", "ccmp");
1232	}
1233
1234	uint32 groupCipher = 0;
1235	result = message.FindUInt32("group_cipher", &groupCipher);
1236	if (result == B_OK) {
1237		message.RemoveName("group_cipher");
1238
1239		if ((groupCipher & B_NETWORK_CIPHER_NONE) != 0)
1240			message.AddString("group_cipher", "none");
1241		if ((groupCipher & B_NETWORK_CIPHER_WEP_40) != 0)
1242			message.AddString("group_cipher", "wep40");
1243		if ((groupCipher & B_NETWORK_CIPHER_WEP_104) != 0)
1244			message.AddString("group_cipher", "wep104");
1245		if ((groupCipher & B_NETWORK_CIPHER_TKIP) != 0)
1246			message.AddString("group_cipher", "tkip");
1247		if ((groupCipher & B_NETWORK_CIPHER_CCMP) != 0)
1248			message.AddString("group_cipher", "ccmp");
1249	}
1250
1251	// TODO: the other fields aren't currently used, add them when they are
1252	// and when it's clear how they will be stored
1253	message.RemoveName("noise_level");
1254	message.RemoveName("signal_strength");
1255	message.RemoveName("flags");
1256	message.RemoveName("key_mode");
1257
1258	return B_OK;
1259}
1260
1261
1262status_t
1263NetServer::_ConvertNetworkFromSettings(BMessage& message)
1264{
1265	message.RemoveName("mac");
1266		// TODO: convert into a flat BNetworkAddress "address"
1267
1268	const char* authentication = NULL;
1269	if (message.FindString("authentication", &authentication) == B_OK) {
1270		message.RemoveName("authentication");
1271
1272		if (strcasecmp(authentication, "none") == 0) {
1273			message.AddUInt32("authentication_mode",
1274				B_NETWORK_AUTHENTICATION_NONE);
1275		} else if (strcasecmp(authentication, "wep") == 0) {
1276			message.AddUInt32("authentication_mode",
1277				B_NETWORK_AUTHENTICATION_WEP);
1278		} else if (strcasecmp(authentication, "wpa") == 0) {
1279			message.AddUInt32("authentication_mode",
1280				B_NETWORK_AUTHENTICATION_WPA);
1281		} else if (strcasecmp(authentication, "wpa2") == 0) {
1282			message.AddUInt32("authentication_mode",
1283				B_NETWORK_AUTHENTICATION_WPA2);
1284		}
1285	}
1286
1287	int32 index = 0;
1288	uint32 cipher = 0;
1289	const char* cipherString = NULL;
1290	while (message.FindString("cipher", index++, &cipherString) == B_OK) {
1291		if (strcasecmp(cipherString, "none") == 0)
1292			cipher |= B_NETWORK_CIPHER_NONE;
1293		else if (strcasecmp(cipherString, "tkip") == 0)
1294			cipher |= B_NETWORK_CIPHER_TKIP;
1295		else if (strcasecmp(cipherString, "ccmp") == 0)
1296			cipher |= B_NETWORK_CIPHER_CCMP;
1297	}
1298
1299	message.RemoveName("cipher");
1300	if (cipher != 0)
1301		message.AddUInt32("cipher", cipher);
1302
1303	index = 0;
1304	cipher = 0;
1305	while (message.FindString("group_cipher", index++, &cipherString) == B_OK) {
1306		if (strcasecmp(cipherString, "none") == 0)
1307			cipher |= B_NETWORK_CIPHER_NONE;
1308		else if (strcasecmp(cipherString, "wep40") == 0)
1309			cipher |= B_NETWORK_CIPHER_WEP_40;
1310		else if (strcasecmp(cipherString, "wep104") == 0)
1311			cipher |= B_NETWORK_CIPHER_WEP_104;
1312		else if (strcasecmp(cipherString, "tkip") == 0)
1313			cipher |= B_NETWORK_CIPHER_TKIP;
1314		else if (strcasecmp(cipherString, "ccmp") == 0)
1315			cipher |= B_NETWORK_CIPHER_CCMP;
1316	}
1317
1318	message.RemoveName("group_cipher");
1319	if (cipher != 0)
1320		message.AddUInt32("group_cipher", cipher);
1321
1322	message.AddUInt32("flags", B_NETWORK_IS_PERSISTENT);
1323
1324	// TODO: add the other fields
1325	message.RemoveName("key");
1326	return B_OK;
1327}
1328
1329
1330//	#pragma mark -
1331
1332
1333int
1334main(int argc, char** argv)
1335{
1336	status_t status;
1337	NetServer server(status);
1338	if (status != B_OK) {
1339		fprintf(stderr, "net_server: Failed to create application: %s\n",
1340			strerror(status));
1341		return 1;
1342	}
1343
1344	server.Run();
1345	return 0;
1346}
1347
1348