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