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