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