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