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