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