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 <NetworkDevice.h> 33 #include <NetworkInterface.h> 34 #include <NetworkRoster.h> 35 #include <Path.h> 36 #include <PathMonitor.h> 37 #include <Roster.h> 38 #include <Server.h> 39 #include <TextView.h> 40 #include <FindDirectory.h> 41 42 #include <AutoDeleter.h> 43 #include <WPASupplicant.h> 44 45 #include "AutoconfigLooper.h" 46 #include "Services.h" 47 #include "Settings.h" 48 49 extern "C" { 50 # include <net80211/ieee80211_ioctl.h> 51 } 52 53 54 typedef std::map<std::string, AutoconfigLooper*> LooperMap; 55 56 57 class NetServer : public BServer { 58 public: 59 NetServer(status_t& status); 60 virtual ~NetServer(); 61 62 virtual void AboutRequested(); 63 virtual void ReadyToRun(); 64 virtual void MessageReceived(BMessage* message); 65 66 private: 67 bool _IsValidInterface(BNetworkInterface& interface); 68 void _RemoveInvalidInterfaces(); 69 status_t _RemoveInterface(const char* name); 70 status_t _DisableInterface(const char* name); 71 bool _TestForInterface(const char* name); 72 status_t _ConfigureInterface(BMessage& interface); 73 status_t _ConfigureResolver( 74 BMessage& resolverConfiguration); 75 bool _QuitLooperForDevice(const char* device); 76 AutoconfigLooper* _LooperForDevice(const char* device); 77 status_t _ConfigureDevice(const char* path); 78 void _ConfigureDevices(const char* path, 79 BMessage* suggestedInterface = NULL); 80 void _ConfigureInterfaces( 81 BMessage* _missingDevice = NULL); 82 void _BringUpInterfaces(); 83 void _StartServices(); 84 status_t _HandleDeviceMonitor(BMessage* message); 85 86 status_t _AutoJoinNetwork(const char* name); 87 status_t _JoinNetwork(const BMessage& message, 88 const char* name = NULL); 89 status_t _LeaveNetwork(const BMessage& message); 90 91 status_t _ConvertNetworkToSettings(BMessage& message); 92 status_t _ConvertNetworkFromSettings(BMessage& message); 93 94 private: 95 Settings fSettings; 96 LooperMap fDeviceMap; 97 BMessenger fServices; 98 }; 99 100 101 struct address_family { 102 int family; 103 const char* name; 104 const char* identifiers[4]; 105 }; 106 107 108 // AF_INET6 family 109 #if INET6 110 static bool inet6_parse_address(const char* string, sockaddr* address); 111 static void inet6_set_any_address(sockaddr* address); 112 static void inet6_set_port(sockaddr* address, int32 port); 113 #endif 114 115 static const address_family kFamilies[] = { 116 { 117 AF_INET, 118 "inet", 119 {"AF_INET", "inet", "ipv4", NULL}, 120 }, 121 { 122 AF_INET6, 123 "inet6", 124 {"AF_INET6", "inet6", "ipv6", NULL}, 125 }, 126 { -1, NULL, {NULL} } 127 }; 128 129 130 // #pragma mark - private functions 131 132 133 static status_t 134 set_80211(const char* name, int32 type, void* data, 135 int32 length = 0, int32 value = 0) 136 { 137 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 138 if (socket < 0) 139 return errno; 140 141 FileDescriptorCloser closer(socket); 142 143 struct ieee80211req ireq; 144 strlcpy(ireq.i_name, name, IF_NAMESIZE); 145 ireq.i_type = type; 146 ireq.i_val = value; 147 ireq.i_len = length; 148 ireq.i_data = data; 149 150 if (ioctl(socket, SIOCS80211, &ireq, sizeof(struct ieee80211req)) < 0) 151 return errno; 152 153 return B_OK; 154 } 155 156 157 // #pragma mark - exported functions 158 159 160 int 161 get_address_family(const char* argument) 162 { 163 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 164 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 165 if (!strcmp(argument, kFamilies[i].identifiers[j])) { 166 // found a match 167 return kFamilies[i].family; 168 } 169 } 170 } 171 172 return AF_UNSPEC; 173 } 174 175 176 /*! Parses the \a argument as network \a address for the specified \a family. 177 If \a family is \c AF_UNSPEC, \a family will be overwritten with the family 178 of the successfully parsed address. 179 */ 180 bool 181 parse_address(int32& family, const char* argument, BNetworkAddress& address) 182 { 183 if (argument == NULL) 184 return false; 185 186 status_t status = address.SetTo(family, argument, (uint16)0, 187 B_NO_ADDRESS_RESOLUTION); 188 if (status != B_OK) 189 return false; 190 191 if (family == AF_UNSPEC) { 192 // Test if we support the resulting address family 193 bool supported = false; 194 195 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 196 if (kFamilies[i].family == address.Family()) { 197 supported = true; 198 break; 199 } 200 } 201 if (!supported) 202 return false; 203 204 // Take over family from address 205 family = address.Family(); 206 } 207 208 return true; 209 } 210 211 212 #if INET6 213 static bool 214 inet6_parse_address(const char* string, sockaddr* _address) 215 { 216 sockaddr_in6& address = *(sockaddr_in6*)_address; 217 218 if (inet_pton(AF_INET6, string, &address.sin6_addr) != 1) 219 return false; 220 221 address.sin6_family = AF_INET6; 222 address.sin6_len = sizeof(sockaddr_in6); 223 address.sin6_port = 0; 224 address.sin6_flowinfo = 0; 225 address.sin6_scope_id = 0; 226 227 return true; 228 } 229 230 231 void 232 inet6_set_any_address(sockaddr* _address) 233 { 234 sockaddr_in6& address = *(sockaddr_in6*)_address; 235 memset(&address, 0, sizeof(sockaddr_in6)); 236 address.sin6_family = AF_INET6; 237 address.sin6_len = sizeof(struct sockaddr_in6); 238 } 239 240 241 void 242 inet6_set_port(sockaddr* _address, int32 port) 243 { 244 sockaddr_in6& address = *(sockaddr_in6*)_address; 245 address.sin6_port = port; 246 } 247 #endif 248 249 250 // #pragma mark - 251 252 253 NetServer::NetServer(status_t& error) 254 : 255 BServer(kNetServerSignature, false, &error) 256 { 257 } 258 259 260 NetServer::~NetServer() 261 { 262 BPrivate::BPathMonitor::StopWatching("/dev/net", this); 263 } 264 265 266 void 267 NetServer::AboutRequested() 268 { 269 BAlert *alert = new BAlert("about", "Networking Server\n" 270 "\tCopyright " B_UTF8_COPYRIGHT "2006, Haiku.\n", "OK"); 271 BTextView *view = alert->TextView(); 272 BFont font; 273 274 view->SetStylable(true); 275 276 view->GetFont(&font); 277 font.SetSize(18); 278 font.SetFace(B_BOLD_FACE); 279 view->SetFontAndColor(0, 17, &font); 280 281 alert->Go(NULL); 282 } 283 284 285 void 286 NetServer::ReadyToRun() 287 { 288 fSettings.StartMonitoring(this); 289 _BringUpInterfaces(); 290 _StartServices(); 291 292 BPrivate::BPathMonitor::StartWatching("/dev/net", B_ENTRY_CREATED 293 | B_ENTRY_REMOVED | B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this); 294 } 295 296 297 void 298 NetServer::MessageReceived(BMessage* message) 299 { 300 switch (message->what) { 301 case B_PATH_MONITOR: 302 { 303 fSettings.Update(message); 304 _HandleDeviceMonitor(message); 305 break; 306 } 307 308 case kMsgInterfaceSettingsUpdated: 309 { 310 _ConfigureInterfaces(); 311 break; 312 } 313 314 case kMsgServiceSettingsUpdated: 315 { 316 BMessage update = fSettings.Services(); 317 update.what = kMsgUpdateServices; 318 319 fServices.SendMessage(&update); 320 break; 321 } 322 323 case kMsgConfigureInterface: 324 { 325 status_t status = _ConfigureInterface(*message); 326 327 BMessage reply(B_REPLY); 328 reply.AddInt32("status", status); 329 message->SendReply(&reply); 330 break; 331 } 332 333 case kMsgConfigureResolver: 334 { 335 status_t status = _ConfigureResolver(*message); 336 337 BMessage reply(B_REPLY); 338 reply.AddInt32("status", status); 339 message->SendReply(&reply); 340 break; 341 } 342 343 case kMsgJoinNetwork: 344 { 345 status_t status = _JoinNetwork(*message); 346 347 BMessage reply(B_REPLY); 348 reply.AddInt32("status", status); 349 message->SendReply(&reply); 350 break; 351 } 352 353 case kMsgLeaveNetwork: 354 { 355 status_t status = _LeaveNetwork(*message); 356 357 BMessage reply(B_REPLY); 358 reply.AddInt32("status", status); 359 message->SendReply(&reply); 360 break; 361 } 362 363 case kMsgCountPersistentNetworks: 364 { 365 BMessage reply(B_REPLY); 366 reply.AddInt32("count", fSettings.CountNetworks()); 367 message->SendReply(&reply); 368 break; 369 } 370 371 case kMsgGetPersistentNetwork: 372 { 373 uint32 index = 0; 374 status_t result = message->FindInt32("index", (int32*)&index); 375 376 BMessage reply(B_REPLY); 377 if (result == B_OK) { 378 BMessage network; 379 result = fSettings.GetNextNetwork(index, network); 380 if (result == B_OK) 381 result = _ConvertNetworkFromSettings(network); 382 if (result == B_OK) 383 result = reply.AddMessage("network", &network); 384 } 385 386 reply.AddInt32("status", result); 387 message->SendReply(&reply); 388 break; 389 } 390 391 case kMsgAddPersistentNetwork: 392 { 393 status_t result = _ConvertNetworkToSettings(*message); 394 if (result == B_OK) 395 result = fSettings.AddNetwork(*message); 396 397 BMessage reply(B_REPLY); 398 reply.AddInt32("status", result); 399 message->SendReply(&reply); 400 break; 401 } 402 403 case kMsgRemovePersistentNetwork: 404 { 405 const char* networkName = NULL; 406 status_t result = message->FindString("name", &networkName); 407 if (result == B_OK) 408 result = fSettings.RemoveNetwork(networkName); 409 410 BMessage reply(B_REPLY); 411 reply.AddInt32("status", result); 412 message->SendReply(&reply); 413 break; 414 } 415 416 default: 417 BApplication::MessageReceived(message); 418 return; 419 } 420 } 421 422 423 /*! Checks if an interface is valid, that is, if it has an address in any 424 family, and, in case of ethernet, a hardware MAC address. 425 */ 426 bool 427 NetServer::_IsValidInterface(BNetworkInterface& interface) 428 { 429 // check if it has an address 430 431 if (interface.CountAddresses() == 0) 432 return false; 433 434 // check if it has a hardware address, too, in case of ethernet 435 436 BNetworkAddress link; 437 if (interface.GetHardwareAddress(link) != B_OK) 438 return false; 439 440 if (link.LinkLevelType() == IFT_ETHER && link.LinkLevelAddressLength() != 6) 441 return false; 442 443 return true; 444 } 445 446 447 void 448 NetServer::_RemoveInvalidInterfaces() 449 { 450 BNetworkRoster& roster = BNetworkRoster::Default(); 451 BNetworkInterface interface; 452 uint32 cookie = 0; 453 454 while (roster.GetNextInterface(&cookie, interface) == B_OK) { 455 if (!_IsValidInterface(interface)) { 456 // remove invalid interface 457 _RemoveInterface(interface.Name()); 458 } 459 } 460 } 461 462 463 bool 464 NetServer::_TestForInterface(const char* name) 465 { 466 467 BNetworkRoster& roster = BNetworkRoster::Default(); 468 int32 nameLength = strlen(name); 469 BNetworkInterface interface; 470 uint32 cookie = 0; 471 472 while (roster.GetNextInterface(&cookie, interface) == B_OK) { 473 if (!strncmp(interface.Name(), name, nameLength)) 474 return true; 475 } 476 477 return false; 478 } 479 480 481 status_t 482 NetServer::_RemoveInterface(const char* name) 483 { 484 BNetworkRoster& roster = BNetworkRoster::Default(); 485 status_t status = roster.RemoveInterface(name); 486 if (status != B_OK) { 487 fprintf(stderr, "%s: Could not delete interface %s: %s\n", 488 Name(), name, strerror(status)); 489 return status; 490 } 491 492 return B_OK; 493 } 494 495 496 status_t 497 NetServer::_DisableInterface(const char* name) 498 { 499 BNetworkInterface interface(name); 500 int32 flags = interface.Flags(); 501 502 // Set interface down 503 flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING); 504 505 status_t status = interface.SetFlags(flags); 506 if (status != B_OK) { 507 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), 508 strerror(status)); 509 return status; 510 } 511 512 fprintf(stderr, "%s: set %s interface down...\n", Name(), name); 513 return B_OK; 514 } 515 516 517 status_t 518 NetServer::_ConfigureInterface(BMessage& message) 519 { 520 const char* name; 521 if (message.FindString("device", &name) != B_OK) 522 return B_BAD_VALUE; 523 524 bool startAutoConfig = false; 525 526 int32 flags; 527 if (message.FindInt32("flags", &flags) != B_OK) 528 flags = IFF_UP; 529 530 bool autoConfigured; 531 if (message.FindBool("auto_configured", &autoConfigured) == B_OK 532 && autoConfigured) { 533 flags |= IFF_AUTO_CONFIGURED; 534 } 535 536 int32 mtu; 537 if (message.FindInt32("mtu", &mtu) != B_OK) 538 mtu = -1; 539 540 int32 metric; 541 if (message.FindInt32("metric", &metric) != B_OK) 542 metric = -1; 543 544 BNetworkInterface interface(name); 545 if (!interface.Exists()) { 546 // the interface does not exist yet, we have to add it first 547 BNetworkRoster& roster = BNetworkRoster::Default(); 548 549 status_t status = roster.AddInterface(interface); 550 if (status != B_OK) { 551 fprintf(stderr, "%s: Could not add interface: %s\n", 552 interface.Name(), strerror(status)); 553 return status; 554 } 555 } 556 557 BNetworkDevice device(name); 558 if (device.IsWireless()) { 559 const char* networkName; 560 if (message.FindString("network", &networkName) == B_OK) { 561 // join configured network 562 status_t status = _JoinNetwork(message, networkName); 563 if (status != B_OK) { 564 fprintf(stderr, "%s: joining network \"%s\" failed: %s\n", 565 interface.Name(), networkName, strerror(status)); 566 } 567 } else { 568 // auto select network to join 569 status_t status = _AutoJoinNetwork(name); 570 if (status != B_OK) { 571 fprintf(stderr, "%s: auto joining network failed: %s\n", 572 interface.Name(), strerror(status)); 573 } 574 } 575 } 576 577 BMessage addressMessage; 578 for (int32 index = 0; message.FindMessage("address", index, 579 &addressMessage) == B_OK; index++) { 580 int32 family; 581 if (addressMessage.FindInt32("family", &family) != B_OK) { 582 const char* familyString; 583 if (addressMessage.FindString("family", &familyString) == B_OK) { 584 if (get_address_family(familyString) == AF_UNSPEC) { 585 // we don't support this family 586 fprintf(stderr, "%s: Ignore unknown family: %s\n", Name(), 587 familyString); 588 continue; 589 } 590 } else 591 family = AF_UNSPEC; 592 } 593 594 // retrieve addresses 595 596 bool autoConfig; 597 if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK) 598 autoConfig = false; 599 600 BNetworkAddress address; 601 BNetworkAddress mask; 602 BNetworkAddress broadcast; 603 BNetworkAddress peer; 604 BNetworkAddress gateway; 605 606 const char* string; 607 608 if (!autoConfig) { 609 if (addressMessage.FindString("address", &string) == B_OK) { 610 parse_address(family, string, address); 611 612 if (addressMessage.FindString("mask", &string) == B_OK) 613 parse_address(family, string, mask); 614 } 615 616 if (addressMessage.FindString("peer", &string) == B_OK) 617 parse_address(family, string, peer); 618 619 if (addressMessage.FindString("broadcast", &string) == B_OK) 620 parse_address(family, string, broadcast); 621 } 622 623 if (autoConfig) { 624 _QuitLooperForDevice(name); 625 startAutoConfig = true; 626 } else if (addressMessage.FindString("gateway", &string) == B_OK 627 && parse_address(family, string, gateway)) { 628 // add gateway route, if we're asked for it 629 interface.RemoveDefaultRoute(family); 630 // Try to remove a previous default route, doesn't matter 631 // if it fails. 632 633 status_t status = interface.AddDefaultRoute(gateway); 634 if (status != B_OK) { 635 fprintf(stderr, "%s: Could not add route for %s: %s\n", 636 Name(), name, strerror(errno)); 637 } 638 } 639 640 // set address/mask/broadcast/peer 641 642 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) { 643 BNetworkInterfaceAddress interfaceAddress; 644 interfaceAddress.SetAddress(address); 645 interfaceAddress.SetMask(mask); 646 if (!broadcast.IsEmpty()) 647 interfaceAddress.SetBroadcast(broadcast); 648 else if (!peer.IsEmpty()) 649 interfaceAddress.SetDestination(peer); 650 651 status_t status = interface.SetAddress(interfaceAddress); 652 if (status != B_OK) { 653 fprintf(stderr, "%s: Setting address failed: %s\n", Name(), 654 strerror(status)); 655 return status; 656 } 657 } 658 659 // set flags 660 661 if (flags != 0) { 662 int32 newFlags = interface.Flags(); 663 newFlags = (newFlags & ~IFF_CONFIGURING) | flags; 664 if (!autoConfigured) 665 newFlags &= ~IFF_AUTO_CONFIGURED; 666 667 status_t status = interface.SetFlags(newFlags); 668 if (status != B_OK) { 669 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), 670 strerror(status)); 671 } 672 } 673 674 // set options 675 676 if (mtu != -1) { 677 status_t status = interface.SetMTU(mtu); 678 if (status != B_OK) { 679 fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), 680 strerror(status)); 681 } 682 } 683 684 if (metric != -1) { 685 status_t status = interface.SetMetric(metric); 686 if (status != B_OK) { 687 fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), 688 strerror(status)); 689 } 690 } 691 } 692 693 if (startAutoConfig) { 694 // start auto configuration 695 AutoconfigLooper* looper = new AutoconfigLooper(this, name); 696 looper->Run(); 697 698 fDeviceMap[name] = looper; 699 } else if (!autoConfigured) 700 _QuitLooperForDevice(name); 701 702 return B_OK; 703 } 704 705 706 status_t 707 NetServer::_ConfigureResolver(BMessage& resolverConfiguration) 708 { 709 // TODO: resolv.conf should be parsed, all information should be 710 // maintained and it should be distinguished between user entered 711 // and auto-generated parts of the file, with this method only re-writing 712 // the auto-generated parts of course. 713 714 BPath path; 715 if (find_directory(B_COMMON_SETTINGS_DIRECTORY, &path) != B_OK 716 || path.Append("network/resolv.conf") != B_OK) 717 return B_ERROR; 718 719 FILE* file = fopen(path.Path(), "w"); 720 if (file != NULL) { 721 const char* nameserver; 722 for (int32 i = 0; resolverConfiguration.FindString("nameserver", i, 723 &nameserver) == B_OK; i++) { 724 fprintf(file, "nameserver %s\n", nameserver); 725 } 726 727 const char* domain; 728 if (resolverConfiguration.FindString("domain", &domain) == B_OK) 729 fprintf(file, "domain %s\n", domain); 730 731 fclose(file); 732 } 733 return B_OK; 734 } 735 736 737 bool 738 NetServer::_QuitLooperForDevice(const char* device) 739 { 740 LooperMap::iterator iterator = fDeviceMap.find(device); 741 if (iterator == fDeviceMap.end()) 742 return false; 743 744 // there is a looper for this device - quit it 745 if (iterator->second->Lock()) 746 iterator->second->Quit(); 747 748 fDeviceMap.erase(iterator); 749 return true; 750 } 751 752 753 AutoconfigLooper* 754 NetServer::_LooperForDevice(const char* device) 755 { 756 LooperMap::const_iterator iterator = fDeviceMap.find(device); 757 if (iterator == fDeviceMap.end()) 758 return NULL; 759 760 return iterator->second; 761 } 762 763 764 status_t 765 NetServer::_ConfigureDevice(const char* device) 766 { 767 // bring interface up, but don't configure it just yet 768 BMessage interface; 769 interface.AddString("device", device); 770 BMessage address; 771 address.AddString("family", "inet"); 772 address.AddBool("auto_config", true); 773 interface.AddMessage("address", &address); 774 775 return _ConfigureInterface(interface); 776 } 777 778 779 void 780 NetServer::_ConfigureDevices(const char* startPath, 781 BMessage* suggestedInterface) 782 { 783 BDirectory directory(startPath); 784 BEntry entry; 785 while (directory.GetNextEntry(&entry) == B_OK) { 786 char name[B_FILE_NAME_LENGTH]; 787 struct stat stat; 788 BPath path; 789 if (entry.GetName(name) != B_OK 790 || entry.GetPath(&path) != B_OK 791 || entry.GetStat(&stat) != B_OK) 792 continue; 793 794 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) { 795 if (suggestedInterface != NULL 796 && suggestedInterface->RemoveName("device") == B_OK 797 && suggestedInterface->AddString("device", path.Path()) == B_OK 798 && _ConfigureInterface(*suggestedInterface) == B_OK) 799 suggestedInterface = NULL; 800 else 801 _ConfigureDevice(path.Path()); 802 } else if (entry.IsDirectory()) 803 _ConfigureDevices(path.Path(), suggestedInterface); 804 } 805 } 806 807 808 void 809 NetServer::_ConfigureInterfaces(BMessage* _missingDevice) 810 { 811 BMessage interface; 812 uint32 cookie = 0; 813 bool missing = false; 814 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 815 const char *device; 816 if (interface.FindString("device", &device) != B_OK) 817 continue; 818 819 bool disabled = false; 820 if (interface.FindBool("disabled", &disabled) == B_OK && disabled) { 821 // disabled by user request 822 _DisableInterface(device); 823 continue; 824 } 825 826 if (!strncmp(device, "/dev/net/", 9)) { 827 // it's a kernel device, check if it's present 828 BEntry entry(device); 829 if (!entry.Exists()) { 830 if (!missing && _missingDevice != NULL) { 831 *_missingDevice = interface; 832 missing = true; 833 } 834 continue; 835 } 836 } 837 838 _ConfigureInterface(interface); 839 } 840 } 841 842 843 void 844 NetServer::_BringUpInterfaces() 845 { 846 // we need a socket to talk to the networking stack 847 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 848 if (socket < 0) { 849 fprintf(stderr, "%s: The networking stack doesn't seem to be " 850 "available.\n", Name()); 851 Quit(); 852 return; 853 } 854 close(socket); 855 856 _RemoveInvalidInterfaces(); 857 858 // First, we look into the settings, and try to bring everything up from there 859 860 BMessage missingDevice; 861 _ConfigureInterfaces(&missingDevice); 862 863 // check configuration 864 865 if (!_TestForInterface("loop")) { 866 // there is no loopback interface, create one 867 BMessage interface; 868 interface.AddString("device", "loop"); 869 BMessage address; 870 address.AddString("family", "inet"); 871 address.AddString("address", "127.0.0.1"); 872 interface.AddMessage("address", &address); 873 874 _ConfigureInterface(interface); 875 } 876 877 // TODO: also check if the networking driver is correctly initialized! 878 // (and check for other devices to take over its configuration) 879 880 if (!_TestForInterface("/dev/net/")) { 881 // there is no driver configured - see if there is one and try to use it 882 _ConfigureDevices("/dev/net", 883 missingDevice.HasString("device") ? &missingDevice : NULL); 884 } 885 } 886 887 888 void 889 NetServer::_StartServices() 890 { 891 BHandler* services = new (std::nothrow) Services(fSettings.Services()); 892 if (services != NULL) { 893 AddHandler(services); 894 fServices = BMessenger(services); 895 } 896 } 897 898 899 status_t 900 NetServer::_HandleDeviceMonitor(BMessage* message) 901 { 902 int32 opcode; 903 const char* path; 904 if (message->FindInt32("opcode", &opcode) != B_OK 905 || (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED) 906 || message->FindString("path", &path) != B_OK) 907 return B_BAD_VALUE; 908 909 if (strncmp(path, "/dev/net", 9)) { 910 // not a device entry, ignore 911 return B_NAME_NOT_FOUND; 912 } 913 914 if (opcode == B_ENTRY_CREATED) 915 _ConfigureDevice(path); 916 else 917 _RemoveInterface(path); 918 919 return B_OK; 920 } 921 922 923 status_t 924 NetServer::_AutoJoinNetwork(const char* name) 925 { 926 BNetworkDevice device(name); 927 928 BMessage message; 929 message.AddString("device", name); 930 931 // Choose among configured networks 932 933 uint32 cookie = 0; 934 BMessage networkMessage; 935 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 936 status_t status = B_ERROR; 937 wireless_network network; 938 const char* networkName; 939 BNetworkAddress link; 940 941 const char* mac; 942 if (networkMessage.FindString("mac", &mac) == B_OK) { 943 link.SetTo(AF_LINK, mac); 944 status = device.GetNetwork(link, network); 945 } else if (networkMessage.FindString("name", &networkName) == B_OK) 946 status = device.GetNetwork(networkName, network); 947 948 if (status == B_OK) { 949 status = _JoinNetwork(message, network.name); 950 printf("auto join network \"%s\": %s\n", network.name, 951 strerror(status)); 952 if (status == B_OK) 953 return B_OK; 954 } 955 } 956 957 return B_NO_INIT; 958 } 959 960 961 status_t 962 NetServer::_JoinNetwork(const BMessage& message, const char* name) 963 { 964 const char* deviceName; 965 if (message.FindString("device", &deviceName) != B_OK) 966 return B_BAD_VALUE; 967 968 BNetworkAddress address; 969 message.FindFlat("address", &address); 970 971 if (name == NULL) 972 message.FindString("name", &name); 973 if (name == NULL) { 974 // No name specified, we need a network address 975 if (address.Family() != AF_LINK) 976 return B_BAD_VALUE; 977 } 978 979 // Search for a network configuration that may override the defaults 980 981 bool found = false; 982 uint32 cookie = 0; 983 BMessage networkMessage; 984 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 985 const char* networkName; 986 if (networkMessage.FindString("name", &networkName) == B_OK 987 && name != NULL && address.Family() != AF_LINK 988 && !strcmp(name, networkName)) { 989 found = true; 990 break; 991 } 992 993 const char* mac; 994 if (networkMessage.FindString("mac", &mac) == B_OK 995 && address.Family() == AF_LINK) { 996 BNetworkAddress link(AF_LINK, mac); 997 if (link == address) { 998 found = true; 999 break; 1000 } 1001 } 1002 } 1003 1004 const char* password; 1005 if (message.FindString("password", &password) != B_OK && found) 1006 password = networkMessage.FindString("password"); 1007 1008 // Get network 1009 BNetworkDevice device(deviceName); 1010 wireless_network network; 1011 1012 bool askForConfig = false; 1013 if ((address.Family() != AF_LINK 1014 || device.GetNetwork(address, network) != B_OK) 1015 && device.GetNetwork(name, network) != B_OK) { 1016 // We did not find a network - just ignore that, and continue 1017 // with some defaults 1018 strlcpy(network.name, name, sizeof(network.name)); 1019 network.address = address; 1020 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 1021 network.cipher = 0; 1022 network.group_cipher = 0; 1023 network.key_mode = 0; 1024 askForConfig = true; 1025 } 1026 1027 const char* string; 1028 if (message.FindString("authentication", &string) == B_OK 1029 || (found && networkMessage.FindString("authentication", &string) 1030 == B_OK)) { 1031 askForConfig = false; 1032 if (!strcasecmp(string, "wpa2")) { 1033 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2; 1034 network.key_mode = B_KEY_MODE_IEEE802_1X; 1035 network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP; 1036 } else if (!strcasecmp(string, "wpa")) { 1037 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA; 1038 network.key_mode = B_KEY_MODE_IEEE802_1X; 1039 network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP; 1040 } else if (!strcasecmp(string, "wep")) { 1041 network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP; 1042 network.key_mode = B_KEY_MODE_NONE; 1043 network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40; 1044 } else if (strcasecmp(string, "none") && strcasecmp(string, "open")) { 1045 fprintf(stderr, "%s: invalid authentication mode.\n", name); 1046 askForConfig = true; 1047 } 1048 } 1049 1050 if (!askForConfig 1051 && network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) { 1052 // we join the network ourselves 1053 status_t status = set_80211(deviceName, IEEE80211_IOC_SSID, 1054 network.name, strlen(network.name)); 1055 if (status != B_OK) { 1056 fprintf(stderr, "%s: joining SSID failed: %s\n", name, 1057 strerror(status)); 1058 return status; 1059 } 1060 1061 return B_OK; 1062 } 1063 1064 // Join via wpa_supplicant 1065 1066 status_t status = be_roster->Launch(kWPASupplicantSignature); 1067 if (status != B_OK && status != B_ALREADY_RUNNING) 1068 return status; 1069 1070 // TODO: listen to notifications from the supplicant! 1071 1072 BMessage join(kMsgWPAJoinNetwork); 1073 status = join.AddString("device", deviceName); 1074 if (status == B_OK) 1075 status = join.AddString("name", network.name); 1076 if (status == B_OK) 1077 status = join.AddFlat("address", &network.address); 1078 if (status == B_OK && !askForConfig) 1079 status = join.AddUInt32("authentication", network.authentication_mode); 1080 if (status == B_OK && password != NULL) 1081 status = join.AddString("password", password); 1082 if (status != B_OK) 1083 return status; 1084 1085 BMessenger wpaSupplicant(kWPASupplicantSignature); 1086 status = wpaSupplicant.SendMessage(&join); 1087 if (status != B_OK) 1088 return status; 1089 1090 return B_OK; 1091 } 1092 1093 1094 status_t 1095 NetServer::_LeaveNetwork(const BMessage& message) 1096 { 1097 // TODO: not yet implemented 1098 return B_NOT_SUPPORTED; 1099 } 1100 1101 1102 status_t 1103 NetServer::_ConvertNetworkToSettings(BMessage& message) 1104 { 1105 BNetworkAddress address; 1106 status_t result = message.FindFlat("address", &address); 1107 if (result == B_OK) 1108 message.RemoveName("address"); 1109 1110 if (result == B_OK && address.Family() == AF_LINK) { 1111 size_t addressLength = address.LinkLevelAddressLength(); 1112 uint8* macAddress = address.LinkLevelAddress(); 1113 bool usable = false; 1114 BString formatted; 1115 1116 for (size_t index = 0; index < addressLength; index++) { 1117 if (index > 0) 1118 formatted.Append(":"); 1119 char buffer[3]; 1120 snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]); 1121 formatted.Append(buffer, sizeof(buffer)); 1122 1123 if (macAddress[index] != 0) 1124 usable = true; 1125 } 1126 1127 if (usable) 1128 message.AddString("mac", formatted); 1129 } 1130 1131 uint32 authentication = 0; 1132 result = message.FindUInt32("authentication_mode", &authentication); 1133 if (result == B_OK) { 1134 message.RemoveName("authentication_mode"); 1135 1136 const char* authenticationString = NULL; 1137 switch (authentication) { 1138 case B_NETWORK_AUTHENTICATION_NONE: 1139 authenticationString = "none"; 1140 break; 1141 case B_NETWORK_AUTHENTICATION_WEP: 1142 authenticationString = "wep"; 1143 break; 1144 case B_NETWORK_AUTHENTICATION_WPA: 1145 authenticationString = "wpa"; 1146 break; 1147 case B_NETWORK_AUTHENTICATION_WPA2: 1148 authenticationString = "wpa2"; 1149 break; 1150 } 1151 1152 if (result == B_OK && authenticationString != NULL) 1153 message.AddString("authentication", authenticationString); 1154 } 1155 1156 uint32 cipher = 0; 1157 result = message.FindUInt32("cipher", &cipher); 1158 if (result == B_OK) { 1159 message.RemoveName("cipher"); 1160 1161 if ((cipher & B_NETWORK_CIPHER_NONE) != 0) 1162 message.AddString("cipher", "none"); 1163 if ((cipher & B_NETWORK_CIPHER_TKIP) != 0) 1164 message.AddString("cipher", "tkip"); 1165 if ((cipher & B_NETWORK_CIPHER_CCMP) != 0) 1166 message.AddString("cipher", "ccmp"); 1167 } 1168 1169 uint32 groupCipher = 0; 1170 result = message.FindUInt32("group_cipher", &groupCipher); 1171 if (result == B_OK) { 1172 message.RemoveName("group_cipher"); 1173 1174 if ((groupCipher & B_NETWORK_CIPHER_NONE) != 0) 1175 message.AddString("group_cipher", "none"); 1176 if ((groupCipher & B_NETWORK_CIPHER_WEP_40) != 0) 1177 message.AddString("group_cipher", "wep40"); 1178 if ((groupCipher & B_NETWORK_CIPHER_WEP_104) != 0) 1179 message.AddString("group_cipher", "wep104"); 1180 if ((groupCipher & B_NETWORK_CIPHER_TKIP) != 0) 1181 message.AddString("group_cipher", "tkip"); 1182 if ((groupCipher & B_NETWORK_CIPHER_CCMP) != 0) 1183 message.AddString("group_cipher", "ccmp"); 1184 } 1185 1186 // TODO: the other fields aren't currently used, add them when they are 1187 // and when it's clear how they will be stored 1188 message.RemoveName("noise_level"); 1189 message.RemoveName("signal_strength"); 1190 message.RemoveName("flags"); 1191 message.RemoveName("key_mode"); 1192 1193 return B_OK; 1194 } 1195 1196 1197 status_t 1198 NetServer::_ConvertNetworkFromSettings(BMessage& message) 1199 { 1200 message.RemoveName("mac"); 1201 // TODO: convert into a flat BNetworkAddress "address" 1202 1203 const char* authentication = NULL; 1204 if (message.FindString("authentication", &authentication) == B_OK) { 1205 message.RemoveName("authentication"); 1206 1207 if (strcasecmp(authentication, "none") == 0) { 1208 message.AddUInt32("authentication_mode", 1209 B_NETWORK_AUTHENTICATION_NONE); 1210 } else if (strcasecmp(authentication, "wep") == 0) { 1211 message.AddUInt32("authentication_mode", 1212 B_NETWORK_AUTHENTICATION_WEP); 1213 } else if (strcasecmp(authentication, "wpa") == 0) { 1214 message.AddUInt32("authentication_mode", 1215 B_NETWORK_AUTHENTICATION_WPA); 1216 } else if (strcasecmp(authentication, "wpa2") == 0) { 1217 message.AddUInt32("authentication_mode", 1218 B_NETWORK_AUTHENTICATION_WPA2); 1219 } 1220 } 1221 1222 int32 index = 0; 1223 uint32 cipher = 0; 1224 const char* cipherString = NULL; 1225 while (message.FindString("cipher", index++, &cipherString) == B_OK) { 1226 if (strcasecmp(cipherString, "none") == 0) 1227 cipher |= B_NETWORK_CIPHER_NONE; 1228 else if (strcasecmp(cipherString, "tkip") == 0) 1229 cipher |= B_NETWORK_CIPHER_TKIP; 1230 else if (strcasecmp(cipherString, "ccmp") == 0) 1231 cipher |= B_NETWORK_CIPHER_CCMP; 1232 } 1233 1234 message.RemoveName("cipher"); 1235 if (cipher != 0) 1236 message.AddUInt32("cipher", cipher); 1237 1238 index = 0; 1239 cipher = 0; 1240 while (message.FindString("group_cipher", index++, &cipherString) == B_OK) { 1241 if (strcasecmp(cipherString, "none") == 0) 1242 cipher |= B_NETWORK_CIPHER_NONE; 1243 else if (strcasecmp(cipherString, "wep40") == 0) 1244 cipher |= B_NETWORK_CIPHER_WEP_40; 1245 else if (strcasecmp(cipherString, "wep104") == 0) 1246 cipher |= B_NETWORK_CIPHER_WEP_104; 1247 else if (strcasecmp(cipherString, "tkip") == 0) 1248 cipher |= B_NETWORK_CIPHER_TKIP; 1249 else if (strcasecmp(cipherString, "ccmp") == 0) 1250 cipher |= B_NETWORK_CIPHER_CCMP; 1251 } 1252 1253 message.RemoveName("group_cipher"); 1254 if (cipher != 0) 1255 message.AddUInt32("group_cipher", cipher); 1256 1257 message.AddUInt32("flags", B_NETWORK_IS_PERSISTENT); 1258 1259 // TODO: add the other fields 1260 message.RemoveName("key"); 1261 return B_OK; 1262 } 1263 1264 1265 // #pragma mark - 1266 1267 1268 int 1269 main(int argc, char** argv) 1270 { 1271 status_t status; 1272 NetServer server(status); 1273 if (status != B_OK) { 1274 fprintf(stderr, "net_server: Failed to create application: %s\n", 1275 strerror(status)); 1276 return 1; 1277 } 1278 1279 server.Run(); 1280 return 0; 1281 } 1282 1283