1 /* 2 * Copyright 2006-2009, 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 std::vector<service_address> AddressList; 40 typedef std::vector<std::string> StringList; 41 42 struct service { 43 std::string name; 44 StringList arguments; 45 uid_t user; 46 gid_t group; 47 AddressList addresses; 48 uint32 update; 49 bool stand_alone; 50 pid_t process; 51 52 ~service(); 53 bool operator!=(const struct service& other) const; 54 bool operator==(const struct service& other) const; 55 }; 56 57 58 int 59 parse_type(const char* string) 60 { 61 if (!strcasecmp(string, "stream")) 62 return SOCK_STREAM; 63 64 return SOCK_DGRAM; 65 } 66 67 68 int 69 parse_protocol(const char* string) 70 { 71 struct protoent* proto = getprotobyname(string); 72 if (proto == NULL) 73 return IPPROTO_TCP; 74 75 return proto->p_proto; 76 } 77 78 79 int 80 type_for_protocol(int protocol) 81 { 82 // default determined by protocol 83 switch (protocol) { 84 case IPPROTO_TCP: 85 return SOCK_STREAM; 86 87 case IPPROTO_UDP: 88 default: 89 return SOCK_DGRAM; 90 } 91 } 92 93 94 // #pragma mark - 95 96 97 bool 98 service_address::operator==(const struct service_address& other) const 99 { 100 return family == other.family 101 && type == other.type 102 && protocol == other.protocol 103 && address.sa_len == other.address.sa_len 104 && !memcmp(&address, &other.address, address.sa_len); 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.sa_len) < 0 278 || fcntl(address.socket, F_SETFD, FD_CLOEXEC) < 0) { 279 failed = true; 280 break; 281 } 282 283 if (address.type == SOCK_STREAM && listen(address.socket, 50) < 0) { 284 failed = true; 285 break; 286 } 287 } 288 289 if (failed) { 290 // open sockets will be closed when the service is deleted 291 return errno; 292 } 293 294 // add service to maps and activate it 295 296 fNameMap[service.name] = &service; 297 service.update = fUpdate; 298 299 iterator = service.addresses.begin(); 300 for (; iterator != service.addresses.end(); iterator++) { 301 service_address& address = *iterator; 302 303 fSocketMap[address.socket] = &address; 304 _UpdateMinMaxSocket(address.socket); 305 FD_SET(address.socket, &fSet); 306 } 307 308 _NotifyListener(); 309 printf("Starting service '%s'\n", service.name.c_str()); 310 return B_OK; 311 } 312 313 314 status_t 315 Services::_StopService(struct service& service) 316 { 317 printf("Stop service '%s'\n", service.name.c_str()); 318 319 // remove service from maps 320 { 321 ServiceNameMap::iterator iterator = fNameMap.find(service.name); 322 if (iterator != fNameMap.end()) 323 fNameMap.erase(iterator); 324 } 325 326 if (!service.stand_alone) { 327 AddressList::const_iterator iterator = service.addresses.begin(); 328 for (; iterator != service.addresses.end(); iterator++) { 329 const service_address& address = *iterator; 330 331 ServiceSocketMap::iterator socketIterator 332 = fSocketMap.find(address.socket); 333 if (socketIterator != fSocketMap.end()) 334 fSocketMap.erase(socketIterator); 335 336 close(address.socket); 337 FD_CLR(address.socket, &fSet); 338 } 339 } 340 341 // Shutdown the running server, if any 342 if (service.process != -1) { 343 printf(" Sending SIGTERM to process %ld\n", service.process); 344 kill(-service.process, SIGTERM); 345 } 346 347 delete &service; 348 return B_OK; 349 } 350 351 352 status_t 353 Services::_ToService(const BMessage& message, struct service*& service) 354 { 355 // get mandatory fields 356 const char* name; 357 if (message.FindString("name", &name) != B_OK 358 || !message.HasString("launch")) 359 return B_BAD_VALUE; 360 361 service = new (std::nothrow) ::service; 362 if (service == NULL) 363 return B_NO_MEMORY; 364 365 service->name = name; 366 367 const char* argument; 368 for (int i = 0; message.FindString("launch", i, &argument) == B_OK; i++) { 369 service->arguments.push_back(argument); 370 } 371 372 service->stand_alone = false; 373 service->process = -1; 374 375 // TODO: user/group is currently ignored! 376 377 // Default family/port/protocol/type for all addresses 378 379 // we default to inet/tcp/port-from-service-name if nothing is specified 380 const char* string; 381 int32 serviceFamilyIndex; 382 int32 serviceFamily = -1; 383 if (message.FindString("family", &string) != B_OK) 384 string = "inet"; 385 386 if (get_family_index(string, serviceFamilyIndex)) 387 serviceFamily = family_at_index(serviceFamilyIndex); 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 = 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 int32 familyIndex; 428 if (!get_family_index(string, familyIndex)) 429 continue; 430 431 serviceAddress.family = family_at_index(familyIndex); 432 433 if (address.FindString("protocol", &string) == B_OK) 434 serviceAddress.protocol = parse_protocol(string); 435 else 436 serviceAddress.protocol = serviceProtocol; 437 438 if (message.FindString("type", &string) == B_OK) 439 serviceAddress.type = parse_type(string); 440 else if (serviceAddress.protocol != serviceProtocol) 441 serviceAddress.type = type_for_protocol(serviceAddress.protocol); 442 else 443 serviceAddress.type = serviceType; 444 445 if (address.FindString("address", &string) == B_OK) { 446 if (!parse_address(familyIndex, string, serviceAddress.address)) 447 continue; 448 } else 449 set_any_address(familyIndex, serviceAddress.address); 450 451 int32 port; 452 if (address.FindInt32("port", &port) != B_OK) 453 port = servicePort; 454 455 set_port(familyIndex, serviceAddress.address, port); 456 serviceAddress.socket = -1; 457 458 serviceAddress.owner = service; 459 service->addresses.push_back(serviceAddress); 460 } 461 462 if (i == 0 && (serviceFamily < 0 || servicePort < 0)) { 463 // no address specified 464 printf("service %s has no address specified\n", name); 465 delete service; 466 return B_BAD_VALUE; 467 } 468 469 if (i == 0) { 470 // no address specified, but family/port were given; add empty address 471 service_address serviceAddress; 472 serviceAddress.family = serviceFamily; 473 serviceAddress.type = serviceType; 474 serviceAddress.protocol = serviceProtocol; 475 476 set_any_address(serviceFamilyIndex, serviceAddress.address); 477 set_port(serviceFamilyIndex, serviceAddress.address, servicePort); 478 serviceAddress.socket = -1; 479 480 serviceAddress.owner = service; 481 service->addresses.push_back(serviceAddress); 482 } 483 484 return B_OK; 485 } 486 487 488 void 489 Services::_Update(const BMessage& services) 490 { 491 BAutolock locker(fLock); 492 fUpdate++; 493 494 BMessage message; 495 for (int32 index = 0; services.FindMessage("service", index, 496 &message) == B_OK; index++) { 497 const char* name; 498 if (message.FindString("name", &name) != B_OK) 499 continue; 500 501 struct service* service; 502 if (_ToService(message, service) != B_OK) 503 continue; 504 505 ServiceNameMap::iterator iterator = fNameMap.find(name); 506 if (iterator == fNameMap.end()) { 507 // this service does not exist yet, start it 508 printf("New service %s\n", service->name.c_str()); 509 _StartService(*service); 510 } else { 511 // this service does already exist - check for any changes 512 513 if (*service != *iterator->second) { 514 printf("Restart service %s\n", service->name.c_str()); 515 _StopService(*iterator->second); 516 _StartService(*service); 517 } else 518 iterator->second->update = fUpdate; 519 } 520 } 521 522 // stop all services that are not part of the update message 523 524 ServiceNameMap::iterator iterator = fNameMap.begin(); 525 while (iterator != fNameMap.end()) { 526 struct service* service = iterator->second; 527 iterator++; 528 529 if (service->update != fUpdate) { 530 // this service has to be removed 531 _StopService(*service); 532 } 533 } 534 } 535 536 537 status_t 538 Services::_LaunchService(struct service& service, int socket) 539 { 540 printf("Launch service: %s\n", service.arguments[0].c_str()); 541 542 if (socket != -1 && fcntl(socket, F_SETFD, 0) < 0) { 543 // could not clear FD_CLOEXEC on socket 544 return errno; 545 } 546 547 pid_t child = fork(); 548 if (child == 0) { 549 setsid(); 550 // make sure we're in our own session, and don't accidently quit 551 // the net_server 552 553 if (socket != -1) { 554 // We're the child, replace standard input/output 555 dup2(socket, STDIN_FILENO); 556 dup2(socket, STDOUT_FILENO); 557 dup2(socket, STDERR_FILENO); 558 close(socket); 559 } 560 561 // build argument array 562 563 const char** args = (const char**)malloc( 564 (service.arguments.size() + 1) * sizeof(char*)); 565 if (args == NULL) 566 exit(1); 567 568 for (size_t i = 0; i < service.arguments.size(); i++) { 569 args[i] = service.arguments[i].c_str(); 570 } 571 args[service.arguments.size()] = NULL; 572 573 if (execv(service.arguments[0].c_str(), (char* const*)args) < 0) 574 exit(1); 575 576 // we'll never trespass here 577 } else { 578 // the server does not need the socket anymore 579 if (socket != -1) 580 close(socket); 581 582 if (service.stand_alone) 583 service.process = child; 584 } 585 586 // TODO: make sure child started successfully... 587 return B_OK; 588 } 589 590 591 status_t 592 Services::_Listener() 593 { 594 while (true) { 595 fLock.Lock(); 596 fd_set set = fSet; 597 fLock.Unlock(); 598 599 if (select(fMaxSocket, &set, NULL, NULL, NULL) < 0) { 600 // sleep a bit before trying again 601 snooze(1000000LL); 602 } 603 604 if (FD_ISSET(fReadPipe, &set)) { 605 char command; 606 if (read(fReadPipe, &command, 1) == 1 && command == 'q') 607 break; 608 } 609 610 BAutolock locker(fLock); 611 612 for (int i = fMinSocket; i < fMaxSocket; i++) { 613 if (!FD_ISSET(i, &set)) 614 continue; 615 616 ServiceSocketMap::iterator iterator = fSocketMap.find(i); 617 if (iterator == fSocketMap.end()) 618 continue; 619 620 struct service_address& address = *iterator->second; 621 int socket; 622 623 if (address.type == SOCK_STREAM) { 624 // accept incoming connection 625 int value = 1; 626 ioctl(i, FIONBIO, &value); 627 // make sure we don't wait for the connection 628 629 socket = accept(address.socket, NULL, NULL); 630 631 value = 0; 632 ioctl(i, FIONBIO, &value); 633 634 if (socket < 0) 635 continue; 636 } else 637 socket = address.socket; 638 639 // launch this service's handler 640 641 _LaunchService(*address.owner, socket); 642 } 643 } 644 return B_OK; 645 } 646 647 648 /*static*/ status_t 649 Services::_Listener(void* _self) 650 { 651 Services* self = (Services*)_self; 652 return self->_Listener(); 653 } 654