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