xref: /haiku/src/servers/net/NetServer.cpp (revision 03187b607b2b5eec7ee059f1ead09bdba14991fb)
1 /*
2  * Copyright 2006-2009, 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 "NetServer.h"
11 
12 #include <errno.h>
13 #include <map>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string>
17 #include <string.h>
18 #include <unistd.h>
19 
20 #include <arpa/inet.h>
21 #include <net/if_dl.h>
22 #include <net/if_types.h>
23 #include <netinet/in.h>
24 #include <sys/socket.h>
25 #include <sys/sockio.h>
26 
27 #include <Alert.h>
28 #include <Deskbar.h>
29 #include <Directory.h>
30 #include <Entry.h>
31 #include <Path.h>
32 #include <PathMonitor.h>
33 #include <Roster.h>
34 #include <Server.h>
35 #include <TextView.h>
36 
37 #include "AutoconfigLooper.h"
38 #include "Services.h"
39 #include "Settings.h"
40 
41 
42 typedef std::map<std::string, AutoconfigLooper*> LooperMap;
43 
44 
45 class NetServer : public BServer {
46 	public:
47 		NetServer(status_t& status);
48 
49 		virtual void AboutRequested();
50 		virtual void ReadyToRun();
51 		virtual void MessageReceived(BMessage* message);
52 
53 	private:
54 		bool _IsValidInterface(int socket, const char* name);
55 		void _RemoveInvalidInterfaces(int socket);
56 		bool _TestForInterface(int socket, const char* name);
57 		status_t _ConfigureInterface(int socket, BMessage& interface,
58 			bool fromMessage = false);
59 		bool _QuitLooperForDevice(const char* device);
60 		AutoconfigLooper* _LooperForDevice(const char* device);
61 		status_t _ConfigureDevice(int socket, const char* path);
62 		void _ConfigureDevices(int socket, const char* path,
63 			BMessage* suggestedInterface = NULL);
64 		void _ConfigureInterfaces(int socket, BMessage* _missingDevice = NULL);
65 		void _BringUpInterfaces();
66 		void _StartServices();
67 
68 		Settings	fSettings;
69 		LooperMap	fDeviceMap;
70 		BMessenger	fServices;
71 };
72 
73 
74 struct address_family {
75 	int			family;
76 	const char*	name;
77 	const char*	identifiers[4];
78 	bool		(*parse_address)(const char* string, sockaddr* _address);
79 	void		(*set_any_address)(sockaddr* address);
80 	void		(*set_port)(sockaddr* address, int32 port);
81 };
82 
83 
84 // AF_INET family
85 static bool inet_parse_address(const char* string, sockaddr* address);
86 static void inet_set_any_address(sockaddr* address);
87 static void inet_set_port(sockaddr* address, int32 port);
88 
89 static const address_family kFamilies[] = {
90 	{
91 		AF_INET,
92 		"inet",
93 		{"AF_INET", "inet", "ipv4", NULL},
94 		inet_parse_address,
95 		inet_set_any_address,
96 		inet_set_port
97 	},
98 	{ -1, NULL, {NULL}, NULL }
99 };
100 
101 
102 static bool
103 inet_parse_address(const char* string, sockaddr* _address)
104 {
105 	in_addr inetAddress;
106 
107 	if (inet_aton(string, &inetAddress) != 1)
108 		return false;
109 
110 	sockaddr_in& address = *(sockaddr_in *)_address;
111 	address.sin_family = AF_INET;
112 	address.sin_len = sizeof(struct sockaddr_in);
113 	address.sin_port = 0;
114 	address.sin_addr = inetAddress;
115 	memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
116 
117 	return true;
118 }
119 
120 
121 void
122 inet_set_any_address(sockaddr* _address)
123 {
124 	sockaddr_in& address = *(sockaddr_in*)_address;
125 	address.sin_family = AF_INET;
126 	address.sin_len = sizeof(struct sockaddr_in);
127 	address.sin_port = 0;
128 	address.sin_addr.s_addr = INADDR_ANY;
129 	memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
130 }
131 
132 
133 void
134 inet_set_port(sockaddr* _address, int32 port)
135 {
136 	sockaddr_in& address = *(sockaddr_in*)_address;
137 	address.sin_port = port;
138 }
139 
140 
141 //	#pragma mark -
142 
143 
144 bool
145 get_family_index(const char* name, int32& familyIndex)
146 {
147 	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
148 		for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
149 			if (!strcmp(name, kFamilies[i].identifiers[j])) {
150 				// found a match
151 				familyIndex = i;
152 				return true;
153 			}
154 		}
155 	}
156 
157 	// defaults to AF_INET
158 	familyIndex = 0;
159 	return false;
160 }
161 
162 
163 int
164 family_at_index(int32 index)
165 {
166 	return kFamilies[index].family;
167 }
168 
169 
170 bool
171 parse_address(int32 familyIndex, const char* argument, struct sockaddr& address)
172 {
173 	if (argument == NULL)
174 		return false;
175 
176 	return kFamilies[familyIndex].parse_address(argument, &address);
177 }
178 
179 
180 void
181 set_any_address(int32 familyIndex, struct sockaddr& address)
182 {
183 	kFamilies[familyIndex].set_any_address(&address);
184 }
185 
186 
187 void
188 set_port(int32 familyIndex, struct sockaddr& address, int32 port)
189 {
190 	kFamilies[familyIndex].set_port(&address, port);
191 }
192 
193 
194 bool
195 prepare_request(ifreq& request, const char* name)
196 {
197 	if (strlen(name) > IF_NAMESIZE)
198 		return false;
199 
200 	strcpy(request.ifr_name, name);
201 	return true;
202 }
203 
204 
205 status_t
206 get_mac_address(const char* device, uint8* address)
207 {
208 	int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
209 	if (socket < 0)
210 		return errno;
211 
212 	ifreq request;
213 	if (!prepare_request(request, device)) {
214 		close(socket);
215 		return B_ERROR;
216 	}
217 
218 	if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
219 		close(socket);
220 		return errno;
221 	}
222 
223 	close(socket);
224 
225 	sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
226 	if (link.sdl_type != IFT_ETHER)
227 		return B_BAD_TYPE;
228 
229 	if (link.sdl_alen == 0)
230 		return B_ENTRY_NOT_FOUND;
231 
232 	uint8 *mac = (uint8 *)LLADDR(&link);
233 	memcpy(address, mac, 6);
234 
235 	return B_OK;
236 }
237 
238 
239 //	#pragma mark -
240 
241 
242 NetServer::NetServer(status_t& error)
243 	: BServer(kNetServerSignature, false, &error)
244 {
245 }
246 
247 
248 void
249 NetServer::AboutRequested()
250 {
251 	BAlert *alert = new BAlert("about", "Networking Server\n"
252 		"\tCopyright " B_UTF8_COPYRIGHT "2006, Haiku.\n", "Ok");
253 	BTextView *view = alert->TextView();
254 	BFont font;
255 
256 	view->SetStylable(true);
257 
258 	view->GetFont(&font);
259 	font.SetSize(18);
260 	font.SetFace(B_BOLD_FACE);
261 	view->SetFontAndColor(0, 17, &font);
262 
263 	alert->Go(NULL);
264 }
265 
266 
267 void
268 NetServer::ReadyToRun()
269 {
270 	fSettings.StartMonitoring(this);
271 	_BringUpInterfaces();
272 	_StartServices();
273 }
274 
275 
276 void
277 NetServer::MessageReceived(BMessage* message)
278 {
279 	switch (message->what) {
280 		case B_PATH_MONITOR:
281 			fSettings.Update(message);
282 			break;
283 
284 		case kMsgInterfaceSettingsUpdated:
285 		{
286 			// we need a socket to talk to the networking stack
287 			int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
288 			if (socket < 0)
289 				break;
290 
291 			_ConfigureInterfaces(socket);
292 			close(socket);
293 			break;
294 		}
295 
296 		case kMsgServiceSettingsUpdated:
297 		{
298 			BMessage update = fSettings.Services();
299 			update.what = kMsgUpdateServices;
300 
301 			fServices.SendMessage(&update);
302 			break;
303 		}
304 
305 		case kMsgConfigureInterface:
306 		{
307 #if 0
308 			if (!message->ReturnAddress().IsTargetLocal()) {
309 				// for now, we only accept this message from add-ons
310 				break;
311 			}
312 #endif
313 
314 			// we need a socket to talk to the networking stack
315 			int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
316 			if (socket < 0)
317 				break;
318 
319 			status_t status = _ConfigureInterface(socket, *message, true);
320 
321 			BMessage reply(B_REPLY);
322 			reply.AddInt32("status", status);
323 			message->SendReply(&reply);
324 
325 			close(socket);
326 			break;
327 		}
328 
329 		default:
330 			BApplication::MessageReceived(message);
331 			return;
332 	}
333 }
334 
335 
336 /*!
337 	Checks if an interface is valid, that is, if it has an address in any
338 	family, and, in case of ethernet, a hardware MAC address.
339 */
340 bool
341 NetServer::_IsValidInterface(int socket, const char* name)
342 {
343 	ifreq request;
344 	if (!prepare_request(request, name))
345 		return B_ERROR;
346 
347 	// check if it has an address
348 
349 	int32 addresses = 0;
350 
351 	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
352 		int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0);
353 		if (familySocket < 0)
354 			continue;
355 
356 		if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) {
357 			if (request.ifr_addr.sa_family == kFamilies[i].family)
358 				addresses++;
359 		}
360 
361 		close(familySocket);
362 	}
363 
364 	if (addresses == 0)
365 		return false;
366 
367 	// check if it has a hardware address, too, in case of ethernet
368 
369 	if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0)
370 		return false;
371 
372 	int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
373 	if (linkSocket < 0)
374 		return false;
375 
376 	prepare_request(request, request.ifr_parameter.device);
377 	if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
378 		close(linkSocket);
379 		return false;
380 	}
381 
382 	close(linkSocket);
383 
384 	sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
385 	if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6)
386 		return false;
387 
388 	return true;
389 }
390 
391 
392 void
393 NetServer::_RemoveInvalidInterfaces(int socket)
394 {
395 	// get a list of all interfaces
396 
397 	ifconf config;
398 	config.ifc_len = sizeof(config.ifc_value);
399 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
400 		return;
401 
402 	uint32 count = (uint32)config.ifc_value;
403 	if (count == 0) {
404 		// there are no interfaces yet
405 		return;
406 	}
407 
408 	void *buffer = malloc(count * sizeof(struct ifreq));
409 	if (buffer == NULL) {
410 		fprintf(stderr, "%s: Out of memory.\n", Name());
411 		return;
412 	}
413 
414 	config.ifc_len = count * sizeof(struct ifreq);
415 	config.ifc_buf = buffer;
416 	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
417 		return;
418 
419 	ifreq *interface = (ifreq *)buffer;
420 
421 	for (uint32 i = 0; i < count; i++) {
422 		if (!_IsValidInterface(socket, interface->ifr_name)) {
423 			// remove invalid interface
424 			ifreq request;
425 			if (!prepare_request(request, interface->ifr_name))
426 				return;
427 
428 			if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
429 				fprintf(stderr, "%s: Could not delete interface %s: %s\n",
430 					Name(), interface->ifr_name, strerror(errno));
431 			}
432 		}
433 
434 		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len);
435 	}
436 
437 	free(buffer);
438 }
439 
440 
441 bool
442 NetServer::_TestForInterface(int socket, const char* name)
443 {
444 	// get a list of all interfaces
445 
446 	ifconf config;
447 	config.ifc_len = sizeof(config.ifc_value);
448 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
449 		return false;
450 
451 	uint32 count = (uint32)config.ifc_value;
452 	if (count == 0) {
453 		// there are no interfaces yet
454 		return false;
455 	}
456 
457 	void *buffer = malloc(count * sizeof(struct ifreq));
458 	if (buffer == NULL) {
459 		fprintf(stderr, "%s: Out of memory.\n", Name());
460 		return false;
461 	}
462 
463 	config.ifc_len = count * sizeof(struct ifreq);
464 	config.ifc_buf = buffer;
465 	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
466 		return false;
467 
468 	ifreq *interface = (ifreq *)buffer;
469 	int32 nameLength = strlen(name);
470 	bool success = false;
471 
472 	for (uint32 i = 0; i < count; i++) {
473 		if (!strncmp(interface->ifr_name, name, nameLength)) {
474 			success = true;
475 			break;
476 		}
477 
478 		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
479 			+ interface->ifr_addr.sa_len);
480 	}
481 
482 	free(buffer);
483 	return success;
484 }
485 
486 
487 status_t
488 NetServer::_ConfigureInterface(int socket, BMessage& interface,
489 	bool fromMessage)
490 {
491 	const char *device;
492 	if (interface.FindString("device", &device) != B_OK)
493 		return B_BAD_VALUE;
494 
495 	ifreq request;
496 	if (!prepare_request(request, device))
497 		return B_ERROR;
498 
499 	bool startAutoConfig = false;
500 
501 	int32 flags;
502 	if (interface.FindInt32("flags", &flags) < B_OK)
503 		flags = IFF_UP;
504 
505 	bool autoConfigured;
506 	if (interface.FindBool("auto", &autoConfigured) == B_OK && autoConfigured)
507 		flags |= IFF_AUTO_CONFIGURED;
508 
509 	int32 mtu;
510 	if (interface.FindInt32("mtu", &mtu) < B_OK)
511 		mtu = -1;
512 
513 	int32 metric;
514 	if (interface.FindInt32("metric", &metric) < B_OK)
515 		metric = -1;
516 
517 	BMessage addressMessage;
518 	for (int32 index = 0; interface.FindMessage("address", index,
519 			&addressMessage) == B_OK; index++) {
520 		const char* family;
521 		if (addressMessage.FindString("family", &family) < B_OK)
522 			continue;
523 
524 		int32 familyIndex;
525 		if (!get_family_index(family, familyIndex)) {
526 			// we don't support this family
527 			continue;
528 		}
529 
530 		int familySocket = socket;
531 		if (family_at_index(familyIndex) != AF_INET)
532 			socket = ::socket(family_at_index(familyIndex), SOCK_DGRAM, 0);
533 		if (socket < 0) {
534 			// the family is not available in this environment
535 			continue;
536 		}
537 
538 		uint32 interfaceIndex = 0;
539 		if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0)
540 			interfaceIndex = request.ifr_index;
541 
542 		if (interfaceIndex == 0) {
543 			// we need to create the interface first
544 			request.ifr_parameter.base_name[0] = '\0';
545 			request.ifr_parameter.device[0] = '\0';
546 			request.ifr_parameter.sub_type = 0;
547 				// the default device is okay for us
548 
549 			if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
550 				fprintf(stderr, "%s: Could not add interface: %s\n", Name(),
551 					strerror(errno));
552 				return errno;
553 			}
554 		}
555 
556 		// retrieve addresses
557 
558 		bool autoConfig;
559 		if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK)
560 			autoConfig = false;
561 #if 0
562 		if (autoConfig && fromMessage) {
563 			// we don't accept auto-config messages this way
564 			continue;
565 		}
566 #endif
567 
568 		bool hasAddress = false, hasMask = false, hasPeer = false;
569 		bool hasBroadcast = false;
570 		struct sockaddr address, mask, peer, broadcast, gateway;
571 		const char* string;
572 
573 		if (!autoConfig) {
574 			if (addressMessage.FindString("address", &string) == B_OK
575 				&& parse_address(familyIndex, string, address)) {
576 				hasAddress = true;
577 
578 				if (addressMessage.FindString("mask", &string) == B_OK
579 					&& parse_address(familyIndex, string, mask))
580 					hasMask = true;
581 			}
582 			if (addressMessage.FindString("peer", &string) == B_OK
583 				&& parse_address(familyIndex, string, peer))
584 				hasPeer = true;
585 			if (addressMessage.FindString("broadcast", &string) == B_OK
586 				&& parse_address(familyIndex, string, broadcast))
587 				hasBroadcast = true;
588 		}
589 
590 		route_entry route;
591 		memset(&route, 0, sizeof(route_entry));
592 		route.flags = RTF_STATIC | RTF_DEFAULT;
593 
594 		request.ifr_route = route;
595 
596 		if (autoConfig) {
597 			_QuitLooperForDevice(device);
598 			startAutoConfig = true;
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 & ~IFF_CONFIGURING) | 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 	if (iterator->second->Lock())
705 		iterator->second->Quit();
706 
707 	fDeviceMap.erase(iterator);
708 	return true;
709 }
710 
711 
712 AutoconfigLooper*
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 "
803 			"available.\n", 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(int argc, char** argv)
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