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