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