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 ioctl(socket, SIOCDELRT, &request, sizeof(request)); 590 // Try to remove a previous default route, doesn't matter 591 // if it fails. 592 593 if (autoConfig) { 594 // add a default route to make the interface accessible, even without an address 595 if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { 596 fprintf(stderr, "%s: Could not add route for %s: %s\n", 597 Name(), device, strerror(errno)); 598 } else { 599 _QuitLooperForDevice(device); 600 startAutoConfig = true; 601 } 602 } else if (addressMessage.FindString("gateway", &string) == B_OK 603 && parse_address(familyIndex, string, gateway)) { 604 // add gateway route, if we're asked for it 605 route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; 606 route.gateway = &gateway; 607 608 request.ifr_route = route; 609 if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { 610 fprintf(stderr, "%s: Could not add route for %s: %s\n", 611 Name(), device, strerror(errno)); 612 } 613 } 614 615 // set addresses 616 617 if (hasAddress) { 618 memcpy(&request.ifr_addr, &address, address.sa_len); 619 620 if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) { 621 fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno)); 622 continue; 623 } 624 } 625 626 if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) { 627 fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno)); 628 continue; 629 } 630 int32 currentFlags = request.ifr_flags; 631 632 if (!hasMask && hasAddress && family_at_index(familyIndex) == AF_INET 633 && ioctl(familySocket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0 634 && request.ifr_mask.sa_family == AF_UNSPEC) { 635 // generate standard netmask if it doesn't have one yet 636 sockaddr_in *netmask = (sockaddr_in *)&mask; 637 netmask->sin_len = sizeof(sockaddr_in); 638 netmask->sin_family = AF_INET; 639 640 // choose default netmask depending on the class of the address 641 in_addr_t net = ((sockaddr_in *)&address)->sin_addr.s_addr; 642 if (IN_CLASSA(net) 643 || (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 644 // class A, or loopback 645 netmask->sin_addr.s_addr = IN_CLASSA_NET; 646 } else if (IN_CLASSB(net)) { 647 // class B 648 netmask->sin_addr.s_addr = IN_CLASSB_NET; 649 } else { 650 // class C and rest 651 netmask->sin_addr.s_addr = IN_CLASSC_NET; 652 } 653 654 hasMask = true; 655 } 656 if (hasMask) { 657 memcpy(&request.ifr_mask, &mask, mask.sa_len); 658 659 if (ioctl(familySocket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) { 660 fprintf(stderr, "%s: Setting subnet mask failed: %s\n", Name(), strerror(errno)); 661 continue; 662 } 663 } 664 665 if (!hasBroadcast && hasAddress && (currentFlags & IFF_BROADCAST) 666 && family_at_index(familyIndex) == AF_INET 667 && ioctl(familySocket, SIOCGIFBRDADDR, &request, sizeof(struct ifreq)) == 0 668 && request.ifr_mask.sa_family == AF_UNSPEC) { 669 // generate standard broadcast address if it doesn't have one yet 670 sockaddr_in *broadcastAddr = (sockaddr_in *)&broadcast; 671 uint32 maskValue = ((sockaddr_in *)&mask)->sin_addr.s_addr; 672 uint32 broadcastValue = ((sockaddr_in *)&address)->sin_addr.s_addr; 673 broadcastValue = (broadcastValue & maskValue) | ~maskValue; 674 broadcastAddr->sin_len = sizeof(sockaddr_in); 675 broadcastAddr->sin_family = AF_INET; 676 broadcastAddr->sin_addr.s_addr = broadcastValue; 677 hasBroadcast = true; 678 } 679 if (hasBroadcast) { 680 memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len); 681 682 if (ioctl(familySocket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) { 683 fprintf(stderr, "%s: Setting broadcast address failed: %s\n", Name(), strerror(errno)); 684 continue; 685 } 686 } 687 688 if (hasPeer) { 689 memcpy(&request.ifr_dstaddr, &peer, peer.sa_len); 690 691 if (ioctl(familySocket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) { 692 fprintf(stderr, "%s: Setting peer address failed: %s\n", Name(), strerror(errno)); 693 continue; 694 } 695 } 696 697 // set flags 698 699 if (flags != 0) { 700 request.ifr_flags = currentFlags | flags; 701 if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) 702 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno)); 703 } 704 705 // set options 706 707 if (mtu != -1) { 708 request.ifr_mtu = mtu; 709 if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) 710 fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno)); 711 } 712 713 if (metric != -1) { 714 request.ifr_metric = metric; 715 if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) 716 fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno)); 717 } 718 } 719 720 if (startAutoConfig) { 721 // start auto configuration 722 AutoconfigLooper* looper = new AutoconfigLooper(this, device); 723 looper->Run(); 724 725 fDeviceMap[device] = looper; 726 } 727 728 return B_OK; 729 } 730 731 732 bool 733 NetServer::_QuitLooperForDevice(const char* device) 734 { 735 LooperMap::iterator iterator = fDeviceMap.find(device); 736 if (iterator == fDeviceMap.end()) 737 return false; 738 739 // there is a looper for this device - quit it 740 iterator->second->Lock(); 741 iterator->second->Quit(); 742 743 fDeviceMap.erase(iterator); 744 return true; 745 } 746 747 748 BLooper* 749 NetServer::_LooperForDevice(const char* device) 750 { 751 LooperMap::const_iterator iterator = fDeviceMap.find(device); 752 if (iterator == fDeviceMap.end()) 753 return NULL; 754 755 return iterator->second; 756 } 757 758 759 status_t 760 NetServer::_ConfigureDevice(int socket, const char* path) 761 { 762 // bring interface up, but don't configure it just yet 763 BMessage interface; 764 interface.AddString("device", path); 765 BMessage address; 766 address.AddString("family", "inet"); 767 address.AddBool("auto config", true); 768 interface.AddMessage("address", &address); 769 770 return _ConfigureInterface(socket, interface); 771 } 772 773 774 void 775 NetServer::_ConfigureDevices(int socket, const char* startPath, 776 BMessage* suggestedInterface) 777 { 778 BDirectory directory(startPath); 779 BEntry entry; 780 while (directory.GetNextEntry(&entry) == B_OK) { 781 char name[B_FILE_NAME_LENGTH]; 782 struct stat stat; 783 BPath path; 784 if (entry.GetName(name) != B_OK 785 || !strcmp(name, "stack") 786 || entry.GetPath(&path) != B_OK 787 || entry.GetStat(&stat) != B_OK) 788 continue; 789 790 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) { 791 if (suggestedInterface != NULL 792 && suggestedInterface->RemoveName("device") == B_OK 793 && suggestedInterface->AddString("device", path.Path()) == B_OK 794 && _ConfigureInterface(socket, *suggestedInterface) == B_OK) 795 suggestedInterface = NULL; 796 else 797 _ConfigureDevice(socket, path.Path()); 798 } else if (entry.IsDirectory()) 799 _ConfigureDevices(socket, path.Path(), suggestedInterface); 800 } 801 } 802 803 804 void 805 NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice) 806 { 807 BMessage interface; 808 uint32 cookie = 0; 809 bool missing = false; 810 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 811 const char *device; 812 if (interface.FindString("device", &device) != B_OK) 813 continue; 814 815 if (!strncmp(device, "/dev/net/", 9)) { 816 // it's a kernel device, check if it's present 817 BEntry entry(device); 818 if (!entry.Exists()) { 819 if (!missing && _missingDevice != NULL) { 820 *_missingDevice = interface; 821 missing = true; 822 } 823 continue; 824 } 825 } 826 827 _ConfigureInterface(socket, interface); 828 } 829 } 830 831 832 void 833 NetServer::_BringUpInterfaces() 834 { 835 // we need a socket to talk to the networking stack 836 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 837 if (socket < 0) { 838 fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n", 839 Name()); 840 Quit(); 841 return; 842 } 843 844 _RemoveInvalidInterfaces(socket); 845 846 // First, we look into the settings, and try to bring everything up from there 847 848 BMessage missingDevice; 849 _ConfigureInterfaces(socket, &missingDevice); 850 851 // check configuration 852 853 if (!_TestForInterface(socket, "loop")) { 854 // there is no loopback interface, create one 855 BMessage interface; 856 interface.AddString("device", "loop"); 857 BMessage address; 858 address.AddString("family", "inet"); 859 address.AddString("address", "127.0.0.1"); 860 interface.AddMessage("address", &address); 861 862 _ConfigureInterface(socket, interface); 863 } 864 865 // TODO: also check if the networking driver is correctly initialized! 866 // (and check for other devices to take over its configuration) 867 868 if (!_TestForInterface(socket, "/dev/net/")) { 869 // there is no driver configured - see if there is one and try to use it 870 _ConfigureDevices(socket, "/dev/net", 871 missingDevice.HasString("device") ? &missingDevice : NULL); 872 } 873 874 close(socket); 875 } 876 877 878 void 879 NetServer::_StartServices() 880 { 881 BHandler* services = new (std::nothrow) Services(fSettings.Services()); 882 if (services != NULL) { 883 AddHandler(services); 884 fServices = BMessenger(services); 885 } 886 } 887 888 889 // #pragma mark - 890 891 892 int 893 main() 894 { 895 status_t status; 896 NetServer server(status); 897 if (status != B_OK) { 898 fprintf(stderr, "net_server: Failed to create application: %s\n", 899 strerror(status)); 900 return 1; 901 } 902 903 server.Run(); 904 return 0; 905 } 906 907