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