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