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", B_ENTRY_CREATED 254 | B_ENTRY_REMOVED | 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 _ConfigureIPv6LinkLocal(name); 543 544 BMessage addressMessage; 545 for (int32 index = 0; message.FindMessage("address", index, 546 &addressMessage) == B_OK; index++) { 547 int32 family; 548 if (addressMessage.FindInt32("family", &family) != B_OK) { 549 const char* familyString; 550 if (addressMessage.FindString("family", &familyString) == B_OK) { 551 if (get_address_family(familyString) == AF_UNSPEC) { 552 // we don't support this family 553 fprintf(stderr, "%s: Ignore unknown family: %s\n", Name(), 554 familyString); 555 continue; 556 } 557 } else 558 family = AF_UNSPEC; 559 } 560 561 // retrieve addresses 562 563 bool autoConfig; 564 if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK) 565 autoConfig = false; 566 567 BNetworkAddress address; 568 BNetworkAddress mask; 569 BNetworkAddress broadcast; 570 BNetworkAddress peer; 571 BNetworkAddress gateway; 572 573 const char* string; 574 575 if (!autoConfig) { 576 if (addressMessage.FindString("address", &string) == B_OK) { 577 parse_address(family, string, address); 578 579 if (addressMessage.FindString("mask", &string) == B_OK) 580 parse_address(family, string, mask); 581 } 582 583 if (addressMessage.FindString("peer", &string) == B_OK) 584 parse_address(family, string, peer); 585 586 if (addressMessage.FindString("broadcast", &string) == B_OK) 587 parse_address(family, string, broadcast); 588 } 589 590 if (autoConfig) { 591 _QuitLooperForDevice(name); 592 startAutoConfig = true; 593 } else if (addressMessage.FindString("gateway", &string) == B_OK 594 && parse_address(family, string, gateway)) { 595 // add gateway route, if we're asked for it 596 interface.RemoveDefaultRoute(family); 597 // Try to remove a previous default route, doesn't matter 598 // if it fails. 599 600 status_t status = interface.AddDefaultRoute(gateway); 601 if (status != B_OK) { 602 fprintf(stderr, "%s: Could not add route for %s: %s\n", 603 Name(), name, strerror(errno)); 604 } 605 } 606 607 // set address/mask/broadcast/peer 608 609 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) { 610 BNetworkInterfaceAddress interfaceAddress; 611 interfaceAddress.SetAddress(address); 612 interfaceAddress.SetMask(mask); 613 if (!broadcast.IsEmpty()) 614 interfaceAddress.SetBroadcast(broadcast); 615 else if (!peer.IsEmpty()) 616 interfaceAddress.SetDestination(peer); 617 618 status_t status = interface.SetAddress(interfaceAddress); 619 if (status != B_OK) { 620 fprintf(stderr, "%s: Setting address failed: %s\n", Name(), 621 strerror(status)); 622 return status; 623 } 624 } 625 626 // set flags 627 628 if (flags != 0) { 629 int32 newFlags = interface.Flags(); 630 newFlags = (newFlags & ~IFF_CONFIGURING) | flags; 631 if (!autoConfigured) 632 newFlags &= ~IFF_AUTO_CONFIGURED; 633 634 status_t status = interface.SetFlags(newFlags); 635 if (status != B_OK) { 636 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), 637 strerror(status)); 638 } 639 } 640 641 // set options 642 643 if (mtu != -1) { 644 status_t status = interface.SetMTU(mtu); 645 if (status != B_OK) { 646 fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), 647 strerror(status)); 648 } 649 } 650 651 if (metric != -1) { 652 status_t status = interface.SetMetric(metric); 653 if (status != B_OK) { 654 fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), 655 strerror(status)); 656 } 657 } 658 } 659 660 const char* networkName; 661 if (message.FindString("network", &networkName) == B_OK) { 662 // We want to join a specific network. 663 BNetworkDevice device(name); 664 if (device.IsWireless() && !device.HasLink()) { 665 status_t status = _JoinNetwork(message, networkName); 666 if (status != B_OK) { 667 fprintf(stderr, "%s: joining network \"%s\" failed: %s\n", 668 interface.Name(), networkName, strerror(status)); 669 } 670 } 671 } 672 673 if (startAutoConfig) { 674 // start auto configuration 675 AutoconfigLooper* looper = new AutoconfigLooper(this, name); 676 looper->Run(); 677 678 fDeviceMap[name] = looper; 679 } else if (!autoConfigured) 680 _QuitLooperForDevice(name); 681 682 return B_OK; 683 } 684 685 686 status_t 687 NetServer::_ConfigureResolver(BMessage& resolverConfiguration) 688 { 689 // TODO: resolv.conf should be parsed, all information should be 690 // maintained and it should be distinguished between user entered 691 // and auto-generated parts of the file, with this method only re-writing 692 // the auto-generated parts of course. 693 694 BPath path; 695 if (find_directory(B_COMMON_SETTINGS_DIRECTORY, &path) != B_OK 696 || path.Append("network/resolv.conf") != B_OK) 697 return B_ERROR; 698 699 FILE* file = fopen(path.Path(), "w"); 700 if (file != NULL) { 701 const char* nameserver; 702 for (int32 i = 0; resolverConfiguration.FindString("nameserver", i, 703 &nameserver) == B_OK; i++) { 704 fprintf(file, "nameserver %s\n", nameserver); 705 } 706 707 const char* domain; 708 if (resolverConfiguration.FindString("domain", &domain) == B_OK) 709 fprintf(file, "domain %s\n", domain); 710 711 fclose(file); 712 } 713 return B_OK; 714 } 715 716 717 bool 718 NetServer::_QuitLooperForDevice(const char* device) 719 { 720 LooperMap::iterator iterator = fDeviceMap.find(device); 721 if (iterator == fDeviceMap.end()) 722 return false; 723 724 // there is a looper for this device - quit it 725 if (iterator->second->Lock()) 726 iterator->second->Quit(); 727 728 fDeviceMap.erase(iterator); 729 return true; 730 } 731 732 733 AutoconfigLooper* 734 NetServer::_LooperForDevice(const char* device) 735 { 736 LooperMap::const_iterator iterator = fDeviceMap.find(device); 737 if (iterator == fDeviceMap.end()) 738 return NULL; 739 740 return iterator->second; 741 } 742 743 744 status_t 745 NetServer::_ConfigureDevice(const char* device) 746 { 747 // bring interface up, but don't configure it just yet 748 BMessage interface; 749 interface.AddString("device", device); 750 BMessage address; 751 address.AddString("family", "inet"); 752 address.AddBool("auto_config", true); 753 interface.AddMessage("address", &address); 754 755 return _ConfigureInterface(interface); 756 } 757 758 759 void 760 NetServer::_ConfigureDevices(const char* startPath, 761 BMessage* suggestedInterface) 762 { 763 BDirectory directory(startPath); 764 BEntry entry; 765 while (directory.GetNextEntry(&entry) == B_OK) { 766 char name[B_FILE_NAME_LENGTH]; 767 struct stat stat; 768 BPath path; 769 if (entry.GetName(name) != B_OK 770 || entry.GetPath(&path) != B_OK 771 || entry.GetStat(&stat) != B_OK) 772 continue; 773 774 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) { 775 if (suggestedInterface != NULL 776 && suggestedInterface->RemoveName("device") == B_OK 777 && suggestedInterface->AddString("device", path.Path()) == B_OK 778 && _ConfigureInterface(*suggestedInterface) == B_OK) 779 suggestedInterface = NULL; 780 else 781 _ConfigureDevice(path.Path()); 782 } else if (entry.IsDirectory()) 783 _ConfigureDevices(path.Path(), suggestedInterface); 784 } 785 } 786 787 788 void 789 NetServer::_ConfigureInterfacesFromSettings(BMessage* _missingDevice) 790 { 791 BMessage interface; 792 uint32 cookie = 0; 793 bool missing = false; 794 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 795 const char *device; 796 if (interface.FindString("device", &device) != B_OK) 797 continue; 798 799 bool disabled = false; 800 if (interface.FindBool("disabled", &disabled) == B_OK && disabled) { 801 // disabled by user request 802 _DisableInterface(device); 803 continue; 804 } 805 806 if (!strncmp(device, "/dev/net/", 9)) { 807 // it's a kernel device, check if it's present 808 BEntry entry(device); 809 if (!entry.Exists()) { 810 if (!missing && _missingDevice != NULL) { 811 *_missingDevice = interface; 812 missing = true; 813 } 814 continue; 815 } 816 } 817 818 _ConfigureInterface(interface); 819 } 820 } 821 822 823 void 824 NetServer::_BringUpInterfaces() 825 { 826 // we need a socket to talk to the networking stack 827 if (!_IsValidFamily(AF_LINK)) { 828 fprintf(stderr, "%s: The networking stack doesn't seem to be " 829 "available.\n", Name()); 830 Quit(); 831 return; 832 } 833 834 _RemoveInvalidInterfaces(); 835 836 // First, we look into the settings, and try to bring everything up from there 837 838 BMessage missingDevice; 839 _ConfigureInterfacesFromSettings(&missingDevice); 840 841 // check configuration 842 843 if (!_TestForInterface("loop")) { 844 // there is no loopback interface, create one 845 BMessage interface; 846 interface.AddString("device", "loop"); 847 BMessage v4address; 848 v4address.AddString("family", "inet"); 849 v4address.AddString("address", "127.0.0.1"); 850 interface.AddMessage("address", &v4address); 851 852 // Check for IPv6 support and add ::1 853 if (_IsValidFamily(AF_INET6)) { 854 BMessage v6address; 855 v6address.AddString("family", "inet6"); 856 v6address.AddString("address", "::1"); 857 interface.AddMessage("address", &v6address); 858 } 859 _ConfigureInterface(interface); 860 } 861 862 // TODO: also check if the networking driver is correctly initialized! 863 // (and check for other devices to take over its configuration) 864 865 if (!_TestForInterface("/dev/net/")) { 866 // there is no driver configured - see if there is one and try to use it 867 _ConfigureDevices("/dev/net", 868 missingDevice.HasString("device") ? &missingDevice : NULL); 869 } 870 } 871 872 873 /*! Configure the link local address based on the network card's MAC address 874 if this isn't a loopback device. 875 */ 876 void 877 NetServer::_ConfigureIPv6LinkLocal(const char* name) 878 { 879 // Check for IPv6 support 880 if (!_IsValidFamily(AF_INET6)) 881 return; 882 883 BNetworkInterface interface(name); 884 885 // Lets make sure this is *not* the loopback interface 886 if ((interface.Flags() & IFF_LOOPBACK) != 0) 887 return; 888 889 BNetworkAddress link; 890 status_t result = interface.GetHardwareAddress(link); 891 892 if (result != B_OK || link.LinkLevelAddressLength() != 6) 893 return; 894 895 const uint8* mac = link.LinkLevelAddress(); 896 897 // Check for a few failure situations 898 static const uint8 zeroMac[6] = {0, 0, 0, 0, 0, 0}; 899 static const uint8 fullMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 900 if (memcmp(mac, zeroMac, 6) == 0 901 || memcmp(mac, fullMac, 6) == 0) { 902 // Mac address is all 0 or all FF's 903 syslog(LOG_DEBUG, "%s: MacAddress for interface '%s' is invalid.", 904 __func__, name); 905 return; 906 } 907 908 // Generate a Link Local Scope address 909 // (IPv6 address based on Mac address) 910 in6_addr addressRaw; 911 memset(addressRaw.s6_addr, 0, sizeof(addressRaw.s6_addr)); 912 addressRaw.s6_addr[0] = 0xfe; 913 addressRaw.s6_addr[1] = 0x80; 914 addressRaw.s6_addr[8] = mac[0] ^ 0x02; 915 addressRaw.s6_addr[9] = mac[1]; 916 addressRaw.s6_addr[10] = mac[2]; 917 addressRaw.s6_addr[11] = 0xff; 918 addressRaw.s6_addr[12] = 0xfe; 919 addressRaw.s6_addr[13] = mac[3]; 920 addressRaw.s6_addr[14] = mac[4]; 921 addressRaw.s6_addr[15] = mac[5]; 922 923 BNetworkAddress localLinkAddress(addressRaw, 0); 924 BNetworkAddress localLinkMask("ffff:ffff:ffff:ffff::"); // 64 925 BNetworkAddress localLinkBroadcast("fe80::ffff:ffff:ffff:ffff"); 926 927 if (interface.FindAddress(localLinkAddress) >= 0) { 928 // uhoh... already has a local link address 929 930 /* TODO: Check for any local link scope addresses assigned to card 931 There isn't any flag at the moment though for address scope 932 */ 933 syslog(LOG_DEBUG, "%s: Local Link address already assigned to %s\n", 934 __func__, name); 935 return; 936 } 937 938 BNetworkInterfaceAddress interfaceAddress; 939 interfaceAddress.SetAddress(localLinkAddress); 940 interfaceAddress.SetMask(localLinkMask); 941 interfaceAddress.SetBroadcast(localLinkMask); 942 943 /* TODO: Duplicate Address Detection. (DAD) 944 Need to blast an icmp packet over the IPv6 network from :: to ensure 945 there aren't duplicate MAC addresses on the network. (definitely an 946 edge case, but a possible issue) 947 */ 948 949 interface.AddAddress(interfaceAddress); 950 } 951 952 953 void 954 NetServer::_StartServices() 955 { 956 BHandler* services = new (std::nothrow) Services(fSettings.Services()); 957 if (services != NULL) { 958 AddHandler(services); 959 fServices = BMessenger(services); 960 } 961 } 962 963 964 status_t 965 NetServer::_HandleDeviceMonitor(BMessage* message) 966 { 967 int32 opcode; 968 const char* path; 969 if (message->FindInt32("opcode", &opcode) != B_OK 970 || (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED) 971 || message->FindString("path", &path) != B_OK) 972 return B_BAD_VALUE; 973 974 if (strncmp(path, "/dev/net/", 9)) { 975 // not a valid device entry, ignore 976 return B_NAME_NOT_FOUND; 977 } 978 979 if (opcode == B_ENTRY_CREATED) 980 _ConfigureDevice(path); 981 else 982 _RemoveInterface(path); 983 984 return B_OK; 985 } 986 987 988 status_t 989 NetServer::_AutoJoinNetwork(const BMessage& message) 990 { 991 const char* name = NULL; 992 if (message.FindString("device", &name) != B_OK) 993 return B_BAD_VALUE; 994 995 BNetworkDevice device(name); 996 997 // Choose among configured networks 998 999 uint32 cookie = 0; 1000 BMessage networkMessage; 1001 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 1002 status_t status = B_ERROR; 1003 wireless_network network; 1004 const char* networkName; 1005 BNetworkAddress link; 1006 1007 const char* mac; 1008 if (networkMessage.FindString("mac", &mac) == B_OK) { 1009 link.SetTo(AF_LINK, mac); 1010 status = device.GetNetwork(link, network); 1011 } else if (networkMessage.FindString("name", &networkName) == B_OK) 1012 status = device.GetNetwork(networkName, network); 1013 1014 if (status == B_OK) { 1015 status = _JoinNetwork(message, network.name); 1016 printf("auto join network \"%s\": %s\n", network.name, 1017 strerror(status)); 1018 if (status == B_OK) 1019 return B_OK; 1020 } 1021 } 1022 1023 return B_NO_INIT; 1024 } 1025 1026 1027 status_t 1028 NetServer::_JoinNetwork(const BMessage& message, const char* name) 1029 { 1030 const char* deviceName; 1031 if (message.FindString("device", &deviceName) != B_OK) 1032 return B_BAD_VALUE; 1033 1034 BNetworkAddress address; 1035 message.FindFlat("address", &address); 1036 1037 if (name == NULL) 1038 message.FindString("name", &name); 1039 if (name == NULL) { 1040 // No name specified, we need a network address 1041 if (address.Family() != AF_LINK) 1042 return B_BAD_VALUE; 1043 } 1044 1045 // Search for a network configuration that may override the defaults 1046 1047 bool found = false; 1048 uint32 cookie = 0; 1049 BMessage networkMessage; 1050 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 1051 const char* networkName; 1052 if (networkMessage.FindString("name", &networkName) == B_OK 1053 && name != NULL && address.Family() != AF_LINK 1054 && !strcmp(name, networkName)) { 1055 found = true; 1056 break; 1057 } 1058 1059 const char* mac; 1060 if (networkMessage.FindString("mac", &mac) == B_OK 1061 && address.Family() == AF_LINK) { 1062 BNetworkAddress link(AF_LINK, mac); 1063 if (link == address) { 1064 found = true; 1065 break; 1066 } 1067 } 1068 } 1069 1070 const char* password; 1071 if (message.FindString("password", &password) != B_OK && found) 1072 password = networkMessage.FindString("password"); 1073 1074 // Get network 1075 BNetworkDevice device(deviceName); 1076 wireless_network network; 1077 1078 bool askForConfig = false; 1079 if ((address.Family() != AF_LINK 1080 || device.GetNetwork(address, network) != B_OK) 1081 && device.GetNetwork(name, network) != B_OK) { 1082 // We did not find a network - just ignore that, and continue 1083 // with some defaults 1084 strlcpy(network.name, name, sizeof(network.name)); 1085 network.address = address; 1086 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 1087 network.cipher = 0; 1088 network.group_cipher = 0; 1089 network.key_mode = 0; 1090 askForConfig = true; 1091 } 1092 1093 const char* string; 1094 if (message.FindString("authentication", &string) == B_OK 1095 || (found && networkMessage.FindString("authentication", &string) 1096 == B_OK)) { 1097 askForConfig = false; 1098 if (!strcasecmp(string, "wpa2")) { 1099 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2; 1100 network.key_mode = B_KEY_MODE_IEEE802_1X; 1101 network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP; 1102 } else if (!strcasecmp(string, "wpa")) { 1103 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA; 1104 network.key_mode = B_KEY_MODE_IEEE802_1X; 1105 network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP; 1106 } else if (!strcasecmp(string, "wep")) { 1107 network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP; 1108 network.key_mode = B_KEY_MODE_NONE; 1109 network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40; 1110 } else if (strcasecmp(string, "none") && strcasecmp(string, "open")) { 1111 fprintf(stderr, "%s: invalid authentication mode.\n", name); 1112 askForConfig = true; 1113 } 1114 } 1115 1116 // We always try to join via the wpa_supplicant. Even if we could join 1117 // ourselves, we need to make sure that the wpa_supplicant knows about 1118 // our intention, as otherwise it would interfere with it. 1119 1120 BMessenger wpaSupplicant(kWPASupplicantSignature); 1121 if (!wpaSupplicant.IsValid()) { 1122 // The wpa_supplicant isn't running yet, we may join ourselves. 1123 if (!askForConfig 1124 && network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) { 1125 // We can join this network ourselves. 1126 status_t status = set_80211(deviceName, IEEE80211_IOC_SSID, 1127 network.name, strlen(network.name)); 1128 if (status != B_OK) { 1129 fprintf(stderr, "%s: joining SSID failed: %s\n", name, 1130 strerror(status)); 1131 return status; 1132 } 1133 } 1134 1135 // We need the supplicant, try to launch it. 1136 status_t status = be_roster->Launch(kWPASupplicantSignature); 1137 if (status != B_OK && status != B_ALREADY_RUNNING) 1138 return status; 1139 1140 wpaSupplicant.SetTo(kWPASupplicantSignature); 1141 if (!wpaSupplicant.IsValid()) 1142 return B_ERROR; 1143 } 1144 1145 // TODO: listen to notifications from the supplicant! 1146 1147 BMessage join(kMsgWPAJoinNetwork); 1148 status_t status = join.AddString("device", deviceName); 1149 if (status == B_OK) 1150 status = join.AddString("name", network.name); 1151 if (status == B_OK) 1152 status = join.AddFlat("address", &network.address); 1153 if (status == B_OK && !askForConfig) 1154 status = join.AddUInt32("authentication", network.authentication_mode); 1155 if (status == B_OK && password != NULL) 1156 status = join.AddString("password", password); 1157 if (status != B_OK) 1158 return status; 1159 1160 status = wpaSupplicant.SendMessage(&join); 1161 if (status != B_OK) 1162 return status; 1163 1164 return B_OK; 1165 } 1166 1167 1168 status_t 1169 NetServer::_LeaveNetwork(const BMessage& message) 1170 { 1171 const char* deviceName; 1172 if (message.FindString("device", &deviceName) != B_OK) 1173 return B_BAD_VALUE; 1174 1175 int32 reason; 1176 if (message.FindInt32("reason", &reason) != B_OK) 1177 reason = IEEE80211_REASON_AUTH_LEAVE; 1178 1179 // We always try to send the leave request to the wpa_supplicant. 1180 1181 BMessenger wpaSupplicant(kWPASupplicantSignature); 1182 if (wpaSupplicant.IsValid()) { 1183 BMessage leave(kMsgWPALeaveNetwork); 1184 status_t status = leave.AddString("device", deviceName); 1185 if (status == B_OK) 1186 status = leave.AddInt32("reason", reason); 1187 if (status != B_OK) 1188 return status; 1189 1190 status = wpaSupplicant.SendMessage(&leave); 1191 if (status == B_OK) 1192 return B_OK; 1193 } 1194 1195 // The wpa_supplicant doesn't seem to be running, check if this was an open 1196 // network we connected ourselves. 1197 BNetworkDevice device(deviceName); 1198 wireless_network network; 1199 1200 uint32 cookie = 0; 1201 if (device.GetNextAssociatedNetwork(cookie, network) != B_OK 1202 || network.authentication_mode != B_NETWORK_AUTHENTICATION_NONE) { 1203 // We didn't join ourselves, we can't do much. 1204 return B_ERROR; 1205 } 1206 1207 // We joined ourselves, so we can just disassociate again. 1208 ieee80211req_mlme mlmeRequest; 1209 memset(&mlmeRequest, 0, sizeof(mlmeRequest)); 1210 mlmeRequest.im_op = IEEE80211_MLME_DISASSOC; 1211 mlmeRequest.im_reason = reason; 1212 1213 return set_80211(deviceName, IEEE80211_IOC_MLME, &mlmeRequest, 1214 sizeof(mlmeRequest)); 1215 } 1216 1217 1218 status_t 1219 NetServer::_ConvertNetworkToSettings(BMessage& message) 1220 { 1221 BNetworkAddress address; 1222 status_t result = message.FindFlat("address", &address); 1223 if (result == B_OK) 1224 message.RemoveName("address"); 1225 1226 if (result == B_OK && address.Family() == AF_LINK) { 1227 size_t addressLength = address.LinkLevelAddressLength(); 1228 uint8* macAddress = address.LinkLevelAddress(); 1229 bool usable = false; 1230 BString formatted; 1231 1232 for (size_t index = 0; index < addressLength; index++) { 1233 if (index > 0) 1234 formatted.Append(":"); 1235 char buffer[3]; 1236 snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]); 1237 formatted.Append(buffer, sizeof(buffer)); 1238 1239 if (macAddress[index] != 0) 1240 usable = true; 1241 } 1242 1243 if (usable) 1244 message.AddString("mac", formatted); 1245 } 1246 1247 uint32 authentication = 0; 1248 result = message.FindUInt32("authentication_mode", &authentication); 1249 if (result == B_OK) { 1250 message.RemoveName("authentication_mode"); 1251 1252 const char* authenticationString = NULL; 1253 switch (authentication) { 1254 case B_NETWORK_AUTHENTICATION_NONE: 1255 authenticationString = "none"; 1256 break; 1257 case B_NETWORK_AUTHENTICATION_WEP: 1258 authenticationString = "wep"; 1259 break; 1260 case B_NETWORK_AUTHENTICATION_WPA: 1261 authenticationString = "wpa"; 1262 break; 1263 case B_NETWORK_AUTHENTICATION_WPA2: 1264 authenticationString = "wpa2"; 1265 break; 1266 } 1267 1268 if (result == B_OK && authenticationString != NULL) 1269 message.AddString("authentication", authenticationString); 1270 } 1271 1272 uint32 cipher = 0; 1273 result = message.FindUInt32("cipher", &cipher); 1274 if (result == B_OK) { 1275 message.RemoveName("cipher"); 1276 1277 if ((cipher & B_NETWORK_CIPHER_NONE) != 0) 1278 message.AddString("cipher", "none"); 1279 if ((cipher & B_NETWORK_CIPHER_TKIP) != 0) 1280 message.AddString("cipher", "tkip"); 1281 if ((cipher & B_NETWORK_CIPHER_CCMP) != 0) 1282 message.AddString("cipher", "ccmp"); 1283 } 1284 1285 uint32 groupCipher = 0; 1286 result = message.FindUInt32("group_cipher", &groupCipher); 1287 if (result == B_OK) { 1288 message.RemoveName("group_cipher"); 1289 1290 if ((groupCipher & B_NETWORK_CIPHER_NONE) != 0) 1291 message.AddString("group_cipher", "none"); 1292 if ((groupCipher & B_NETWORK_CIPHER_WEP_40) != 0) 1293 message.AddString("group_cipher", "wep40"); 1294 if ((groupCipher & B_NETWORK_CIPHER_WEP_104) != 0) 1295 message.AddString("group_cipher", "wep104"); 1296 if ((groupCipher & B_NETWORK_CIPHER_TKIP) != 0) 1297 message.AddString("group_cipher", "tkip"); 1298 if ((groupCipher & B_NETWORK_CIPHER_CCMP) != 0) 1299 message.AddString("group_cipher", "ccmp"); 1300 } 1301 1302 // TODO: the other fields aren't currently used, add them when they are 1303 // and when it's clear how they will be stored 1304 message.RemoveName("noise_level"); 1305 message.RemoveName("signal_strength"); 1306 message.RemoveName("flags"); 1307 message.RemoveName("key_mode"); 1308 1309 return B_OK; 1310 } 1311 1312 1313 status_t 1314 NetServer::_ConvertNetworkFromSettings(BMessage& message) 1315 { 1316 message.RemoveName("mac"); 1317 // TODO: convert into a flat BNetworkAddress "address" 1318 1319 const char* authentication = NULL; 1320 if (message.FindString("authentication", &authentication) == B_OK) { 1321 message.RemoveName("authentication"); 1322 1323 if (strcasecmp(authentication, "none") == 0) { 1324 message.AddUInt32("authentication_mode", 1325 B_NETWORK_AUTHENTICATION_NONE); 1326 } else if (strcasecmp(authentication, "wep") == 0) { 1327 message.AddUInt32("authentication_mode", 1328 B_NETWORK_AUTHENTICATION_WEP); 1329 } else if (strcasecmp(authentication, "wpa") == 0) { 1330 message.AddUInt32("authentication_mode", 1331 B_NETWORK_AUTHENTICATION_WPA); 1332 } else if (strcasecmp(authentication, "wpa2") == 0) { 1333 message.AddUInt32("authentication_mode", 1334 B_NETWORK_AUTHENTICATION_WPA2); 1335 } 1336 } 1337 1338 int32 index = 0; 1339 uint32 cipher = 0; 1340 const char* cipherString = NULL; 1341 while (message.FindString("cipher", index++, &cipherString) == B_OK) { 1342 if (strcasecmp(cipherString, "none") == 0) 1343 cipher |= B_NETWORK_CIPHER_NONE; 1344 else if (strcasecmp(cipherString, "tkip") == 0) 1345 cipher |= B_NETWORK_CIPHER_TKIP; 1346 else if (strcasecmp(cipherString, "ccmp") == 0) 1347 cipher |= B_NETWORK_CIPHER_CCMP; 1348 } 1349 1350 message.RemoveName("cipher"); 1351 if (cipher != 0) 1352 message.AddUInt32("cipher", cipher); 1353 1354 index = 0; 1355 cipher = 0; 1356 while (message.FindString("group_cipher", index++, &cipherString) == B_OK) { 1357 if (strcasecmp(cipherString, "none") == 0) 1358 cipher |= B_NETWORK_CIPHER_NONE; 1359 else if (strcasecmp(cipherString, "wep40") == 0) 1360 cipher |= B_NETWORK_CIPHER_WEP_40; 1361 else if (strcasecmp(cipherString, "wep104") == 0) 1362 cipher |= B_NETWORK_CIPHER_WEP_104; 1363 else if (strcasecmp(cipherString, "tkip") == 0) 1364 cipher |= B_NETWORK_CIPHER_TKIP; 1365 else if (strcasecmp(cipherString, "ccmp") == 0) 1366 cipher |= B_NETWORK_CIPHER_CCMP; 1367 } 1368 1369 message.RemoveName("group_cipher"); 1370 if (cipher != 0) 1371 message.AddUInt32("group_cipher", cipher); 1372 1373 message.AddUInt32("flags", B_NETWORK_IS_PERSISTENT); 1374 1375 // TODO: add the other fields 1376 message.RemoveName("key"); 1377 return B_OK; 1378 } 1379 1380 1381 // #pragma mark - 1382 1383 1384 int 1385 main(int argc, char** argv) 1386 { 1387 status_t status; 1388 NetServer server(status); 1389 if (status != B_OK) { 1390 fprintf(stderr, "net_server: Failed to create application: %s\n", 1391 strerror(status)); 1392 return 1; 1393 } 1394 1395 server.Run(); 1396 return 0; 1397 } 1398 1399