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