xref: /haiku/src/servers/net/NetServer.cpp (revision 35ead8815b679605a9b4db8130613ea100f4b14c)
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 (!autoConfigured)
690 				request.ifr_flags = request.ifr_flags & ~IFF_AUTO_CONFIGURED;
691 
692 			if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0)
693 				fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno));
694 		}
695 
696 		// set options
697 
698 		if (mtu != -1) {
699 			request.ifr_mtu = mtu;
700 			if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0)
701 				fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno));
702 		}
703 
704 		if (metric != -1) {
705 			request.ifr_metric = metric;
706 			if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0)
707 				fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno));
708 		}
709 	}
710 
711 	if (startAutoConfig) {
712 		// start auto configuration
713 		AutoconfigLooper* looper = new AutoconfigLooper(this, device);
714 		looper->Run();
715 
716 		fDeviceMap[device] = looper;
717 	}
718 
719 	return B_OK;
720 }
721 
722 
723 bool
724 NetServer::_QuitLooperForDevice(const char* device)
725 {
726 	LooperMap::iterator iterator = fDeviceMap.find(device);
727 	if (iterator == fDeviceMap.end())
728 		return false;
729 
730 	// there is a looper for this device - quit it
731 	if (iterator->second->Lock())
732 		iterator->second->Quit();
733 
734 	fDeviceMap.erase(iterator);
735 	return true;
736 }
737 
738 
739 AutoconfigLooper*
740 NetServer::_LooperForDevice(const char* device)
741 {
742 	LooperMap::const_iterator iterator = fDeviceMap.find(device);
743 	if (iterator == fDeviceMap.end())
744 		return NULL;
745 
746 	return iterator->second;
747 }
748 
749 
750 status_t
751 NetServer::_ConfigureDevice(int socket, const char* path)
752 {
753 	// bring interface up, but don't configure it just yet
754 	BMessage interface;
755 	interface.AddString("device", path);
756 	BMessage address;
757 	address.AddString("family", "inet");
758 	address.AddBool("auto_config", true);
759 	interface.AddMessage("address", &address);
760 
761 	return _ConfigureInterface(socket, interface);
762 }
763 
764 
765 void
766 NetServer::_ConfigureDevices(int socket, const char* startPath,
767 	BMessage* suggestedInterface)
768 {
769 	BDirectory directory(startPath);
770 	BEntry entry;
771 	while (directory.GetNextEntry(&entry) == B_OK) {
772 		char name[B_FILE_NAME_LENGTH];
773 		struct stat stat;
774 		BPath path;
775 		if (entry.GetName(name) != B_OK
776 			|| !strcmp(name, "stack")
777 			|| entry.GetPath(&path) != B_OK
778 			|| entry.GetStat(&stat) != B_OK)
779 			continue;
780 
781 		if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) {
782 			if (suggestedInterface != NULL
783 				&& suggestedInterface->RemoveName("device") == B_OK
784 				&& suggestedInterface->AddString("device", path.Path()) == B_OK
785 				&& _ConfigureInterface(socket, *suggestedInterface) == B_OK)
786 				suggestedInterface = NULL;
787 			else
788 				_ConfigureDevice(socket, path.Path());
789 		} else if (entry.IsDirectory())
790 			_ConfigureDevices(socket, path.Path(), suggestedInterface);
791 	}
792 }
793 
794 
795 void
796 NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
797 {
798 	BMessage interface;
799 	uint32 cookie = 0;
800 	bool missing = false;
801 	while (fSettings.GetNextInterface(cookie, interface) == B_OK) {
802 		const char *device;
803 		if (interface.FindString("device", &device) != B_OK)
804 			continue;
805 
806 		if (!strncmp(device, "/dev/net/", 9)) {
807 			// it's a kernel device, check if it's present
808 			BEntry entry(device);
809 			if (!entry.Exists()) {
810 				if (!missing && _missingDevice != NULL) {
811 					*_missingDevice = interface;
812 					missing = true;
813 				}
814 				continue;
815 			}
816 		}
817 
818 		_ConfigureInterface(socket, interface);
819 	}
820 }
821 
822 
823 void
824 NetServer::_BringUpInterfaces()
825 {
826 	// we need a socket to talk to the networking stack
827 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
828 	if (socket < 0) {
829 		fprintf(stderr, "%s: The networking stack doesn't seem to be "
830 			"available.\n", Name());
831 		Quit();
832 		return;
833 	}
834 
835 	_RemoveInvalidInterfaces(socket);
836 
837 	// First, we look into the settings, and try to bring everything up from there
838 
839 	BMessage missingDevice;
840 	_ConfigureInterfaces(socket, &missingDevice);
841 
842 	// check configuration
843 
844 	if (!_TestForInterface(socket, "loop")) {
845 		// there is no loopback interface, create one
846 		BMessage interface;
847 		interface.AddString("device", "loop");
848 		BMessage address;
849 		address.AddString("family", "inet");
850 		address.AddString("address", "127.0.0.1");
851 		interface.AddMessage("address", &address);
852 
853 		_ConfigureInterface(socket, interface);
854 	}
855 
856 	// TODO: also check if the networking driver is correctly initialized!
857 	//	(and check for other devices to take over its configuration)
858 
859 	if (!_TestForInterface(socket, "/dev/net/")) {
860 		// there is no driver configured - see if there is one and try to use it
861 		_ConfigureDevices(socket, "/dev/net",
862 			missingDevice.HasString("device") ? &missingDevice : NULL);
863 	}
864 
865 	close(socket);
866 }
867 
868 
869 void
870 NetServer::_StartServices()
871 {
872 	BHandler* services = new (std::nothrow) Services(fSettings.Services());
873 	if (services != NULL) {
874 		AddHandler(services);
875 		fServices = BMessenger(services);
876 	}
877 }
878 
879 
880 void
881 NetServer::_HandleDeviceMonitor(int socket, BMessage* message)
882 {
883 	int32 opcode;
884 	if (message->FindInt32("opcode", &opcode) != B_OK
885 		|| (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED))
886 		return;
887 
888 	const char* path;
889 	const char* watchedPath;
890 	if (message->FindString("watched_path", &watchedPath) != B_OK
891 		|| message->FindString("path", &path) != B_OK)
892 		return;
893 
894 	if (opcode == B_ENTRY_CREATED)
895 		_ConfigureDevice(socket, path);
896 	else {
897 		ifreq request;
898 		if (!prepare_request(request, path))
899 			return;
900 
901 		if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
902 			fprintf(stderr, "%s: Could not delete interface %s: %s\n",
903 				Name(), path, strerror(errno));
904 		}
905 	}
906 }
907 
908 
909 //	#pragma mark -
910 
911 
912 int
913 main(int argc, char** argv)
914 {
915 	status_t status;
916 	NetServer server(status);
917 	if (status != B_OK) {
918 		fprintf(stderr, "net_server: Failed to create application: %s\n",
919 			strerror(status));
920 		return 1;
921 	}
922 
923 	server.Run();
924 	return 0;
925 }
926 
927