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