xref: /haiku/src/servers/net/Services.cpp (revision b46615c55ad2c8fe6de54412055a0713da3d610a)
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  */
8 
9 
10 #include "Services.h"
11 #include "NetServer.h"
12 #include "Settings.h"
13 
14 #include <Autolock.h>
15 #include <NetworkAddress.h>
16 
17 #include <errno.h>
18 #include <netdb.h>
19 #include <netinet/in.h>
20 #include <new>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <vector>
26 
27 using namespace std;
28 
29 struct service_address {
30 	struct service* owner;
31 	int		socket;
32 	int		family;
33 	int		type;
34 	int		protocol;
35 	BNetworkAddress address;
36 
37 	bool operator==(const struct service_address& other) const;
38 };
39 
40 typedef std::vector<service_address> AddressList;
41 typedef std::vector<std::string> StringList;
42 
43 struct service {
44 	std::string	name;
45 	StringList	arguments;
46 	uid_t		user;
47 	gid_t		group;
48 	AddressList	addresses;
49 	uint32		update;
50 	bool		stand_alone;
51 	pid_t		process;
52 
53 	~service();
54 	bool operator!=(const struct service& other) const;
55 	bool operator==(const struct service& other) const;
56 };
57 
58 
59 int
60 parse_type(const char* string)
61 {
62 	if (!strcasecmp(string, "stream"))
63 		return SOCK_STREAM;
64 
65 	return SOCK_DGRAM;
66 }
67 
68 
69 int
70 parse_protocol(const char* string)
71 {
72 	struct protoent* proto = getprotobyname(string);
73 	if (proto == NULL)
74 		return IPPROTO_TCP;
75 
76 	return proto->p_proto;
77 }
78 
79 
80 int
81 type_for_protocol(int protocol)
82 {
83 	// default determined by protocol
84 	switch (protocol) {
85 		case IPPROTO_TCP:
86 			return SOCK_STREAM;
87 
88 		case IPPROTO_UDP:
89 		default:
90 			return SOCK_DGRAM;
91 	}
92 }
93 
94 
95 //	#pragma mark -
96 
97 
98 bool
99 service_address::operator==(const struct service_address& other) const
100 {
101 	return family == other.family
102 		&& type == other.type
103 		&& protocol == other.protocol
104 		&& address == other.address;
105 }
106 
107 
108 //	#pragma mark -
109 
110 
111 service::~service()
112 {
113 	// close all open sockets
114 	AddressList::const_iterator iterator = addresses.begin();
115 	for (; iterator != addresses.end(); iterator++) {
116 		const service_address& address = *iterator;
117 
118 		close(address.socket);
119 	}
120 }
121 
122 
123 bool
124 service::operator!=(const struct service& other) const
125 {
126 	return !(*this == other);
127 }
128 
129 
130 bool
131 service::operator==(const struct service& other) const
132 {
133 	if (name != other.name
134 		|| arguments.size() != other.arguments.size()
135 		|| addresses.size() != other.addresses.size()
136 		|| stand_alone != other.stand_alone)
137 		return false;
138 
139 	// compare arguments
140 
141 	for(size_t i = 0; i < arguments.size(); i++) {
142 		if (arguments[i] != other.arguments[i])
143 			return false;
144 	}
145 
146 	// compare addresses
147 
148 	AddressList::const_iterator iterator = addresses.begin();
149 	for (; iterator != addresses.end(); iterator++) {
150 		const service_address& address = *iterator;
151 
152 		// find address in other addresses
153 
154 		AddressList::const_iterator otherIterator = other.addresses.begin();
155 		for (; otherIterator != other.addresses.end(); otherIterator++) {
156 			if (address == *otherIterator)
157 				break;
158 		}
159 
160 		if (otherIterator == other.addresses.end())
161 			return false;
162 	}
163 
164 	return true;
165 }
166 
167 
168 //	#pragma mark -
169 
170 
171 Services::Services(const BMessage& services)
172 	:
173 	fListener(-1),
174 	fUpdate(0),
175 	fMaxSocket(0)
176 {
177 	// setup pipe to communicate with the listener thread - as the listener
178 	// blocks on select(), we need a mechanism to interrupt it
179 	if (pipe(&fReadPipe) < 0) {
180 		fReadPipe = -1;
181 		return;
182 	}
183 
184 	fcntl(fReadPipe, F_SETFD, FD_CLOEXEC);
185 	fcntl(fWritePipe, F_SETFD, FD_CLOEXEC);
186 
187 	FD_ZERO(&fSet);
188 	FD_SET(fReadPipe, &fSet);
189 
190 	fMinSocket = fWritePipe + 1;
191 	fMaxSocket = fWritePipe + 1;
192 
193 	_Update(services);
194 
195 	fListener = spawn_thread(_Listener, "services listener", B_NORMAL_PRIORITY,
196 		this);
197 	if (fListener >= B_OK)
198 		resume_thread(fListener);
199 }
200 
201 
202 Services::~Services()
203 {
204 	wait_for_thread(fListener, NULL);
205 
206 	close(fReadPipe);
207 	close(fWritePipe);
208 
209 	// stop all services
210 
211 	while (!fNameMap.empty()) {
212 		_StopService(*fNameMap.begin()->second);
213 	}
214 }
215 
216 
217 status_t
218 Services::InitCheck() const
219 {
220 	return fListener >= B_OK ? B_OK : fListener;
221 }
222 
223 
224 void
225 Services::MessageReceived(BMessage* message)
226 {
227 	switch (message->what) {
228 		case kMsgUpdateServices:
229 			_Update(*message);
230 			break;
231 
232 		default:
233 			BHandler::MessageReceived(message);
234 	}
235 }
236 
237 
238 void
239 Services::_NotifyListener(bool quit)
240 {
241 	write(fWritePipe, quit ? "q" : "u", 1);
242 }
243 
244 
245 void
246 Services::_UpdateMinMaxSocket(int socket)
247 {
248 	if (socket >= fMaxSocket)
249 		fMaxSocket = socket + 1;
250 	if (socket < fMinSocket)
251 		fMinSocket = socket;
252 }
253 
254 
255 status_t
256 Services::_StartService(struct service& service)
257 {
258 	if (service.stand_alone && service.process == -1) {
259 		status_t status = _LaunchService(service, -1);
260 		if (status == B_OK) {
261 			// add service
262 			fNameMap[service.name] = &service;
263 			service.update = fUpdate;
264 		}
265 		return status;
266 	}
267 
268 	// create socket
269 
270 	bool failed = false;
271 	AddressList::iterator iterator = service.addresses.begin();
272 	for (; iterator != service.addresses.end(); iterator++) {
273 		service_address& address = *iterator;
274 
275 		address.socket = socket(address.family, address.type, address.protocol);
276 		if (address.socket < 0
277 			|| bind(address.socket, address.address, address.address.Length())
278 					< 0
279 			|| fcntl(address.socket, F_SETFD, FD_CLOEXEC) < 0) {
280 			failed = true;
281 			break;
282 		}
283 
284 		if (address.type == SOCK_STREAM && listen(address.socket, 50) < 0) {
285 			failed = true;
286 			break;
287 		}
288 	}
289 
290 	if (failed) {
291 		// open sockets will be closed when the service is deleted
292 		return errno;
293 	}
294 
295 	// add service to maps and activate it
296 
297 	fNameMap[service.name] = &service;
298 	service.update = fUpdate;
299 
300 	iterator = service.addresses.begin();
301 	for (; iterator != service.addresses.end(); iterator++) {
302 		service_address& address = *iterator;
303 
304 		fSocketMap[address.socket] = &address;
305 		_UpdateMinMaxSocket(address.socket);
306 		FD_SET(address.socket, &fSet);
307 	}
308 
309 	_NotifyListener();
310 	printf("Starting service '%s'\n", service.name.c_str());
311 	return B_OK;
312 }
313 
314 
315 status_t
316 Services::_StopService(struct service& service)
317 {
318 	printf("Stop service '%s'\n", service.name.c_str());
319 
320 	// remove service from maps
321 	{
322 		ServiceNameMap::iterator iterator = fNameMap.find(service.name);
323 		if (iterator != fNameMap.end())
324 			fNameMap.erase(iterator);
325 	}
326 
327 	if (!service.stand_alone) {
328 		AddressList::const_iterator iterator = service.addresses.begin();
329 		for (; iterator != service.addresses.end(); iterator++) {
330 			const service_address& address = *iterator;
331 
332 			ServiceSocketMap::iterator socketIterator
333 				= fSocketMap.find(address.socket);
334 			if (socketIterator != fSocketMap.end())
335 				fSocketMap.erase(socketIterator);
336 
337 			close(address.socket);
338 			FD_CLR(address.socket, &fSet);
339 		}
340 	}
341 
342 	// Shutdown the running server, if any
343 	if (service.process != -1) {
344 		printf("  Sending SIGTERM to process %ld\n", service.process);
345 		kill(-service.process, SIGTERM);
346 	}
347 
348 	delete &service;
349 	return B_OK;
350 }
351 
352 
353 status_t
354 Services::_ToService(const BMessage& message, struct service*& service)
355 {
356 	// get mandatory fields
357 	const char* name;
358 	if (message.FindString("name", &name) != B_OK
359 		|| !message.HasString("launch"))
360 		return B_BAD_VALUE;
361 
362 	service = new (std::nothrow) ::service;
363 	if (service == NULL)
364 		return B_NO_MEMORY;
365 
366 	service->name = name;
367 
368 	const char* argument;
369 	for (int i = 0; message.FindString("launch", i, &argument) == B_OK; i++) {
370 		service->arguments.push_back(argument);
371 	}
372 
373 	service->stand_alone = false;
374 	service->process = -1;
375 
376 	// TODO: user/group is currently ignored!
377 
378 	// Default family/port/protocol/type for all addresses
379 
380 	// we default to inet/tcp/port-from-service-name if nothing is specified
381 	const char* string;
382 	if (message.FindString("family", &string) != B_OK)
383 		string = "inet";
384 
385 	int32 serviceFamily = get_address_family(string);
386 	if (serviceFamily == AF_UNSPEC)
387 		serviceFamily = AF_INET;
388 
389 	int32 serviceProtocol;
390 	if (message.FindString("protocol", &string) == B_OK)
391 		serviceProtocol = parse_protocol(string);
392 	else {
393 		string = "tcp";
394 			// we set 'string' here for an eventual call to getservbyname()
395 			// below
396 		serviceProtocol = IPPROTO_TCP;
397 	}
398 
399 	int32 servicePort;
400 	if (message.FindInt32("port", &servicePort) != B_OK) {
401 		struct servent* servent = getservbyname(name, string);
402 		if (servent != NULL)
403 			servicePort = ntohs(servent->s_port);
404 		else
405 			servicePort = -1;
406 	}
407 
408 	int32 serviceType = -1;
409 	if (message.FindString("type", &string) == B_OK) {
410 		serviceType = parse_type(string);
411 	} else {
412 		serviceType = type_for_protocol(serviceProtocol);
413 	}
414 
415 	bool standAlone = false;
416 	if (message.FindBool("stand_alone", &standAlone) == B_OK)
417 		service->stand_alone = standAlone;
418 
419 	BMessage address;
420 	int32 i = 0;
421 	for (; message.FindMessage("address", i, &address) == B_OK; i++) {
422 		// TODO: dump problems in the settings to syslog
423 		service_address serviceAddress;
424 		if (address.FindString("family", &string) != B_OK)
425 			continue;
426 
427 		serviceAddress.family = get_address_family(string);
428 		if (serviceAddress.family == AF_UNSPEC)
429 			continue;
430 
431 		if (address.FindString("protocol", &string) == B_OK)
432 			serviceAddress.protocol = parse_protocol(string);
433 		else
434 			serviceAddress.protocol = serviceProtocol;
435 
436 		if (message.FindString("type", &string) == B_OK)
437 			serviceAddress.type = parse_type(string);
438 		else if (serviceAddress.protocol != serviceProtocol)
439 			serviceAddress.type = type_for_protocol(serviceAddress.protocol);
440 		else
441 			serviceAddress.type = serviceType;
442 
443 		if (address.FindString("address", &string) == B_OK) {
444 			if (!parse_address(serviceFamily, string, serviceAddress.address))
445 				continue;
446 		} else
447 			serviceAddress.address.SetToWildcard(serviceFamily);
448 
449 		int32 port;
450 		if (address.FindInt32("port", &port) != B_OK)
451 			port = servicePort;
452 
453 		serviceAddress.address.SetPort(port);
454 		serviceAddress.socket = -1;
455 
456 		serviceAddress.owner = service;
457 		service->addresses.push_back(serviceAddress);
458 	}
459 
460 	if (i == 0 && (serviceFamily < 0 || servicePort < 0)) {
461 		// no address specified
462 		printf("service %s has no address specified\n", name);
463 		delete service;
464 		return B_BAD_VALUE;
465 	}
466 
467 	if (i == 0) {
468 		// no address specified, but family/port were given; add empty address
469 		service_address serviceAddress;
470 		serviceAddress.family = serviceFamily;
471 		serviceAddress.type = serviceType;
472 		serviceAddress.protocol = serviceProtocol;
473 		serviceAddress.address.SetToWildcard(serviceFamily, servicePort);
474 
475 		serviceAddress.socket = -1;
476 
477 		serviceAddress.owner = service;
478 		service->addresses.push_back(serviceAddress);
479 	}
480 
481 	return B_OK;
482 }
483 
484 
485 void
486 Services::_Update(const BMessage& services)
487 {
488 	BAutolock locker(fLock);
489 	fUpdate++;
490 
491 	BMessage message;
492 	for (int32 index = 0; services.FindMessage("service", index,
493 			&message) == B_OK; index++) {
494 		const char* name;
495 		if (message.FindString("name", &name) != B_OK)
496 			continue;
497 
498 		struct service* service;
499 		if (_ToService(message, service) != B_OK)
500 			continue;
501 
502 		ServiceNameMap::iterator iterator = fNameMap.find(name);
503 		if (iterator == fNameMap.end()) {
504 			// this service does not exist yet, start it
505 			printf("New service %s\n", service->name.c_str());
506 			_StartService(*service);
507 		} else {
508 			// this service does already exist - check for any changes
509 
510 			if (*service != *iterator->second) {
511 				printf("Restart service %s\n", service->name.c_str());
512 				_StopService(*iterator->second);
513 				_StartService(*service);
514 			} else
515 				iterator->second->update = fUpdate;
516 		}
517 	}
518 
519 	// stop all services that are not part of the update message
520 
521 	ServiceNameMap::iterator iterator = fNameMap.begin();
522 	while (iterator != fNameMap.end()) {
523 		struct service* service = iterator->second;
524 		iterator++;
525 
526 		if (service->update != fUpdate) {
527 			// this service has to be removed
528 			_StopService(*service);
529 		}
530 	}
531 }
532 
533 
534 status_t
535 Services::_LaunchService(struct service& service, int socket)
536 {
537 	printf("Launch service: %s\n", service.arguments[0].c_str());
538 
539 	if (socket != -1 && fcntl(socket, F_SETFD, 0) < 0) {
540 		// could not clear FD_CLOEXEC on socket
541 		return errno;
542 	}
543 
544 	pid_t child = fork();
545 	if (child == 0) {
546 		setsid();
547 			// make sure we're in our own session, and don't accidently quit
548 			// the net_server
549 
550 		if (socket != -1) {
551 			// We're the child, replace standard input/output
552 			dup2(socket, STDIN_FILENO);
553 			dup2(socket, STDOUT_FILENO);
554 			dup2(socket, STDERR_FILENO);
555 			close(socket);
556 		}
557 
558 		// build argument array
559 
560 		const char** args = (const char**)malloc(
561 			(service.arguments.size() + 1) * sizeof(char*));
562 		if (args == NULL)
563 			exit(1);
564 
565 		for (size_t i = 0; i < service.arguments.size(); i++) {
566 			args[i] = service.arguments[i].c_str();
567 		}
568 		args[service.arguments.size()] = NULL;
569 
570 		if (execv(service.arguments[0].c_str(), (char* const*)args) < 0)
571 			exit(1);
572 
573 		// we'll never trespass here
574 	} else {
575 		// the server does not need the socket anymore
576 		if (socket != -1)
577 			close(socket);
578 
579 		if (service.stand_alone)
580 			service.process = child;
581 	}
582 
583 	// TODO: make sure child started successfully...
584 	return B_OK;
585 }
586 
587 
588 status_t
589 Services::_Listener()
590 {
591 	while (true) {
592 		fLock.Lock();
593 		fd_set set = fSet;
594 		fLock.Unlock();
595 
596 		if (select(fMaxSocket, &set, NULL, NULL, NULL) < 0) {
597 			// sleep a bit before trying again
598 			snooze(1000000LL);
599 		}
600 
601 		if (FD_ISSET(fReadPipe, &set)) {
602 			char command;
603 			if (read(fReadPipe, &command, 1) == 1 && command == 'q')
604 				break;
605 		}
606 
607 		BAutolock locker(fLock);
608 
609 		for (int i = fMinSocket; i < fMaxSocket; i++) {
610 			if (!FD_ISSET(i, &set))
611 				continue;
612 
613 			ServiceSocketMap::iterator iterator = fSocketMap.find(i);
614 			if (iterator == fSocketMap.end())
615 				continue;
616 
617 			struct service_address& address = *iterator->second;
618 			int socket;
619 
620 			if (address.type == SOCK_STREAM) {
621 				// accept incoming connection
622 				int value = 1;
623 				ioctl(i, FIONBIO, &value);
624 					// make sure we don't wait for the connection
625 
626 				socket = accept(address.socket, NULL, NULL);
627 
628 				value = 0;
629 				ioctl(i, FIONBIO, &value);
630 
631 				if (socket < 0)
632 					continue;
633 			} else
634 				socket = address.socket;
635 
636 			// launch this service's handler
637 
638 			_LaunchService(*address.owner, socket);
639 		}
640 	}
641 	return B_OK;
642 }
643 
644 
645 /*static*/ status_t
646 Services::_Listener(void* _self)
647 {
648 	Services* self = (Services*)_self;
649 	return self->_Listener();
650 }
651