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