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