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