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 } else if (!addressSettings.Gateway().IsEmpty()) { 472 // add gateway route, if we're asked for it 473 interface.RemoveDefaultRoute(addressSettings.Family()); 474 // Try to remove a previous default route, doesn't matter 475 // if it fails. 476 477 status_t status = interface.AddDefaultRoute( 478 addressSettings.Gateway()); 479 if (status != B_OK) { 480 fprintf(stderr, "%s: Could not add route for %s: %s\n", 481 Name(), name, strerror(errno)); 482 } 483 } 484 485 // set address/mask/broadcast/peer 486 487 if (!addressSettings.Address().IsEmpty() 488 || !addressSettings.Mask().IsEmpty() 489 || !addressSettings.Broadcast().IsEmpty() 490 || !addressSettings.Peer().IsEmpty() 491 || !addressSettings.IsAutoConfigure()) { 492 BNetworkInterfaceAddress interfaceAddress; 493 interfaceAddress.SetAddress(addressSettings.Address()); 494 interfaceAddress.SetMask(addressSettings.Mask()); 495 if (!addressSettings.Broadcast().IsEmpty()) 496 interfaceAddress.SetBroadcast(addressSettings.Broadcast()); 497 else if (!addressSettings.Peer().IsEmpty()) 498 interfaceAddress.SetDestination(addressSettings.Peer()); 499 500 status_t status = interface.SetAddress(interfaceAddress); 501 if (status != B_OK) { 502 fprintf(stderr, "%s: Setting address failed: %s\n", Name(), 503 strerror(status)); 504 return status; 505 } 506 } 507 508 // set flags 509 510 if (flags != 0) { 511 int32 newFlags = interface.Flags(); 512 newFlags = (newFlags & ~IFF_CONFIGURING) | flags; 513 if (!autoConfigured) 514 newFlags &= ~IFF_AUTO_CONFIGURED; 515 516 status_t status = interface.SetFlags(newFlags); 517 if (status != B_OK) { 518 fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), 519 strerror(status)); 520 } 521 } 522 523 // set options 524 525 if (mtu != -1) { 526 status_t status = interface.SetMTU(mtu); 527 if (status != B_OK) { 528 fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), 529 strerror(status)); 530 } 531 } 532 533 if (metric != -1) { 534 status_t status = interface.SetMetric(metric); 535 if (status != B_OK) { 536 fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), 537 strerror(status)); 538 } 539 } 540 } 541 542 // Join the specified networks 543 BMessage networkMessage; 544 for (int32 index = 0; message.FindMessage("network", index, 545 &networkMessage) == B_OK; index++) { 546 const char* networkName = message.GetString("name", NULL); 547 const char* addressString = message.GetString("mac", NULL); 548 549 BNetworkAddress address; 550 status_t addressStatus = address.SetTo(AF_LINK, addressString); 551 552 BNetworkDevice device(name); 553 if (device.IsWireless() && !device.HasLink()) { 554 status_t status = _JoinNetwork(message, 555 addressStatus == B_OK ? &address : NULL, networkName); 556 if (status != B_OK) { 557 fprintf(stderr, "%s: joining network \"%s\" failed: %s\n", 558 interface.Name(), networkName, strerror(status)); 559 } 560 } 561 } 562 563 if (startAutoConfig) { 564 // start auto configuration 565 AutoconfigLooper* looper = new AutoconfigLooper(this, name); 566 looper->Run(); 567 568 fDeviceMap[name] = looper; 569 } else if (!autoConfigured) 570 _QuitLooperForDevice(name); 571 572 return B_OK; 573 } 574 575 576 status_t 577 NetServer::_ConfigureResolver(BMessage& resolverConfiguration) 578 { 579 // Store resolver settings in resolv.conf file, while maintaining any 580 // user specified settings already present. 581 582 BPath path; 583 if (find_directory(B_SYSTEM_SETTINGS_DIRECTORY, &path) != B_OK 584 || path.Append("network/resolv.conf") != B_OK) 585 return B_ERROR; 586 587 FILE* file = fopen(path.Path(), "r+"); 588 // open existing resolv.conf if possible 589 if (file == NULL) { 590 // no existing resolv.conf, create a new one 591 file = fopen(path.Path(), "w"); 592 if (file == NULL) { 593 fprintf(stderr, "Could not open resolv.conf: %s\n", 594 strerror(errno)); 595 return errno; 596 } 597 } else { 598 // An existing resolv.conf was found, parse it for user settings 599 const char* staticDNS = "# Static DNS Only"; 600 size_t sizeStaticDNS = strlen(staticDNS); 601 const char* dynamicDNS = "# Dynamic DNS entries"; 602 size_t sizeDynamicDNS = strlen(dynamicDNS); 603 char resolveConfBuffer[80]; 604 size_t sizeResolveConfBuffer = sizeof(resolveConfBuffer); 605 606 while (fgets(resolveConfBuffer, sizeResolveConfBuffer, file)) { 607 if (strncmp(resolveConfBuffer, staticDNS, sizeStaticDNS) == 0) { 608 // If DNS is set to static only, don't modify 609 fclose(file); 610 return B_OK; 611 } else if (strncmp(resolveConfBuffer, dynamicDNS, sizeDynamicDNS) 612 == 0) { 613 // Overwrite existing dynamic entries 614 break; 615 } 616 } 617 618 if (feof(file) != 0) { 619 // No static entries found, close and re-open as new file 620 fclose(file); 621 file = fopen(path.Path(), "w"); 622 if (file == NULL) { 623 fprintf(stderr, "Could not open resolv.conf: %s\n", 624 strerror(errno)); 625 return errno; 626 } 627 } 628 } 629 630 fprintf(file, "# Added automatically by DHCP\n"); 631 632 const char* nameserver; 633 for (int32 i = 0; resolverConfiguration.FindString("nameserver", i, 634 &nameserver) == B_OK; i++) { 635 fprintf(file, "nameserver %s\n", nameserver); 636 } 637 638 const char* domain; 639 if (resolverConfiguration.FindString("domain", &domain) == B_OK) 640 fprintf(file, "domain %s\n", domain); 641 642 fprintf(file, "# End of automatic DHCP additions\n"); 643 644 fclose(file); 645 646 return B_OK; 647 } 648 649 650 bool 651 NetServer::_QuitLooperForDevice(const char* device) 652 { 653 LooperMap::iterator iterator = fDeviceMap.find(device); 654 if (iterator == fDeviceMap.end()) 655 return false; 656 657 // there is a looper for this device - quit it 658 if (iterator->second->Lock()) 659 iterator->second->Quit(); 660 661 fDeviceMap.erase(iterator); 662 return true; 663 } 664 665 666 AutoconfigLooper* 667 NetServer::_LooperForDevice(const char* device) 668 { 669 LooperMap::const_iterator iterator = fDeviceMap.find(device); 670 if (iterator == fDeviceMap.end()) 671 return NULL; 672 673 return iterator->second; 674 } 675 676 677 status_t 678 NetServer::_ConfigureDevice(const char* device) 679 { 680 // bring interface up, but don't configure it just yet 681 BMessage interface; 682 interface.AddString("device", device); 683 BMessage address; 684 address.AddString("family", "inet"); 685 address.AddBool("auto_config", true); 686 interface.AddMessage("address", &address); 687 688 return _ConfigureInterface(interface); 689 } 690 691 692 /*! \brief Traverses the device tree starting from \a startPath, and configures 693 everything that has not yet been configured via settings before. 694 695 \param suggestedInterface Contains the configuration of an interface that 696 does not have any hardware left. It is used to configure the first 697 unconfigured device. This allows to move a Haiku configuration around 698 without losing the network configuration. 699 */ 700 void 701 NetServer::_ConfigureDevices(const char* startPath, 702 BStringList& devicesAlreadyConfigured, BMessage* suggestedInterface) 703 { 704 BDirectory directory(startPath); 705 BEntry entry; 706 while (directory.GetNextEntry(&entry) == B_OK) { 707 char name[B_FILE_NAME_LENGTH]; 708 struct stat stat; 709 BPath path; 710 if (entry.GetName(name) != B_OK 711 || entry.GetPath(&path) != B_OK 712 || entry.GetStat(&stat) != B_OK 713 || devicesAlreadyConfigured.HasString(path.Path())) 714 continue; 715 716 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) { 717 if (suggestedInterface != NULL 718 && suggestedInterface->SetString("device", path.Path()) == B_OK 719 && _ConfigureInterface(*suggestedInterface) == B_OK) 720 suggestedInterface = NULL; 721 else 722 _ConfigureDevice(path.Path()); 723 } else if (entry.IsDirectory()) { 724 _ConfigureDevices(path.Path(), devicesAlreadyConfigured, 725 suggestedInterface); 726 } 727 } 728 } 729 730 731 void 732 NetServer::_ConfigureInterfacesFromSettings(BStringList& devicesSet, 733 BMessage* _missingDevice) 734 { 735 BMessage interface; 736 uint32 cookie = 0; 737 bool missing = false; 738 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 739 const char *device; 740 if (interface.FindString("device", &device) != B_OK) 741 continue; 742 743 bool disabled = false; 744 if (interface.FindBool("disabled", &disabled) == B_OK && disabled) { 745 // disabled by user request 746 _DisableInterface(device); 747 continue; 748 } 749 750 if (!strncmp(device, "/dev/net/", 9)) { 751 // it's a kernel device, check if it's present 752 BEntry entry(device); 753 if (!entry.Exists()) { 754 if (!missing && _missingDevice != NULL) { 755 *_missingDevice = interface; 756 missing = true; 757 } 758 continue; 759 } 760 } 761 762 if (_ConfigureInterface(interface) == B_OK) 763 devicesSet.Add(device); 764 } 765 } 766 767 768 void 769 NetServer::_BringUpInterfaces() 770 { 771 // we need a socket to talk to the networking stack 772 if (!_IsValidFamily(AF_LINK)) { 773 fprintf(stderr, "%s: The networking stack doesn't seem to be " 774 "available.\n", Name()); 775 Quit(); 776 return; 777 } 778 779 _RemoveInvalidInterfaces(); 780 781 // First, we look into the settings, and try to bring everything up from 782 // there 783 784 BStringList devicesAlreadyConfigured; 785 BMessage missingDevice; 786 _ConfigureInterfacesFromSettings(devicesAlreadyConfigured, &missingDevice); 787 788 // Check configuration 789 790 if (!_TestForInterface("loop")) { 791 // there is no loopback interface, create one 792 BMessage interface; 793 interface.AddString("device", "loop"); 794 BMessage v4address; 795 v4address.AddString("family", "inet"); 796 v4address.AddString("address", "127.0.0.1"); 797 interface.AddMessage("address", &v4address); 798 799 // Check for IPv6 support and add ::1 800 if (_IsValidFamily(AF_INET6)) { 801 BMessage v6address; 802 v6address.AddString("family", "inet6"); 803 v6address.AddString("address", "::1"); 804 interface.AddMessage("address", &v6address); 805 } 806 _ConfigureInterface(interface); 807 } 808 809 // TODO: also check if the networking driver is correctly initialized! 810 // (and check for other devices to take over its configuration) 811 812 // There is no driver configured - see if there is one and try to use it 813 _ConfigureDevices("/dev/net", devicesAlreadyConfigured, 814 missingDevice.HasString("device") ? &missingDevice : NULL); 815 } 816 817 818 /*! Configure the link local address based on the network card's MAC address 819 if this isn't a loopback device. 820 */ 821 void 822 NetServer::_ConfigureIPv6LinkLocal(const char* name) 823 { 824 // Check for IPv6 support 825 if (!_IsValidFamily(AF_INET6)) 826 return; 827 828 BNetworkInterface interface(name); 829 830 // Lets make sure this is *not* the loopback interface 831 if ((interface.Flags() & IFF_LOOPBACK) != 0) 832 return; 833 834 BNetworkAddress link; 835 status_t result = interface.GetHardwareAddress(link); 836 837 if (result != B_OK || link.LinkLevelAddressLength() != 6) 838 return; 839 840 const uint8* mac = link.LinkLevelAddress(); 841 842 // Check for a few failure situations 843 static const uint8 zeroMac[6] = {0, 0, 0, 0, 0, 0}; 844 static const uint8 fullMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 845 if (memcmp(mac, zeroMac, 6) == 0 846 || memcmp(mac, fullMac, 6) == 0) { 847 // Mac address is all 0 or all FF's 848 syslog(LOG_DEBUG, "%s: MacAddress for interface '%s' is invalid.", 849 __func__, name); 850 return; 851 } 852 853 // Generate a Link Local Scope address 854 // (IPv6 address based on Mac address) 855 in6_addr addressRaw; 856 memset(addressRaw.s6_addr, 0, sizeof(addressRaw.s6_addr)); 857 addressRaw.s6_addr[0] = 0xfe; 858 addressRaw.s6_addr[1] = 0x80; 859 addressRaw.s6_addr[8] = mac[0] ^ 0x02; 860 addressRaw.s6_addr[9] = mac[1]; 861 addressRaw.s6_addr[10] = mac[2]; 862 addressRaw.s6_addr[11] = 0xff; 863 addressRaw.s6_addr[12] = 0xfe; 864 addressRaw.s6_addr[13] = mac[3]; 865 addressRaw.s6_addr[14] = mac[4]; 866 addressRaw.s6_addr[15] = mac[5]; 867 868 BNetworkAddress localLinkAddress(addressRaw, 0); 869 BNetworkAddress localLinkMask( 870 AF_INET6, 871 "ffff:ffff:ffff:ffff::", // 64 872 (uint16)0, 873 B_UNCONFIGURED_ADDRESS_FAMILIES); 874 BNetworkAddress localLinkBroadcast( 875 AF_INET6, 876 "fe80::ffff:ffff:ffff:ffff", 877 (uint16)0, 878 B_UNCONFIGURED_ADDRESS_FAMILIES); 879 880 if (interface.FindAddress(localLinkAddress) >= 0) { 881 // uhoh... already has a local link address 882 883 /* TODO: Check for any local link scope addresses assigned to card 884 There isn't any flag at the moment though for address scope 885 */ 886 syslog(LOG_DEBUG, "%s: Local Link address already assigned to %s\n", 887 __func__, name); 888 return; 889 } 890 891 BNetworkInterfaceAddress interfaceAddress; 892 interfaceAddress.SetAddress(localLinkAddress); 893 interfaceAddress.SetMask(localLinkMask); 894 interfaceAddress.SetBroadcast(localLinkMask); 895 896 /* TODO: Duplicate Address Detection. (DAD) 897 Need to blast an icmp packet over the IPv6 network from :: to ensure 898 there aren't duplicate MAC addresses on the network. (definitely an 899 edge case, but a possible issue) 900 */ 901 902 interface.AddAddress(interfaceAddress); 903 } 904 905 906 void 907 NetServer::_StartServices() 908 { 909 BHandler* services = new (std::nothrow) Services(fSettings.Services()); 910 if (services != NULL) { 911 AddHandler(services); 912 fServices = BMessenger(services); 913 } 914 } 915 916 917 status_t 918 NetServer::_HandleDeviceMonitor(BMessage* message) 919 { 920 int32 opcode; 921 const char* path; 922 if (message->FindInt32("opcode", &opcode) != B_OK 923 || (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED) 924 || message->FindString("path", &path) != B_OK) 925 return B_BAD_VALUE; 926 927 if (strncmp(path, "/dev/net/", 9)) { 928 // not a valid device entry, ignore 929 return B_NAME_NOT_FOUND; 930 } 931 932 if (opcode == B_ENTRY_CREATED) 933 _ConfigureDevice(path); 934 else 935 _RemoveInterface(path); 936 937 return B_OK; 938 } 939 940 941 status_t 942 NetServer::_AutoJoinNetwork(const BMessage& message) 943 { 944 const char* name = NULL; 945 if (message.FindString("device", &name) != B_OK) 946 return B_BAD_VALUE; 947 948 BNetworkDevice device(name); 949 950 // Choose among configured networks 951 952 uint32 cookie = 0; 953 BMessage networkMessage; 954 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 955 status_t status = B_ERROR; 956 wireless_network network; 957 const char* networkName; 958 BNetworkAddress link; 959 960 const char* mac = NULL; 961 if (networkMessage.FindString("mac", &mac) == B_OK) { 962 link.SetTo(AF_LINK, mac); 963 status = device.GetNetwork(link, network); 964 } else if (networkMessage.FindString("name", &networkName) == B_OK) 965 status = device.GetNetwork(networkName, network); 966 967 if (status == B_OK) { 968 status = _JoinNetwork(message, mac != NULL ? &link : NULL, 969 network.name); 970 printf("auto join network \"%s\": %s\n", network.name, 971 strerror(status)); 972 if (status == B_OK) 973 return B_OK; 974 } 975 } 976 977 return B_NO_INIT; 978 } 979 980 981 status_t 982 NetServer::_JoinNetwork(const BMessage& message, const BNetworkAddress* address, 983 const char* name) 984 { 985 const char* deviceName; 986 if (message.FindString("device", &deviceName) != B_OK) 987 return B_BAD_VALUE; 988 989 BNetworkAddress deviceAddress; 990 message.FindFlat("address", &deviceAddress); 991 if (address == NULL) 992 address = &deviceAddress; 993 994 if (name == NULL) 995 message.FindString("name", &name); 996 if (name == NULL) { 997 // No name specified, we need a network address 998 if (address->Family() != AF_LINK) 999 return B_BAD_VALUE; 1000 } 1001 1002 // Search for a network configuration that may override the defaults 1003 1004 bool found = false; 1005 uint32 cookie = 0; 1006 BMessage networkMessage; 1007 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 1008 const char* networkName; 1009 if (networkMessage.FindString("name", &networkName) == B_OK 1010 && name != NULL && address->Family() != AF_LINK 1011 && !strcmp(name, networkName)) { 1012 found = true; 1013 break; 1014 } 1015 1016 const char* mac; 1017 if (networkMessage.FindString("mac", &mac) == B_OK 1018 && address->Family() == AF_LINK) { 1019 BNetworkAddress link(AF_LINK, mac); 1020 if (link == *address) { 1021 found = true; 1022 break; 1023 } 1024 } 1025 } 1026 1027 const char* password; 1028 if (message.FindString("password", &password) != B_OK && found) 1029 password = networkMessage.FindString("password"); 1030 1031 // Get network 1032 BNetworkDevice device(deviceName); 1033 wireless_network network; 1034 1035 bool askForConfig = false; 1036 if ((address->Family() != AF_LINK 1037 || device.GetNetwork(*address, network) != B_OK) 1038 && device.GetNetwork(name, network) != B_OK) { 1039 // We did not find a network - just ignore that, and continue 1040 // with some defaults 1041 strlcpy(network.name, name != NULL ? name : "", sizeof(network.name)); 1042 network.address = *address; 1043 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 1044 network.cipher = 0; 1045 network.group_cipher = 0; 1046 network.key_mode = 0; 1047 askForConfig = true; 1048 } 1049 1050 BString string; 1051 if ((message.FindString("authentication", &string) == B_OK 1052 && !string.IsEmpty()) 1053 || (found && networkMessage.FindString("authentication", &string) 1054 == B_OK && !string.IsEmpty())) { 1055 askForConfig = false; 1056 if (string.ICompare("wpa2") == 0) { 1057 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2; 1058 network.key_mode = B_KEY_MODE_IEEE802_1X; 1059 network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP; 1060 } else if (string.ICompare("wpa") == 0) { 1061 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA; 1062 network.key_mode = B_KEY_MODE_IEEE802_1X; 1063 network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP; 1064 } else if (string.ICompare("wep") == 0) { 1065 network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP; 1066 network.key_mode = B_KEY_MODE_NONE; 1067 network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40; 1068 } else if (string.ICompare("none") != 0 && string.ICompare("open") != 0) { 1069 fprintf(stderr, "%s: invalid authentication mode.\n", name); 1070 askForConfig = true; 1071 } 1072 } 1073 1074 // We always try to join via the wpa_supplicant. Even if we could join 1075 // ourselves, we need to make sure that the wpa_supplicant knows about 1076 // our intention, as otherwise it would interfere with it. 1077 1078 BMessenger wpaSupplicant(kWPASupplicantSignature); 1079 if (!wpaSupplicant.IsValid()) { 1080 // The wpa_supplicant isn't running yet, we may join ourselves. 1081 if (!askForConfig 1082 && network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) { 1083 // We can join this network ourselves. 1084 status_t status = set_80211(deviceName, IEEE80211_IOC_SSID, 1085 network.name, strlen(network.name)); 1086 if (status != B_OK) { 1087 fprintf(stderr, "%s: joining SSID failed: %s\n", name, 1088 strerror(status)); 1089 return status; 1090 } 1091 } 1092 1093 // We need the supplicant, try to launch it. 1094 status_t status = be_roster->Launch(kWPASupplicantSignature); 1095 if (status != B_OK && status != B_ALREADY_RUNNING) 1096 return status; 1097 1098 wpaSupplicant.SetTo(kWPASupplicantSignature); 1099 if (!wpaSupplicant.IsValid()) 1100 return B_ERROR; 1101 } 1102 1103 // TODO: listen to notifications from the supplicant! 1104 1105 BMessage join(kMsgWPAJoinNetwork); 1106 status_t status = join.AddString("device", deviceName); 1107 if (status == B_OK) 1108 status = join.AddString("name", network.name); 1109 if (status == B_OK) 1110 status = join.AddFlat("address", &network.address); 1111 if (status == B_OK && !askForConfig) 1112 status = join.AddUInt32("authentication", network.authentication_mode); 1113 if (status == B_OK && password != NULL) 1114 status = join.AddString("password", password); 1115 if (status != B_OK) 1116 return status; 1117 1118 status = wpaSupplicant.SendMessage(&join); 1119 if (status != B_OK) 1120 return status; 1121 1122 return B_OK; 1123 } 1124 1125 1126 status_t 1127 NetServer::_LeaveNetwork(const BMessage& message) 1128 { 1129 const char* deviceName; 1130 if (message.FindString("device", &deviceName) != B_OK) 1131 return B_BAD_VALUE; 1132 1133 int32 reason; 1134 if (message.FindInt32("reason", &reason) != B_OK) 1135 reason = IEEE80211_REASON_AUTH_LEAVE; 1136 1137 // We always try to send the leave request to the wpa_supplicant. 1138 1139 BMessenger wpaSupplicant(kWPASupplicantSignature); 1140 if (wpaSupplicant.IsValid()) { 1141 BMessage leave(kMsgWPALeaveNetwork); 1142 status_t status = leave.AddString("device", deviceName); 1143 if (status == B_OK) 1144 status = leave.AddInt32("reason", reason); 1145 if (status != B_OK) 1146 return status; 1147 1148 status = wpaSupplicant.SendMessage(&leave); 1149 if (status == B_OK) 1150 return B_OK; 1151 } 1152 1153 // The wpa_supplicant doesn't seem to be running, check if this was an open 1154 // network we connected ourselves. 1155 BNetworkDevice device(deviceName); 1156 wireless_network network; 1157 1158 uint32 cookie = 0; 1159 if (device.GetNextAssociatedNetwork(cookie, network) != B_OK 1160 || network.authentication_mode != B_NETWORK_AUTHENTICATION_NONE) { 1161 // We didn't join ourselves, we can't do much. 1162 return B_ERROR; 1163 } 1164 1165 // We joined ourselves, so we can just disassociate again. 1166 ieee80211req_mlme mlmeRequest; 1167 memset(&mlmeRequest, 0, sizeof(mlmeRequest)); 1168 mlmeRequest.im_op = IEEE80211_MLME_DISASSOC; 1169 mlmeRequest.im_reason = reason; 1170 1171 return set_80211(deviceName, IEEE80211_IOC_MLME, &mlmeRequest, 1172 sizeof(mlmeRequest)); 1173 } 1174 1175 1176 // #pragma mark - 1177 1178 1179 int 1180 main(int argc, char** argv) 1181 { 1182 srand(system_time()); 1183 1184 status_t status; 1185 NetServer server(status); 1186 if (status != B_OK) { 1187 fprintf(stderr, "net_server: Failed to create application: %s\n", 1188 strerror(status)); 1189 return 1; 1190 } 1191 1192 server.Run(); 1193 return 0; 1194 } 1195 1196