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