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