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