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