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