xref: /haiku/src/servers/net/NetServer.cpp (revision 14b32de1d5efe99b4c6d4ef8c25df47eb009cf0f)
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 
51 extern "C" {
52 #	include <net80211/ieee80211_ioctl.h>
53 }
54 
55 
56 typedef std::map<std::string, AutoconfigLooper*> LooperMap;
57 
58 
59 class NetServer : public BServer {
60 public:
61 								NetServer(status_t& status);
62 	virtual						~NetServer();
63 
64 	virtual	void				AboutRequested();
65 	virtual	void				ReadyToRun();
66 	virtual	void				MessageReceived(BMessage* message);
67 
68 private:
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				_ConfigureInterfacesFromSettings(
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 BMessage& message);
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 
99 private:
100 			Settings			fSettings;
101 			LooperMap			fDeviceMap;
102 			BMessenger			fServices;
103 };
104 
105 
106 struct address_family {
107 	int			family;
108 	const char*	name;
109 	const char*	identifiers[4];
110 };
111 
112 
113 static 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 
131 static status_t
132 set_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 
158 int
159 get_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 */
178 bool
179 parse_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 
213 NetServer::NetServer(status_t& error)
214 	:
215 	BServer(kNetServerSignature, false, &error)
216 {
217 }
218 
219 
220 NetServer::~NetServer()
221 {
222 	BPrivate::BPathMonitor::StopWatching("/dev/net", this);
223 }
224 
225 
226 void
227 NetServer::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 
246 void
247 NetServer::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 
258 void
259 NetServer::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 			_ConfigureInterfacesFromSettings();
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 kMsgAutoJoinNetwork:
325 		{
326 			_AutoJoinNetwork(*message);
327 			break;
328 		}
329 
330 		case kMsgCountPersistentNetworks:
331 		{
332 			BMessage reply(B_REPLY);
333 			reply.AddInt32("count", fSettings.CountNetworks());
334 			message->SendReply(&reply);
335 			break;
336 		}
337 
338 		case kMsgGetPersistentNetwork:
339 		{
340 			uint32 index = 0;
341 			status_t result = message->FindInt32("index", (int32*)&index);
342 
343 			BMessage reply(B_REPLY);
344 			if (result == B_OK) {
345 				BMessage network;
346 				result = fSettings.GetNextNetwork(index, network);
347 				if (result == B_OK)
348 					result = _ConvertNetworkFromSettings(network);
349 				if (result == B_OK)
350 					result = reply.AddMessage("network", &network);
351 			}
352 
353 			reply.AddInt32("status", result);
354 			message->SendReply(&reply);
355 			break;
356 		}
357 
358 		case kMsgAddPersistentNetwork:
359 		{
360 			BMessage network = *message;
361 			status_t result = _ConvertNetworkToSettings(network);
362 			if (result == B_OK)
363 				result = fSettings.AddNetwork(network);
364 
365 			BMessage reply(B_REPLY);
366 			reply.AddInt32("status", result);
367 			message->SendReply(&reply);
368 			break;
369 		}
370 
371 		case kMsgRemovePersistentNetwork:
372 		{
373 			const char* networkName = NULL;
374 			status_t result = message->FindString("name", &networkName);
375 			if (result == B_OK)
376 				result = fSettings.RemoveNetwork(networkName);
377 
378 			BMessage reply(B_REPLY);
379 			reply.AddInt32("status", result);
380 			message->SendReply(&reply);
381 			break;
382 		}
383 
384 		default:
385 			BApplication::MessageReceived(message);
386 			return;
387 	}
388 }
389 
390 
391 /*!	Checks if provided address family is valid.
392 	Families include AF_INET, AF_INET6, AF_APPLETALK, etc
393 */
394 bool
395 NetServer::_IsValidFamily(uint32 family)
396 {
397 	// Mostly verifies add-on is present
398 	int socket = ::socket(family, SOCK_DGRAM, 0);
399 	if (socket < 0)
400 		return false;
401 
402 	close(socket);
403 	return true;
404 }
405 
406 
407 /*!	Checks if an interface is valid, that is, if it has an address in any
408 	family, and, in case of ethernet, a hardware MAC address.
409 */
410 bool
411 NetServer::_IsValidInterface(BNetworkInterface& interface)
412 {
413 	// check if it has an address
414 
415 	if (interface.CountAddresses() == 0)
416 		return false;
417 
418 	// check if it has a hardware address, too, in case of ethernet
419 
420 	BNetworkAddress link;
421 	if (interface.GetHardwareAddress(link) != B_OK)
422 		return false;
423 
424 	if (link.LinkLevelType() == IFT_ETHER && link.LinkLevelAddressLength() != 6)
425 		return false;
426 
427 	return true;
428 }
429 
430 
431 void
432 NetServer::_RemoveInvalidInterfaces()
433 {
434 	BNetworkRoster& roster = BNetworkRoster::Default();
435 	BNetworkInterface interface;
436 	uint32 cookie = 0;
437 
438 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
439 		if (!_IsValidInterface(interface)) {
440 			// remove invalid interface
441 			_RemoveInterface(interface.Name());
442 		}
443 	}
444 }
445 
446 
447 bool
448 NetServer::_TestForInterface(const char* name)
449 {
450 
451 	BNetworkRoster& roster = BNetworkRoster::Default();
452 	int32 nameLength = strlen(name);
453 	BNetworkInterface interface;
454 	uint32 cookie = 0;
455 
456 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
457 		if (!strncmp(interface.Name(), name, nameLength))
458 			return true;
459 	}
460 
461 	return false;
462 }
463 
464 
465 status_t
466 NetServer::_RemoveInterface(const char* name)
467 {
468 	BNetworkRoster& roster = BNetworkRoster::Default();
469 	status_t status = roster.RemoveInterface(name);
470 	if (status != B_OK) {
471 		fprintf(stderr, "%s: Could not delete interface %s: %s\n",
472 			Name(), name, strerror(status));
473 		return status;
474 	}
475 
476 	return B_OK;
477 }
478 
479 
480 status_t
481 NetServer::_DisableInterface(const char* name)
482 {
483 	BNetworkInterface interface(name);
484 	int32 flags = interface.Flags();
485 
486 	// Set interface down
487 	flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING);
488 
489 	status_t status = interface.SetFlags(flags);
490 	if (status != B_OK) {
491 		fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
492 			strerror(status));
493 		return status;
494 	}
495 
496 	fprintf(stderr, "%s: set %s interface down...\n", Name(), name);
497 	return B_OK;
498 }
499 
500 
501 status_t
502 NetServer::_ConfigureInterface(BMessage& message)
503 {
504 	const char* name;
505 	if (message.FindString("device", &name) != B_OK)
506 		return B_BAD_VALUE;
507 
508 	bool startAutoConfig = false;
509 
510 	int32 flags;
511 	if (message.FindInt32("flags", &flags) != B_OK)
512 		flags = IFF_UP;
513 
514 	bool autoConfigured;
515 	if (message.FindBool("auto_configured", &autoConfigured) == B_OK
516 			&& autoConfigured) {
517 		flags |= IFF_AUTO_CONFIGURED;
518 	}
519 
520 	int32 mtu;
521 	if (message.FindInt32("mtu", &mtu) != B_OK)
522 		mtu = -1;
523 
524 	int32 metric;
525 	if (message.FindInt32("metric", &metric) != B_OK)
526 		metric = -1;
527 
528 	BNetworkInterface interface(name);
529 	if (!interface.Exists()) {
530 		// the interface does not exist yet, we have to add it first
531 		BNetworkRoster& roster = BNetworkRoster::Default();
532 
533 		status_t status = roster.AddInterface(interface);
534 		if (status != B_OK) {
535 			fprintf(stderr, "%s: Could not add interface: %s\n",
536 				interface.Name(), strerror(status));
537 			return status;
538 		}
539 	}
540 
541 	// Set up IPv6 Link Local address (based on MAC, if not loopback)
542 	_ConfigureIPv6LinkLocal(name);
543 
544 	BMessage addressMessage;
545 	for (int32 index = 0; message.FindMessage("address", index,
546 			&addressMessage) == B_OK; index++) {
547 		int32 family;
548 		if (addressMessage.FindInt32("family", &family) != B_OK) {
549 			const char* familyString;
550 			if (addressMessage.FindString("family", &familyString) == B_OK) {
551 				if (get_address_family(familyString) == AF_UNSPEC) {
552 					// we don't support this family
553 					fprintf(stderr, "%s: Ignore unknown family: %s\n", Name(),
554 						familyString);
555 					continue;
556 				}
557 			} else
558 				family = AF_UNSPEC;
559 		}
560 
561 		// retrieve addresses
562 
563 		bool autoConfig;
564 		if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK)
565 			autoConfig = false;
566 
567 		BNetworkAddress address;
568 		BNetworkAddress mask;
569 		BNetworkAddress broadcast;
570 		BNetworkAddress peer;
571 		BNetworkAddress gateway;
572 
573 		const char* string;
574 
575 		if (!autoConfig) {
576 			if (addressMessage.FindString("address", &string) == B_OK) {
577 				parse_address(family, string, address);
578 
579 				if (addressMessage.FindString("mask", &string) == B_OK)
580 					parse_address(family, string, mask);
581 			}
582 
583 			if (addressMessage.FindString("peer", &string) == B_OK)
584 				parse_address(family, string, peer);
585 
586 			if (addressMessage.FindString("broadcast", &string) == B_OK)
587 				parse_address(family, string, broadcast);
588 		}
589 
590 		if (autoConfig) {
591 			_QuitLooperForDevice(name);
592 			startAutoConfig = true;
593 		} else if (addressMessage.FindString("gateway", &string) == B_OK
594 			&& parse_address(family, string, gateway)) {
595 			// add gateway route, if we're asked for it
596 			interface.RemoveDefaultRoute(family);
597 				// Try to remove a previous default route, doesn't matter
598 				// if it fails.
599 
600 			status_t status = interface.AddDefaultRoute(gateway);
601 			if (status != B_OK) {
602 				fprintf(stderr, "%s: Could not add route for %s: %s\n",
603 					Name(), name, strerror(errno));
604 			}
605 		}
606 
607 		// set address/mask/broadcast/peer
608 
609 		if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) {
610 			BNetworkInterfaceAddress interfaceAddress;
611 			interfaceAddress.SetAddress(address);
612 			interfaceAddress.SetMask(mask);
613 			if (!broadcast.IsEmpty())
614 				interfaceAddress.SetBroadcast(broadcast);
615 			else if (!peer.IsEmpty())
616 				interfaceAddress.SetDestination(peer);
617 
618 			status_t status = interface.SetAddress(interfaceAddress);
619 			if (status != B_OK) {
620 				fprintf(stderr, "%s: Setting address failed: %s\n", Name(),
621 					strerror(status));
622 				return status;
623 			}
624 		}
625 
626 		// set flags
627 
628 		if (flags != 0) {
629 			int32 newFlags = interface.Flags();
630 			newFlags = (newFlags & ~IFF_CONFIGURING) | flags;
631 			if (!autoConfigured)
632 				newFlags &= ~IFF_AUTO_CONFIGURED;
633 
634 			status_t status = interface.SetFlags(newFlags);
635 			if (status != B_OK) {
636 				fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
637 					strerror(status));
638 			}
639 		}
640 
641 		// set options
642 
643 		if (mtu != -1) {
644 			status_t status = interface.SetMTU(mtu);
645 			if (status != B_OK) {
646 				fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(),
647 					strerror(status));
648 			}
649 		}
650 
651 		if (metric != -1) {
652 			status_t status = interface.SetMetric(metric);
653 			if (status != B_OK) {
654 				fprintf(stderr, "%s: Setting metric failed: %s\n", Name(),
655 					strerror(status));
656 			}
657 		}
658 	}
659 
660 	const char* networkName;
661 	if (message.FindString("network", &networkName) == B_OK) {
662 		// We want to join a specific network.
663 		BNetworkDevice device(name);
664 		if (device.IsWireless() && !device.HasLink()) {
665 			status_t status = _JoinNetwork(message, networkName);
666 			if (status != B_OK) {
667 				fprintf(stderr, "%s: joining network \"%s\" failed: %s\n",
668 					interface.Name(), networkName, 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 
686 status_t
687 NetServer::_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 
717 bool
718 NetServer::_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 
733 AutoconfigLooper*
734 NetServer::_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 
744 status_t
745 NetServer::_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 
759 void
760 NetServer::_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 
788 void
789 NetServer::_ConfigureInterfacesFromSettings(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 
823 void
824 NetServer::_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 	_ConfigureInterfacesFromSettings(&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 */
876 void
877 NetServer::_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 uint8 zeroMac[6] = {0, 0, 0, 0, 0, 0};
899 	static const uint8 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 
953 void
954 NetServer::_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 
964 status_t
965 NetServer::_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 valid 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 
988 status_t
989 NetServer::_AutoJoinNetwork(const BMessage& message)
990 {
991 	const char* name = NULL;
992 	if (message.FindString("device", &name) != B_OK)
993 		return B_BAD_VALUE;
994 
995 	BNetworkDevice device(name);
996 
997 	// Choose among configured networks
998 
999 	uint32 cookie = 0;
1000 	BMessage networkMessage;
1001 	while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) {
1002 		status_t status = B_ERROR;
1003 		wireless_network network;
1004 		const char* networkName;
1005 		BNetworkAddress link;
1006 
1007 		const char* mac;
1008 		if (networkMessage.FindString("mac", &mac) == B_OK) {
1009 			link.SetTo(AF_LINK, mac);
1010 			status = device.GetNetwork(link, network);
1011 		} else if (networkMessage.FindString("name", &networkName) == B_OK)
1012 			status = device.GetNetwork(networkName, network);
1013 
1014 		if (status == B_OK) {
1015 			status = _JoinNetwork(message, network.name);
1016 			printf("auto join network \"%s\": %s\n", network.name,
1017 				strerror(status));
1018 			if (status == B_OK)
1019 				return B_OK;
1020 		}
1021 	}
1022 
1023 	return B_NO_INIT;
1024 }
1025 
1026 
1027 status_t
1028 NetServer::_JoinNetwork(const BMessage& message, const char* name)
1029 {
1030 	const char* deviceName;
1031 	if (message.FindString("device", &deviceName) != B_OK)
1032 		return B_BAD_VALUE;
1033 
1034 	BNetworkAddress address;
1035 	message.FindFlat("address", &address);
1036 
1037 	if (name == NULL)
1038 		message.FindString("name", &name);
1039 	if (name == NULL) {
1040 		// No name specified, we need a network address
1041 		if (address.Family() != AF_LINK)
1042 			return B_BAD_VALUE;
1043 	}
1044 
1045 	// Search for a network configuration that may override the defaults
1046 
1047 	bool found = false;
1048 	uint32 cookie = 0;
1049 	BMessage networkMessage;
1050 	while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) {
1051 		const char* networkName;
1052 		if (networkMessage.FindString("name", &networkName) == B_OK
1053 			&& name != NULL && address.Family() != AF_LINK
1054 			&& !strcmp(name, networkName)) {
1055 			found = true;
1056 			break;
1057 		}
1058 
1059 		const char* mac;
1060 		if (networkMessage.FindString("mac", &mac) == B_OK
1061 			&& address.Family() == AF_LINK) {
1062 			BNetworkAddress link(AF_LINK, mac);
1063 			if (link == address) {
1064 				found = true;
1065 				break;
1066 			}
1067 		}
1068 	}
1069 
1070 	const char* password;
1071 	if (message.FindString("password", &password) != B_OK && found)
1072 		password = networkMessage.FindString("password");
1073 
1074 	// Get network
1075 	BNetworkDevice device(deviceName);
1076 	wireless_network network;
1077 
1078 	bool askForConfig = false;
1079 	if ((address.Family() != AF_LINK
1080 			|| device.GetNetwork(address, network) != B_OK)
1081 		&& device.GetNetwork(name, network) != B_OK) {
1082 		// We did not find a network - just ignore that, and continue
1083 		// with some defaults
1084 		strlcpy(network.name, name, sizeof(network.name));
1085 		network.address = address;
1086 		network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE;
1087 		network.cipher = 0;
1088 		network.group_cipher = 0;
1089 		network.key_mode = 0;
1090 		askForConfig = true;
1091 	}
1092 
1093 	const char* string;
1094 	if (message.FindString("authentication", &string) == B_OK
1095 		|| (found && networkMessage.FindString("authentication", &string)
1096 				== B_OK)) {
1097 		askForConfig = false;
1098 		if (!strcasecmp(string, "wpa2")) {
1099 			network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2;
1100 			network.key_mode = B_KEY_MODE_IEEE802_1X;
1101 			network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP;
1102 		} else if (!strcasecmp(string, "wpa")) {
1103 			network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA;
1104 			network.key_mode = B_KEY_MODE_IEEE802_1X;
1105 			network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP;
1106 		} else if (!strcasecmp(string, "wep")) {
1107 			network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP;
1108 			network.key_mode = B_KEY_MODE_NONE;
1109 			network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40;
1110 		} else if (strcasecmp(string, "none") && strcasecmp(string, "open")) {
1111 			fprintf(stderr, "%s: invalid authentication mode.\n", name);
1112 			askForConfig = true;
1113 		}
1114 	}
1115 
1116 	// We always try to join via the wpa_supplicant. Even if we could join
1117 	// ourselves, we need to make sure that the wpa_supplicant knows about
1118 	// our intention, as otherwise it would interfere with it.
1119 
1120 	BMessenger wpaSupplicant(kWPASupplicantSignature);
1121 	if (!wpaSupplicant.IsValid()) {
1122 		// The wpa_supplicant isn't running yet, we may join ourselves.
1123 		if (!askForConfig
1124 			&& network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) {
1125 			// We can join this network ourselves.
1126 			status_t status = set_80211(deviceName, IEEE80211_IOC_SSID,
1127 				network.name, strlen(network.name));
1128 			if (status != B_OK) {
1129 				fprintf(stderr, "%s: joining SSID failed: %s\n", name,
1130 					strerror(status));
1131 				return status;
1132 			}
1133 		}
1134 
1135 		// We need the supplicant, try to launch it.
1136 		status_t status = be_roster->Launch(kWPASupplicantSignature);
1137 		if (status != B_OK && status != B_ALREADY_RUNNING)
1138 			return status;
1139 
1140 		wpaSupplicant.SetTo(kWPASupplicantSignature);
1141 		if (!wpaSupplicant.IsValid())
1142 			return B_ERROR;
1143 	}
1144 
1145 	// TODO: listen to notifications from the supplicant!
1146 
1147 	BMessage join(kMsgWPAJoinNetwork);
1148 	status_t status = join.AddString("device", deviceName);
1149 	if (status == B_OK)
1150 		status = join.AddString("name", network.name);
1151 	if (status == B_OK)
1152 		status = join.AddFlat("address", &network.address);
1153 	if (status == B_OK && !askForConfig)
1154 		status = join.AddUInt32("authentication", network.authentication_mode);
1155 	if (status == B_OK && password != NULL)
1156 		status = join.AddString("password", password);
1157 	if (status != B_OK)
1158 		return status;
1159 
1160 	status = wpaSupplicant.SendMessage(&join);
1161 	if (status != B_OK)
1162 		return status;
1163 
1164 	return B_OK;
1165 }
1166 
1167 
1168 status_t
1169 NetServer::_LeaveNetwork(const BMessage& message)
1170 {
1171 	const char* deviceName;
1172 	if (message.FindString("device", &deviceName) != B_OK)
1173 		return B_BAD_VALUE;
1174 
1175 	int32 reason;
1176 	if (message.FindInt32("reason", &reason) != B_OK)
1177 		reason = IEEE80211_REASON_AUTH_LEAVE;
1178 
1179 	// We always try to send the leave request to the wpa_supplicant.
1180 
1181 	BMessenger wpaSupplicant(kWPASupplicantSignature);
1182 	if (wpaSupplicant.IsValid()) {
1183 		BMessage leave(kMsgWPALeaveNetwork);
1184 		status_t status = leave.AddString("device", deviceName);
1185 		if (status == B_OK)
1186 			status = leave.AddInt32("reason", reason);
1187 		if (status != B_OK)
1188 			return status;
1189 
1190 		status = wpaSupplicant.SendMessage(&leave);
1191 		if (status == B_OK)
1192 			return B_OK;
1193 	}
1194 
1195 	// The wpa_supplicant doesn't seem to be running, check if this was an open
1196 	// network we connected ourselves.
1197 	BNetworkDevice device(deviceName);
1198 	wireless_network network;
1199 
1200 	uint32 cookie = 0;
1201 	if (device.GetNextAssociatedNetwork(cookie, network) != B_OK
1202 		|| network.authentication_mode != B_NETWORK_AUTHENTICATION_NONE) {
1203 		// We didn't join ourselves, we can't do much.
1204 		return B_ERROR;
1205 	}
1206 
1207 	// We joined ourselves, so we can just disassociate again.
1208 	ieee80211req_mlme mlmeRequest;
1209 	memset(&mlmeRequest, 0, sizeof(mlmeRequest));
1210 	mlmeRequest.im_op = IEEE80211_MLME_DISASSOC;
1211 	mlmeRequest.im_reason = reason;
1212 
1213 	return set_80211(deviceName, IEEE80211_IOC_MLME, &mlmeRequest,
1214 		sizeof(mlmeRequest));
1215 }
1216 
1217 
1218 status_t
1219 NetServer::_ConvertNetworkToSettings(BMessage& message)
1220 {
1221 	BNetworkAddress address;
1222 	status_t result = message.FindFlat("address", &address);
1223 	if (result == B_OK)
1224 		message.RemoveName("address");
1225 
1226 	if (result == B_OK && address.Family() == AF_LINK) {
1227 		size_t addressLength = address.LinkLevelAddressLength();
1228 		uint8* macAddress = address.LinkLevelAddress();
1229 		bool usable = false;
1230 		BString formatted;
1231 
1232 		for (size_t index = 0; index < addressLength; index++) {
1233 			if (index > 0)
1234 				formatted.Append(":");
1235 			char buffer[3];
1236 			snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]);
1237 			formatted.Append(buffer, sizeof(buffer));
1238 
1239 			if (macAddress[index] != 0)
1240 				usable = true;
1241 		}
1242 
1243 		if (usable)
1244 			message.AddString("mac", formatted);
1245 	}
1246 
1247 	uint32 authentication = 0;
1248 	result = message.FindUInt32("authentication_mode", &authentication);
1249 	if (result == B_OK) {
1250 		message.RemoveName("authentication_mode");
1251 
1252 		const char* authenticationString = NULL;
1253 		switch (authentication) {
1254 			case B_NETWORK_AUTHENTICATION_NONE:
1255 				authenticationString = "none";
1256 				break;
1257 			case B_NETWORK_AUTHENTICATION_WEP:
1258 				authenticationString = "wep";
1259 				break;
1260 			case B_NETWORK_AUTHENTICATION_WPA:
1261 				authenticationString = "wpa";
1262 				break;
1263 			case B_NETWORK_AUTHENTICATION_WPA2:
1264 				authenticationString = "wpa2";
1265 				break;
1266 		}
1267 
1268 		if (result == B_OK && authenticationString != NULL)
1269 			message.AddString("authentication", authenticationString);
1270 	}
1271 
1272 	uint32 cipher = 0;
1273 	result = message.FindUInt32("cipher", &cipher);
1274 	if (result == B_OK) {
1275 		message.RemoveName("cipher");
1276 
1277 		if ((cipher & B_NETWORK_CIPHER_NONE) != 0)
1278 			message.AddString("cipher", "none");
1279 		if ((cipher & B_NETWORK_CIPHER_TKIP) != 0)
1280 			message.AddString("cipher", "tkip");
1281 		if ((cipher & B_NETWORK_CIPHER_CCMP) != 0)
1282 			message.AddString("cipher", "ccmp");
1283 	}
1284 
1285 	uint32 groupCipher = 0;
1286 	result = message.FindUInt32("group_cipher", &groupCipher);
1287 	if (result == B_OK) {
1288 		message.RemoveName("group_cipher");
1289 
1290 		if ((groupCipher & B_NETWORK_CIPHER_NONE) != 0)
1291 			message.AddString("group_cipher", "none");
1292 		if ((groupCipher & B_NETWORK_CIPHER_WEP_40) != 0)
1293 			message.AddString("group_cipher", "wep40");
1294 		if ((groupCipher & B_NETWORK_CIPHER_WEP_104) != 0)
1295 			message.AddString("group_cipher", "wep104");
1296 		if ((groupCipher & B_NETWORK_CIPHER_TKIP) != 0)
1297 			message.AddString("group_cipher", "tkip");
1298 		if ((groupCipher & B_NETWORK_CIPHER_CCMP) != 0)
1299 			message.AddString("group_cipher", "ccmp");
1300 	}
1301 
1302 	// TODO: the other fields aren't currently used, add them when they are
1303 	// and when it's clear how they will be stored
1304 	message.RemoveName("noise_level");
1305 	message.RemoveName("signal_strength");
1306 	message.RemoveName("flags");
1307 	message.RemoveName("key_mode");
1308 
1309 	return B_OK;
1310 }
1311 
1312 
1313 status_t
1314 NetServer::_ConvertNetworkFromSettings(BMessage& message)
1315 {
1316 	message.RemoveName("mac");
1317 		// TODO: convert into a flat BNetworkAddress "address"
1318 
1319 	const char* authentication = NULL;
1320 	if (message.FindString("authentication", &authentication) == B_OK) {
1321 		message.RemoveName("authentication");
1322 
1323 		if (strcasecmp(authentication, "none") == 0) {
1324 			message.AddUInt32("authentication_mode",
1325 				B_NETWORK_AUTHENTICATION_NONE);
1326 		} else if (strcasecmp(authentication, "wep") == 0) {
1327 			message.AddUInt32("authentication_mode",
1328 				B_NETWORK_AUTHENTICATION_WEP);
1329 		} else if (strcasecmp(authentication, "wpa") == 0) {
1330 			message.AddUInt32("authentication_mode",
1331 				B_NETWORK_AUTHENTICATION_WPA);
1332 		} else if (strcasecmp(authentication, "wpa2") == 0) {
1333 			message.AddUInt32("authentication_mode",
1334 				B_NETWORK_AUTHENTICATION_WPA2);
1335 		}
1336 	}
1337 
1338 	int32 index = 0;
1339 	uint32 cipher = 0;
1340 	const char* cipherString = NULL;
1341 	while (message.FindString("cipher", index++, &cipherString) == B_OK) {
1342 		if (strcasecmp(cipherString, "none") == 0)
1343 			cipher |= B_NETWORK_CIPHER_NONE;
1344 		else if (strcasecmp(cipherString, "tkip") == 0)
1345 			cipher |= B_NETWORK_CIPHER_TKIP;
1346 		else if (strcasecmp(cipherString, "ccmp") == 0)
1347 			cipher |= B_NETWORK_CIPHER_CCMP;
1348 	}
1349 
1350 	message.RemoveName("cipher");
1351 	if (cipher != 0)
1352 		message.AddUInt32("cipher", cipher);
1353 
1354 	index = 0;
1355 	cipher = 0;
1356 	while (message.FindString("group_cipher", index++, &cipherString) == B_OK) {
1357 		if (strcasecmp(cipherString, "none") == 0)
1358 			cipher |= B_NETWORK_CIPHER_NONE;
1359 		else if (strcasecmp(cipherString, "wep40") == 0)
1360 			cipher |= B_NETWORK_CIPHER_WEP_40;
1361 		else if (strcasecmp(cipherString, "wep104") == 0)
1362 			cipher |= B_NETWORK_CIPHER_WEP_104;
1363 		else if (strcasecmp(cipherString, "tkip") == 0)
1364 			cipher |= B_NETWORK_CIPHER_TKIP;
1365 		else if (strcasecmp(cipherString, "ccmp") == 0)
1366 			cipher |= B_NETWORK_CIPHER_CCMP;
1367 	}
1368 
1369 	message.RemoveName("group_cipher");
1370 	if (cipher != 0)
1371 		message.AddUInt32("group_cipher", cipher);
1372 
1373 	message.AddUInt32("flags", B_NETWORK_IS_PERSISTENT);
1374 
1375 	// TODO: add the other fields
1376 	message.RemoveName("key");
1377 	return B_OK;
1378 }
1379 
1380 
1381 //	#pragma mark -
1382 
1383 
1384 int
1385 main(int argc, char** argv)
1386 {
1387 	status_t status;
1388 	NetServer server(status);
1389 	if (status != B_OK) {
1390 		fprintf(stderr, "net_server: Failed to create application: %s\n",
1391 			strerror(status));
1392 		return 1;
1393 	}
1394 
1395 	server.Run();
1396 	return 0;
1397 }
1398 
1399