1 /* 2 * Copyright 2006-2018, 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 continue; 736 737 if (S_ISBLK(stat.st_mode) || S_ISCHR(stat.st_mode)) { 738 if (suggestedInterface != NULL 739 && suggestedInterface->SetString("device", path.Path()) == B_OK 740 && _ConfigureInterface(*suggestedInterface) == B_OK) 741 suggestedInterface = NULL; 742 else if (!devicesAlreadyConfigured.HasString(path.Path())) 743 _ConfigureDevice(path.Path()); 744 } else if (entry.IsDirectory()) { 745 _ConfigureDevices(path.Path(), devicesAlreadyConfigured, 746 suggestedInterface); 747 } 748 } 749 } 750 751 752 void 753 NetServer::_ConfigureInterfacesFromSettings(BStringList& devicesSet, 754 BMessage* _missingDevice) 755 { 756 BMessage interface; 757 uint32 cookie = 0; 758 bool missing = false; 759 while (fSettings.GetNextInterface(cookie, interface) == B_OK) { 760 const char *device; 761 if (interface.FindString("device", &device) != B_OK) 762 continue; 763 764 bool disabled = false; 765 if (interface.FindBool("disabled", &disabled) == B_OK && disabled) { 766 // disabled by user request 767 _DisableInterface(device); 768 continue; 769 } 770 771 if (!strncmp(device, "/dev/net/", 9)) { 772 // it's a kernel device, check if it's present 773 BEntry entry(device); 774 if (!entry.Exists()) { 775 if (!missing && _missingDevice != NULL) { 776 *_missingDevice = interface; 777 missing = true; 778 } 779 continue; 780 } 781 } 782 783 if (_ConfigureInterface(interface) == B_OK) 784 devicesSet.Add(device); 785 } 786 } 787 788 789 void 790 NetServer::_BringUpInterfaces() 791 { 792 // we need a socket to talk to the networking stack 793 if (!_IsValidFamily(AF_LINK)) { 794 fprintf(stderr, "%s: The networking stack doesn't seem to be " 795 "available.\n", Name()); 796 Quit(); 797 return; 798 } 799 800 _RemoveInvalidInterfaces(); 801 802 // First, we look into the settings, and try to bring everything up from 803 // there 804 805 BStringList devicesAlreadyConfigured; 806 BMessage missingDevice; 807 _ConfigureInterfacesFromSettings(devicesAlreadyConfigured, &missingDevice); 808 809 // Check configuration 810 811 if (!_TestForInterface("loop")) { 812 // there is no loopback interface, create one 813 BMessage interface; 814 interface.AddString("device", "loop"); 815 BMessage v4address; 816 v4address.AddString("family", "inet"); 817 v4address.AddString("address", "127.0.0.1"); 818 interface.AddMessage("address", &v4address); 819 820 // Check for IPv6 support and add ::1 821 if (_IsValidFamily(AF_INET6)) { 822 BMessage v6address; 823 v6address.AddString("family", "inet6"); 824 v6address.AddString("address", "::1"); 825 interface.AddMessage("address", &v6address); 826 } 827 _ConfigureInterface(interface); 828 } 829 830 // TODO: also check if the networking driver is correctly initialized! 831 // (and check for other devices to take over its configuration) 832 833 // There is no driver configured - see if there is one and try to use it 834 _ConfigureDevices("/dev/net", devicesAlreadyConfigured, 835 missingDevice.HasString("device") ? &missingDevice : NULL); 836 } 837 838 839 /*! Configure the link local address based on the network card's MAC address 840 if this isn't a loopback device. 841 */ 842 void 843 NetServer::_ConfigureIPv6LinkLocal(const char* name) 844 { 845 // Check for IPv6 support 846 if (!_IsValidFamily(AF_INET6)) 847 return; 848 849 BNetworkInterface interface(name); 850 851 // Lets make sure this is *not* the loopback interface 852 if ((interface.Flags() & IFF_LOOPBACK) != 0) 853 return; 854 855 BNetworkAddress link; 856 status_t result = interface.GetHardwareAddress(link); 857 858 if (result != B_OK || link.LinkLevelAddressLength() != 6) 859 return; 860 861 const uint8* mac = link.LinkLevelAddress(); 862 863 // Check for a few failure situations 864 static const uint8 zeroMac[6] = {0, 0, 0, 0, 0, 0}; 865 static const uint8 fullMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 866 if (memcmp(mac, zeroMac, 6) == 0 867 || memcmp(mac, fullMac, 6) == 0) { 868 // Mac address is all 0 or all FF's 869 syslog(LOG_DEBUG, "%s: MacAddress for interface '%s' is invalid.", 870 __func__, name); 871 return; 872 } 873 874 // Generate a Link Local Scope address 875 // (IPv6 address based on Mac address) 876 in6_addr addressRaw; 877 memset(addressRaw.s6_addr, 0, sizeof(addressRaw.s6_addr)); 878 addressRaw.s6_addr[0] = 0xfe; 879 addressRaw.s6_addr[1] = 0x80; 880 addressRaw.s6_addr[8] = mac[0] ^ 0x02; 881 addressRaw.s6_addr[9] = mac[1]; 882 addressRaw.s6_addr[10] = mac[2]; 883 addressRaw.s6_addr[11] = 0xff; 884 addressRaw.s6_addr[12] = 0xfe; 885 addressRaw.s6_addr[13] = mac[3]; 886 addressRaw.s6_addr[14] = mac[4]; 887 addressRaw.s6_addr[15] = mac[5]; 888 889 BNetworkAddress localLinkAddress(addressRaw, 0); 890 BNetworkAddress localLinkMask("ffff:ffff:ffff:ffff::"); // 64 891 BNetworkAddress localLinkBroadcast("fe80::ffff:ffff:ffff:ffff"); 892 893 if (interface.FindAddress(localLinkAddress) >= 0) { 894 // uhoh... already has a local link address 895 896 /* TODO: Check for any local link scope addresses assigned to card 897 There isn't any flag at the moment though for address scope 898 */ 899 syslog(LOG_DEBUG, "%s: Local Link address already assigned to %s\n", 900 __func__, name); 901 return; 902 } 903 904 BNetworkInterfaceAddress interfaceAddress; 905 interfaceAddress.SetAddress(localLinkAddress); 906 interfaceAddress.SetMask(localLinkMask); 907 interfaceAddress.SetBroadcast(localLinkMask); 908 909 /* TODO: Duplicate Address Detection. (DAD) 910 Need to blast an icmp packet over the IPv6 network from :: to ensure 911 there aren't duplicate MAC addresses on the network. (definitely an 912 edge case, but a possible issue) 913 */ 914 915 interface.AddAddress(interfaceAddress); 916 } 917 918 919 void 920 NetServer::_StartServices() 921 { 922 BHandler* services = new (std::nothrow) Services(fSettings.Services()); 923 if (services != NULL) { 924 AddHandler(services); 925 fServices = BMessenger(services); 926 } 927 } 928 929 930 status_t 931 NetServer::_HandleDeviceMonitor(BMessage* message) 932 { 933 int32 opcode; 934 const char* path; 935 if (message->FindInt32("opcode", &opcode) != B_OK 936 || (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED) 937 || message->FindString("path", &path) != B_OK) 938 return B_BAD_VALUE; 939 940 if (strncmp(path, "/dev/net/", 9)) { 941 // not a valid device entry, ignore 942 return B_NAME_NOT_FOUND; 943 } 944 945 if (opcode == B_ENTRY_CREATED) 946 _ConfigureDevice(path); 947 else 948 _RemoveInterface(path); 949 950 return B_OK; 951 } 952 953 954 status_t 955 NetServer::_AutoJoinNetwork(const BMessage& message) 956 { 957 const char* name = NULL; 958 if (message.FindString("device", &name) != B_OK) 959 return B_BAD_VALUE; 960 961 BNetworkDevice device(name); 962 963 // Choose among configured networks 964 965 uint32 cookie = 0; 966 BMessage networkMessage; 967 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 968 status_t status = B_ERROR; 969 wireless_network network; 970 const char* networkName; 971 BNetworkAddress link; 972 973 const char* mac = NULL; 974 if (networkMessage.FindString("mac", &mac) == B_OK) { 975 link.SetTo(AF_LINK, mac); 976 status = device.GetNetwork(link, network); 977 } else if (networkMessage.FindString("name", &networkName) == B_OK) 978 status = device.GetNetwork(networkName, network); 979 980 if (status == B_OK) { 981 status = _JoinNetwork(message, mac != NULL ? &link : NULL, 982 network.name); 983 printf("auto join network \"%s\": %s\n", network.name, 984 strerror(status)); 985 if (status == B_OK) 986 return B_OK; 987 } 988 } 989 990 return B_NO_INIT; 991 } 992 993 994 status_t 995 NetServer::_JoinNetwork(const BMessage& message, const BNetworkAddress* address, 996 const char* name) 997 { 998 const char* deviceName; 999 if (message.FindString("device", &deviceName) != B_OK) 1000 return B_BAD_VALUE; 1001 1002 BNetworkAddress deviceAddress; 1003 message.FindFlat("address", &deviceAddress); 1004 if (address == NULL) 1005 address = &deviceAddress; 1006 1007 if (name == NULL) 1008 message.FindString("name", &name); 1009 if (name == NULL) { 1010 // No name specified, we need a network address 1011 if (address->Family() != AF_LINK) 1012 return B_BAD_VALUE; 1013 } 1014 1015 // Search for a network configuration that may override the defaults 1016 1017 bool found = false; 1018 uint32 cookie = 0; 1019 BMessage networkMessage; 1020 while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { 1021 const char* networkName; 1022 if (networkMessage.FindString("name", &networkName) == B_OK 1023 && name != NULL && address->Family() != AF_LINK 1024 && !strcmp(name, networkName)) { 1025 found = true; 1026 break; 1027 } 1028 1029 const char* mac; 1030 if (networkMessage.FindString("mac", &mac) == B_OK 1031 && address->Family() == AF_LINK) { 1032 BNetworkAddress link(AF_LINK, mac); 1033 if (link == *address) { 1034 found = true; 1035 break; 1036 } 1037 } 1038 } 1039 1040 const char* password; 1041 if (message.FindString("password", &password) != B_OK && found) 1042 password = networkMessage.FindString("password"); 1043 1044 // Get network 1045 BNetworkDevice device(deviceName); 1046 wireless_network network; 1047 1048 bool askForConfig = false; 1049 if ((address->Family() != AF_LINK 1050 || device.GetNetwork(*address, network) != B_OK) 1051 && device.GetNetwork(name, network) != B_OK) { 1052 // We did not find a network - just ignore that, and continue 1053 // with some defaults 1054 strlcpy(network.name, name != NULL ? name : "", sizeof(network.name)); 1055 network.address = *address; 1056 network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; 1057 network.cipher = 0; 1058 network.group_cipher = 0; 1059 network.key_mode = 0; 1060 askForConfig = true; 1061 } 1062 1063 BString string; 1064 if ((message.FindString("authentication", &string) == B_OK 1065 && !string.IsEmpty()) 1066 || (found && networkMessage.FindString("authentication", &string) 1067 == B_OK && !string.IsEmpty())) { 1068 askForConfig = false; 1069 if (string.ICompare("wpa2") == 0) { 1070 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2; 1071 network.key_mode = B_KEY_MODE_IEEE802_1X; 1072 network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP; 1073 } else if (string.ICompare("wpa") == 0) { 1074 network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA; 1075 network.key_mode = B_KEY_MODE_IEEE802_1X; 1076 network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP; 1077 } else if (string.ICompare("wep") == 0) { 1078 network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP; 1079 network.key_mode = B_KEY_MODE_NONE; 1080 network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40; 1081 } else if (string.ICompare("none") != 0 && string.ICompare("open") != 0) { 1082 fprintf(stderr, "%s: invalid authentication mode.\n", name); 1083 askForConfig = true; 1084 } 1085 } 1086 1087 // We always try to join via the wpa_supplicant. Even if we could join 1088 // ourselves, we need to make sure that the wpa_supplicant knows about 1089 // our intention, as otherwise it would interfere with it. 1090 1091 BMessenger wpaSupplicant(kWPASupplicantSignature); 1092 if (!wpaSupplicant.IsValid()) { 1093 // The wpa_supplicant isn't running yet, we may join ourselves. 1094 if (!askForConfig 1095 && network.authentication_mode == B_NETWORK_AUTHENTICATION_NONE) { 1096 // We can join this network ourselves. 1097 status_t status = set_80211(deviceName, IEEE80211_IOC_SSID, 1098 network.name, strlen(network.name)); 1099 if (status != B_OK) { 1100 fprintf(stderr, "%s: joining SSID failed: %s\n", name, 1101 strerror(status)); 1102 return status; 1103 } 1104 } 1105 1106 // We need the supplicant, try to launch it. 1107 status_t status = be_roster->Launch(kWPASupplicantSignature); 1108 if (status != B_OK && status != B_ALREADY_RUNNING) 1109 return status; 1110 1111 wpaSupplicant.SetTo(kWPASupplicantSignature); 1112 if (!wpaSupplicant.IsValid()) 1113 return B_ERROR; 1114 } 1115 1116 // TODO: listen to notifications from the supplicant! 1117 1118 BMessage join(kMsgWPAJoinNetwork); 1119 status_t status = join.AddString("device", deviceName); 1120 if (status == B_OK) 1121 status = join.AddString("name", network.name); 1122 if (status == B_OK) 1123 status = join.AddFlat("address", &network.address); 1124 if (status == B_OK && !askForConfig) 1125 status = join.AddUInt32("authentication", network.authentication_mode); 1126 if (status == B_OK && password != NULL) 1127 status = join.AddString("password", password); 1128 if (status != B_OK) 1129 return status; 1130 1131 status = wpaSupplicant.SendMessage(&join); 1132 if (status != B_OK) 1133 return status; 1134 1135 return B_OK; 1136 } 1137 1138 1139 status_t 1140 NetServer::_LeaveNetwork(const BMessage& message) 1141 { 1142 const char* deviceName; 1143 if (message.FindString("device", &deviceName) != B_OK) 1144 return B_BAD_VALUE; 1145 1146 int32 reason; 1147 if (message.FindInt32("reason", &reason) != B_OK) 1148 reason = IEEE80211_REASON_AUTH_LEAVE; 1149 1150 // We always try to send the leave request to the wpa_supplicant. 1151 1152 BMessenger wpaSupplicant(kWPASupplicantSignature); 1153 if (wpaSupplicant.IsValid()) { 1154 BMessage leave(kMsgWPALeaveNetwork); 1155 status_t status = leave.AddString("device", deviceName); 1156 if (status == B_OK) 1157 status = leave.AddInt32("reason", reason); 1158 if (status != B_OK) 1159 return status; 1160 1161 status = wpaSupplicant.SendMessage(&leave); 1162 if (status == B_OK) 1163 return B_OK; 1164 } 1165 1166 // The wpa_supplicant doesn't seem to be running, check if this was an open 1167 // network we connected ourselves. 1168 BNetworkDevice device(deviceName); 1169 wireless_network network; 1170 1171 uint32 cookie = 0; 1172 if (device.GetNextAssociatedNetwork(cookie, network) != B_OK 1173 || network.authentication_mode != B_NETWORK_AUTHENTICATION_NONE) { 1174 // We didn't join ourselves, we can't do much. 1175 return B_ERROR; 1176 } 1177 1178 // We joined ourselves, so we can just disassociate again. 1179 ieee80211req_mlme mlmeRequest; 1180 memset(&mlmeRequest, 0, sizeof(mlmeRequest)); 1181 mlmeRequest.im_op = IEEE80211_MLME_DISASSOC; 1182 mlmeRequest.im_reason = reason; 1183 1184 return set_80211(deviceName, IEEE80211_IOC_MLME, &mlmeRequest, 1185 sizeof(mlmeRequest)); 1186 } 1187 1188 1189 // #pragma mark - 1190 1191 1192 int 1193 main(int argc, char** argv) 1194 { 1195 srand(system_time()); 1196 1197 status_t status; 1198 NetServer server(status); 1199 if (status != B_OK) { 1200 fprintf(stderr, "net_server: Failed to create application: %s\n", 1201 strerror(status)); 1202 return 1; 1203 } 1204 1205 server.Run(); 1206 return 0; 1207 } 1208 1209