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 "AutoconfigLooper.h" 11 #include "NetServer.h" 12 #include "Services.h" 13 #include "Settings.h" 14 #include "StatusReplicant.h" 15 16 #include <Alert.h> 17 #include <Deskbar.h> 18 #include <Directory.h> 19 #include <Entry.h> 20 #include <NodeMonitor.h> 21 #include <Path.h> 22 #include <Roster.h> 23 #include <Server.h> 24 #include <TextView.h> 25 26 #include <arpa/inet.h> 27 #include <net/if_dl.h> 28 #include <net/if_types.h> 29 #include <netinet/in.h> 30 #include <sys/socket.h> 31 #include <sys/sockio.h> 32 33 #include <map> 34 #include <errno.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string> 38 #include <string.h> 39 #include <unistd.h> 40 41 42 const char *kSignature = "application/x-vnd.haiku-net_server"; 43 static const char *kDeskbarSignature = "application/x-vnd.Be-TSKB"; 44 45 46 typedef std::map<std::string, BLooper*> LooperMap; 47 typedef std::map<std::string, int> StatusMap; 48 49 50 class NetServer : public BServer { 51 public: 52 NetServer(status_t& status); 53 54 virtual void AboutRequested(); 55 virtual void ReadyToRun(); 56 virtual void MessageReceived(BMessage* message); 57 58 private: 59 bool _IsValidInterface(int socket, const char* name); 60 void _RemoveInvalidInterfaces(int socket); 61 bool _TestForInterface(int socket, const char* name); 62 status_t _ConfigureInterface(int socket, BMessage& interface, 63 bool fromMessage = false); 64 bool _QuitLooperForDevice(const char* device); 65 BLooper* _LooperForDevice(const char* device); 66 status_t _ConfigureDevice(int socket, const char* path); 67 void _ConfigureDevices(int socket, const char* path, 68 BMessage* suggestedInterface = NULL); 69 void _ConfigureInterfaces(int socket, BMessage* _missingDevice = NULL); 70 void _BringUpInterfaces(); 71 void _StartServices(); 72 status_t _AddStatusReplicant(bool force); 73 void _UpdateDeviceStatus(const char *device, int status); 74 void _UpdateReplicantStatus(); 75 76 Settings fSettings; 77 LooperMap fDeviceMap; 78 StatusMap fStatusMap; 79 BMessenger fServices; 80 BMessenger fStatusMessenger; 81 }; 82 83 84 struct address_family { 85 int family; 86 const char* name; 87 const char* identifiers[4]; 88 bool (*parse_address)(const char* string, sockaddr* _address); 89 void (*set_any_address)(sockaddr* address); 90 void (*set_port)(sockaddr* address, int32 port); 91 }; 92 93 // AF_INET family 94 static bool inet_parse_address(const char* string, sockaddr* address); 95 static void inet_set_any_address(sockaddr* address); 96 static void inet_set_port(sockaddr* address, int32 port); 97 98 static const address_family kFamilies[] = { 99 { 100 AF_INET, 101 "inet", 102 {"AF_INET", "inet", "ipv4", NULL}, 103 inet_parse_address, 104 inet_set_any_address, 105 inet_set_port 106 }, 107 { -1, NULL, {NULL}, NULL } 108 }; 109 110 111 static bool 112 inet_parse_address(const char* string, sockaddr* _address) 113 { 114 in_addr inetAddress; 115 116 if (inet_aton(string, &inetAddress) != 1) 117 return false; 118 119 sockaddr_in& address = *(sockaddr_in *)_address; 120 address.sin_family = AF_INET; 121 address.sin_len = sizeof(struct sockaddr_in); 122 address.sin_port = 0; 123 address.sin_addr = inetAddress; 124 memset(&address.sin_zero[0], 0, sizeof(address.sin_zero)); 125 126 return true; 127 } 128 129 130 void 131 inet_set_any_address(sockaddr* _address) 132 { 133 sockaddr_in& address = *(sockaddr_in*)_address; 134 address.sin_family = AF_INET; 135 address.sin_len = sizeof(struct sockaddr_in); 136 address.sin_port = 0; 137 address.sin_addr.s_addr = INADDR_ANY; 138 memset(&address.sin_zero[0], 0, sizeof(address.sin_zero)); 139 } 140 141 142 void 143 inet_set_port(sockaddr* _address, int32 port) 144 { 145 sockaddr_in& address = *(sockaddr_in*)_address; 146 address.sin_port = port; 147 } 148 149 150 // #pragma mark - 151 152 153 bool 154 get_family_index(const char* name, int32& familyIndex) 155 { 156 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 157 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 158 if (!strcmp(name, kFamilies[i].identifiers[j])) { 159 // found a match 160 familyIndex = i; 161 return true; 162 } 163 } 164 } 165 166 // defaults to AF_INET 167 familyIndex = 0; 168 return false; 169 } 170 171 172 int 173 family_at_index(int32 index) 174 { 175 return kFamilies[index].family; 176 } 177 178 179 bool 180 parse_address(int32 familyIndex, const char* argument, struct sockaddr& address) 181 { 182 if (argument == NULL) 183 return false; 184 185 return kFamilies[familyIndex].parse_address(argument, &address); 186 } 187 188 189 void 190 set_any_address(int32 familyIndex, struct sockaddr& address) 191 { 192 kFamilies[familyIndex].set_any_address(&address); 193 } 194 195 196 void 197 set_port(int32 familyIndex, struct sockaddr& address, int32 port) 198 { 199 kFamilies[familyIndex].set_port(&address, port); 200 } 201 202 203 bool 204 prepare_request(ifreq& request, const char* name) 205 { 206 if (strlen(name) > IF_NAMESIZE) 207 return false; 208 209 strcpy(request.ifr_name, name); 210 return true; 211 } 212 213 214 status_t 215 get_mac_address(const char* device, uint8* address) 216 { 217 int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); 218 if (socket < 0) 219 return errno; 220 221 ifreq request; 222 if (!prepare_request(request, device)) { 223 close(socket); 224 return B_ERROR; 225 } 226 227 if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) { 228 close(socket); 229 return errno; 230 } 231 232 close(socket); 233 234 sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr; 235 if (link.sdl_type != IFT_ETHER) 236 return B_BAD_TYPE; 237 238 if (link.sdl_alen == 0) 239 return B_ENTRY_NOT_FOUND; 240 241 uint8 *mac = (uint8 *)LLADDR(&link); 242 memcpy(address, mac, 6); 243 244 return B_OK; 245 } 246 247 248 // #pragma mark - 249 250 251 NetServer::NetServer(status_t& error) 252 : BServer(kSignature, false, &error) 253 { 254 } 255 256 257 void 258 NetServer::AboutRequested() 259 { 260 BAlert *alert = new BAlert("about", "Networking Server\n" 261 "\tCopyright " B_UTF8_COPYRIGHT "2006, Haiku.\n", "Ok"); 262 BTextView *view = alert->TextView(); 263 BFont font; 264 265 view->SetStylable(true); 266 267 view->GetFont(&font); 268 font.SetSize(18); 269 font.SetFace(B_BOLD_FACE); 270 view->SetFontAndColor(0, 17, &font); 271 272 alert->Go(NULL); 273 } 274 275 276 void 277 NetServer::ReadyToRun() 278 { 279 fSettings.StartMonitoring(this); 280 _BringUpInterfaces(); 281 _StartServices(); 282 283 // we have to wait for Deskbar to show up before 284 // adding the status replicant 285 be_roster->StartWatching(BMessenger(this), B_REQUEST_LAUNCHED); 286 // but possibly the Deskbar is already running 287 // so add immediatly 288 _AddStatusReplicant(true); 289 } 290 291 292 void 293 NetServer::MessageReceived(BMessage* message) 294 { 295 switch (message->what) { 296 case B_NODE_MONITOR: 297 fSettings.Update(message); 298 break; 299 300 case kMsgInterfaceSettingsUpdated: 301 { 302 // we need a socket to talk to the networking stack 303 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 304 if (socket < 0) 305 break; 306 307 _ConfigureInterfaces(socket); 308 close(socket); 309 break; 310 } 311 312 case kMsgServiceSettingsUpdated: 313 { 314 BMessage update = fSettings.Services(); 315 update.what = kMsgUpdateServices; 316 317 fServices.SendMessage(&update); 318 break; 319 } 320 321 case kMsgConfigureInterface: 322 { 323 if (!message->ReturnAddress().IsTargetLocal()) { 324 // for now, we only accept this message from add-ons 325 break; 326 } 327 328 status_t status = B_OK; 329 if (message->GetInfo("address", NULL) != B_NAME_NOT_FOUND) { 330 // we need a socket to talk to the networking stack 331 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 332 if (socket < 0) 333 break; 334 335 status = _ConfigureInterface(socket, *message, true); 336 337 BMessage reply(B_REPLY); 338 reply.AddInt32("status", status); 339 message->SendReply(&reply); 340 341 close(socket); 342 } 343 344 if (status == B_OK) { 345 const char *device; 346 int32 net_status; 347 if (message->FindInt32("net:status", &net_status) == B_OK && 348 message->FindString("device", &device) == B_OK) { 349 _UpdateDeviceStatus(device, net_status); 350 } 351 } 352 353 break; 354 } 355 356 case B_SOME_APP_LAUNCHED: 357 { 358 // check if Deskbar was launched 359 const char *signature; 360 if (message->FindString("be:signature", &signature) == B_OK) { 361 if (strcmp(signature, kDeskbarSignature) == 0) 362 _AddStatusReplicant(true); 363 } 364 break; 365 } 366 367 case kRegisterStatusReplicant: 368 { 369 if (message->FindMessenger("messenger", &fStatusMessenger) == B_OK) 370 _UpdateReplicantStatus(); 371 break; 372 } 373 374 default: 375 BApplication::MessageReceived(message); 376 return; 377 } 378 } 379 380 381 /*! 382 Checks if an interface is valid, that is, if it has an address in any 383 family, and, in case of ethernet, a hardware MAC address. 384 */ 385 bool 386 NetServer::_IsValidInterface(int socket, const char* name) 387 { 388 ifreq request; 389 if (!prepare_request(request, name)) 390 return B_ERROR; 391 392 // check if it has an address 393 394 int32 addresses = 0; 395 396 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 397 int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0); 398 if (familySocket < 0) 399 continue; 400 401 if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) { 402 if (request.ifr_addr.sa_family == kFamilies[i].family) 403 addresses++; 404 } 405 406 close(familySocket); 407 } 408 409 if (addresses == 0) 410 return false; 411 412 // check if it has a hardware address, too, in case of ethernet 413 414 if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0) 415 return false; 416 417 int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); 418 if (linkSocket < 0) 419 return false; 420 421 prepare_request(request, request.ifr_parameter.device); 422 if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) { 423 close(linkSocket); 424 return false; 425 } 426 427 close(linkSocket); 428 429 sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr; 430 if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6) 431 return false; 432 433 return true; 434 } 435 436 437 void 438 NetServer::_RemoveInvalidInterfaces(int socket) 439 { 440 // get a list of all interfaces 441 442 ifconf config; 443 config.ifc_len = sizeof(config.ifc_value); 444 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) 445 return; 446 447 uint32 count = (uint32)config.ifc_value; 448 if (count == 0) { 449 // there are no interfaces yet 450 return; 451 } 452 453 void *buffer = malloc(count * sizeof(struct ifreq)); 454 if (buffer == NULL) { 455 fprintf(stderr, "%s: Out of memory.\n", Name()); 456 return; 457 } 458 459 config.ifc_len = count * sizeof(struct ifreq); 460 config.ifc_buf = buffer; 461 if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) 462 return; 463 464 ifreq *interface = (ifreq *)buffer; 465 466 for (uint32 i = 0; i < count; i++) { 467 if (!_IsValidInterface(socket, interface->ifr_name)) { 468 // remove invalid interface 469 ifreq request; 470 if (!prepare_request(request, interface->ifr_name)) 471 return; 472 473 if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) { 474 fprintf(stderr, "%s: Could not delete interface %s: %s\n", 475 Name(), interface->ifr_name, strerror(errno)); 476 } 477 } 478 479 interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len); 480 } 481 482 free(buffer); 483 } 484 485 486 bool 487 NetServer::_TestForInterface(int socket, const char* name) 488 { 489 // get a list of all interfaces 490 491 ifconf config; 492 config.ifc_len = sizeof(config.ifc_value); 493 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) 494 return false; 495 496 uint32 count = (uint32)config.ifc_value; 497 if (count == 0) { 498 // there are no interfaces yet 499 return false; 500 } 501 502 void *buffer = malloc(count * sizeof(struct ifreq)); 503 if (buffer == NULL) { 504 fprintf(stderr, "%s: Out of memory.\n", Name()); 505 return false; 506 } 507 508 config.ifc_len = count * sizeof(struct ifreq); 509 config.ifc_buf = buffer; 510 if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) 511 return false; 512 513 ifreq *interface = (ifreq *)buffer; 514 int32 nameLength = strlen(name); 515 bool success = false; 516 517 for (uint32 i = 0; i < count; i++) { 518 if (!strncmp(interface->ifr_name, name, nameLength)) { 519 success = true; 520 break; 521 } 522 523 interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len); 524 } 525 526 free(buffer); 527 return success; 528 } 529 530 531 status_t 532 NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage) 533 { 534 const char *device; 535 if (interface.FindString("device", &device) != B_OK) 536 return B_BAD_VALUE; 537 538 ifreq request; 539 if (!prepare_request(request, device)) 540 return B_ERROR; 541 542 bool startAutoConfig = false; 543 544 int32 flags; 545 if (interface.FindInt32("flags", &flags) < B_OK) 546 flags = IFF_UP; 547 548 int32 mtu; 549 if (interface.FindInt32("mtu", &mtu) < B_OK) 550 mtu = -1; 551 552 int32 metric; 553 if (interface.FindInt32("metric", &metric) < B_OK) 554 metric = -1; 555 556 BMessage addressMessage; 557 for (int32 index = 0; interface.FindMessage("address", index, &addressMessage) == B_OK; 558 index++) { 559 const char* family; 560 if (addressMessage.FindString("family", &family) < B_OK) 561 continue; 562 563 int32 familyIndex; 564 if (!get_family_index(family, familyIndex)) { 565 // we don't support this family 566 continue; 567 } 568 569 int familySocket = socket; 570 if (family_at_index(familyIndex) != AF_INET) 571 socket = ::socket(family_at_index(familyIndex), SOCK_DGRAM, 0); 572 if (socket < 0) { 573 // the family is not available in this environment 574 continue; 575 } 576 577 uint32 interfaceIndex = 0; 578 if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0) 579 interfaceIndex = request.ifr_index; 580 581 if (interfaceIndex == 0) { 582 // we need to create the interface first 583 request.ifr_parameter.base_name[0] = '\0'; 584 request.ifr_parameter.device[0] = '\0'; 585 request.ifr_parameter.sub_type = 0; 586 // the default device is okay for us 587 588 if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) { 589 fprintf(stderr, "%s: Could not add interface: %s\n", Name(), 590 strerror(errno)); 591 return errno; 592 } 593 } 594 595 // retrieve addresses 596 597 bool autoConfig; 598 if (addressMessage.FindBool("auto config", &autoConfig) != B_OK) 599 autoConfig = false; 600 if (autoConfig && fromMessage) { 601 // we don't accept auto-config messages this way 602 continue; 603 } 604 605 bool hasAddress = false, hasMask = false, hasPeer = false, hasBroadcast = false; 606 struct sockaddr address, mask, peer, broadcast, gateway; 607 const char* string; 608 609 if (!autoConfig) { 610 if (addressMessage.FindString("address", &string) == B_OK 611 && parse_address(familyIndex, string, address)) { 612 hasAddress = true; 613 614 if (addressMessage.FindString("mask", &string) == B_OK 615 && parse_address(familyIndex, string, mask)) 616 hasMask = true; 617 } 618 if (addressMessage.FindString("peer", &string) == B_OK 619 && parse_address(familyIndex, string, peer)) 620 hasPeer = true; 621 if (addressMessage.FindString("broadcast", &string) == B_OK 622 && parse_address(familyIndex, string, broadcast)) 623 hasBroadcast = true; 624 } 625 626 route_entry route; 627 memset(&route, 0, sizeof(route_entry)); 628 route.flags = RTF_STATIC | RTF_DEFAULT; 629 630 request.ifr_route = route; 631 ioctl(socket, SIOCDELRT, &request, sizeof(request)); 632 // Try to remove a previous default route, doesn't matter 633 // if it fails. 634 635 if (autoConfig) { 636 // add a default route to make the interface accessible, even without an address 637 if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { 638 fprintf(stderr, "%s: Could not add route for %s: %s\n", 639 Name(), device, strerror(errno)); 640 } else { 641 _QuitLooperForDevice(device); 642 startAutoConfig = true; 643 } 644 } else if (addressMessage.FindString("gateway", &string) == B_OK 645 && parse_address(familyIndex, string, gateway)) { 646 // add gateway route, if we're asked for it 647 route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; 648 route.gateway = &gateway; 649 650 request.ifr_route = route; 651 if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { 652 fprintf(stderr, "%s: Could not add route for %s: %s\n", 653 Name(), device, strerror(errno)); 654 } 655 } 656 657 // set addresses 658 659 if (hasAddress) { 660 memcpy(&request.ifr_addr, &address, address.sa_len); 661 662 if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) { 663 fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno)); 664 continue; 665 } 666 } 667 668 if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) { 669 fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno)); 670 continue; 671 } 672 int32 currentFlags = request.ifr_flags; 673 674 if (!hasMask && hasAddress && family_at_index(familyIndex) == AF_INET 675 && ioctl(familySocket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0 676 && request.ifr_mask.sa_family == AF_UNSPEC) { 677 // generate standard netmask if it doesn't have one yet 678 sockaddr_in *netmask = (sockaddr_in *)&mask; 679 netmask->sin_len = sizeof(sockaddr_in); 680 netmask->sin_family = AF_INET; 681 682 // choose default netmask depending on the class of the address 683 in_addr_t net = ((sockaddr_in *)&address)->sin_addr.s_addr; 684 if (IN_CLASSA(net) 685 || (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 686 // class A, or loopback 687 netmask->sin_addr.s_addr = IN_CLASSA_NET; 688 } else if (IN_CLASSB(net)) { 689 // class B 690 netmask->sin_addr.s_addr = IN_CLASSB_NET; 691 } else { 692 // class C and rest 693 netmask->sin_addr.s_addr = IN_CLASSC_NET; 694 } 695 696 hasMask = true; 697 } 698 if (hasMask) { 699 memcpy(&request.ifr_mask, &mask, mask.sa_len); 700 701 if (ioctl(familySocket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) { 702 fprintf(stderr, "%s: Setting subnet mask failed: %s\n", Name(), strerror(errno)); 703 continue; 704 } 705 } 706 707 if (!hasBroadcast && hasAddress && (currentFlags & IFF_BROADCAST) 708 && family_at_index(familyIndex) == AF_INET 709 && ioctl(familySocket, SIOCGIFBRDADDR, &request, sizeof(struct ifreq)) == 0 710 && request.ifr_mask.sa_family == AF_UNSPEC) { 711 // generate standard broadcast address if it doesn't have one yet 712 sockaddr_in *broadcastAddr = (sockaddr_in *)&broadcast; 713 uint32 maskValue = ((sockaddr_in *)&mask)->sin_addr.s_addr; 714 uint32 broadcastValue = ((sockaddr_in *)&address)->sin_addr.s_addr; 715 broadcastValue = (broadcastValue & maskValue) | ~maskValue; 716 broadcastAddr->sin_len = sizeof(sockaddr_in); 717 broadcastAddr->sin_family = AF_INET; 718 broadcastAddr->sin_addr.s_addr = broadcastValue; 719 hasBroadcast = true; 720 } 721 if (hasBroadcast) { 722 memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len); 723 724 if (ioctl(familySocket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) { 725 fprintf(stderr, "%s: Setting broadcast address failed: %s\n", Name(), strerror(errno)); 726 continue; 727 } 728 } 729 730 if (hasPeer) { 731 memcpy(&request.ifr_dstaddr, &peer, peer.sa_len); 732 733 if (ioctl(familySocket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) { 734 fprintf(stderr, "%s: Setting peer address failed: %s\n", Name(), strerror(errno)); 735 continue; 736 } 737 } 738 739 // set flags 740 741 if (flags != 0) { 742 request.ifr_flags = currentFlags | flags; 743 if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) 744 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno)); 745 } 746 747 // set options 748 749 if (mtu != -1) { 750 request.ifr_mtu = mtu; 751 if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) 752 fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno)); 753 } 754 755 if (metric != -1) { 756 request.ifr_metric = metric; 757 if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) 758 fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno)); 759 } 760 } 761 762 if (startAutoConfig) { 763 // start auto configuration 764 AutoconfigLooper* looper = new AutoconfigLooper(this, device); 765 looper->Run(); 766 767 fDeviceMap[device] = looper; 768 } 769 770 return B_OK; 771 } 772 773 774 bool 775 NetServer::_QuitLooperForDevice(const char* device) 776 { 777 LooperMap::iterator iterator = fDeviceMap.find(device); 778 if (iterator == fDeviceMap.end()) 779 return false; 780 781 // there is a looper for this device - quit it 782 iterator->second->Lock(); 783 iterator->second->Quit(); 784 785 fDeviceMap.erase(iterator); 786 787 StatusMap::iterator it = fStatusMap.find(device); 788 if (it != fStatusMap.end()) { 789 fStatusMap.erase(it); 790 _UpdateReplicantStatus(); 791 } 792 793 return true; 794 } 795 796 797 BLooper* 798 NetServer::_LooperForDevice(const char* device) 799 { 800 LooperMap::const_iterator iterator = fDeviceMap.find(device); 801 if (iterator == fDeviceMap.end()) 802 return NULL; 803 804 return iterator->second; 805 } 806 807 808 status_t 809 NetServer::_ConfigureDevice(int socket, const char* path) 810 { 811 // bring interface up, but don't configure it just yet 812 BMessage interface; 813 interface.AddString("device", path); 814 BMessage address; 815 address.AddString("family", "inet"); 816 address.AddBool("auto config", true); 817 interface.AddMessage("address", &address); 818 819 return _ConfigureInterface(socket, interface); 820 } 821 822 823 void 824 NetServer::_ConfigureDevices(int socket, const char* startPath, 825 BMessage* suggestedInterface) 826 { 827 BDirectory directory(startPath); 828 BEntry entry; 829 while (directory.GetNextEntry(&entry) == B_OK) { 830 char name[B_FILE_NAME_LENGTH]; 831 struct stat stat; 832 BPath path; 833 if (entry.GetName(name) != B_OK 834 || !strcmp(name, "stack") 835 || entry.GetPath(&path) != B_OK 836 || entry.GetStat(&stat) != B_OK) 837 continue; 838 839 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) { 840 if (suggestedInterface != NULL 841 && suggestedInterface->RemoveName("device") == B_OK 842 && suggestedInterface->AddString("device", path.Path()) == B_OK 843 && _ConfigureInterface(socket, *suggestedInterface) == B_OK) 844 suggestedInterface = NULL; 845 else 846 _ConfigureDevice(socket, path.Path()); 847 } else if (entry.IsDirectory()) 848 _ConfigureDevices(socket, path.Path(), suggestedInterface); 849 } 850 } 851 852 853 void 854 NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice) 855 { 856 BMessage interface; 857 uint32 cookie = 0; 858 bool missing = false; 859 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 860 const char *device; 861 if (interface.FindString("device", &device) != B_OK) 862 continue; 863 864 if (!strncmp(device, "/dev/net/", 9)) { 865 // it's a kernel device, check if it's present 866 BEntry entry(device); 867 if (!entry.Exists()) { 868 if (!missing && _missingDevice != NULL) { 869 *_missingDevice = interface; 870 missing = true; 871 } 872 continue; 873 } 874 } 875 876 if (_ConfigureInterface(socket, interface) == B_OK) 877 _UpdateDeviceStatus(device, kStatusConnected); 878 } 879 } 880 881 882 void 883 NetServer::_BringUpInterfaces() 884 { 885 // we need a socket to talk to the networking stack 886 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 887 if (socket < 0) { 888 fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n", 889 Name()); 890 Quit(); 891 return; 892 } 893 894 _RemoveInvalidInterfaces(socket); 895 896 // First, we look into the settings, and try to bring everything up from there 897 898 BMessage missingDevice; 899 _ConfigureInterfaces(socket, &missingDevice); 900 901 // check configuration 902 903 if (!_TestForInterface(socket, "loop")) { 904 // there is no loopback interface, create one 905 BMessage interface; 906 interface.AddString("device", "loop"); 907 BMessage address; 908 address.AddString("family", "inet"); 909 address.AddString("address", "127.0.0.1"); 910 interface.AddMessage("address", &address); 911 912 _ConfigureInterface(socket, interface); 913 } 914 915 // TODO: also check if the networking driver is correctly initialized! 916 // (and check for other devices to take over its configuration) 917 918 if (!_TestForInterface(socket, "/dev/net/")) { 919 // there is no driver configured - see if there is one and try to use it 920 _ConfigureDevices(socket, "/dev/net", 921 missingDevice.HasString("device") ? &missingDevice : NULL); 922 } 923 924 close(socket); 925 } 926 927 928 void 929 NetServer::_StartServices() 930 { 931 BHandler* services = new (std::nothrow) Services(fSettings.Services()); 932 if (services != NULL) { 933 AddHandler(services); 934 fServices = BMessenger(services); 935 } 936 } 937 938 939 status_t 940 NetServer::_AddStatusReplicant(bool force) 941 { 942 BDeskbar deskbar; 943 status_t status; 944 945 if (deskbar.HasItem(kStatusReplicant)) { 946 if (force) { 947 status = deskbar.RemoveItem(kStatusReplicant); 948 if (status != B_OK) 949 return status; 950 } else { 951 return B_OK; 952 } 953 } 954 955 StatusReplicant *replicant = new StatusReplicant(); 956 status = deskbar.AddItem(replicant); 957 delete replicant; 958 959 return status; 960 } 961 962 963 void 964 NetServer::_UpdateDeviceStatus(const char *device, int status) 965 { 966 if (strcmp(device, "loop") == 0) 967 return; 968 969 StatusMap::iterator it = fStatusMap.find(device); 970 if (it != fStatusMap.end() && it->second == status) 971 return; 972 973 fStatusMap[device] = status; 974 _UpdateReplicantStatus(); 975 } 976 977 978 void 979 NetServer::_UpdateReplicantStatus() 980 { 981 if (!fStatusMessenger.IsValid()) 982 return; 983 984 int prevaling = kStatusUnknown; 985 986 BMessage message(kStatusUpdate); 987 988 for (StatusMap::iterator it = fStatusMap.begin(); 989 it != fStatusMap.end(); ++it) { 990 if (it->second > prevaling) 991 prevaling = it->second; 992 993 message.AddString("interface:name", it->first.c_str()); 994 message.AddInt32("interface:status", it->second); 995 } 996 997 message.AddInt32("net:status", prevaling); 998 999 fStatusMessenger.SendMessage(&message); 1000 } 1001 1002 1003 // #pragma mark - 1004 1005 1006 int 1007 main() 1008 { 1009 status_t status; 1010 NetServer server(status); 1011 if (status != B_OK) { 1012 fprintf(stderr, "net_server: Failed to create application: %s\n", 1013 strerror(status)); 1014 return 1; 1015 } 1016 1017 server.Run(); 1018 return 0; 1019 } 1020 1021