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