xref: /haiku/src/servers/net/NetServer.cpp (revision e9c4d47ad719d6fd67cd9b75b41ebbec563e7a79)
1 /*
2  * Copyright 2006-2008, 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  */
8 
9 
10 #include "AutoconfigLooper.h"
11 #include "NetServer.h"
12 #include "Services.h"
13 #include "Settings.h"
14 
15 #include <Alert.h>
16 #include <Deskbar.h>
17 #include <Directory.h>
18 #include <Entry.h>
19 #include <Path.h>
20 #include <PathMonitor.h>
21 #include <Roster.h>
22 #include <Server.h>
23 #include <TextView.h>
24 
25 #include <arpa/inet.h>
26 #include <net/if_dl.h>
27 #include <net/if_types.h>
28 #include <netinet/in.h>
29 #include <sys/socket.h>
30 #include <sys/sockio.h>
31 
32 #include <map>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string>
37 #include <string.h>
38 #include <unistd.h>
39 
40 
41 static const char *kSignature = "application/x-vnd.haiku-net_server";
42 
43 
44 typedef std::map<std::string, BLooper*> LooperMap;
45 
46 
47 class NetServer : public BServer {
48 	public:
49 		NetServer(status_t& status);
50 
51 		virtual void AboutRequested();
52 		virtual void ReadyToRun();
53 		virtual void MessageReceived(BMessage* message);
54 
55 	private:
56 		bool _IsValidInterface(int socket, const char* name);
57 		void _RemoveInvalidInterfaces(int socket);
58 		bool _TestForInterface(int socket, const char* name);
59 		status_t _ConfigureInterface(int socket, BMessage& interface,
60 			bool fromMessage = false);
61 		bool _QuitLooperForDevice(const char* device);
62 		BLooper* _LooperForDevice(const char* device);
63 		status_t _ConfigureDevice(int socket, const char* path);
64 		void _ConfigureDevices(int socket, const char* path,
65 			BMessage* suggestedInterface = NULL);
66 		void _ConfigureInterfaces(int socket, BMessage* _missingDevice = NULL);
67 		void _BringUpInterfaces();
68 		void _StartServices();
69 
70 		Settings	fSettings;
71 		LooperMap	fDeviceMap;
72 		BMessenger	fServices;
73 };
74 
75 
76 struct address_family {
77 	int			family;
78 	const char*	name;
79 	const char*	identifiers[4];
80 	bool		(*parse_address)(const char* string, sockaddr* _address);
81 	void		(*set_any_address)(sockaddr* address);
82 	void		(*set_port)(sockaddr* address, int32 port);
83 };
84 
85 // AF_INET family
86 static bool inet_parse_address(const char* string, sockaddr* address);
87 static void inet_set_any_address(sockaddr* address);
88 static void inet_set_port(sockaddr* address, int32 port);
89 
90 static const address_family kFamilies[] = {
91 	{
92 		AF_INET,
93 		"inet",
94 		{"AF_INET", "inet", "ipv4", NULL},
95 		inet_parse_address,
96 		inet_set_any_address,
97 		inet_set_port
98 	},
99 	{ -1, NULL, {NULL}, NULL }
100 };
101 
102 
103 static bool
104 inet_parse_address(const char* string, sockaddr* _address)
105 {
106 	in_addr inetAddress;
107 
108 	if (inet_aton(string, &inetAddress) != 1)
109 		return false;
110 
111 	sockaddr_in& address = *(sockaddr_in *)_address;
112 	address.sin_family = AF_INET;
113 	address.sin_len = sizeof(struct sockaddr_in);
114 	address.sin_port = 0;
115 	address.sin_addr = inetAddress;
116 	memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
117 
118 	return true;
119 }
120 
121 
122 void
123 inet_set_any_address(sockaddr* _address)
124 {
125 	sockaddr_in& address = *(sockaddr_in*)_address;
126 	address.sin_family = AF_INET;
127 	address.sin_len = sizeof(struct sockaddr_in);
128 	address.sin_port = 0;
129 	address.sin_addr.s_addr = INADDR_ANY;
130 	memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
131 }
132 
133 
134 void
135 inet_set_port(sockaddr* _address, int32 port)
136 {
137 	sockaddr_in& address = *(sockaddr_in*)_address;
138 	address.sin_port = port;
139 }
140 
141 
142 //	#pragma mark -
143 
144 
145 bool
146 get_family_index(const char* name, int32& familyIndex)
147 {
148 	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
149 		for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
150 			if (!strcmp(name, kFamilies[i].identifiers[j])) {
151 				// found a match
152 				familyIndex = i;
153 				return true;
154 			}
155 		}
156 	}
157 
158 	// defaults to AF_INET
159 	familyIndex = 0;
160 	return false;
161 }
162 
163 
164 int
165 family_at_index(int32 index)
166 {
167 	return kFamilies[index].family;
168 }
169 
170 
171 bool
172 parse_address(int32 familyIndex, const char* argument, struct sockaddr& address)
173 {
174 	if (argument == NULL)
175 		return false;
176 
177 	return kFamilies[familyIndex].parse_address(argument, &address);
178 }
179 
180 
181 void
182 set_any_address(int32 familyIndex, struct sockaddr& address)
183 {
184 	kFamilies[familyIndex].set_any_address(&address);
185 }
186 
187 
188 void
189 set_port(int32 familyIndex, struct sockaddr& address, int32 port)
190 {
191 	kFamilies[familyIndex].set_port(&address, port);
192 }
193 
194 
195 bool
196 prepare_request(ifreq& request, const char* name)
197 {
198 	if (strlen(name) > IF_NAMESIZE)
199 		return false;
200 
201 	strcpy(request.ifr_name, name);
202 	return true;
203 }
204 
205 
206 status_t
207 get_mac_address(const char* device, uint8* address)
208 {
209 	int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
210 	if (socket < 0)
211 		return errno;
212 
213 	ifreq request;
214 	if (!prepare_request(request, device)) {
215 		close(socket);
216 		return B_ERROR;
217 	}
218 
219 	if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
220 		close(socket);
221 		return errno;
222 	}
223 
224 	close(socket);
225 
226 	sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
227 	if (link.sdl_type != IFT_ETHER)
228 		return B_BAD_TYPE;
229 
230 	if (link.sdl_alen == 0)
231 		return B_ENTRY_NOT_FOUND;
232 
233 	uint8 *mac = (uint8 *)LLADDR(&link);
234 	memcpy(address, mac, 6);
235 
236 	return B_OK;
237 }
238 
239 
240 //	#pragma mark -
241 
242 
243 NetServer::NetServer(status_t& error)
244 	: BServer(kSignature, false, &error)
245 {
246 }
247 
248 
249 void
250 NetServer::AboutRequested()
251 {
252 	BAlert *alert = new BAlert("about", "Networking Server\n"
253 		"\tCopyright " B_UTF8_COPYRIGHT "2006, Haiku.\n", "Ok");
254 	BTextView *view = alert->TextView();
255 	BFont font;
256 
257 	view->SetStylable(true);
258 
259 	view->GetFont(&font);
260 	font.SetSize(18);
261 	font.SetFace(B_BOLD_FACE);
262 	view->SetFontAndColor(0, 17, &font);
263 
264 	alert->Go(NULL);
265 }
266 
267 
268 void
269 NetServer::ReadyToRun()
270 {
271 	fSettings.StartMonitoring(this);
272 	_BringUpInterfaces();
273 	_StartServices();
274 }
275 
276 
277 void
278 NetServer::MessageReceived(BMessage* message)
279 {
280 	switch (message->what) {
281 		case B_PATH_MONITOR:
282 			fSettings.Update(message);
283 			break;
284 
285 		case kMsgInterfaceSettingsUpdated:
286 		{
287 			// we need a socket to talk to the networking stack
288 			int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
289 			if (socket < 0)
290 				break;
291 
292 			_ConfigureInterfaces(socket);
293 			close(socket);
294 			break;
295 		}
296 
297 		case kMsgServiceSettingsUpdated:
298 		{
299 			BMessage update = fSettings.Services();
300 			update.what = kMsgUpdateServices;
301 
302 			fServices.SendMessage(&update);
303 			break;
304 		}
305 
306 		case kMsgConfigureInterface:
307 		{
308 			if (!message->ReturnAddress().IsTargetLocal()) {
309 				// for now, we only accept this message from add-ons
310 				break;
311 			}
312 
313 			// we need a socket to talk to the networking stack
314 			int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
315 			if (socket < 0)
316 				break;
317 
318 			status_t status = _ConfigureInterface(socket, *message, true);
319 
320 			BMessage reply(B_REPLY);
321 			reply.AddInt32("status", status);
322 			message->SendReply(&reply);
323 
324 			close(socket);
325 			break;
326 		}
327 
328 		default:
329 			BApplication::MessageReceived(message);
330 			return;
331 	}
332 }
333 
334 
335 /*!
336 	Checks if an interface is valid, that is, if it has an address in any
337 	family, and, in case of ethernet, a hardware MAC address.
338 */
339 bool
340 NetServer::_IsValidInterface(int socket, const char* name)
341 {
342 	ifreq request;
343 	if (!prepare_request(request, name))
344 		return B_ERROR;
345 
346 	// check if it has an address
347 
348 	int32 addresses = 0;
349 
350 	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
351 		int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0);
352 		if (familySocket < 0)
353 			continue;
354 
355 		if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) {
356 			if (request.ifr_addr.sa_family == kFamilies[i].family)
357 				addresses++;
358 		}
359 
360 		close(familySocket);
361 	}
362 
363 	if (addresses == 0)
364 		return false;
365 
366 	// check if it has a hardware address, too, in case of ethernet
367 
368 	if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0)
369 		return false;
370 
371 	int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
372 	if (linkSocket < 0)
373 		return false;
374 
375 	prepare_request(request, request.ifr_parameter.device);
376 	if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
377 		close(linkSocket);
378 		return false;
379 	}
380 
381 	close(linkSocket);
382 
383 	sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
384 	if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6)
385 		return false;
386 
387 	return true;
388 }
389 
390 
391 void
392 NetServer::_RemoveInvalidInterfaces(int socket)
393 {
394 	// get a list of all interfaces
395 
396 	ifconf config;
397 	config.ifc_len = sizeof(config.ifc_value);
398 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
399 		return;
400 
401 	uint32 count = (uint32)config.ifc_value;
402 	if (count == 0) {
403 		// there are no interfaces yet
404 		return;
405 	}
406 
407 	void *buffer = malloc(count * sizeof(struct ifreq));
408 	if (buffer == NULL) {
409 		fprintf(stderr, "%s: Out of memory.\n", Name());
410 		return;
411 	}
412 
413 	config.ifc_len = count * sizeof(struct ifreq);
414 	config.ifc_buf = buffer;
415 	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
416 		return;
417 
418 	ifreq *interface = (ifreq *)buffer;
419 
420 	for (uint32 i = 0; i < count; i++) {
421 		if (!_IsValidInterface(socket, interface->ifr_name)) {
422 			// remove invalid interface
423 			ifreq request;
424 			if (!prepare_request(request, interface->ifr_name))
425 				return;
426 
427 			if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
428 				fprintf(stderr, "%s: Could not delete interface %s: %s\n",
429 					Name(), interface->ifr_name, strerror(errno));
430 			}
431 		}
432 
433 		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len);
434 	}
435 
436 	free(buffer);
437 }
438 
439 
440 bool
441 NetServer::_TestForInterface(int socket, const char* name)
442 {
443 	// get a list of all interfaces
444 
445 	ifconf config;
446 	config.ifc_len = sizeof(config.ifc_value);
447 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
448 		return false;
449 
450 	uint32 count = (uint32)config.ifc_value;
451 	if (count == 0) {
452 		// there are no interfaces yet
453 		return false;
454 	}
455 
456 	void *buffer = malloc(count * sizeof(struct ifreq));
457 	if (buffer == NULL) {
458 		fprintf(stderr, "%s: Out of memory.\n", Name());
459 		return false;
460 	}
461 
462 	config.ifc_len = count * sizeof(struct ifreq);
463 	config.ifc_buf = buffer;
464 	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
465 		return false;
466 
467 	ifreq *interface = (ifreq *)buffer;
468 	int32 nameLength = strlen(name);
469 	bool success = false;
470 
471 	for (uint32 i = 0; i < count; i++) {
472 		if (!strncmp(interface->ifr_name, name, nameLength)) {
473 			success = true;
474 			break;
475 		}
476 
477 		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len);
478 	}
479 
480 	free(buffer);
481 	return success;
482 }
483 
484 
485 status_t
486 NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage)
487 {
488 	const char *device;
489 	if (interface.FindString("device", &device) != B_OK)
490 		return B_BAD_VALUE;
491 
492 	ifreq request;
493 	if (!prepare_request(request, device))
494 		return B_ERROR;
495 
496 	bool startAutoConfig = false;
497 
498 	int32 flags;
499 	if (interface.FindInt32("flags", &flags) < B_OK)
500 		flags = IFF_UP;
501 
502 	bool autoConfigured;
503 	if (interface.FindBool("auto", &autoConfigured) == B_OK && autoConfigured)
504 		flags |= IFF_AUTO_CONFIGURED;
505 
506 	int32 mtu;
507 	if (interface.FindInt32("mtu", &mtu) < B_OK)
508 		mtu = -1;
509 
510 	int32 metric;
511 	if (interface.FindInt32("metric", &metric) < B_OK)
512 		metric = -1;
513 
514 	BMessage addressMessage;
515 	for (int32 index = 0; interface.FindMessage("address", index, &addressMessage) == B_OK;
516 			index++) {
517 		const char* family;
518 		if (addressMessage.FindString("family", &family) < B_OK)
519 			continue;
520 
521 		int32 familyIndex;
522 		if (!get_family_index(family, familyIndex)) {
523 			// we don't support this family
524 			continue;
525 		}
526 
527 		int familySocket = socket;
528 		if (family_at_index(familyIndex) != AF_INET)
529 			socket = ::socket(family_at_index(familyIndex), SOCK_DGRAM, 0);
530 		if (socket < 0) {
531 			// the family is not available in this environment
532 			continue;
533 		}
534 
535 		uint32 interfaceIndex = 0;
536 		if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0)
537 			interfaceIndex = request.ifr_index;
538 
539 		if (interfaceIndex == 0) {
540 			// we need to create the interface first
541 			request.ifr_parameter.base_name[0] = '\0';
542 			request.ifr_parameter.device[0] = '\0';
543 			request.ifr_parameter.sub_type = 0;
544 				// the default device is okay for us
545 
546 			if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
547 				fprintf(stderr, "%s: Could not add interface: %s\n", Name(),
548 					strerror(errno));
549 				return errno;
550 			}
551 		}
552 
553 		// retrieve addresses
554 
555 		bool autoConfig;
556 		if (addressMessage.FindBool("auto config", &autoConfig) != B_OK)
557 			autoConfig = false;
558 		if (autoConfig && fromMessage) {
559 			// we don't accept auto-config messages this way
560 			continue;
561 		}
562 
563 		bool hasAddress = false, hasMask = false, hasPeer = false, hasBroadcast = false;
564 		struct sockaddr address, mask, peer, broadcast, gateway;
565 		const char* string;
566 
567 		if (!autoConfig) {
568 			if (addressMessage.FindString("address", &string) == B_OK
569 				&& parse_address(familyIndex, string, address)) {
570 				hasAddress = true;
571 
572 				if (addressMessage.FindString("mask", &string) == B_OK
573 					&& parse_address(familyIndex, string, mask))
574 					hasMask = true;
575 			}
576 			if (addressMessage.FindString("peer", &string) == B_OK
577 				&& parse_address(familyIndex, string, peer))
578 				hasPeer = true;
579 			if (addressMessage.FindString("broadcast", &string) == B_OK
580 				&& parse_address(familyIndex, string, broadcast))
581 				hasBroadcast = true;
582 		}
583 
584 		route_entry route;
585 		memset(&route, 0, sizeof(route_entry));
586 		route.flags = RTF_STATIC | RTF_DEFAULT;
587 
588 		request.ifr_route = route;
589 
590 		if (autoConfig) {
591 			// add a default route to make the interface accessible, even without an address
592 			if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
593 				fprintf(stderr, "%s: Could not add route for %s: %s\n",
594 					Name(), device, strerror(errno));
595 			} else {
596 				_QuitLooperForDevice(device);
597 				startAutoConfig = true;
598 			}
599 		} else if (addressMessage.FindString("gateway", &string) == B_OK
600 			&& parse_address(familyIndex, string, gateway)) {
601 			// add gateway route, if we're asked for it
602 
603 			ioctl(socket, SIOCDELRT, &request, sizeof(request));
604 				// Try to remove a previous default route, doesn't matter
605 				// if it fails.
606 
607 			route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY;
608 			route.gateway = &gateway;
609 
610 			request.ifr_route = route;
611 			if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
612 				fprintf(stderr, "%s: Could not add route for %s: %s\n",
613 					Name(), device, strerror(errno));
614 			}
615 		}
616 
617 		// set addresses
618 
619 		if (hasAddress) {
620 			memcpy(&request.ifr_addr, &address, address.sa_len);
621 
622 			if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) {
623 				fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno));
624 				continue;
625 			}
626 		}
627 
628 		if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
629 			fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno));
630 			continue;
631 		}
632 		int32 currentFlags = request.ifr_flags;
633 
634 		if (hasMask) {
635 			memcpy(&request.ifr_mask, &mask, mask.sa_len);
636 
637 			if (ioctl(familySocket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) {
638 				fprintf(stderr, "%s: Setting subnet mask failed: %s\n", Name(), strerror(errno));
639 				continue;
640 			}
641 		}
642 
643 		if (hasBroadcast) {
644 			memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len);
645 
646 			if (ioctl(familySocket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) {
647 				fprintf(stderr, "%s: Setting broadcast address failed: %s\n", Name(), strerror(errno));
648 				continue;
649 			}
650 		}
651 
652 		if (hasPeer) {
653 			memcpy(&request.ifr_dstaddr, &peer, peer.sa_len);
654 
655 			if (ioctl(familySocket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) {
656 				fprintf(stderr, "%s: Setting peer address failed: %s\n", Name(), strerror(errno));
657 				continue;
658 			}
659 		}
660 
661 		// set flags
662 
663 		if (flags != 0) {
664 			request.ifr_flags = currentFlags | flags;
665 			if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0)
666 				fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno));
667 		}
668 
669 		// set options
670 
671 		if (mtu != -1) {
672 			request.ifr_mtu = mtu;
673 			if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0)
674 				fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno));
675 		}
676 
677 		if (metric != -1) {
678 			request.ifr_metric = metric;
679 			if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0)
680 				fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno));
681 		}
682 	}
683 
684 	if (startAutoConfig) {
685 		// start auto configuration
686 		AutoconfigLooper* looper = new AutoconfigLooper(this, device);
687 		looper->Run();
688 
689 		fDeviceMap[device] = looper;
690 	}
691 
692 	return B_OK;
693 }
694 
695 
696 bool
697 NetServer::_QuitLooperForDevice(const char* device)
698 {
699 	LooperMap::iterator iterator = fDeviceMap.find(device);
700 	if (iterator == fDeviceMap.end())
701 		return false;
702 
703 	// there is a looper for this device - quit it
704 	iterator->second->Lock();
705 	iterator->second->Quit();
706 
707 	fDeviceMap.erase(iterator);
708 	return true;
709 }
710 
711 
712 BLooper*
713 NetServer::_LooperForDevice(const char* device)
714 {
715 	LooperMap::const_iterator iterator = fDeviceMap.find(device);
716 	if (iterator == fDeviceMap.end())
717 		return NULL;
718 
719 	return iterator->second;
720 }
721 
722 
723 status_t
724 NetServer::_ConfigureDevice(int socket, const char* path)
725 {
726 	// bring interface up, but don't configure it just yet
727 	BMessage interface;
728 	interface.AddString("device", path);
729 	BMessage address;
730 	address.AddString("family", "inet");
731 	address.AddBool("auto config", true);
732 	interface.AddMessage("address", &address);
733 
734 	return _ConfigureInterface(socket, interface);
735 }
736 
737 
738 void
739 NetServer::_ConfigureDevices(int socket, const char* startPath,
740 	BMessage* suggestedInterface)
741 {
742 	BDirectory directory(startPath);
743 	BEntry entry;
744 	while (directory.GetNextEntry(&entry) == B_OK) {
745 		char name[B_FILE_NAME_LENGTH];
746 		struct stat stat;
747 		BPath path;
748 		if (entry.GetName(name) != B_OK
749 			|| !strcmp(name, "stack")
750 			|| entry.GetPath(&path) != B_OK
751 			|| entry.GetStat(&stat) != B_OK)
752 			continue;
753 
754 		if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) {
755 			if (suggestedInterface != NULL
756 				&& suggestedInterface->RemoveName("device") == B_OK
757 				&& suggestedInterface->AddString("device", path.Path()) == B_OK
758 				&& _ConfigureInterface(socket, *suggestedInterface) == B_OK)
759 				suggestedInterface = NULL;
760 			else
761 				_ConfigureDevice(socket, path.Path());
762 		} else if (entry.IsDirectory())
763 			_ConfigureDevices(socket, path.Path(), suggestedInterface);
764 	}
765 }
766 
767 
768 void
769 NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
770 {
771 	BMessage interface;
772 	uint32 cookie = 0;
773 	bool missing = false;
774 	while (fSettings.GetNextInterface(cookie, interface) == B_OK) {
775 		const char *device;
776 		if (interface.FindString("device", &device) != B_OK)
777 			continue;
778 
779 		if (!strncmp(device, "/dev/net/", 9)) {
780 			// it's a kernel device, check if it's present
781 			BEntry entry(device);
782 			if (!entry.Exists()) {
783 				if (!missing && _missingDevice != NULL) {
784 					*_missingDevice = interface;
785 					missing = true;
786 				}
787 				continue;
788 			}
789 		}
790 
791 		_ConfigureInterface(socket, interface);
792 	}
793 }
794 
795 
796 void
797 NetServer::_BringUpInterfaces()
798 {
799 	// we need a socket to talk to the networking stack
800 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
801 	if (socket < 0) {
802 		fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n",
803 			Name());
804 		Quit();
805 		return;
806 	}
807 
808 	_RemoveInvalidInterfaces(socket);
809 
810 	// First, we look into the settings, and try to bring everything up from there
811 
812 	BMessage missingDevice;
813 	_ConfigureInterfaces(socket, &missingDevice);
814 
815 	// check configuration
816 
817 	if (!_TestForInterface(socket, "loop")) {
818 		// there is no loopback interface, create one
819 		BMessage interface;
820 		interface.AddString("device", "loop");
821 		BMessage address;
822 		address.AddString("family", "inet");
823 		address.AddString("address", "127.0.0.1");
824 		interface.AddMessage("address", &address);
825 
826 		_ConfigureInterface(socket, interface);
827 	}
828 
829 	// TODO: also check if the networking driver is correctly initialized!
830 	//	(and check for other devices to take over its configuration)
831 
832 	if (!_TestForInterface(socket, "/dev/net/")) {
833 		// there is no driver configured - see if there is one and try to use it
834 		_ConfigureDevices(socket, "/dev/net",
835 			missingDevice.HasString("device") ? &missingDevice : NULL);
836 	}
837 
838 	close(socket);
839 }
840 
841 
842 void
843 NetServer::_StartServices()
844 {
845 	BHandler* services = new (std::nothrow) Services(fSettings.Services());
846 	if (services != NULL) {
847 		AddHandler(services);
848 		fServices = BMessenger(services);
849 	}
850 }
851 
852 
853 //	#pragma mark -
854 
855 
856 int
857 main()
858 {
859 	status_t status;
860 	NetServer server(status);
861 	if (status != B_OK) {
862 		fprintf(stderr, "net_server: Failed to create application: %s\n",
863 			strerror(status));
864 		return 1;
865 	}
866 
867 	server.Run();
868 	return 0;
869 }
870 
871