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