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 */ 8 9 10#include <NetworkSettings.h> 11 12#include <netdb.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16 17#include <Directory.h> 18#include <File.h> 19#include <FindDirectory.h> 20#include <fs_interface.h> 21#include <NetworkDevice.h> 22#include <NetworkInterface.h> 23#include <Path.h> 24#include <PathMonitor.h> 25#include <String.h> 26 27#include <DriverSettingsMessageAdapter.h> 28#include <NetServer.h> 29 30 31using namespace BNetworkKit; 32 33 34static const char* kInterfaceSettingsName = "interfaces"; 35static const char* kServicesSettingsName = "services"; 36static const char* kNetworksSettingsName = "wireless_networks"; 37 38 39// Interface templates 40 41namespace BPrivate { 42 43 44class InterfaceAddressFamilyConverter : public DriverSettingsConverter { 45public: 46 virtual status_t ConvertFromDriverSettings( 47 const driver_parameter& parameter, 48 const char* name, int32 index, uint32 type, 49 BMessage& target); 50 virtual status_t ConvertToDriverSettings(const BMessage& source, 51 const char* name, int32 index, 52 uint32 type, BString& value); 53}; 54 55 56} // namespace BPrivate 57 58using BPrivate::InterfaceAddressFamilyConverter; 59 60 61const static settings_template kInterfaceAddressTemplate[] = { 62 {B_STRING_TYPE, "family", NULL, true, new InterfaceAddressFamilyConverter}, 63 {B_STRING_TYPE, "address", NULL}, 64 {B_STRING_TYPE, "mask", NULL}, 65 {B_STRING_TYPE, "peer", NULL}, 66 {B_STRING_TYPE, "broadcast", NULL}, 67 {B_STRING_TYPE, "gateway", NULL}, 68 {B_BOOL_TYPE, "auto_config", NULL}, 69 {0, NULL, NULL} 70}; 71 72const static settings_template kInterfaceNetworkTemplate[] = { 73 {B_STRING_TYPE, "name", NULL, true}, 74 {B_STRING_TYPE, "mac", NULL}, 75}; 76 77const static settings_template kInterfaceTemplate[] = { 78 {B_STRING_TYPE, "device", NULL, true}, 79 {B_BOOL_TYPE, "disabled", NULL}, 80 {B_MESSAGE_TYPE, "address", kInterfaceAddressTemplate}, 81 {B_MESSAGE_TYPE, "network", kInterfaceNetworkTemplate}, 82 {B_INT32_TYPE, "flags", NULL}, 83 {B_INT32_TYPE, "metric", NULL}, 84 {B_INT32_TYPE, "mtu", NULL}, 85 {0, NULL, NULL} 86}; 87 88const static settings_template kInterfacesTemplate[] = { 89 {B_MESSAGE_TYPE, "interface", kInterfaceTemplate}, 90 {0, NULL, NULL} 91}; 92 93// Network templates 94 95const static settings_template kNetworkTemplate[] = { 96 {B_STRING_TYPE, "name", NULL, true}, 97 {B_STRING_TYPE, "mac", NULL}, 98 {B_STRING_TYPE, "password", NULL}, 99 {B_STRING_TYPE, "authentication", NULL}, 100 {B_STRING_TYPE, "cipher", NULL}, 101 {B_STRING_TYPE, "group_cipher", NULL}, 102 {B_STRING_TYPE, "key", NULL}, 103 {0, NULL, NULL} 104}; 105 106const static settings_template kNetworksTemplate[] = { 107 {B_MESSAGE_TYPE, "network", kNetworkTemplate}, 108 {0, NULL, NULL} 109}; 110 111// Service templates 112 113const static settings_template kServiceAddressTemplate[] = { 114 {B_STRING_TYPE, "family", NULL, true}, 115 {B_STRING_TYPE, "type", NULL}, 116 {B_STRING_TYPE, "protocol", NULL}, 117 {B_STRING_TYPE, "address", NULL}, 118 {B_INT32_TYPE, "port", NULL}, 119 {0, NULL, NULL} 120}; 121 122const static settings_template kServiceTemplate[] = { 123 {B_STRING_TYPE, "name", NULL, true}, 124 {B_BOOL_TYPE, "disabled", NULL}, 125 {B_MESSAGE_TYPE, "address", kServiceAddressTemplate}, 126 {B_STRING_TYPE, "user", NULL}, 127 {B_STRING_TYPE, "group", NULL}, 128 {B_STRING_TYPE, "launch", NULL}, 129 {B_STRING_TYPE, "family", NULL}, 130 {B_STRING_TYPE, "type", NULL}, 131 {B_STRING_TYPE, "protocol", NULL}, 132 {B_INT32_TYPE, "port", NULL}, 133 {B_BOOL_TYPE, "stand_alone", NULL}, 134 {0, NULL, NULL} 135}; 136 137const static settings_template kServicesTemplate[] = { 138 {B_MESSAGE_TYPE, "service", kServiceTemplate}, 139 {0, NULL, NULL} 140}; 141 142 143struct address_family { 144 int family; 145 const char* name; 146 const char* identifiers[4]; 147}; 148 149 150static const address_family kFamilies[] = { 151 { 152 AF_INET, 153 "inet", 154 {"AF_INET", "inet", "ipv4", NULL}, 155 }, 156 { 157 AF_INET6, 158 "inet6", 159 {"AF_INET6", "inet6", "ipv6", NULL}, 160 }, 161 { -1, NULL, {NULL} } 162}; 163 164 165static const char* 166get_family_name(int family) 167{ 168 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 169 if (kFamilies[i].family == family) 170 return kFamilies[i].name; 171 } 172 return NULL; 173} 174 175 176static int 177get_address_family(const char* argument) 178{ 179 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 180 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 181 if (!strcmp(argument, kFamilies[i].identifiers[j])) { 182 // found a match 183 return kFamilies[i].family; 184 } 185 } 186 } 187 188 return AF_UNSPEC; 189} 190 191 192/*! Parses the \a argument as network \a address for the specified \a family. 193 If \a family is \c AF_UNSPEC, \a family will be overwritten with the family 194 of the successfully parsed address. 195*/ 196static bool 197parse_address(int32& family, const char* argument, BNetworkAddress& address) 198{ 199 if (argument == NULL) { 200 if (family != AF_UNSPEC) 201 address.SetToWildcard(family); 202 return false; 203 } 204 205 status_t status = address.SetTo(family, argument, (uint16)0, 206 B_NO_ADDRESS_RESOLUTION); 207 if (status != B_OK) 208 return false; 209 210 if (family == AF_UNSPEC) { 211 // Test if we support the resulting address family 212 bool supported = false; 213 214 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 215 if (kFamilies[i].family == address.Family()) { 216 supported = true; 217 break; 218 } 219 } 220 if (!supported) 221 return false; 222 223 // Take over family from address 224 family = address.Family(); 225 } 226 227 return true; 228} 229 230 231static int 232parse_type(const char* string) 233{ 234 if (!strcasecmp(string, "stream")) 235 return SOCK_STREAM; 236 237 return SOCK_DGRAM; 238} 239 240 241static int 242parse_protocol(const char* string) 243{ 244 struct protoent* proto = getprotobyname(string); 245 if (proto == NULL) 246 return IPPROTO_TCP; 247 248 return proto->p_proto; 249} 250 251 252static int 253type_for_protocol(int protocol) 254{ 255 // default determined by protocol 256 switch (protocol) { 257 case IPPROTO_TCP: 258 return SOCK_STREAM; 259 260 case IPPROTO_UDP: 261 default: 262 return SOCK_DGRAM; 263 } 264} 265 266 267// #pragma mark - 268 269 270status_t 271InterfaceAddressFamilyConverter::ConvertFromDriverSettings( 272 const driver_parameter& parameter, const char* name, int32 index, 273 uint32 type, BMessage& target) 274{ 275 return B_NOT_SUPPORTED; 276} 277 278 279status_t 280InterfaceAddressFamilyConverter::ConvertToDriverSettings(const BMessage& source, 281 const char* name, int32 index, uint32 type, BString& value) 282{ 283 int32 family; 284 if (source.FindInt32("family", &family) == B_OK) { 285 const char* familyName = get_family_name(family); 286 if (familyName != NULL) 287 value << familyName; 288 else 289 value << family; 290 291 return B_OK; 292 } 293 294 return B_NOT_SUPPORTED; 295} 296 297 298// #pragma mark - 299 300 301BNetworkSettings::BNetworkSettings() 302{ 303 _Load(); 304} 305 306 307BNetworkSettings::~BNetworkSettings() 308{ 309} 310 311 312status_t 313BNetworkSettings::GetNextInterface(uint32& cookie, BMessage& interface) 314{ 315 status_t status = fInterfaces.FindMessage("interface", cookie, &interface); 316 if (status != B_OK) 317 return status; 318 319 cookie++; 320 return B_OK; 321} 322 323 324status_t 325BNetworkSettings::GetInterface(const char* name, BMessage& interface) const 326{ 327 int32 index; 328 return _GetItem(fInterfaces, "interface", "device", name, index, interface); 329} 330 331 332status_t 333BNetworkSettings::AddInterface(const BMessage& interface) 334{ 335 const char* name = NULL; 336 if (interface.FindString("device", &name) != B_OK) 337 return B_BAD_VALUE; 338 339 _RemoveItem(fInterfaces, "interface", "device", name); 340 341 status_t result = fInterfaces.AddMessage("interface", &interface); 342 if (result != B_OK) 343 return result; 344 345 return _Save(kInterfaceSettingsName); 346} 347 348 349status_t 350BNetworkSettings::RemoveInterface(const char* name) 351{ 352 return _RemoveItem(fInterfaces, "interface", "device", name, 353 kInterfaceSettingsName); 354} 355 356 357BNetworkInterfaceSettings 358BNetworkSettings::Interface(const char* name) 359{ 360 BMessage interface; 361 GetInterface(name, interface); 362 return BNetworkInterfaceSettings(interface); 363} 364 365 366const BNetworkInterfaceSettings 367BNetworkSettings::Interface(const char* name) const 368{ 369 BMessage interface; 370 GetInterface(name, interface); 371 return BNetworkInterfaceSettings(interface); 372} 373 374 375int32 376BNetworkSettings::CountNetworks() const 377{ 378 int32 count = 0; 379 if (fNetworks.GetInfo("network", NULL, &count) != B_OK) 380 return 0; 381 382 return count; 383} 384 385 386status_t 387BNetworkSettings::GetNextNetwork(uint32& cookie, BMessage& network) const 388{ 389 status_t status = fNetworks.FindMessage("network", cookie, &network); 390 if (status != B_OK) 391 return status; 392 393 cookie++; 394 return B_OK; 395} 396 397 398status_t 399BNetworkSettings::GetNetwork(const char* name, BMessage& network) const 400{ 401 int32 index; 402 return _GetItem(fNetworks, "network", "name", name, index, network); 403} 404 405 406status_t 407BNetworkSettings::AddNetwork(const BMessage& network) 408{ 409 const char* name = NULL; 410 if (network.FindString("name", &name) != B_OK) 411 return B_BAD_VALUE; 412 413 _RemoveItem(fNetworks, "network", "name", name); 414 415 status_t result = fNetworks.AddMessage("network", &network); 416 if (result != B_OK) 417 return result; 418 419 return _Save(kNetworksSettingsName); 420} 421 422 423status_t 424BNetworkSettings::RemoveNetwork(const char* name) 425{ 426 return _RemoveItem(fNetworks, "network", "name", name, 427 kNetworksSettingsName); 428} 429 430 431const BMessage& 432BNetworkSettings::Services() const 433{ 434 return fServices; 435} 436 437 438status_t 439BNetworkSettings::GetNextService(uint32& cookie, BMessage& service) 440{ 441 status_t status = fServices.FindMessage("service", cookie, &service); 442 if (status != B_OK) 443 return status; 444 445 cookie++; 446 return B_OK; 447} 448 449 450status_t 451BNetworkSettings::GetService(const char* name, BMessage& service) const 452{ 453 int32 index; 454 return _GetItem(fServices, "service", "name", name, index, service); 455} 456 457 458status_t 459BNetworkSettings::AddService(const BMessage& service) 460{ 461 const char* name = service.GetString("name"); 462 if (name == NULL) 463 return B_BAD_VALUE; 464 465 _RemoveItem(fServices, "service", "name", name); 466 467 status_t result = fServices.AddMessage("service", &service); 468 if (result != B_OK) 469 return result; 470 471 return _Save(kServicesSettingsName); 472} 473 474 475status_t 476BNetworkSettings::RemoveService(const char* name) 477{ 478 return _RemoveItem(fServices, "service", "name", name, 479 kServicesSettingsName); 480} 481 482 483BNetworkServiceSettings 484BNetworkSettings::Service(const char* name) 485{ 486 BMessage service; 487 GetService(name, service); 488 return BNetworkServiceSettings(service); 489} 490 491 492const BNetworkServiceSettings 493BNetworkSettings::Service(const char* name) const 494{ 495 BMessage service; 496 GetService(name, service); 497 return BNetworkServiceSettings(service); 498} 499 500 501status_t 502BNetworkSettings::StartMonitoring(const BMessenger& target) 503{ 504 if (_IsWatching(target)) 505 return B_OK; 506 if (_IsWatching()) 507 StopMonitoring(fListener); 508 509 fListener = target; 510 511 status_t status = _StartWatching(kInterfaceSettingsName, target); 512 if (status == B_OK) 513 status = _StartWatching(kNetworksSettingsName, target); 514 if (status == B_OK) 515 status = _StartWatching(kServicesSettingsName, target); 516 517 return status; 518} 519 520 521status_t 522BNetworkSettings::StopMonitoring(const BMessenger& target) 523{ 524 // TODO: this needs to be changed in case the server will watch 525 // anything else but settings 526 return BPrivate::BPathMonitor::StopWatching(target); 527} 528 529 530status_t 531BNetworkSettings::Update(BMessage* message) 532{ 533 const char* pathName; 534 int32 opcode; 535 if (message->FindInt32("opcode", &opcode) != B_OK 536 || message->FindString("path", &pathName) != B_OK) 537 return B_BAD_VALUE; 538 539 BPath settingsFolderPath; 540 _GetPath(NULL, settingsFolderPath); 541 if (strncmp(pathName, settingsFolderPath.Path(), 542 strlen(settingsFolderPath.Path()))) { 543 return B_NAME_NOT_FOUND; 544 } 545 546 if (message->FindBool("removed")) { 547 // for now, we only consider existing settings files 548 // (ie. deleting "services" won't stop any) 549 return B_OK; 550 } 551 552 int32 fields; 553 if (opcode == B_STAT_CHANGED 554 && message->FindInt32("fields", &fields) == B_OK 555 && (fields & (B_STAT_MODIFICATION_TIME | B_STAT_SIZE)) == 0) { 556 // only update when the modified time or size has changed 557 return B_OK; 558 } 559 560 BPath path(pathName); 561 uint32 type; 562 if (_Load(path.Leaf(), &type) == B_OK) { 563 BMessage update(type); 564 fListener.SendMessage(&update); 565 } 566 567 return B_OK; 568} 569 570 571// #pragma mark - private 572 573 574status_t 575BNetworkSettings::_Load(const char* name, uint32* _type) 576{ 577 BPath path; 578 status_t status = _GetPath(NULL, path); 579 if (status != B_OK) 580 return status; 581 582 DriverSettingsMessageAdapter adapter; 583 status = B_ENTRY_NOT_FOUND; 584 585 if (name == NULL || strcmp(name, kInterfaceSettingsName) == 0) { 586 status = adapter.ConvertFromDriverSettings( 587 _Path(path, kInterfaceSettingsName).Path(), kInterfacesTemplate, 588 fInterfaces); 589 if (status == B_OK && _type != NULL) 590 *_type = kMsgInterfaceSettingsUpdated; 591 } 592 if (name == NULL || strcmp(name, kNetworksSettingsName) == 0) { 593 status = adapter.ConvertFromDriverSettings( 594 _Path(path, kNetworksSettingsName).Path(), 595 kNetworksTemplate, fNetworks); 596 if (status == B_OK) { 597 // Convert settings for simpler consumption 598 BMessage network; 599 for (int32 index = 0; fNetworks.FindMessage("network", index, 600 &network); index++) { 601 if (_ConvertNetworkFromSettings(network) == B_OK) 602 fNetworks.ReplaceMessage("network", index, &network); 603 } 604 605 if (_type != NULL) 606 *_type = kMsgNetworkSettingsUpdated; 607 } 608 } 609 if (name == NULL || strcmp(name, kServicesSettingsName) == 0) { 610 status = adapter.ConvertFromDriverSettings( 611 _Path(path, kServicesSettingsName).Path(), kServicesTemplate, 612 fServices); 613 if (status == B_OK && _type != NULL) 614 *_type = kMsgServiceSettingsUpdated; 615 } 616 617 return status; 618} 619 620 621status_t 622BNetworkSettings::_Save(const char* name) 623{ 624 BPath path; 625 status_t status = _GetPath(NULL, path); 626 if (status != B_OK) 627 return status; 628 629 DriverSettingsMessageAdapter adapter; 630 status = B_ENTRY_NOT_FOUND; 631 632 if (name == NULL || strcmp(name, kInterfaceSettingsName) == 0) { 633 status = adapter.ConvertToDriverSettings( 634 _Path(path, kInterfaceSettingsName).Path(), 635 kInterfacesTemplate, fInterfaces); 636 } 637 if (name == NULL || strcmp(name, kNetworksSettingsName) == 0) { 638 // Convert settings to storage format 639 BMessage networks = fNetworks; 640 BMessage network; 641 for (int32 index = 0; networks.FindMessage("network", index, 642 &network); index++) { 643 if (_ConvertNetworkToSettings(network) == B_OK) 644 networks.ReplaceMessage("network", index, &network); 645 } 646 647 status = adapter.ConvertToDriverSettings( 648 _Path(path, kNetworksSettingsName).Path(), 649 kNetworksTemplate, networks); 650 } 651 if (name == NULL || strcmp(name, kServicesSettingsName) == 0) { 652 status = adapter.ConvertToDriverSettings( 653 _Path(path, kServicesSettingsName).Path(), 654 kServicesTemplate, fServices); 655 } 656 657 return status; 658} 659 660 661BPath 662BNetworkSettings::_Path(BPath& parent, const char* leaf) 663{ 664 return BPath(parent.Path(), leaf); 665} 666 667 668status_t 669BNetworkSettings::_GetPath(const char* name, BPath& path) 670{ 671 if (find_directory(B_SYSTEM_SETTINGS_DIRECTORY, &path, true) != B_OK) 672 return B_ERROR; 673 674 path.Append("network"); 675 create_directory(path.Path(), 0755); 676 677 if (name != NULL) 678 path.Append(name); 679 return B_OK; 680} 681 682 683status_t 684BNetworkSettings::_StartWatching(const char* name, const BMessenger& target) 685{ 686 BPath path; 687 status_t status = _GetPath(name, path); 688 if (status != B_OK) 689 return status; 690 691 return BPrivate::BPathMonitor::StartWatching(path.Path(), B_WATCH_STAT, 692 target); 693} 694 695 696status_t 697BNetworkSettings::_ConvertNetworkToSettings(BMessage& message) 698{ 699 BNetworkAddress address; 700 status_t result = message.FindFlat("address", &address); 701 if (result == B_OK) 702 message.RemoveName("address"); 703 704 if (result == B_OK && address.Family() == AF_LINK) { 705 size_t addressLength = address.LinkLevelAddressLength(); 706 uint8* macAddress = address.LinkLevelAddress(); 707 bool usable = false; 708 BString formatted; 709 710 for (size_t index = 0; index < addressLength; index++) { 711 if (index > 0) 712 formatted.Append(":"); 713 char buffer[3]; 714 snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]); 715 formatted.Append(buffer, sizeof(buffer)); 716 717 if (macAddress[index] != 0) 718 usable = true; 719 } 720 721 if (usable) 722 message.AddString("mac", formatted); 723 } 724 725 uint32 authentication = 0; 726 result = message.FindUInt32("authentication_mode", &authentication); 727 if (result == B_OK) { 728 message.RemoveName("authentication_mode"); 729 730 const char* authenticationString = NULL; 731 switch (authentication) { 732 case B_NETWORK_AUTHENTICATION_NONE: 733 authenticationString = "none"; 734 break; 735 case B_NETWORK_AUTHENTICATION_WEP: 736 authenticationString = "wep"; 737 break; 738 case B_NETWORK_AUTHENTICATION_WPA: 739 authenticationString = "wpa"; 740 break; 741 case B_NETWORK_AUTHENTICATION_WPA2: 742 authenticationString = "wpa2"; 743 break; 744 } 745 746 if (result == B_OK && authenticationString != NULL) 747 message.AddString("authentication", authenticationString); 748 } 749 750 uint32 cipher = 0; 751 result = message.FindUInt32("cipher", &cipher); 752 if (result == B_OK) { 753 message.RemoveName("cipher"); 754 755 if ((cipher & B_NETWORK_CIPHER_NONE) != 0) 756 message.AddString("cipher", "none"); 757 if ((cipher & B_NETWORK_CIPHER_TKIP) != 0) 758 message.AddString("cipher", "tkip"); 759 if ((cipher & B_NETWORK_CIPHER_CCMP) != 0) 760 message.AddString("cipher", "ccmp"); 761 } 762 763 uint32 groupCipher = 0; 764 result = message.FindUInt32("group_cipher", &groupCipher); 765 if (result == B_OK) { 766 message.RemoveName("group_cipher"); 767 768 if ((groupCipher & B_NETWORK_CIPHER_NONE) != 0) 769 message.AddString("group_cipher", "none"); 770 if ((groupCipher & B_NETWORK_CIPHER_WEP_40) != 0) 771 message.AddString("group_cipher", "wep40"); 772 if ((groupCipher & B_NETWORK_CIPHER_WEP_104) != 0) 773 message.AddString("group_cipher", "wep104"); 774 if ((groupCipher & B_NETWORK_CIPHER_TKIP) != 0) 775 message.AddString("group_cipher", "tkip"); 776 if ((groupCipher & B_NETWORK_CIPHER_CCMP) != 0) 777 message.AddString("group_cipher", "ccmp"); 778 } 779 780 // TODO: the other fields aren't currently used, add them when they are 781 // and when it's clear how they will be stored 782 message.RemoveName("noise_level"); 783 message.RemoveName("signal_strength"); 784 message.RemoveName("flags"); 785 message.RemoveName("key_mode"); 786 787 return B_OK; 788} 789 790 791status_t 792BNetworkSettings::_ConvertNetworkFromSettings(BMessage& message) 793{ 794 message.RemoveName("mac"); 795 // TODO: convert into a flat BNetworkAddress "address" 796 797 const char* authentication = NULL; 798 if (message.FindString("authentication", &authentication) == B_OK) { 799 message.RemoveName("authentication"); 800 801 if (strcasecmp(authentication, "none") == 0) { 802 message.AddUInt32("authentication_mode", 803 B_NETWORK_AUTHENTICATION_NONE); 804 } else if (strcasecmp(authentication, "wep") == 0) { 805 message.AddUInt32("authentication_mode", 806 B_NETWORK_AUTHENTICATION_WEP); 807 } else if (strcasecmp(authentication, "wpa") == 0) { 808 message.AddUInt32("authentication_mode", 809 B_NETWORK_AUTHENTICATION_WPA); 810 } else if (strcasecmp(authentication, "wpa2") == 0) { 811 message.AddUInt32("authentication_mode", 812 B_NETWORK_AUTHENTICATION_WPA2); 813 } 814 } 815 816 int32 index = 0; 817 uint32 cipher = 0; 818 const char* cipherString = NULL; 819 while (message.FindString("cipher", index++, &cipherString) == B_OK) { 820 if (strcasecmp(cipherString, "none") == 0) 821 cipher |= B_NETWORK_CIPHER_NONE; 822 else if (strcasecmp(cipherString, "tkip") == 0) 823 cipher |= B_NETWORK_CIPHER_TKIP; 824 else if (strcasecmp(cipherString, "ccmp") == 0) 825 cipher |= B_NETWORK_CIPHER_CCMP; 826 } 827 828 message.RemoveName("cipher"); 829 if (cipher != 0) 830 message.AddUInt32("cipher", cipher); 831 832 index = 0; 833 cipher = 0; 834 while (message.FindString("group_cipher", index++, &cipherString) == B_OK) { 835 if (strcasecmp(cipherString, "none") == 0) 836 cipher |= B_NETWORK_CIPHER_NONE; 837 else if (strcasecmp(cipherString, "wep40") == 0) 838 cipher |= B_NETWORK_CIPHER_WEP_40; 839 else if (strcasecmp(cipherString, "wep104") == 0) 840 cipher |= B_NETWORK_CIPHER_WEP_104; 841 else if (strcasecmp(cipherString, "tkip") == 0) 842 cipher |= B_NETWORK_CIPHER_TKIP; 843 else if (strcasecmp(cipherString, "ccmp") == 0) 844 cipher |= B_NETWORK_CIPHER_CCMP; 845 } 846 847 message.RemoveName("group_cipher"); 848 if (cipher != 0) 849 message.AddUInt32("group_cipher", cipher); 850 851 message.AddUInt32("flags", B_NETWORK_IS_PERSISTENT); 852 853 // TODO: add the other fields 854 message.RemoveName("key"); 855 return B_OK; 856} 857 858 859status_t 860BNetworkSettings::_GetItem(const BMessage& container, const char* itemField, 861 const char* nameField, const char* name, int32& _index, 862 BMessage& item) const 863{ 864 int32 index = 0; 865 while (container.FindMessage(itemField, index, &item) == B_OK) { 866 const char* itemName = NULL; 867 if (item.FindString(nameField, &itemName) == B_OK 868 && strcmp(itemName, name) == 0) { 869 _index = index; 870 return B_OK; 871 } 872 873 index++; 874 } 875 876 return B_ENTRY_NOT_FOUND; 877} 878 879 880status_t 881BNetworkSettings::_RemoveItem(BMessage& container, const char* itemField, 882 const char* nameField, const char* name, const char* store) 883{ 884 BMessage item; 885 int32 index; 886 if (_GetItem(container, itemField, nameField, name, index, item) == B_OK) { 887 container.RemoveData(itemField, index); 888 if (store != NULL) 889 return _Save(store); 890 return B_OK; 891 } 892 893 return B_ENTRY_NOT_FOUND; 894} 895 896 897// #pragma mark - BNetworkInterfaceAddressSettings 898 899 900BNetworkInterfaceAddressSettings::BNetworkInterfaceAddressSettings() 901 : 902 fFamily(AF_UNSPEC), 903 fAutoConfigure(true) 904{ 905} 906 907 908BNetworkInterfaceAddressSettings::BNetworkInterfaceAddressSettings( 909 const BMessage& data) 910{ 911 if (data.FindInt32("family", &fFamily) != B_OK) { 912 const char* familyString; 913 if (data.FindString("family", &familyString) == B_OK) { 914 fFamily = get_address_family(familyString); 915 if (fFamily == AF_UNSPEC) { 916 // we don't support this family 917 fprintf(stderr, "Ignore unknown family: %s\n", 918 familyString); 919 return; 920 } 921 } else 922 fFamily = AF_UNSPEC; 923 } 924 925 fAutoConfigure = data.GetBool("auto_config", false); 926 927 if (!fAutoConfigure) { 928 if (parse_address(fFamily, data.GetString("address", NULL), fAddress)) 929 parse_address(fFamily, data.GetString("mask", NULL), fMask); 930 931 parse_address(fFamily, data.GetString("peer", NULL), fPeer); 932 parse_address(fFamily, data.GetString("broadcast", NULL), fBroadcast); 933 parse_address(fFamily, data.GetString("gateway", NULL), fGateway); 934 } 935} 936 937 938BNetworkInterfaceAddressSettings::BNetworkInterfaceAddressSettings( 939 const BNetworkInterfaceAddressSettings& other) 940 : 941 fFamily(other.fFamily), 942 fAutoConfigure(other.fAutoConfigure), 943 fAddress(other.fAddress), 944 fMask(other.fMask), 945 fPeer(other.fPeer), 946 fBroadcast(other.fBroadcast), 947 fGateway(other.fGateway) 948{ 949} 950 951 952BNetworkInterfaceAddressSettings::~BNetworkInterfaceAddressSettings() 953{ 954} 955 956 957int 958BNetworkInterfaceAddressSettings::Family() const 959{ 960 return fFamily; 961} 962 963 964void 965BNetworkInterfaceAddressSettings::SetFamily(int family) 966{ 967 fFamily = family; 968} 969 970 971bool 972BNetworkInterfaceAddressSettings::IsAutoConfigure() const 973{ 974 return fAutoConfigure; 975} 976 977 978void 979BNetworkInterfaceAddressSettings::SetAutoConfigure(bool configure) 980{ 981 fAutoConfigure = configure; 982} 983 984 985const BNetworkAddress& 986BNetworkInterfaceAddressSettings::Address() const 987{ 988 return fAddress; 989} 990 991 992BNetworkAddress& 993BNetworkInterfaceAddressSettings::Address() 994{ 995 return fAddress; 996} 997 998 999const BNetworkAddress& 1000BNetworkInterfaceAddressSettings::Mask() const 1001{ 1002 return fMask; 1003} 1004 1005 1006BNetworkAddress& 1007BNetworkInterfaceAddressSettings::Mask() 1008{ 1009 return fMask; 1010} 1011 1012 1013const BNetworkAddress& 1014BNetworkInterfaceAddressSettings::Peer() const 1015{ 1016 return fPeer; 1017} 1018 1019 1020BNetworkAddress& 1021BNetworkInterfaceAddressSettings::Peer() 1022{ 1023 return fPeer; 1024} 1025 1026 1027const BNetworkAddress& 1028BNetworkInterfaceAddressSettings::Broadcast() const 1029{ 1030 return fBroadcast; 1031} 1032 1033 1034BNetworkAddress& 1035BNetworkInterfaceAddressSettings::Broadcast() 1036{ 1037 return fBroadcast; 1038} 1039 1040 1041const BNetworkAddress& 1042BNetworkInterfaceAddressSettings::Gateway() const 1043{ 1044 return fGateway; 1045} 1046 1047 1048BNetworkAddress& 1049BNetworkInterfaceAddressSettings::Gateway() 1050{ 1051 return fGateway; 1052} 1053 1054 1055status_t 1056BNetworkInterfaceAddressSettings::GetMessage(BMessage& data) const 1057{ 1058 status_t status = B_OK; 1059 if (fFamily != AF_UNSPEC) 1060 status = data.SetInt32("family", fFamily); 1061 if (status == B_OK && fAutoConfigure) 1062 return data.SetBool("auto_config", fAutoConfigure); 1063 1064 if (status == B_OK && !fAddress.IsEmpty()) { 1065 status = data.SetString("address", fAddress.ToString()); 1066 if (status == B_OK && !fMask.IsEmpty()) 1067 status = data.SetString("mask", fMask.ToString()); 1068 } 1069 if (status == B_OK && !fPeer.IsEmpty()) 1070 status = data.SetString("peer", fPeer.ToString()); 1071 if (status == B_OK && !fBroadcast.IsEmpty()) 1072 status = data.SetString("broadcast", fBroadcast.ToString()); 1073 if (status == B_OK && !fGateway.IsEmpty()) 1074 status = data.SetString("gateway", fGateway.ToString()); 1075 1076 return status; 1077} 1078 1079 1080BNetworkInterfaceAddressSettings& 1081BNetworkInterfaceAddressSettings::operator=( 1082 const BNetworkInterfaceAddressSettings& other) 1083{ 1084 fFamily = other.fFamily; 1085 fAutoConfigure = other.fAutoConfigure; 1086 fAddress = other.fAddress; 1087 fMask = other.fMask; 1088 fPeer = other.fPeer; 1089 fBroadcast = other.fBroadcast; 1090 fGateway = other.fGateway; 1091 1092 return *this; 1093} 1094 1095 1096// #pragma mark - BNetworkInterfaceSettings 1097 1098 1099BNetworkInterfaceSettings::BNetworkInterfaceSettings() 1100 : 1101 fFlags(0), 1102 fMTU(0), 1103 fMetric(0) 1104{ 1105} 1106 1107 1108BNetworkInterfaceSettings::BNetworkInterfaceSettings(const BMessage& message) 1109{ 1110 fName = message.GetString("device"); 1111 fFlags = message.GetInt32("flags", 0); 1112 fMTU = message.GetInt32("mtu", 0); 1113 fMetric = message.GetInt32("metric", 0); 1114 1115 BMessage addressData; 1116 for (int32 index = 0; message.FindMessage("address", index, 1117 &addressData) == B_OK; index++) { 1118 BNetworkInterfaceAddressSettings address(addressData); 1119 fAddresses.push_back(address); 1120 } 1121} 1122 1123 1124BNetworkInterfaceSettings::~BNetworkInterfaceSettings() 1125{ 1126} 1127 1128 1129const char* 1130BNetworkInterfaceSettings::Name() const 1131{ 1132 return fName; 1133} 1134 1135 1136void 1137BNetworkInterfaceSettings::SetName(const char* name) 1138{ 1139 fName = name; 1140} 1141 1142 1143int32 1144BNetworkInterfaceSettings::Flags() const 1145{ 1146 return fFlags; 1147} 1148 1149 1150void 1151BNetworkInterfaceSettings::SetFlags(int32 flags) 1152{ 1153 fFlags = flags; 1154} 1155 1156 1157int32 1158BNetworkInterfaceSettings::MTU() const 1159{ 1160 return fMTU; 1161} 1162 1163 1164void 1165BNetworkInterfaceSettings::SetMTU(int32 mtu) 1166{ 1167 fMTU = mtu; 1168} 1169 1170 1171int32 1172BNetworkInterfaceSettings::Metric() const 1173{ 1174 return fMetric; 1175} 1176 1177 1178void 1179BNetworkInterfaceSettings::SetMetric(int32 metric) 1180{ 1181 fMetric = metric; 1182} 1183 1184 1185int32 1186BNetworkInterfaceSettings::CountAddresses() const 1187{ 1188 return fAddresses.size(); 1189} 1190 1191 1192const BNetworkInterfaceAddressSettings& 1193BNetworkInterfaceSettings::AddressAt(int32 index) const 1194{ 1195 return fAddresses[index]; 1196} 1197 1198 1199BNetworkInterfaceAddressSettings& 1200BNetworkInterfaceSettings::AddressAt(int32 index) 1201{ 1202 return fAddresses[index]; 1203} 1204 1205 1206int32 1207BNetworkInterfaceSettings::FindFirstAddress(int family) const 1208{ 1209 for (int32 index = 0; index < CountAddresses(); index++) { 1210 const BNetworkInterfaceAddressSettings address = AddressAt(index); 1211 if (address.Family() == family) 1212 return index; 1213 } 1214 return -1; 1215} 1216 1217 1218void 1219BNetworkInterfaceSettings::AddAddress( 1220 const BNetworkInterfaceAddressSettings& address) 1221{ 1222 fAddresses.push_back(address); 1223} 1224 1225 1226void 1227BNetworkInterfaceSettings::RemoveAddress(int32 index) 1228{ 1229 fAddresses.erase(fAddresses.begin() + index); 1230} 1231 1232 1233/*! This is a convenience method that returns the current state of the 1234 interface, not just the one configured. 1235 1236 This means, even if the settings say: auto configured, this method 1237 may still return false, if the configuration has been manually tempered 1238 with. 1239*/ 1240bool 1241BNetworkInterfaceSettings::IsAutoConfigure(int family) const 1242{ 1243 BNetworkInterface interface(fName); 1244 // TODO: this needs to happen at protocol level 1245 if ((interface.Flags() & (IFF_AUTO_CONFIGURED | IFF_CONFIGURING)) != 0) 1246 return true; 1247 1248 BNetworkInterfaceAddress address; 1249 status_t status = B_ERROR; 1250 1251 int32 index = interface.FindFirstAddress(family); 1252 if (index >= 0) 1253 status = interface.GetAddressAt(index, address); 1254 if (index < 0 || status != B_OK || address.Address().IsEmpty()) { 1255 if (status == B_OK) { 1256 // Check persistent settings for the mode -- the address 1257 // can also be empty if the automatic configuration hasn't 1258 // started yet (for example, because there is no link). 1259 int32 index = FindFirstAddress(family); 1260 if (index < 0) 1261 index = FindFirstAddress(AF_UNSPEC); 1262 if (index >= 0) { 1263 const BNetworkInterfaceAddressSettings& address 1264 = AddressAt(index); 1265 return address.IsAutoConfigure(); 1266 } 1267 } 1268 } 1269 1270 return false; 1271} 1272 1273 1274status_t 1275BNetworkInterfaceSettings::GetMessage(BMessage& data) const 1276{ 1277 status_t status = data.SetString("device", fName); 1278 if (status == B_OK && fFlags != 0) 1279 status = data.SetInt32("flags", fFlags); 1280 if (status == B_OK && fMTU != 0) 1281 status = data.SetInt32("mtu", fMTU); 1282 if (status == B_OK && fMetric != 0) 1283 status = data.SetInt32("metric", fMetric); 1284 1285 for (int32 i = 0; i < CountAddresses(); i++) { 1286 BMessage address; 1287 status = AddressAt(i).GetMessage(address); 1288 if (status == B_OK) 1289 status = data.AddMessage("address", &address); 1290 if (status != B_OK) 1291 break; 1292 } 1293 return status; 1294} 1295 1296 1297// #pragma mark - BNetworkServiceAddressSettings 1298 1299 1300BNetworkServiceAddressSettings::BNetworkServiceAddressSettings() 1301{ 1302} 1303 1304 1305BNetworkServiceAddressSettings::BNetworkServiceAddressSettings( 1306 const BMessage& data, int serviceFamily, int serviceType, 1307 int serviceProtocol, int servicePort) 1308{ 1309 // TODO: dump problems in the settings to syslog 1310 if (data.FindInt32("family", &fFamily) != B_OK) { 1311 const char* familyString; 1312 if (data.FindString("family", &familyString) == B_OK) { 1313 fFamily = get_address_family(familyString); 1314 if (fFamily == AF_UNSPEC) { 1315 // we don't support this family 1316 fprintf(stderr, "Ignore unknown family: %s\n", 1317 familyString); 1318 return; 1319 } 1320 } else 1321 fFamily = serviceFamily; 1322 } 1323 1324 if (!parse_address(fFamily, data.GetString("address"), fAddress)) 1325 fAddress.SetToWildcard(fFamily); 1326 1327 const char* string; 1328 if (data.FindString("protocol", &string) == B_OK) 1329 fProtocol = parse_protocol(string); 1330 else 1331 fProtocol = serviceProtocol; 1332 1333 if (data.FindString("type", &string) == B_OK) 1334 fType = parse_type(string); 1335 else if (fProtocol != serviceProtocol) 1336 fType = type_for_protocol(fProtocol); 1337 else 1338 fType = serviceType; 1339 1340 fAddress.SetPort(data.GetInt32("port", servicePort)); 1341} 1342 1343 1344BNetworkServiceAddressSettings::~BNetworkServiceAddressSettings() 1345{ 1346} 1347 1348 1349int 1350BNetworkServiceAddressSettings::Family() const 1351{ 1352 return fFamily; 1353} 1354 1355 1356void 1357BNetworkServiceAddressSettings::SetFamily(int family) 1358{ 1359 fFamily = family; 1360} 1361 1362 1363int 1364BNetworkServiceAddressSettings::Protocol() const 1365{ 1366 return fProtocol; 1367} 1368 1369 1370void 1371BNetworkServiceAddressSettings::SetProtocol(int protocol) 1372{ 1373 fProtocol = protocol; 1374} 1375 1376 1377int 1378BNetworkServiceAddressSettings::Type() const 1379{ 1380 return fType; 1381} 1382 1383 1384void 1385BNetworkServiceAddressSettings::SetType(int type) 1386{ 1387 fType = type; 1388} 1389 1390 1391const BNetworkAddress& 1392BNetworkServiceAddressSettings::Address() const 1393{ 1394 return fAddress; 1395} 1396 1397 1398BNetworkAddress& 1399BNetworkServiceAddressSettings::Address() 1400{ 1401 return fAddress; 1402} 1403 1404 1405status_t 1406BNetworkServiceAddressSettings::GetMessage(BMessage& data) const 1407{ 1408 // TODO! 1409 return B_NOT_SUPPORTED; 1410} 1411 1412 1413bool 1414BNetworkServiceAddressSettings::operator==( 1415 const BNetworkServiceAddressSettings& other) const 1416{ 1417 return Family() == other.Family() 1418 && Type() == other.Type() 1419 && Protocol() == other.Protocol() 1420 && Address() == other.Address(); 1421} 1422 1423 1424// #pragma mark - BNetworkServiceSettings 1425 1426 1427BNetworkServiceSettings::BNetworkServiceSettings() 1428 : 1429 fFamily(AF_UNSPEC), 1430 fType(-1), 1431 fProtocol(-1), 1432 fPort(-1), 1433 fEnabled(true), 1434 fStandAlone(false) 1435{ 1436} 1437 1438 1439BNetworkServiceSettings::BNetworkServiceSettings(const BMessage& message) 1440 : 1441 fType(-1), 1442 fProtocol(-1), 1443 fPort(-1), 1444 fEnabled(true), 1445 fStandAlone(false) 1446{ 1447 // TODO: user/group is currently ignored! 1448 1449 fName = message.GetString("name"); 1450 1451 // Default family/port/protocol/type for all addresses 1452 1453 // we default to inet/tcp/port-from-service-name if nothing is specified 1454 const char* string; 1455 if (message.FindString("family", &string) != B_OK) 1456 string = "inet"; 1457 1458 fFamily = get_address_family(string); 1459 if (fFamily == AF_UNSPEC) 1460 fFamily = AF_INET; 1461 1462 if (message.FindString("protocol", &string) == B_OK) 1463 fProtocol = parse_protocol(string); 1464 else { 1465 string = "tcp"; 1466 // we set 'string' here for an eventual call to getservbyname() 1467 // below 1468 fProtocol = IPPROTO_TCP; 1469 } 1470 1471 if (message.FindInt32("port", &fPort) != B_OK) { 1472 struct servent* servent = getservbyname(Name(), string); 1473 if (servent != NULL) 1474 fPort = ntohs(servent->s_port); 1475 else 1476 fPort = -1; 1477 } 1478 1479 if (message.FindString("type", &string) == B_OK) 1480 fType = parse_type(string); 1481 else 1482 fType = type_for_protocol(fProtocol); 1483 1484 fStandAlone = message.GetBool("stand_alone"); 1485 1486 const char* argument; 1487 for (int i = 0; message.FindString("launch", i, &argument) == B_OK; i++) { 1488 fArguments.Add(argument); 1489 } 1490 1491 BMessage addressData; 1492 int32 i = 0; 1493 for (; message.FindMessage("address", i, &addressData) == B_OK; i++) { 1494 BNetworkServiceAddressSettings address(addressData, fFamily, 1495 fType, fProtocol, fPort); 1496 fAddresses.push_back(address); 1497 } 1498 1499 if (i == 0 && (fFamily < 0 || fPort < 0)) { 1500 // no address specified 1501 printf("service %s has no address specified\n", Name()); 1502 return; 1503 } 1504 1505 if (i == 0) { 1506 // no address specified, but family/port were given; add empty address 1507 BNetworkServiceAddressSettings address; 1508 address.SetFamily(fFamily); 1509 address.SetType(fType); 1510 address.SetProtocol(fProtocol); 1511 address.Address().SetToWildcard(fFamily, fPort); 1512 1513 fAddresses.push_back(address); 1514 } 1515} 1516 1517 1518BNetworkServiceSettings::~BNetworkServiceSettings() 1519{ 1520} 1521 1522 1523status_t 1524BNetworkServiceSettings::InitCheck() const 1525{ 1526 if (!fName.IsEmpty() && !fArguments.IsEmpty() && CountAddresses() > 0) 1527 return B_OK; 1528 1529 return B_BAD_VALUE; 1530} 1531 1532 1533const char* 1534BNetworkServiceSettings::Name() const 1535{ 1536 return fName.String(); 1537} 1538 1539 1540void 1541BNetworkServiceSettings::SetName(const char* name) 1542{ 1543 fName = name; 1544} 1545 1546 1547bool 1548BNetworkServiceSettings::IsStandAlone() const 1549{ 1550 return fStandAlone; 1551} 1552 1553 1554void 1555BNetworkServiceSettings::SetStandAlone(bool alone) 1556{ 1557 fStandAlone = alone; 1558} 1559 1560 1561bool 1562BNetworkServiceSettings::IsEnabled() const 1563{ 1564 return InitCheck() == B_OK && fEnabled; 1565} 1566 1567 1568void 1569BNetworkServiceSettings::SetEnabled(bool enable) 1570{ 1571 fEnabled = enable; 1572} 1573 1574 1575int 1576BNetworkServiceSettings::Family() const 1577{ 1578 return fFamily; 1579} 1580 1581 1582void 1583BNetworkServiceSettings::SetFamily(int family) 1584{ 1585 fFamily = family; 1586} 1587 1588 1589int 1590BNetworkServiceSettings::Protocol() const 1591{ 1592 return fProtocol; 1593} 1594 1595 1596void 1597BNetworkServiceSettings::SetProtocol(int protocol) 1598{ 1599 fProtocol = protocol; 1600} 1601 1602 1603int 1604BNetworkServiceSettings::Type() const 1605{ 1606 return fType; 1607} 1608 1609 1610void 1611BNetworkServiceSettings::SetType(int type) 1612{ 1613 fType = type; 1614} 1615 1616 1617int 1618BNetworkServiceSettings::Port() const 1619{ 1620 return fPort; 1621} 1622 1623 1624void 1625BNetworkServiceSettings::SetPort(int port) 1626{ 1627 fPort = port; 1628} 1629 1630 1631int32 1632BNetworkServiceSettings::CountArguments() const 1633{ 1634 return fArguments.CountStrings(); 1635} 1636 1637 1638const char* 1639BNetworkServiceSettings::ArgumentAt(int32 index) const 1640{ 1641 return fArguments.StringAt(index); 1642} 1643 1644 1645void 1646BNetworkServiceSettings::AddArgument(const char* argument) 1647{ 1648 fArguments.Add(argument); 1649} 1650 1651 1652void 1653BNetworkServiceSettings::RemoveArgument(int32 index) 1654{ 1655 fArguments.Remove(index); 1656} 1657 1658 1659int32 1660BNetworkServiceSettings::CountAddresses() const 1661{ 1662 return fAddresses.size(); 1663} 1664 1665 1666const BNetworkServiceAddressSettings& 1667BNetworkServiceSettings::AddressAt(int32 index) const 1668{ 1669 return fAddresses[index]; 1670} 1671 1672 1673void 1674BNetworkServiceSettings::AddAddress( 1675 const BNetworkServiceAddressSettings& address) 1676{ 1677 fAddresses.push_back(address); 1678} 1679 1680 1681void 1682BNetworkServiceSettings::RemoveAddress(int32 index) 1683{ 1684 fAddresses.erase(fAddresses.begin() + index); 1685} 1686 1687 1688/*! This is a convenience method that returns the current state of the 1689 service, independent of the current settings. 1690*/ 1691bool 1692BNetworkServiceSettings::IsRunning() const 1693{ 1694 BMessage request(kMsgIsServiceRunning); 1695 request.AddString("name", fName); 1696 1697 BMessenger networkServer(kNetServerSignature); 1698 BMessage reply; 1699 status_t status = networkServer.SendMessage(&request, &reply); 1700 if (status == B_OK) 1701 return reply.GetBool("running"); 1702 1703 return false; 1704} 1705 1706 1707status_t 1708BNetworkServiceSettings::GetMessage(BMessage& data) const 1709{ 1710 status_t status = data.SetString("name", fName); 1711 if (status == B_OK && !fEnabled) 1712 status = data.SetBool("disabled", true); 1713 if (status == B_OK && fStandAlone) 1714 status = data.SetBool("stand_alone", true); 1715 1716 if (fFamily != AF_UNSPEC) 1717 status = data.SetInt32("family", fFamily); 1718 if (fType != -1) 1719 status = data.SetInt32("type", fType); 1720 if (fProtocol != -1) 1721 status = data.SetInt32("protocol", fProtocol); 1722 if (fPort != -1) 1723 status = data.SetInt32("port", fPort); 1724 1725 for (int32 i = 0; i < fArguments.CountStrings(); i++) { 1726 if (status == B_OK) 1727 status = data.AddString("launch", fArguments.StringAt(i)); 1728 if (status != B_OK) 1729 break; 1730 } 1731 1732 for (int32 i = 0; i < CountAddresses(); i++) { 1733 BNetworkServiceAddressSettings address = AddressAt(i); 1734 if (address.Family() == Family() 1735 && address.Type() == Type() 1736 && address.Protocol() == Protocol() 1737 && address.Address().IsWildcard() 1738 && address.Address().Port() == Port()) { 1739 // This address will be created automatically, no need to store it 1740 continue; 1741 } 1742 1743 BMessage addressMessage; 1744 status = AddressAt(i).GetMessage(addressMessage); 1745 if (status == B_OK) 1746 status = data.AddMessage("address", &addressMessage); 1747 if (status != B_OK) 1748 break; 1749 } 1750 return status; 1751} 1752