xref: /haiku/src/servers/net/NetServer.cpp (revision ae5abb58266fba43b3479995388d13e92013e08f)
1 /*
2  * Copyright 2006-2019, 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 <strings.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 <NetworkSettings.h>
38 #include <Path.h>
39 #include <PathMonitor.h>
40 #include <Roster.h>
41 #include <Server.h>
42 #include <TextView.h>
43 #include <FindDirectory.h>
44 
45 #include <AutoDeleter.h>
46 #include <WPASupplicant.h>
47 
48 #include "AutoconfigLooper.h"
49 #include "Services.h"
50 
51 extern "C" {
52 #	include <freebsd_network/compat/sys/cdefs.h>
53 #	include <freebsd_network/compat/sys/ioccom.h>
54 #	include <net80211/ieee80211_ioctl.h>
55 }
56 
57 
58 using namespace BNetworkKit;
59 
60 
61 typedef std::map<std::string, AutoconfigLooper*> LooperMap;
62 
63 
64 class NetServer : public BServer {
65 public:
66 								NetServer(status_t& status);
67 	virtual						~NetServer();
68 
69 	virtual	void				ReadyToRun();
70 	virtual	void				MessageReceived(BMessage* message);
71 
72 private:
73 			bool				_IsValidFamily(uint32 family);
74 			bool				_IsValidInterface(BNetworkInterface& interface);
75 			void				_RemoveInvalidInterfaces();
76 			status_t			_RemoveInterface(const char* name);
77 			status_t			_DisableInterface(const char* name);
78 			bool				_TestForInterface(const char* name);
79 			status_t			_ConfigureInterface(BMessage& interface);
80 			status_t			_ConfigureResolver(
81 									BMessage& resolverConfiguration);
82 			bool				_QuitLooperForDevice(const char* device);
83 			AutoconfigLooper*	_LooperForDevice(const char* device);
84 			status_t			_ConfigureDevice(const char* path);
85 			void				_ConfigureDevices(const char* path,
86 									BStringList& devicesAlreadyConfigured,
87 									BMessage* suggestedInterface = NULL);
88 			void				_ConfigureInterfacesFromSettings(
89 									BStringList& devicesSet,
90 									BMessage* _missingDevice = NULL);
91 			void				_ConfigureIPv6LinkLocal(const char* name);
92 
93 			void				_BringUpInterfaces();
94 			void				_StartServices();
95 			status_t			_HandleDeviceMonitor(BMessage* message);
96 
97 			status_t			_AutoJoinNetwork(const BMessage& message);
98 			status_t			_JoinNetwork(const BMessage& message,
99 									const BNetworkAddress* address = NULL,
100 									const char* name = NULL);
101 			status_t			_LeaveNetwork(const BMessage& message);
102 
103 			status_t			_ConvertNetworkToSettings(BMessage& message);
104 			status_t			_ConvertNetworkFromSettings(BMessage& message);
105 
106 private:
107 			BNetworkSettings	fSettings;
108 			LooperMap			fDeviceMap;
109 			BMessenger			fServices;
110 };
111 
112 
113 // #pragma mark - private functions
114 
115 
116 static status_t
117 set_80211(const char* name, int32 type, void* data,
118 	int32 length = 0, int32 value = 0)
119 {
120 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
121 	if (socket < 0)
122 		return errno;
123 
124 	FileDescriptorCloser closer(socket);
125 
126 	struct ieee80211req ireq;
127 	strlcpy(ireq.i_name, name, IF_NAMESIZE);
128 	ireq.i_type = type;
129 	ireq.i_val = value;
130 	ireq.i_len = length;
131 	ireq.i_data = data;
132 
133 	if (ioctl(socket, SIOCS80211, &ireq, sizeof(struct ieee80211req)) < 0)
134 		return errno;
135 
136 	return B_OK;
137 }
138 
139 
140 //	#pragma mark -
141 
142 
143 NetServer::NetServer(status_t& error)
144 	:
145 	BServer(kNetServerSignature, false, &error)
146 {
147 }
148 
149 
150 NetServer::~NetServer()
151 {
152 	BPrivate::BPathMonitor::StopWatching("/dev/net", this);
153 }
154 
155 
156 void
157 NetServer::ReadyToRun()
158 {
159 	fSettings.StartMonitoring(this);
160 	_BringUpInterfaces();
161 	_StartServices();
162 
163 	BPrivate::BPathMonitor::StartWatching("/dev/net",
164 		B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this);
165 }
166 
167 
168 void
169 NetServer::MessageReceived(BMessage* message)
170 {
171 	switch (message->what) {
172 		case B_PATH_MONITOR:
173 		{
174 			fSettings.Update(message);
175 			_HandleDeviceMonitor(message);
176 			break;
177 		}
178 
179 		case BNetworkSettings::kMsgInterfaceSettingsUpdated:
180 		{
181 			BStringList devicesSet;
182 			_ConfigureInterfacesFromSettings(devicesSet);
183 			break;
184 		}
185 
186 		case BNetworkSettings::kMsgServiceSettingsUpdated:
187 		{
188 			BMessage update = fSettings.Services();
189 			update.what = kMsgUpdateServices;
190 
191 			fServices.SendMessage(&update);
192 			break;
193 		}
194 
195 		case kMsgConfigureInterface:
196 		{
197 			status_t status = _ConfigureInterface(*message);
198 
199 			BMessage reply(B_REPLY);
200 			reply.AddInt32("status", status);
201 			message->SendReply(&reply);
202 			break;
203 		}
204 
205 		case kMsgConfigureResolver:
206 		{
207 			status_t status = _ConfigureResolver(*message);
208 
209 			BMessage reply(B_REPLY);
210 			reply.AddInt32("status", status);
211 			message->SendReply(&reply);
212 			break;
213 		}
214 
215 		case kMsgJoinNetwork:
216 		{
217 			status_t status = _JoinNetwork(*message);
218 
219 			BMessage reply(B_REPLY);
220 			reply.AddInt32("status", status);
221 			message->SendReply(&reply);
222 			break;
223 		}
224 
225 		case kMsgLeaveNetwork:
226 		{
227 			status_t status = _LeaveNetwork(*message);
228 
229 			BMessage reply(B_REPLY);
230 			reply.AddInt32("status", status);
231 			message->SendReply(&reply);
232 			break;
233 		}
234 
235 		case kMsgAutoJoinNetwork:
236 		{
237 			_AutoJoinNetwork(*message);
238 			break;
239 		}
240 
241 		case kMsgCountPersistentNetworks:
242 		{
243 			BMessage reply(B_REPLY);
244 			reply.AddInt32("count", fSettings.CountNetworks());
245 			message->SendReply(&reply);
246 			break;
247 		}
248 
249 		case kMsgGetPersistentNetwork:
250 		{
251 			uint32 index = 0;
252 			status_t result = message->FindInt32("index", (int32*)&index);
253 
254 			BMessage reply(B_REPLY);
255 			if (result == B_OK) {
256 				BMessage network;
257 				result = fSettings.GetNextNetwork(index, network);
258 				if (result == B_OK)
259 					result = reply.AddMessage("network", &network);
260 			}
261 
262 			reply.AddInt32("status", result);
263 			message->SendReply(&reply);
264 			break;
265 		}
266 
267 		case kMsgAddPersistentNetwork:
268 		{
269 			BMessage network = *message;
270 			status_t result = fSettings.AddNetwork(network);
271 
272 			BMessage reply(B_REPLY);
273 			reply.AddInt32("status", result);
274 			message->SendReply(&reply);
275 			break;
276 		}
277 
278 		case kMsgRemovePersistentNetwork:
279 		{
280 			const char* networkName = NULL;
281 			status_t result = message->FindString("name", &networkName);
282 			if (result == B_OK)
283 				result = fSettings.RemoveNetwork(networkName);
284 
285 			BMessage reply(B_REPLY);
286 			reply.AddInt32("status", result);
287 			message->SendReply(&reply);
288 			break;
289 		}
290 
291 		case kMsgIsServiceRunning:
292 		{
293 			// Forward the message to the handler that can answer it
294 			BHandler* handler = fServices.Target(NULL);
295 			if (handler != NULL)
296 				handler->MessageReceived(message);
297 			break;
298 		}
299 
300 		default:
301 			BApplication::MessageReceived(message);
302 			return;
303 	}
304 }
305 
306 
307 /*!	Checks if provided address family is valid.
308 	Families include AF_INET, AF_INET6, AF_APPLETALK, etc
309 */
310 bool
311 NetServer::_IsValidFamily(uint32 family)
312 {
313 	// Mostly verifies add-on is present
314 	int socket = ::socket(family, SOCK_DGRAM, 0);
315 	if (socket < 0)
316 		return false;
317 
318 	close(socket);
319 	return true;
320 }
321 
322 
323 /*!	Checks if an interface is valid, that is, if it has an address in any
324 	family, and, in case of ethernet, a hardware MAC address.
325 */
326 bool
327 NetServer::_IsValidInterface(BNetworkInterface& interface)
328 {
329 	// check if it has an address
330 
331 	if (interface.CountAddresses() == 0)
332 		return false;
333 
334 	// check if it has a hardware address, too, in case of ethernet
335 
336 	BNetworkAddress link;
337 	if (interface.GetHardwareAddress(link) != B_OK)
338 		return false;
339 
340 	if (link.LinkLevelType() == IFT_ETHER && link.LinkLevelAddressLength() != 6)
341 		return false;
342 
343 	return true;
344 }
345 
346 
347 void
348 NetServer::_RemoveInvalidInterfaces()
349 {
350 	BNetworkRoster& roster = BNetworkRoster::Default();
351 	BNetworkInterface interface;
352 	uint32 cookie = 0;
353 
354 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
355 		if (!_IsValidInterface(interface)) {
356 			// remove invalid interface
357 			_RemoveInterface(interface.Name());
358 		}
359 	}
360 }
361 
362 
363 bool
364 NetServer::_TestForInterface(const char* name)
365 {
366 
367 	BNetworkRoster& roster = BNetworkRoster::Default();
368 	int32 nameLength = strlen(name);
369 	BNetworkInterface interface;
370 	uint32 cookie = 0;
371 
372 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
373 		if (!strncmp(interface.Name(), name, nameLength))
374 			return true;
375 	}
376 
377 	return false;
378 }
379 
380 
381 status_t
382 NetServer::_RemoveInterface(const char* name)
383 {
384 	BNetworkRoster& roster = BNetworkRoster::Default();
385 	status_t status = roster.RemoveInterface(name);
386 	if (status != B_OK) {
387 		fprintf(stderr, "%s: Could not delete interface %s: %s\n",
388 			Name(), name, strerror(status));
389 		return status;
390 	}
391 
392 	return B_OK;
393 }
394 
395 
396 status_t
397 NetServer::_DisableInterface(const char* name)
398 {
399 	BNetworkInterface interface(name);
400 	int32 flags = interface.Flags();
401 
402 	// Set interface down
403 	flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING);
404 
405 	status_t status = interface.SetFlags(flags);
406 	if (status != B_OK) {
407 		fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
408 			strerror(status));
409 		return status;
410 	}
411 
412 	fprintf(stderr, "%s: set %s interface down...\n", Name(), name);
413 	return B_OK;
414 }
415 
416 
417 status_t
418 NetServer::_ConfigureInterface(BMessage& message)
419 {
420 	const char* name;
421 	if (message.FindString("device", &name) != B_OK)
422 		return B_BAD_VALUE;
423 
424 	bool startAutoConfig = false;
425 
426 	int32 flags;
427 	if (message.FindInt32("flags", &flags) != B_OK)
428 		flags = IFF_UP;
429 
430 	bool autoConfigured;
431 	if (message.FindBool("auto_configured", &autoConfigured) == B_OK
432 			&& autoConfigured) {
433 		flags |= IFF_AUTO_CONFIGURED;
434 	}
435 
436 	int32 mtu;
437 	if (message.FindInt32("mtu", &mtu) != B_OK)
438 		mtu = -1;
439 
440 	int32 metric;
441 	if (message.FindInt32("metric", &metric) != B_OK)
442 		metric = -1;
443 
444 	BNetworkInterface interface(name);
445 	if (!interface.Exists()) {
446 		// the interface does not exist yet, we have to add it first
447 		BNetworkRoster& roster = BNetworkRoster::Default();
448 
449 		status_t status = roster.AddInterface(interface);
450 		if (status != B_OK) {
451 			fprintf(stderr, "%s: Could not add interface: %s\n",
452 				interface.Name(), strerror(status));
453 			return status;
454 		}
455 	}
456 
457 	// Set up IPv6 Link Local address (based on MAC, if not loopback)
458 
459 	// TODO: our IPv6 stack is still fairly fragile. We need more v6 work
460 	// (including IPv6 address scope flags before we start attaching link
461 	// local addresses by default.
462 	//_ConfigureIPv6LinkLocal(name);
463 
464 	BMessage addressMessage;
465 	for (int32 index = 0; message.FindMessage("address", index,
466 			&addressMessage) == B_OK; index++) {
467 		BNetworkInterfaceAddressSettings addressSettings(addressMessage);
468 
469 		if (addressSettings.IsAutoConfigure()) {
470 			_QuitLooperForDevice(name);
471 			startAutoConfig = true;
472 		} else if (!addressSettings.Gateway().IsEmpty()) {
473 			// add gateway route, if we're asked for it
474 			interface.RemoveDefaultRoute(addressSettings.Family());
475 				// Try to remove a previous default route, doesn't matter
476 				// if it fails.
477 
478 			status_t status = interface.AddDefaultRoute(
479 				addressSettings.Gateway());
480 			if (status != B_OK) {
481 				fprintf(stderr, "%s: Could not add route for %s: %s\n",
482 					Name(), name, strerror(errno));
483 			}
484 		}
485 
486 		// set address/mask/broadcast/peer
487 
488 		if (!addressSettings.Address().IsEmpty()
489 			|| !addressSettings.Mask().IsEmpty()
490 			|| !addressSettings.Broadcast().IsEmpty()
491 			|| !addressSettings.Peer().IsEmpty()
492 			|| !addressSettings.IsAutoConfigure()) {
493 			BNetworkInterfaceAddress interfaceAddress;
494 			interfaceAddress.SetAddress(addressSettings.Address());
495 			interfaceAddress.SetMask(addressSettings.Mask());
496 			if (!addressSettings.Broadcast().IsEmpty())
497 				interfaceAddress.SetBroadcast(addressSettings.Broadcast());
498 			else if (!addressSettings.Peer().IsEmpty())
499 				interfaceAddress.SetDestination(addressSettings.Peer());
500 
501 			status_t status = interface.SetAddress(interfaceAddress);
502 			if (status != B_OK) {
503 				fprintf(stderr, "%s: Setting address failed: %s\n", Name(),
504 					strerror(status));
505 				return status;
506 			}
507 		}
508 
509 		// set flags
510 
511 		if (flags != 0) {
512 			int32 newFlags = interface.Flags();
513 			newFlags = (newFlags & ~IFF_CONFIGURING) | flags;
514 			if (!autoConfigured)
515 				newFlags &= ~IFF_AUTO_CONFIGURED;
516 
517 			status_t status = interface.SetFlags(newFlags);
518 			if (status != B_OK) {
519 				fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
520 					strerror(status));
521 			}
522 		}
523 
524 		// set options
525 
526 		if (mtu != -1) {
527 			status_t status = interface.SetMTU(mtu);
528 			if (status != B_OK) {
529 				fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(),
530 					strerror(status));
531 			}
532 		}
533 
534 		if (metric != -1) {
535 			status_t status = interface.SetMetric(metric);
536 			if (status != B_OK) {
537 				fprintf(stderr, "%s: Setting metric failed: %s\n", Name(),
538 					strerror(status));
539 			}
540 		}
541 	}
542 
543 	// Join the specified networks
544 	BMessage networkMessage;
545 	for (int32 index = 0; message.FindMessage("network", index,
546 			&networkMessage) == B_OK; index++) {
547 		const char* networkName = message.GetString("name", NULL);
548 		const char* addressString = message.GetString("mac", NULL);
549 
550 		BNetworkAddress address;
551 		status_t addressStatus = address.SetTo(AF_LINK, addressString);
552 
553 		BNetworkDevice device(name);
554 		if (device.IsWireless() && !device.HasLink()) {
555 			status_t status = _JoinNetwork(message,
556 				addressStatus == B_OK ? &address : NULL, networkName);
557 			if (status != B_OK) {
558 				fprintf(stderr, "%s: joining network \"%s\" failed: %s\n",
559 					interface.Name(), networkName, strerror(status));
560 			}
561 		}
562 	}
563 
564 	if (startAutoConfig) {
565 		// start auto configuration
566 		AutoconfigLooper* looper = new AutoconfigLooper(this, name);
567 		looper->Run();
568 
569 		fDeviceMap[name] = looper;
570 	} else if (!autoConfigured)
571 		_QuitLooperForDevice(name);
572 
573 	return B_OK;
574 }
575 
576 
577 status_t
578 NetServer::_ConfigureResolver(BMessage& resolverConfiguration)
579 {
580 	// Store resolver settings in resolv.conf file, while maintaining any
581 	// user specified settings already present.
582 
583 	BPath path;
584 	if (find_directory(B_SYSTEM_SETTINGS_DIRECTORY, &path) != B_OK
585 		|| path.Append("network/resolv.conf") != B_OK)
586 		return B_ERROR;
587 
588 	FILE* file = fopen(path.Path(), "r+");
589 	// open existing resolv.conf if possible
590 	if (file == NULL) {
591 		// no existing resolv.conf, create a new one
592 		file = fopen(path.Path(), "w");
593 		if (file == NULL) {
594 			fprintf(stderr, "Could not open resolv.conf: %s\n",
595 				strerror(errno));
596 			return errno;
597 		}
598 	} else {
599 		// An existing resolv.conf was found, parse it for user settings
600 		const char* staticDNS = "# Static DNS Only";
601 		size_t sizeStaticDNS = strlen(staticDNS);
602 		const char* dynamicDNS = "# Dynamic DNS entries";
603 		size_t sizeDynamicDNS = strlen(dynamicDNS);
604 		char resolveConfBuffer[80];
605 		size_t sizeResolveConfBuffer = sizeof(resolveConfBuffer);
606 
607 		while (fgets(resolveConfBuffer, sizeResolveConfBuffer, file)) {
608 			if (strncmp(resolveConfBuffer, staticDNS, sizeStaticDNS) == 0) {
609 				// If DNS is set to static only, don't modify
610 				fclose(file);
611 				return B_OK;
612 			} else if (strncmp(resolveConfBuffer, dynamicDNS, sizeDynamicDNS)
613 					== 0) {
614 				// Overwrite existing dynamic entries
615 				break;
616 			}
617 		}
618 
619 		if (feof(file) != 0) {
620 			// No static entries found, close and re-open as new file
621 			fclose(file);
622 			file = fopen(path.Path(), "w");
623 			if (file == NULL) {
624 				fprintf(stderr, "Could not open resolv.conf: %s\n",
625 					strerror(errno));
626 				return errno;
627 			}
628 		}
629 	}
630 
631 	fprintf(file, "# Added automatically by DHCP\n");
632 
633 	const char* nameserver;
634 	for (int32 i = 0; resolverConfiguration.FindString("nameserver", i,
635 			&nameserver) == B_OK; i++) {
636 		fprintf(file, "nameserver %s\n", nameserver);
637 	}
638 
639 	const char* domain;
640 	if (resolverConfiguration.FindString("domain", &domain) == B_OK)
641 		fprintf(file, "domain %s\n", domain);
642 
643 	fprintf(file, "# End of automatic DHCP additions\n");
644 
645 	fclose(file);
646 
647 	return B_OK;
648 }
649 
650 
651 bool
652 NetServer::_QuitLooperForDevice(const char* device)
653 {
654 	LooperMap::iterator iterator = fDeviceMap.find(device);
655 	if (iterator == fDeviceMap.end())
656 		return false;
657 
658 	// there is a looper for this device - quit it
659 	if (iterator->second->Lock())
660 		iterator->second->Quit();
661 
662 	fDeviceMap.erase(iterator);
663 	return true;
664 }
665 
666 
667 AutoconfigLooper*
668 NetServer::_LooperForDevice(const char* device)
669 {
670 	LooperMap::const_iterator iterator = fDeviceMap.find(device);
671 	if (iterator == fDeviceMap.end())
672 		return NULL;
673 
674 	return iterator->second;
675 }
676 
677 
678 status_t
679 NetServer::_ConfigureDevice(const char* device)
680 {
681 	// bring interface up, but don't configure it just yet
682 	BMessage interface;
683 	interface.AddString("device", device);
684 	BMessage address;
685 	address.AddString("family", "inet");
686 	address.AddBool("auto_config", true);
687 	interface.AddMessage("address", &address);
688 
689 	return _ConfigureInterface(interface);
690 }
691 
692 
693 /*! \brief Traverses the device tree starting from \a startPath, and configures
694 		everything that has not yet been configured via settings before.
695 
696 	\param suggestedInterface Contains the configuration of an interface that
697 		does not have any hardware left. It is used to configure the first
698 		unconfigured device. This allows to move a Haiku configuration around
699 		without losing the network configuration.
700 */
701 void
702 NetServer::_ConfigureDevices(const char* startPath,
703 	BStringList& devicesAlreadyConfigured, BMessage* suggestedInterface)
704 {
705 	BDirectory directory(startPath);
706 	BEntry entry;
707 	while (directory.GetNextEntry(&entry) == B_OK) {
708 		char name[B_FILE_NAME_LENGTH];
709 		struct stat stat;
710 		BPath path;
711 		if (entry.GetName(name) != B_OK
712 			|| entry.GetPath(&path) != B_OK
713 			|| entry.GetStat(&stat) != B_OK
714 			|| devicesAlreadyConfigured.HasString(path.Path()))
715 			continue;
716 
717 		if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) {
718 			if (suggestedInterface != NULL
719 				&& suggestedInterface->SetString("device", path.Path()) == B_OK
720 				&& _ConfigureInterface(*suggestedInterface) == B_OK)
721 				suggestedInterface = NULL;
722 			else
723 				_ConfigureDevice(path.Path());
724 		} else if (entry.IsDirectory()) {
725 			_ConfigureDevices(path.Path(), devicesAlreadyConfigured,
726 				suggestedInterface);
727 		}
728 	}
729 }
730 
731 
732 void
733 NetServer::_ConfigureInterfacesFromSettings(BStringList& devicesSet,
734 	BMessage* _missingDevice)
735 {
736 	BMessage interface;
737 	uint32 cookie = 0;
738 	bool missing = false;
739 	while (fSettings.GetNextInterface(cookie, interface) == B_OK) {
740 		const char *device;
741 		if (interface.FindString("device", &device) != B_OK)
742 			continue;
743 
744 		bool disabled = false;
745 		if (interface.FindBool("disabled", &disabled) == B_OK && disabled) {
746 			// disabled by user request
747 			_DisableInterface(device);
748 			continue;
749 		}
750 
751 		if (!strncmp(device, "/dev/net/", 9)) {
752 			// it's a kernel device, check if it's present
753 			BEntry entry(device);
754 			if (!entry.Exists()) {
755 				if (!missing && _missingDevice != NULL) {
756 					*_missingDevice = interface;
757 					missing = true;
758 				}
759 				continue;
760 			}
761 		}
762 
763 		if (_ConfigureInterface(interface) == B_OK)
764 			devicesSet.Add(device);
765 	}
766 }
767 
768 
769 void
770 NetServer::_BringUpInterfaces()
771 {
772 	// we need a socket to talk to the networking stack
773 	if (!_IsValidFamily(AF_LINK)) {
774 		fprintf(stderr, "%s: The networking stack doesn't seem to be "
775 			"available.\n", Name());
776 		Quit();
777 		return;
778 	}
779 
780 	_RemoveInvalidInterfaces();
781 
782 	// First, we look into the settings, and try to bring everything up from
783 	// there
784 
785 	BStringList devicesAlreadyConfigured;
786 	BMessage missingDevice;
787 	_ConfigureInterfacesFromSettings(devicesAlreadyConfigured, &missingDevice);
788 
789 	// Check configuration
790 
791 	if (!_TestForInterface("loop")) {
792 		// there is no loopback interface, create one
793 		BMessage interface;
794 		interface.AddString("device", "loop");
795 		BMessage v4address;
796 		v4address.AddString("family", "inet");
797 		v4address.AddString("address", "127.0.0.1");
798 		interface.AddMessage("address", &v4address);
799 
800 		// Check for IPv6 support and add ::1
801 		if (_IsValidFamily(AF_INET6)) {
802 			BMessage v6address;
803 			v6address.AddString("family", "inet6");
804 			v6address.AddString("address", "::1");
805 			interface.AddMessage("address", &v6address);
806 		}
807 		_ConfigureInterface(interface);
808 	}
809 
810 	// TODO: also check if the networking driver is correctly initialized!
811 	//	(and check for other devices to take over its configuration)
812 
813 	// There is no driver configured - see if there is one and try to use it
814 	_ConfigureDevices("/dev/net", devicesAlreadyConfigured,
815 		missingDevice.HasString("device") ? &missingDevice : NULL);
816 }
817 
818 
819 /*!	Configure the link local address based on the network card's MAC address
820 	if this isn't a loopback device.
821 */
822 void
823 NetServer::_ConfigureIPv6LinkLocal(const char* name)
824 {
825 	// Check for IPv6 support
826 	if (!_IsValidFamily(AF_INET6))
827 		return;
828 
829 	BNetworkInterface interface(name);
830 
831 	// Lets make sure this is *not* the loopback interface
832 	if ((interface.Flags() & IFF_LOOPBACK) != 0)
833 		return;
834 
835 	BNetworkAddress link;
836 	status_t result = interface.GetHardwareAddress(link);
837 
838 	if (result != B_OK || link.LinkLevelAddressLength() != 6)
839 		return;
840 
841 	const uint8* mac = link.LinkLevelAddress();
842 
843 	// Check for a few failure situations
844 	static const uint8 zeroMac[6] = {0, 0, 0, 0, 0, 0};
845 	static const uint8 fullMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
846 	if (memcmp(mac, zeroMac, 6) == 0
847 		|| memcmp(mac, fullMac, 6) == 0) {
848 		// Mac address is all 0 or all FF's
849 		syslog(LOG_DEBUG, "%s: MacAddress for interface '%s' is invalid.",
850 			__func__, name);
851 		return;
852 	}
853 
854 	// Generate a Link Local Scope address
855 	// (IPv6 address based on Mac address)
856 	in6_addr addressRaw;
857 	memset(addressRaw.s6_addr, 0, sizeof(addressRaw.s6_addr));
858 	addressRaw.s6_addr[0] = 0xfe;
859 	addressRaw.s6_addr[1] = 0x80;
860 	addressRaw.s6_addr[8] = mac[0] ^ 0x02;
861 	addressRaw.s6_addr[9] = mac[1];
862 	addressRaw.s6_addr[10] = mac[2];
863 	addressRaw.s6_addr[11] = 0xff;
864 	addressRaw.s6_addr[12] = 0xfe;
865 	addressRaw.s6_addr[13] = mac[3];
866 	addressRaw.s6_addr[14] = mac[4];
867 	addressRaw.s6_addr[15] = mac[5];
868 
869 	BNetworkAddress localLinkAddress(addressRaw, 0);
870 	BNetworkAddress localLinkMask(
871 		AF_INET6,
872 		"ffff:ffff:ffff:ffff::", // 64
873 		(uint16)0,
874 		B_UNCONFIGURED_ADDRESS_FAMILIES);
875 	BNetworkAddress localLinkBroadcast(
876 		AF_INET6,
877 		"fe80::ffff:ffff:ffff:ffff",
878 		(uint16)0,
879 		B_UNCONFIGURED_ADDRESS_FAMILIES);
880 
881 	if (interface.FindAddress(localLinkAddress) >= 0) {
882 		// uhoh... already has a local link address
883 
884 		/*	TODO: Check for any local link scope addresses assigned to card
885 			There isn't any flag at the moment though for address scope
886 		*/
887 		syslog(LOG_DEBUG, "%s: Local Link address already assigned to %s\n",
888 			__func__, name);
889 		return;
890 	}
891 
892 	BNetworkInterfaceAddress interfaceAddress;
893 	interfaceAddress.SetAddress(localLinkAddress);
894 	interfaceAddress.SetMask(localLinkMask);
895 	interfaceAddress.SetBroadcast(localLinkMask);
896 
897 	/*	TODO: Duplicate Address Detection.  (DAD)
898 		Need to blast an icmp packet over the IPv6 network from :: to ensure
899 		there aren't duplicate MAC addresses on the network. (definitely an
900 		edge case, but a possible issue)
901 	*/
902 
903 	interface.AddAddress(interfaceAddress);
904 }
905 
906 
907 void
908 NetServer::_StartServices()
909 {
910 	BHandler* services = new (std::nothrow) Services(fSettings.Services());
911 	if (services != NULL) {
912 		AddHandler(services);
913 		fServices = BMessenger(services);
914 	}
915 }
916 
917 
918 status_t
919 NetServer::_HandleDeviceMonitor(BMessage* message)
920 {
921 	int32 opcode;
922 	const char* path;
923 	if (message->FindInt32("opcode", &opcode) != B_OK
924 		|| (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED)
925 		|| message->FindString("path", &path) != B_OK)
926 		return B_BAD_VALUE;
927 
928 	if (strncmp(path, "/dev/net/", 9)) {
929 		// not a valid device entry, ignore
930 		return B_NAME_NOT_FOUND;
931 	}
932 
933 	if (opcode == B_ENTRY_CREATED)
934 		_ConfigureDevice(path);
935 	else
936 		_RemoveInterface(path);
937 
938 	return B_OK;
939 }
940 
941 
942 status_t
943 NetServer::_AutoJoinNetwork(const BMessage& message)
944 {
945 	const char* name = NULL;
946 	if (message.FindString("device", &name) != B_OK)
947 		return B_BAD_VALUE;
948 
949 	BNetworkDevice device(name);
950 
951 	// Choose among configured networks
952 
953 	uint32 cookie = 0;
954 	BMessage networkMessage;
955 	while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) {
956 		status_t status = B_ERROR;
957 		wireless_network network;
958 		const char* networkName;
959 		BNetworkAddress link;
960 
961 		const char* mac = NULL;
962 		if (networkMessage.FindString("mac", &mac) == B_OK) {
963 			link.SetTo(AF_LINK, mac);
964 			status = device.GetNetwork(link, network);
965 		} else if (networkMessage.FindString("name", &networkName) == B_OK)
966 			status = device.GetNetwork(networkName, network);
967 
968 		if (status == B_OK) {
969 			status = _JoinNetwork(message, mac != NULL ? &link : NULL,
970 				network.name);
971 			printf("auto join network \"%s\": %s\n", network.name,
972 				strerror(status));
973 			if (status == B_OK)
974 				return B_OK;
975 		}
976 	}
977 
978 	return B_NO_INIT;
979 }
980 
981 
982 status_t
983 NetServer::_JoinNetwork(const BMessage& message, const BNetworkAddress* address,
984 	const char* name)
985 {
986 	const char* deviceName;
987 	if (message.FindString("device", &deviceName) != B_OK)
988 		return B_BAD_VALUE;
989 
990 	BNetworkAddress deviceAddress;
991 	message.FindFlat("address", &deviceAddress);
992 	if (address == NULL)
993 		address = &deviceAddress;
994 
995 	if (name == NULL)
996 		message.FindString("name", &name);
997 	if (name == NULL) {
998 		// No name specified, we need a network address
999 		if (address->Family() != AF_LINK)
1000 			return B_BAD_VALUE;
1001 	}
1002 
1003 	// Search for a network configuration that may override the defaults
1004 
1005 	bool found = false;
1006 	uint32 cookie = 0;
1007 	BMessage networkMessage;
1008 	while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) {
1009 		const char* networkName;
1010 		if (networkMessage.FindString("name", &networkName) == B_OK
1011 			&& name != NULL && address->Family() != AF_LINK
1012 			&& !strcmp(name, networkName)) {
1013 			found = true;
1014 			break;
1015 		}
1016 
1017 		const char* mac;
1018 		if (networkMessage.FindString("mac", &mac) == B_OK
1019 			&& address->Family() == AF_LINK) {
1020 			BNetworkAddress link(AF_LINK, mac);
1021 			if (link == *address) {
1022 				found = true;
1023 				break;
1024 			}
1025 		}
1026 	}
1027 
1028 	const char* password;
1029 	if (message.FindString("password", &password) != B_OK && found)
1030 		password = networkMessage.FindString("password");
1031 
1032 	// Get network
1033 	BNetworkDevice device(deviceName);
1034 	wireless_network network;
1035 
1036 	bool askForConfig = false;
1037 	if ((address->Family() != AF_LINK
1038 			|| device.GetNetwork(*address, network) != B_OK)
1039 		&& device.GetNetwork(name, network) != B_OK) {
1040 		// We did not find a network - just ignore that, and continue
1041 		// with some defaults
1042 		strlcpy(network.name, name != NULL ? name : "", sizeof(network.name));
1043 		network.address = *address;
1044 		network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE;
1045 		network.cipher = 0;
1046 		network.group_cipher = 0;
1047 		network.key_mode = 0;
1048 		askForConfig = true;
1049 	}
1050 
1051 	BString string;
1052 	if ((message.FindString("authentication", &string) == B_OK
1053 			&& !string.IsEmpty())
1054 		|| (found && networkMessage.FindString("authentication", &string)
1055 				== B_OK && !string.IsEmpty())) {
1056 		askForConfig = false;
1057 		if (string.ICompare("wpa2") == 0) {
1058 			network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2;
1059 			network.key_mode = B_KEY_MODE_IEEE802_1X;
1060 			network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP;
1061 		} else if (string.ICompare("wpa") == 0) {
1062 			network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA;
1063 			network.key_mode = B_KEY_MODE_IEEE802_1X;
1064 			network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP;
1065 		} else if (string.ICompare("wep") == 0) {
1066 			network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP;
1067 			network.key_mode = B_KEY_MODE_NONE;
1068 			network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40;
1069 		} else if (string.ICompare("none") != 0 && string.ICompare("open") != 0) {
1070 			fprintf(stderr, "%s: invalid authentication mode.\n", name);
1071 			askForConfig = true;
1072 		}
1073 	}
1074 
1075 	// We always try to join via the wpa_supplicant. Even if we could join
1076 	// ourselves, we need to make sure that the wpa_supplicant knows about
1077 	// our intention, as otherwise it would interfere with it.
1078 
1079 	BMessenger wpaSupplicant(kWPASupplicantSignature);
1080 	if (!wpaSupplicant.IsValid()) {
1081 		// The wpa_supplicant isn't running yet, we may join ourselves.
1082 		if (!askForConfig
1083 			&& network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) {
1084 			// We can join this network ourselves.
1085 			status_t status = set_80211(deviceName, IEEE80211_IOC_SSID,
1086 				network.name, strlen(network.name));
1087 			if (status != B_OK) {
1088 				fprintf(stderr, "%s: joining SSID failed: %s\n", name,
1089 					strerror(status));
1090 				return status;
1091 			}
1092 		}
1093 
1094 		// We need the supplicant, try to launch it.
1095 		status_t status = be_roster->Launch(kWPASupplicantSignature);
1096 		if (status != B_OK && status != B_ALREADY_RUNNING)
1097 			return status;
1098 
1099 		wpaSupplicant.SetTo(kWPASupplicantSignature);
1100 		if (!wpaSupplicant.IsValid())
1101 			return B_ERROR;
1102 	}
1103 
1104 	// TODO: listen to notifications from the supplicant!
1105 
1106 	BMessage join(kMsgWPAJoinNetwork);
1107 	status_t status = join.AddString("device", deviceName);
1108 	if (status == B_OK)
1109 		status = join.AddString("name", network.name);
1110 	if (status == B_OK)
1111 		status = join.AddFlat("address", &network.address);
1112 	if (status == B_OK && !askForConfig)
1113 		status = join.AddUInt32("authentication", network.authentication_mode);
1114 	if (status == B_OK && password != NULL)
1115 		status = join.AddString("password", password);
1116 	if (status != B_OK)
1117 		return status;
1118 
1119 	status = wpaSupplicant.SendMessage(&join);
1120 	if (status != B_OK)
1121 		return status;
1122 
1123 	return B_OK;
1124 }
1125 
1126 
1127 status_t
1128 NetServer::_LeaveNetwork(const BMessage& message)
1129 {
1130 	const char* deviceName;
1131 	if (message.FindString("device", &deviceName) != B_OK)
1132 		return B_BAD_VALUE;
1133 
1134 	int32 reason;
1135 	if (message.FindInt32("reason", &reason) != B_OK)
1136 		reason = IEEE80211_REASON_AUTH_LEAVE;
1137 
1138 	// We always try to send the leave request to the wpa_supplicant.
1139 
1140 	BMessenger wpaSupplicant(kWPASupplicantSignature);
1141 	if (wpaSupplicant.IsValid()) {
1142 		BMessage leave(kMsgWPALeaveNetwork);
1143 		status_t status = leave.AddString("device", deviceName);
1144 		if (status == B_OK)
1145 			status = leave.AddInt32("reason", reason);
1146 		if (status != B_OK)
1147 			return status;
1148 
1149 		status = wpaSupplicant.SendMessage(&leave);
1150 		if (status == B_OK)
1151 			return B_OK;
1152 	}
1153 
1154 	// The wpa_supplicant doesn't seem to be running, check if this was an open
1155 	// network we connected ourselves.
1156 	BNetworkDevice device(deviceName);
1157 	wireless_network network;
1158 
1159 	uint32 cookie = 0;
1160 	if (device.GetNextAssociatedNetwork(cookie, network) != B_OK
1161 		|| network.authentication_mode != B_NETWORK_AUTHENTICATION_NONE) {
1162 		// We didn't join ourselves, we can't do much.
1163 		return B_ERROR;
1164 	}
1165 
1166 	// We joined ourselves, so we can just disassociate again.
1167 	ieee80211req_mlme mlmeRequest;
1168 	memset(&mlmeRequest, 0, sizeof(mlmeRequest));
1169 	mlmeRequest.im_op = IEEE80211_MLME_DISASSOC;
1170 	mlmeRequest.im_reason = reason;
1171 
1172 	return set_80211(deviceName, IEEE80211_IOC_MLME, &mlmeRequest,
1173 		sizeof(mlmeRequest));
1174 }
1175 
1176 
1177 //	#pragma mark -
1178 
1179 
1180 int
1181 main(int argc, char** argv)
1182 {
1183 	srand(system_time());
1184 
1185 	status_t status;
1186 	NetServer server(status);
1187 	if (status != B_OK) {
1188 		fprintf(stderr, "net_server: Failed to create application: %s\n",
1189 			strerror(status));
1190 		return 1;
1191 	}
1192 
1193 	server.Run();
1194 	return 0;
1195 }
1196 
1197