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 * Oliver Tappe, zooey@hirschkaefer.de 8 * Atis Elsts, the.kfx@gmail.com 9 */ 10 11 12 #include <errno.h> 13 #include <net/if_media.h> 14 #include <net/if_types.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <unistd.h> 19 20 #include <Message.h> 21 #include <Messenger.h> 22 #include <NetworkDevice.h> 23 #include <NetworkInterface.h> 24 #include <NetworkRoster.h> 25 26 #include <NetServer.h> 27 28 #include "MediaTypes.h" 29 30 31 extern const char* __progname; 32 const char* kProgramName = __progname; 33 34 35 enum preferred_output_format { 36 PREFER_OUTPUT_MASK, 37 PREFER_OUTPUT_PREFIX_LENGTH, 38 }; 39 40 41 struct address_family { 42 int family; 43 const char* name; 44 const char* identifiers[4]; 45 preferred_output_format preferred_format; 46 }; 47 48 49 static const address_family kFamilies[] = { 50 { 51 AF_INET, 52 "inet", 53 {"AF_INET", "inet", "ipv4", NULL}, 54 PREFER_OUTPUT_MASK 55 }, 56 { 57 AF_INET6, 58 "inet6", 59 {"AF_INET6", "inet6", "ipv6", NULL}, 60 PREFER_OUTPUT_PREFIX_LENGTH 61 }, 62 { -1, NULL, {NULL}, PREFER_OUTPUT_MASK } 63 }; 64 65 66 static void 67 usage(int status) 68 { 69 printf("usage: %s [<interface> [<address family>] [<address> [<mask>] | " 70 "auto-config] [<option/flags>...]]\n" 71 " %s --delete <interface> [...]\n" 72 " %s <interface> [scan|join|leave] [<network> " 73 "[<password>]]\n\n" 74 "Where <option> can be the following:\n" 75 " netmask <addr> - networking subnet mask\n" 76 " prefixlen <number> - subnet mask length in bits\n" 77 " broadcast <addr> - set broadcast address\n" 78 " peer <addr> - ppp-peer address\n" 79 " mtu <bytes> - maximal transfer unit\n" 80 " metric <number> - metric number to use (defaults to 0)\n" 81 " media <media> - media type to use (defaults to auto)\n", 82 kProgramName, kProgramName, kProgramName); 83 84 for (int32 i = 0; const char* type = get_media_type_name(i); i++) { 85 printf("For %s <media> can be one of: ", type); 86 for (int32 j = 0; const char* subType = get_media_subtype_name(i, j); 87 j++) { 88 printf("%s ", subType); 89 } 90 printf("\n"); 91 } 92 printf("And <flags> can be: up, down, [-]promisc, [-]allmulti, [-]bcast, " 93 "loopback\n" 94 "If you specify \"auto-config\" instead of an address, it will be " 95 "configured automatically.\n\n" 96 "Example:\n" 97 "\t%s loop 127.0.0.1 255.0.0.0 up\n", 98 kProgramName); 99 100 exit(status); 101 } 102 103 104 int 105 get_address_family(const char* argument) 106 { 107 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 108 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 109 if (!strcmp(argument, kFamilies[i].identifiers[j])) { 110 // found a match 111 return kFamilies[i].family; 112 } 113 } 114 } 115 116 return AF_UNSPEC; 117 } 118 119 120 static const address_family* 121 address_family_for(int family) 122 { 123 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 124 if (kFamilies[i].family == family) 125 return &kFamilies[i]; 126 } 127 128 // defaults to AF_INET 129 return &kFamilies[0]; 130 } 131 132 133 /*! Parses the \a argument as network \a address for the specified \a family. 134 If \a family is \c AF_UNSPEC, \a family will be overwritten with the family 135 of the successfully parsed address. 136 */ 137 bool 138 parse_address(int& family, const char* argument, BNetworkAddress& address) 139 { 140 if (argument == NULL) 141 return false; 142 143 status_t status = address.SetTo(family, argument, (uint16)0, 144 B_NO_ADDRESS_RESOLUTION); 145 if (status != B_OK) 146 return false; 147 148 if (family == AF_UNSPEC) { 149 // Test if we support the resulting address family 150 bool supported = false; 151 152 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 153 if (kFamilies[i].family == address.Family()) { 154 supported = true; 155 break; 156 } 157 } 158 if (!supported) 159 return false; 160 161 // Take over family from address 162 family = address.Family(); 163 } 164 165 return true; 166 } 167 168 169 bool 170 prefix_length_to_mask(int family, const char* argument, BNetworkAddress& mask) 171 { 172 char *end; 173 uint32 prefixLength = strtoul(argument, &end, 10); 174 if (end == argument) 175 return false; 176 177 return mask.SetToMask(family, prefixLength) == B_OK; 178 } 179 180 181 BString 182 to_string(const BNetworkAddress& address) 183 { 184 if (address.IsEmpty()) 185 return "--"; 186 187 return address.ToString(); 188 } 189 190 191 // #pragma mark - wireless support 192 193 194 const char* 195 get_key_mode(uint32 mode) 196 { 197 if ((mode & B_KEY_MODE_WPS) != 0) 198 return "WPS"; 199 if ((mode & B_KEY_MODE_PSK_SHA256) != 0) 200 return "PSK-SHA256"; 201 if ((mode & B_KEY_MODE_IEEE802_1X_SHA256) != 0) 202 return "IEEE 802.1x-SHA256"; 203 if ((mode & B_KEY_MODE_FT_PSK) != 0) 204 return "FT-PSK"; 205 if ((mode & B_KEY_MODE_FT_IEEE802_1X) != 0) 206 return "FT-IEEE 802.1x"; 207 if ((mode & B_KEY_MODE_NONE) != 0) 208 return "-"; 209 if ((mode & B_KEY_MODE_PSK) != 0) 210 return "PSK"; 211 if ((mode & B_KEY_MODE_IEEE802_1X) != 0) 212 return "IEEE 802.1x"; 213 214 return ""; 215 } 216 217 218 const char* 219 get_cipher(uint32 cipher) 220 { 221 if ((cipher & B_NETWORK_CIPHER_AES_128_CMAC) != 0) 222 return "AES-128-CMAC"; 223 if ((cipher & B_NETWORK_CIPHER_CCMP) != 0) 224 return "CCMP"; 225 if ((cipher & B_NETWORK_CIPHER_TKIP) != 0) 226 return "TKIP"; 227 if ((cipher & B_NETWORK_CIPHER_WEP_104) != 0) 228 return "WEP-104"; 229 if ((cipher & B_NETWORK_CIPHER_WEP_40) != 0) 230 return "WEP-40"; 231 232 return ""; 233 } 234 235 236 const char* 237 get_authentication_mode(uint32 mode, uint32 flags) 238 { 239 switch (mode) { 240 default: 241 case B_NETWORK_AUTHENTICATION_NONE: 242 if ((flags & B_NETWORK_IS_ENCRYPTED) != 0) 243 return "(encrypted)"; 244 return "-"; 245 case B_NETWORK_AUTHENTICATION_WEP: 246 return "WEP"; 247 case B_NETWORK_AUTHENTICATION_WPA: 248 return "WPA"; 249 case B_NETWORK_AUTHENTICATION_WPA2: 250 return "WPA2"; 251 } 252 } 253 254 255 void 256 show_wireless_network_header(bool verbose) 257 { 258 printf("%-32s %-20s %s %s\n", "name", "address", "signal", "auth"); 259 } 260 261 262 void 263 show_wireless_network(const wireless_network& network, bool verbose) 264 { 265 printf("%-32s %-20s %6u %s\n", network.name, 266 network.address.ToString().String(), 267 network.signal_strength / 2, 268 get_authentication_mode(network.authentication_mode, network.flags)); 269 } 270 271 272 bool 273 configure_wireless(const char* name, char* const* args, int32 argCount) 274 { 275 enum { 276 NONE, 277 LIST, 278 JOIN, 279 LEAVE 280 } mode = NONE; 281 282 if (!strcmp(args[0], "list") || !strcmp(args[0], "scan")) 283 mode = LIST; 284 else if (!strcmp(args[0], "join")) 285 mode = JOIN; 286 else if (!strcmp(args[0], "leave")) 287 mode = LEAVE; 288 289 if (mode == NONE) 290 return false; 291 292 BNetworkDevice device(name); 293 if (!device.Exists()) { 294 fprintf(stderr, "%s: \"%s\" does not exist!\n", kProgramName, name); 295 exit(1); 296 } 297 if (!device.IsWireless()) { 298 fprintf(stderr, "%s: \"%s\" is not a WLAN device!\n", kProgramName, 299 name); 300 exit(1); 301 } 302 303 args++; 304 argCount--; 305 306 switch (mode) { 307 case LIST: 308 { 309 // list wireless network(s) 310 311 bool verbose = false; 312 if (argCount > 0 && !strcmp(args[0], "-v")) { 313 verbose = true; 314 args++; 315 argCount--; 316 } 317 show_wireless_network_header(verbose); 318 319 if (argCount > 0) { 320 // list the named entries 321 for (int32 i = 0; i < argCount; i++) { 322 wireless_network network; 323 BNetworkAddress link; 324 status_t status; 325 if (link.SetTo(AF_LINK, args[i]) == B_OK) 326 status = device.GetNetwork(link, network); 327 else 328 status = device.GetNetwork(args[i], network); 329 if (status != B_OK) { 330 fprintf(stderr, "%s: Getting network failed: %s\n", 331 kProgramName, strerror(status)); 332 } else 333 show_wireless_network(network, verbose); 334 } 335 } else { 336 // list them all 337 wireless_network network; 338 uint32 cookie = 0; 339 while (device.GetNextNetwork(cookie, network) == B_OK) 340 show_wireless_network(network, verbose); 341 } 342 break; 343 } 344 345 case JOIN: 346 { 347 // join a wireless network 348 if (argCount > 2) { 349 fprintf(stderr, "usage: %s %s join <network> [<password>]\n", 350 kProgramName, name); 351 exit(1); 352 } 353 354 const char* password = NULL; 355 if (argCount == 2) 356 password = args[1]; 357 358 BNetworkAddress link; 359 status_t status; 360 if (link.SetTo(AF_LINK, args[0]) == B_OK) 361 status = device.JoinNetwork(link, password); 362 else 363 status = device.JoinNetwork(args[0], password); 364 if (status != B_OK) { 365 fprintf(stderr, "%s: Joining network failed: %s\n", 366 kProgramName, strerror(status)); 367 exit(1); 368 } 369 break; 370 } 371 372 case LEAVE: 373 { 374 // leave a wireless network 375 if (argCount != 1) { 376 fprintf(stderr, "usage: %s %s leave <network>\n", kProgramName, 377 name); 378 exit(1); 379 } 380 381 BNetworkAddress link; 382 status_t status; 383 if (link.SetTo(AF_LINK, args[0]) == B_OK) 384 status = device.LeaveNetwork(link); 385 else 386 status = device.LeaveNetwork(args[0]); 387 if (status != B_OK) { 388 fprintf(stderr, "%s: Leaving network failed: %s\n", 389 kProgramName, strerror(status)); 390 exit(1); 391 } 392 break; 393 } 394 395 case NONE: 396 break; 397 } 398 399 return true; 400 } 401 402 403 // #pragma mark - 404 405 406 void 407 list_interface_addresses(BNetworkInterface& interface, uint32 flags) 408 { 409 int32 count = interface.CountAddresses(); 410 for (int32 i = 0; i < count; i++) { 411 BNetworkInterfaceAddress address; 412 if (interface.GetAddressAt(i, address) != B_OK) 413 break; 414 415 const address_family* family 416 = address_family_for(address.Address().Family()); 417 418 printf("\t%s addr: %s", family->name, 419 to_string(address.Address()).String()); 420 421 if ((flags & IFF_BROADCAST) != 0) 422 printf(", Bcast: %s", to_string(address.Broadcast()).String()); 423 424 switch (family->preferred_format) { 425 case PREFER_OUTPUT_MASK: 426 printf(", Mask: %s", to_string(address.Mask()).String()); 427 break; 428 case PREFER_OUTPUT_PREFIX_LENGTH: 429 printf(", Prefix Length: %zu", address.Mask().PrefixLength()); 430 break; 431 } 432 433 putchar('\n'); 434 } 435 } 436 437 438 bool 439 list_interface(const char* name) 440 { 441 printf("%s", name); 442 size_t length = strlen(name); 443 if (length < 8) 444 putchar('\t'); 445 else 446 printf("\n\t"); 447 448 // get link level interface for this interface 449 450 BNetworkInterface interface(name); 451 if (!interface.Exists()) { 452 printf("Interface not found!\n"); 453 return false; 454 } 455 456 BNetworkAddress linkAddress; 457 status_t status = interface.GetHardwareAddress(linkAddress); 458 if (status == B_OK) { 459 const char *type = "unknown"; 460 switch (linkAddress.LinkLevelType()) { 461 case IFT_ETHER: 462 type = "Ethernet"; 463 break; 464 case IFT_LOOP: 465 type = "Local Loopback"; 466 break; 467 case IFT_MODEM: 468 type = "Modem"; 469 break; 470 } 471 472 BString address = linkAddress.ToString(); 473 if (address.Length() == 0) 474 address = "none"; 475 476 printf("Hardware type: %s, Address: %s\n", type, address.String()); 477 } else 478 printf("No link level: %s\n", strerror(status)); 479 480 int media = interface.Media(); 481 if ((media & IFM_ACTIVE) != 0) { 482 // dump media state in case we're linked 483 const char* type = media_type_to_string(media); 484 if (type != NULL) 485 printf("\tMedia type: %s\n", type); 486 } 487 488 // Print associated wireless network(s) 489 490 BNetworkDevice device(name); 491 if (device.IsWireless()) { 492 wireless_network network; 493 bool first = true; 494 uint32 cookie = 0; 495 while (device.GetNextAssociatedNetwork(cookie, network) == B_OK) { 496 if (first) { 497 printf("\tNetwork: "); 498 first = false; 499 } else 500 printf("\t\t"); 501 502 printf("%s, Address: %s, %s", network.name, 503 network.address.ToString().String(), 504 get_authentication_mode(network.authentication_mode, 505 network.flags)); 506 const char* keyMode = get_key_mode(network.key_mode); 507 if (keyMode != NULL) 508 printf(", %s/%s", keyMode, get_cipher(network.cipher)); 509 putchar('\n'); 510 } 511 } 512 513 uint32 flags = interface.Flags(); 514 515 list_interface_addresses(interface, flags); 516 517 // Print MTU, metric, flags 518 519 printf("\tMTU: %" B_PRId32 ", Metric: %" B_PRId32, interface.MTU(), 520 interface.Metric()); 521 522 if (flags != 0) { 523 const struct { 524 int value; 525 const char *name; 526 } kFlags[] = { 527 {IFF_UP, "up"}, 528 {IFF_NOARP, "noarp"}, 529 {IFF_BROADCAST, "broadcast"}, 530 {IFF_LOOPBACK, "loopback"}, 531 {IFF_PROMISC, "promiscuous"}, 532 {IFF_ALLMULTI, "allmulti"}, 533 {IFF_AUTOUP, "autoup"}, 534 {IFF_LINK, "link"}, 535 {IFF_AUTO_CONFIGURED, "auto-configured"}, 536 {IFF_CONFIGURING, "configuring"}, 537 }; 538 bool first = true; 539 540 for (uint32 i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); i++) { 541 if ((flags & kFlags[i].value) != 0) { 542 if (first) { 543 printf(","); 544 first = false; 545 } 546 putchar(' '); 547 printf(kFlags[i].name); 548 } 549 } 550 } 551 552 putchar('\n'); 553 554 // Print statistics 555 556 ifreq_stats stats; 557 if (interface.GetStats(stats) == B_OK) { 558 printf("\tReceive: %d packets, %d errors, %Ld bytes, %d mcasts, %d " 559 "dropped\n", stats.receive.packets, stats.receive.errors, 560 stats.receive.bytes, stats.receive.multicast_packets, 561 stats.receive.dropped); 562 printf("\tTransmit: %d packets, %d errors, %Ld bytes, %d mcasts, %d " 563 "dropped\n", stats.send.packets, stats.send.errors, 564 stats.send.bytes, stats.send.multicast_packets, stats.send.dropped); 565 printf("\tCollisions: %d\n", stats.collisions); 566 } 567 568 putchar('\n'); 569 return true; 570 } 571 572 573 void 574 list_interfaces(const char* name) 575 { 576 if (name != NULL) { 577 list_interface(name); 578 return; 579 } 580 581 // get a list of all interfaces 582 583 BNetworkRoster& roster = BNetworkRoster::Default(); 584 585 BNetworkInterface interface; 586 uint32 cookie = 0; 587 588 while (roster.GetNextInterface(&cookie, interface) == B_OK) { 589 list_interface(interface.Name()); 590 } 591 } 592 593 594 /*! If there are any arguments given, this will remove only the specified 595 addresses from the interface named \a name. 596 If there are no arguments, it will remove the complete interface with all 597 of its addresses. 598 */ 599 void 600 delete_interface(const char* name, char* const* args, int32 argCount) 601 { 602 BNetworkInterface interface(name); 603 604 for (int32 i = 0; i < argCount; i++) { 605 int family = get_address_family(args[i]); 606 if (family != AF_UNSPEC) 607 i++; 608 609 BNetworkAddress address; 610 if (!parse_address(family, args[i], address)) { 611 fprintf(stderr, "%s: Could not parse address \"%s\".\n", 612 kProgramName, args[i]); 613 exit(1); 614 } 615 616 status_t status = interface.RemoveAddress(address); 617 if (status != B_OK) { 618 fprintf(stderr, "%s: Could not delete address %s from interface %s:" 619 " %s\n", kProgramName, args[i], name, strerror(status)); 620 } 621 } 622 623 if (argCount == 0) { 624 // Delete interface 625 BNetworkRoster& roster = BNetworkRoster::Default(); 626 627 status_t status = roster.RemoveInterface(interface); 628 if (status != B_OK) { 629 fprintf(stderr, "%s: Could not delete interface %s: %s\n", 630 kProgramName, name, strerror(errno)); 631 } 632 } 633 } 634 635 636 void 637 configure_interface(const char* name, char* const* args, int32 argCount) 638 { 639 // try to parse address family 640 641 int32 i = 0; 642 int family = get_address_family(args[i]); 643 if (family != AF_UNSPEC) 644 i++; 645 646 // try to parse address 647 648 BNetworkAddress address; 649 BNetworkAddress mask; 650 651 if (parse_address(family, args[i], address)) { 652 i++; 653 654 if (parse_address(family, args[i], mask)) 655 i++; 656 } 657 658 BNetworkInterface interface(name); 659 if (!interface.Exists()) { 660 // the interface does not exist yet, we have to add it first 661 BNetworkRoster& roster = BNetworkRoster::Default(); 662 663 status_t status = roster.AddInterface(interface); 664 if (status != B_OK) { 665 fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName, 666 strerror(status)); 667 exit(1); 668 } 669 } 670 671 BNetworkAddress broadcast; 672 BNetworkAddress peer; 673 int mtu = -1, metric = -1, media = -1; 674 int addFlags = 0, currentFlags = 0, removeFlags = 0; 675 bool doAutoConfig = false; 676 677 // parse parameters and flags 678 679 while (i < argCount) { 680 if (!strcmp(args[i], "peer")) { 681 if (!parse_address(family, args[i + 1], peer)) { 682 fprintf(stderr, "%s: Option 'peer' needs valid address " 683 "parameter\n", kProgramName); 684 exit(1); 685 } 686 i++; 687 } else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) { 688 if (!mask.IsEmpty()) { 689 fprintf(stderr, "%s: Netmask or prefix length is specified " 690 "twice\n", kProgramName); 691 exit(1); 692 } 693 if (!parse_address(family, args[i + 1], mask)) { 694 fprintf(stderr, "%s: Option 'netmask' needs valid address " 695 "parameter\n", kProgramName); 696 exit(1); 697 } 698 i++; 699 } else if (!strcmp(args[i], "prefixlen") || !strcmp(args[i], "plen") 700 || !strcmp(args[i], "prefix-length")) { 701 if (!mask.IsEmpty()) { 702 fprintf(stderr, "%s: Netmask or prefix length is specified " 703 "twice\n", kProgramName); 704 exit(1); 705 } 706 707 // default to AF_INET if no address family has been specified yet 708 if (family == AF_UNSPEC) 709 family = AF_INET; 710 711 if (!prefix_length_to_mask(family, args[i + 1], mask)) { 712 fprintf(stderr, "%s: Option 'prefix-length %s' is invalid for " 713 "this address family\n", kProgramName, args[i + 1]); 714 exit(1); 715 } 716 i++; 717 } else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) { 718 if (!broadcast.IsEmpty()) { 719 fprintf(stderr, "%s: broadcast address is specified twice\n", 720 kProgramName); 721 exit(1); 722 } 723 if (!parse_address(family, args[i + 1], broadcast)) { 724 fprintf(stderr, "%s: Option 'broadcast' needs valid address " 725 "parameter\n", kProgramName); 726 exit(1); 727 } 728 addFlags |= IFF_BROADCAST; 729 i++; 730 } else if (!strcmp(args[i], "mtu")) { 731 mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0; 732 if (mtu <= 500) { 733 fprintf(stderr, "%s: Option 'mtu' expected valid max transfer " 734 "unit size\n", kProgramName); 735 exit(1); 736 } 737 i++; 738 } else if (!strcmp(args[i], "metric")) { 739 if (i + 1 >= argCount) { 740 fprintf(stderr, "%s: Option 'metric' expected parameter\n", 741 kProgramName); 742 exit(1); 743 } 744 metric = strtol(args[i + 1], NULL, 0); 745 i++; 746 } else if (!strcmp(args[i], "media")) { 747 media = interface.Media(); 748 if (media < 0) { 749 fprintf(stderr, "%s: Unable to detect media type\n", 750 kProgramName); 751 exit(1); 752 } 753 if (i + 1 >= argCount) { 754 fprintf(stderr, "%s: Option 'media' expected parameter\n", 755 kProgramName); 756 exit(1); 757 } 758 if (!media_parse_subtype(args[i + 1], IFM_TYPE(media), &media)) { 759 fprintf(stderr, "%s: Invalid parameter for option 'media': " 760 "'%s'\n", kProgramName, args[i + 1]); 761 exit(1); 762 } 763 i++; 764 } else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) { 765 addFlags |= IFF_UP; 766 } else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) { 767 removeFlags |= IFF_UP; 768 } else if (!strcmp(args[i], "bcast")) { 769 addFlags |= IFF_BROADCAST; 770 } else if (!strcmp(args[i], "-bcast")) { 771 removeFlags |= IFF_BROADCAST; 772 } else if (!strcmp(args[i], "promisc")) { 773 addFlags |= IFF_PROMISC; 774 } else if (!strcmp(args[i], "-promisc")) { 775 removeFlags |= IFF_PROMISC; 776 } else if (!strcmp(args[i], "allmulti")) { 777 addFlags |= IFF_ALLMULTI; 778 } else if (!strcmp(args[i], "-allmulti")) { 779 removeFlags |= IFF_ALLMULTI; 780 } else if (!strcmp(args[i], "loopback")) { 781 addFlags |= IFF_LOOPBACK; 782 } else if (!strcmp(args[i], "auto-config")) { 783 doAutoConfig = true; 784 } else 785 usage(1); 786 787 i++; 788 } 789 790 if ((addFlags & removeFlags) != 0) { 791 fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName); 792 exit(1); 793 } 794 795 if (doAutoConfig && (!address.IsEmpty() || !mask.IsEmpty() 796 || !broadcast.IsEmpty() || !peer.IsEmpty())) { 797 fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName); 798 exit(1); 799 } 800 801 // set address/mask/broadcast/peer 802 803 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) { 804 BNetworkInterfaceAddress interfaceAddress; 805 interfaceAddress.SetAddress(address); 806 interfaceAddress.SetMask(mask); 807 if (!broadcast.IsEmpty()) 808 interfaceAddress.SetBroadcast(broadcast); 809 else if (!peer.IsEmpty()) 810 interfaceAddress.SetDestination(peer); 811 812 status_t status = interface.SetAddress(interfaceAddress); 813 if (status != B_OK) { 814 fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName, 815 strerror(status)); 816 exit(1); 817 } 818 } 819 820 currentFlags = interface.Flags(); 821 822 // set flags 823 824 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty() 825 || !peer.IsEmpty()) 826 removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING; 827 828 if (addFlags || removeFlags) { 829 status_t status 830 = interface.SetFlags((currentFlags & ~removeFlags) | addFlags); 831 if (status != B_OK) { 832 fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName, 833 strerror(status)); 834 } 835 } 836 837 // set options 838 839 if (mtu != -1) { 840 status_t status = interface.SetMTU(mtu); 841 if (status != B_OK) { 842 fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName, 843 strerror(status)); 844 } 845 } 846 847 if (metric != -1) { 848 status_t status = interface.SetMetric(metric); 849 if (status != B_OK) { 850 fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName, 851 strerror(status)); 852 } 853 } 854 855 if (media != -1) { 856 status_t status = interface.SetMedia(media); 857 if (status != B_OK) { 858 fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName, 859 strerror(status)); 860 } 861 } 862 863 // start auto configuration, if asked for 864 865 if (doAutoConfig) { 866 status_t status = interface.AutoConfigure(family); 867 if (status == B_BAD_PORT_ID) { 868 fprintf(stderr, "%s: The net_server needs to run for the auto " 869 "configuration!\n", kProgramName); 870 } else if (status != B_OK) { 871 fprintf(stderr, "%s: Auto-configuring failed: %s\n", kProgramName, 872 strerror(status)); 873 } 874 } 875 } 876 877 878 // #pragma mark - 879 880 881 int 882 main(int argc, char** argv) 883 { 884 if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) 885 usage(0); 886 887 int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); 888 if (socket < 0) { 889 fprintf(stderr, "%s: The networking stack doesn't seem to be " 890 "available.\n", kProgramName); 891 return 1; 892 } 893 close(socket); 894 895 if (argc > 1 896 && (!strcmp(argv[1], "--delete") 897 || !strcmp(argv[1], "--del") 898 || !strcmp(argv[1], "-d") 899 || !strcmp(argv[1], "del") 900 || !strcmp(argv[1], "delete"))) { 901 // Delete interface (addresses) 902 903 if (argc < 3) 904 usage(1); 905 906 const char* name = argv[2]; 907 delete_interface(name, argv + 3, argc - 3); 908 return 0; 909 } 910 911 if (argc > 1 && !strcmp(argv[1], "-a")) { 912 // Accept an optional "-a" option to list all interfaces for those 913 // that are used to it from other platforms. 914 915 if (argc > 2) 916 usage(1); 917 918 list_interfaces(NULL); 919 return 0; 920 } 921 922 const char* name = argv[1]; 923 if (argc > 2) { 924 if (configure_wireless(name, argv + 2, argc - 2)) 925 return 0; 926 927 // Add or configure an interface 928 929 configure_interface(name, argv + 2, argc - 2); 930 return 0; 931 } 932 933 // list interfaces 934 935 list_interfaces(name); 936 return 0; 937 } 938