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 SCAN, 285 LIST, 286 JOIN, 287 LEAVE, 288 CONTROL 289 } mode = NONE; 290 291 int controlOption = -1; 292 int controlValue = -1; 293 294 if (!strcmp(args[0], "scan")) 295 mode = SCAN; 296 else if (!strcmp(args[0], "list")) 297 mode = LIST; 298 else if (!strcmp(args[0], "join")) 299 mode = JOIN; 300 else if (!strcmp(args[0], "leave")) 301 mode = LEAVE; 302 else if (!strcmp(args[0], "ht")) { 303 mode = CONTROL; 304 controlOption = IEEE80211_IOC_HTCONF; 305 controlValue = 3; 306 } else if (!strcmp(args[0], "-ht")) { 307 mode = CONTROL; 308 controlOption = IEEE80211_IOC_HTCONF; 309 controlValue = 0; 310 } 311 312 if (mode == NONE) 313 return false; 314 315 BNetworkDevice device(name); 316 if (!device.Exists()) { 317 fprintf(stderr, "%s: \"%s\" does not exist!\n", kProgramName, name); 318 exit(1); 319 } 320 if (!device.IsWireless()) { 321 fprintf(stderr, "%s: \"%s\" is not a WLAN device!\n", kProgramName, 322 name); 323 exit(1); 324 } 325 326 args++; 327 argCount--; 328 329 switch (mode) { 330 case SCAN: 331 { 332 status_t status = device.Scan(true, true); 333 if (status != B_OK) { 334 fprintf(stderr, "%s: Scan on \"%s\" failed: %s\n", kProgramName, 335 name, strerror(status)); 336 exit(1); 337 } 338 // fall through 339 } 340 case LIST: 341 { 342 // list wireless network(s) 343 344 bool verbose = false; 345 if (argCount > 0 && !strcmp(args[0], "-v")) { 346 verbose = true; 347 args++; 348 argCount--; 349 } 350 show_wireless_network_header(verbose); 351 352 if (argCount > 0) { 353 // list the named entries 354 for (int32 i = 0; i < argCount; i++) { 355 wireless_network network; 356 BNetworkAddress link; 357 status_t status; 358 if (link.SetTo(AF_LINK, args[i]) == B_OK) 359 status = device.GetNetwork(link, network); 360 else 361 status = device.GetNetwork(args[i], network); 362 if (status != B_OK) { 363 fprintf(stderr, "%s: Getting network failed: %s\n", 364 kProgramName, strerror(status)); 365 } else 366 show_wireless_network(network, verbose); 367 } 368 } else { 369 // list them all 370 uint32 networksCount = 0; 371 wireless_network* networks = NULL; 372 status_t status = device.GetNetworks(networks, networksCount); 373 if (status != B_OK) { 374 fprintf(stderr, "%s: Getting networks failed: %s\n", 375 kProgramName, strerror(status)); 376 } 377 for (uint32 i = 0; i < networksCount; i++) 378 show_wireless_network(networks[i], verbose); 379 delete[] networks; 380 } 381 break; 382 } 383 384 case JOIN: 385 { 386 // join a wireless network 387 if (argCount > 2) { 388 fprintf(stderr, "usage: %s %s join <network> [<password>]\n", 389 kProgramName, name); 390 exit(1); 391 } 392 393 const char* password = NULL; 394 if (argCount == 2) 395 password = args[1]; 396 397 BNetworkAddress link; 398 status_t status; 399 if (link.SetTo(AF_LINK, args[0]) == B_OK) 400 status = device.JoinNetwork(link, password); 401 else 402 status = device.JoinNetwork(args[0], password); 403 if (status != B_OK) { 404 fprintf(stderr, "%s: Joining network failed: %s\n", 405 kProgramName, strerror(status)); 406 exit(1); 407 } 408 break; 409 } 410 411 case LEAVE: 412 { 413 // leave a wireless network 414 if (argCount != 1) { 415 fprintf(stderr, "usage: %s %s leave <network>\n", kProgramName, 416 name); 417 exit(1); 418 } 419 420 BNetworkAddress link; 421 status_t status; 422 if (link.SetTo(AF_LINK, args[0]) == B_OK) 423 status = device.LeaveNetwork(link); 424 else 425 status = device.LeaveNetwork(args[0]); 426 if (status != B_OK) { 427 fprintf(stderr, "%s: Leaving network failed: %s\n", 428 kProgramName, strerror(status)); 429 exit(1); 430 } 431 break; 432 } 433 434 case CONTROL: 435 { 436 ieee80211req request; 437 memset(&request, 0, sizeof(request)); 438 request.i_type = controlOption; 439 request.i_val = controlValue; 440 status_t status = device.Control(SIOCS80211, &request); 441 if (status != B_OK) { 442 fprintf(stderr, "%s: Control failed: %s\n", kProgramName, 443 strerror(status)); 444 exit(1); 445 } 446 break; 447 } 448 449 case NONE: 450 break; 451 } 452 453 return true; 454 } 455 456 457 // #pragma mark - 458 459 460 void 461 list_interface_addresses(BNetworkInterface& interface, uint32 flags) 462 { 463 int32 count = interface.CountAddresses(); 464 for (int32 i = 0; i < count; i++) { 465 BNetworkInterfaceAddress address; 466 if (interface.GetAddressAt(i, address) != B_OK) 467 break; 468 469 const address_family* family 470 = address_family_for(address.Address().Family()); 471 472 printf("\t%s addr: %s", family->name, 473 to_string(address.Address()).String()); 474 475 if ((flags & IFF_BROADCAST) != 0) 476 printf(", Bcast: %s", to_string(address.Broadcast()).String()); 477 478 switch (family->preferred_format) { 479 case PREFER_OUTPUT_MASK: 480 printf(", Mask: %s", to_string(address.Mask()).String()); 481 break; 482 case PREFER_OUTPUT_PREFIX_LENGTH: 483 printf(", Prefix Length: %zu", address.Mask().PrefixLength()); 484 break; 485 } 486 487 putchar('\n'); 488 } 489 } 490 491 492 bool 493 list_interface(const char* name) 494 { 495 printf("%s", name); 496 size_t length = strlen(name); 497 if (length < 8) 498 putchar('\t'); 499 else 500 printf("\n\t"); 501 502 // get link level interface for this interface 503 504 BNetworkInterface interface(name); 505 if (!interface.Exists()) { 506 printf("Interface not found!\n"); 507 return false; 508 } 509 510 BNetworkAddress linkAddress; 511 status_t status = interface.GetHardwareAddress(linkAddress); 512 if (status == B_OK) { 513 const char *type = "unknown"; 514 switch (linkAddress.LinkLevelType()) { 515 case IFT_ETHER: 516 type = "Ethernet"; 517 break; 518 case IFT_LOOP: 519 type = "Local Loopback"; 520 break; 521 case IFT_MODEM: 522 type = "Modem"; 523 break; 524 } 525 526 BString address = linkAddress.ToString(); 527 if (address.Length() == 0) 528 address = "none"; 529 530 printf("Hardware type: %s, Address: %s\n", type, address.String()); 531 } else 532 printf("No link level: %s\n", strerror(status)); 533 534 int media = interface.Media(); 535 if ((media & IFM_ACTIVE) != 0) { 536 // dump media state in case we're linked 537 const char* type = media_type_to_string(media); 538 if (type != NULL) 539 printf("\tMedia type: %s\n", type); 540 } 541 542 // Print associated wireless network(s) 543 544 BNetworkDevice device(name); 545 if (device.IsWireless()) { 546 wireless_network network; 547 bool first = true; 548 uint32 cookie = 0; 549 while (device.GetNextAssociatedNetwork(cookie, network) == B_OK) { 550 if (first) { 551 printf("\tNetwork: "); 552 first = false; 553 } else 554 printf("\t\t"); 555 556 printf("%s, Address: %s, %s", network.name, 557 network.address.ToString().String(), 558 get_authentication_mode(network.authentication_mode, 559 network.flags)); 560 const char* keyMode = get_key_mode(network.key_mode); 561 if (keyMode != NULL) 562 printf(", %s/%s", keyMode, get_cipher(network.cipher)); 563 putchar('\n'); 564 } 565 } 566 567 uint32 flags = interface.Flags(); 568 569 list_interface_addresses(interface, flags); 570 571 // Print MTU, metric, flags 572 573 printf("\tMTU: %" B_PRId32 ", Metric: %" B_PRId32, interface.MTU(), 574 interface.Metric()); 575 576 if (flags != 0) { 577 const struct { 578 int value; 579 const char *name; 580 } kFlags[] = { 581 {IFF_UP, "up"}, 582 {IFF_NOARP, "noarp"}, 583 {IFF_BROADCAST, "broadcast"}, 584 {IFF_LOOPBACK, "loopback"}, 585 {IFF_PROMISC, "promiscuous"}, 586 {IFF_ALLMULTI, "allmulti"}, 587 {IFF_AUTOUP, "autoup"}, 588 {IFF_LINK, "link"}, 589 {IFF_AUTO_CONFIGURED, "auto-configured"}, 590 {IFF_CONFIGURING, "configuring"}, 591 }; 592 bool first = true; 593 594 for (uint32 i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); i++) { 595 if ((flags & kFlags[i].value) != 0) { 596 if (first) { 597 printf(","); 598 first = false; 599 } 600 putchar(' '); 601 fputs(kFlags[i].name, stdout); 602 } 603 } 604 } 605 606 putchar('\n'); 607 608 // Print statistics 609 610 ifreq_stats stats; 611 if (interface.GetStats(stats) == B_OK) { 612 printf("\tReceive: %d packets, %d errors, %" B_PRId64 " bytes, %d mcasts, %d " 613 "dropped\n", stats.receive.packets, stats.receive.errors, 614 stats.receive.bytes, stats.receive.multicast_packets, 615 stats.receive.dropped); 616 printf("\tTransmit: %d packets, %d errors, %" B_PRId64 " bytes, %d mcasts, %d " 617 "dropped\n", stats.send.packets, stats.send.errors, 618 stats.send.bytes, stats.send.multicast_packets, stats.send.dropped); 619 printf("\tCollisions: %d\n", stats.collisions); 620 } 621 622 putchar('\n'); 623 return true; 624 } 625 626 627 void 628 list_interfaces(const char* name) 629 { 630 if (name != NULL) { 631 list_interface(name); 632 return; 633 } 634 635 // get a list of all interfaces 636 637 BNetworkRoster& roster = BNetworkRoster::Default(); 638 639 BNetworkInterface interface; 640 uint32 cookie = 0; 641 642 while (roster.GetNextInterface(&cookie, interface) == B_OK) { 643 list_interface(interface.Name()); 644 } 645 } 646 647 648 /*! If there are any arguments given, this will remove only the specified 649 addresses from the interface named \a name. 650 If there are no arguments, it will remove the complete interface with all 651 of its addresses. 652 */ 653 void 654 delete_interface(const char* name, char* const* args, int32 argCount) 655 { 656 BNetworkInterface interface(name); 657 658 for (int32 i = 0; i < argCount; i++) { 659 int family = get_address_family(args[i]); 660 if (family != AF_UNSPEC) 661 i++; 662 663 BNetworkAddress address; 664 if (!parse_address(family, args[i], address)) { 665 fprintf(stderr, "%s: Could not parse address \"%s\".\n", 666 kProgramName, args[i]); 667 exit(1); 668 } 669 670 status_t status = interface.RemoveAddress(address); 671 if (status != B_OK) { 672 fprintf(stderr, "%s: Could not delete address %s from interface %s:" 673 " %s\n", kProgramName, args[i], name, strerror(status)); 674 } 675 } 676 677 if (argCount == 0) { 678 // Delete interface 679 BNetworkRoster& roster = BNetworkRoster::Default(); 680 681 status_t status = roster.RemoveInterface(interface); 682 if (status != B_OK) { 683 fprintf(stderr, "%s: Could not delete interface %s: %s\n", 684 kProgramName, name, strerror(errno)); 685 } 686 } 687 } 688 689 690 void 691 configure_interface(const char* name, char* const* args, int32 argCount) 692 { 693 // try to parse address family 694 695 int32 i = 0; 696 int family = get_address_family(args[i]); 697 if (family != AF_UNSPEC) { 698 i++; 699 700 int socket = ::socket(family, SOCK_DGRAM, 0); 701 if (socket < 0) { 702 fprintf(stderr, "%s: The requested address family is not available.\n", 703 kProgramName); 704 exit(1); 705 } 706 close(socket); 707 } 708 709 710 // try to parse address 711 712 BNetworkAddress address; 713 BNetworkAddress mask; 714 715 if (parse_address(family, args[i], address)) { 716 i++; 717 718 if (parse_address(family, args[i], mask)) 719 i++; 720 } 721 722 BNetworkInterface interface(name); 723 if (!interface.Exists()) { 724 // the interface does not exist yet, we have to add it first 725 BNetworkRoster& roster = BNetworkRoster::Default(); 726 727 status_t status = roster.AddInterface(interface); 728 if (status != B_OK) { 729 fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName, 730 strerror(status)); 731 exit(1); 732 } 733 } 734 735 BNetworkAddress broadcast; 736 BNetworkAddress peer; 737 int mtu = -1, metric = -1, media = -1; 738 int addFlags = 0, currentFlags = 0, removeFlags = 0; 739 bool doAutoConfig = false; 740 741 // parse parameters and flags 742 743 while (i < argCount) { 744 if (!strcmp(args[i], "peer")) { 745 if (!parse_address(family, args[i + 1], peer)) { 746 fprintf(stderr, "%s: Option 'peer' needs valid address " 747 "parameter\n", kProgramName); 748 exit(1); 749 } 750 i++; 751 } else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) { 752 if (!mask.IsEmpty()) { 753 fprintf(stderr, "%s: Netmask or prefix length is specified " 754 "twice\n", kProgramName); 755 exit(1); 756 } 757 if (!parse_address(family, args[i + 1], mask)) { 758 fprintf(stderr, "%s: Option 'netmask' needs valid address " 759 "parameter\n", kProgramName); 760 exit(1); 761 } 762 i++; 763 } else if (!strcmp(args[i], "prefixlen") || !strcmp(args[i], "plen") 764 || !strcmp(args[i], "prefix-length")) { 765 if (!mask.IsEmpty()) { 766 fprintf(stderr, "%s: Netmask or prefix length is specified " 767 "twice\n", kProgramName); 768 exit(1); 769 } 770 771 // default to AF_INET if no address family has been specified yet 772 if (family == AF_UNSPEC) 773 family = AF_INET; 774 775 if (!prefix_length_to_mask(family, args[i + 1], mask)) { 776 fprintf(stderr, "%s: Option 'prefix-length %s' is invalid for " 777 "this address family\n", kProgramName, args[i + 1]); 778 exit(1); 779 } 780 i++; 781 } else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) { 782 if (!broadcast.IsEmpty()) { 783 fprintf(stderr, "%s: broadcast address is specified twice\n", 784 kProgramName); 785 exit(1); 786 } 787 if (!parse_address(family, args[i + 1], broadcast)) { 788 fprintf(stderr, "%s: Option 'broadcast' needs valid address " 789 "parameter\n", kProgramName); 790 exit(1); 791 } 792 addFlags |= IFF_BROADCAST; 793 i++; 794 } else if (!strcmp(args[i], "mtu")) { 795 mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0; 796 if (mtu <= 500) { 797 fprintf(stderr, "%s: Option 'mtu' expected valid max transfer " 798 "unit size\n", kProgramName); 799 exit(1); 800 } 801 i++; 802 } else if (!strcmp(args[i], "metric")) { 803 if (i + 1 >= argCount) { 804 fprintf(stderr, "%s: Option 'metric' expected parameter\n", 805 kProgramName); 806 exit(1); 807 } 808 metric = strtol(args[i + 1], NULL, 0); 809 i++; 810 } else if (!strcmp(args[i], "media")) { 811 media = interface.Media(); 812 if (media < 0) { 813 fprintf(stderr, "%s: Unable to detect media type\n", 814 kProgramName); 815 exit(1); 816 } 817 if (i + 1 >= argCount) { 818 fprintf(stderr, "%s: Option 'media' expected parameter\n", 819 kProgramName); 820 exit(1); 821 } 822 if (!media_parse_subtype(args[i + 1], IFM_TYPE(media), &media)) { 823 fprintf(stderr, "%s: Invalid parameter for option 'media': " 824 "'%s'\n", kProgramName, args[i + 1]); 825 exit(1); 826 } 827 i++; 828 } else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) { 829 addFlags |= IFF_UP; 830 } else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) { 831 removeFlags |= IFF_UP; 832 } else if (!strcmp(args[i], "bcast")) { 833 addFlags |= IFF_BROADCAST; 834 } else if (!strcmp(args[i], "-bcast")) { 835 removeFlags |= IFF_BROADCAST; 836 } else if (!strcmp(args[i], "promisc")) { 837 addFlags |= IFF_PROMISC; 838 } else if (!strcmp(args[i], "-promisc")) { 839 removeFlags |= IFF_PROMISC; 840 } else if (!strcmp(args[i], "allmulti")) { 841 addFlags |= IFF_ALLMULTI; 842 } else if (!strcmp(args[i], "-allmulti")) { 843 removeFlags |= IFF_ALLMULTI; 844 } else if (!strcmp(args[i], "loopback")) { 845 addFlags |= IFF_LOOPBACK; 846 } else if (!strcmp(args[i], "auto-config")) { 847 doAutoConfig = true; 848 } else 849 usage(1); 850 851 i++; 852 } 853 854 if ((addFlags & removeFlags) != 0) { 855 fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName); 856 exit(1); 857 } 858 859 if (doAutoConfig && (!address.IsEmpty() || !mask.IsEmpty() 860 || !broadcast.IsEmpty() || !peer.IsEmpty())) { 861 fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName); 862 exit(1); 863 } 864 865 // set address/mask/broadcast/peer 866 867 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) { 868 BNetworkInterfaceAddress interfaceAddress; 869 interfaceAddress.SetAddress(address); 870 interfaceAddress.SetMask(mask); 871 if (!broadcast.IsEmpty()) 872 interfaceAddress.SetBroadcast(broadcast); 873 else if (!peer.IsEmpty()) 874 interfaceAddress.SetDestination(peer); 875 876 status_t status = interface.SetAddress(interfaceAddress); 877 if (status != B_OK) { 878 fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName, 879 strerror(status)); 880 exit(1); 881 } 882 } 883 884 currentFlags = interface.Flags(); 885 886 // set flags 887 888 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty() 889 || !peer.IsEmpty()) 890 removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING; 891 892 if (addFlags || removeFlags) { 893 status_t status 894 = interface.SetFlags((currentFlags & ~removeFlags) | addFlags); 895 if (status != B_OK) { 896 fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName, 897 strerror(status)); 898 } 899 } 900 901 // set options 902 903 if (mtu != -1) { 904 status_t status = interface.SetMTU(mtu); 905 if (status != B_OK) { 906 fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName, 907 strerror(status)); 908 } 909 } 910 911 if (metric != -1) { 912 status_t status = interface.SetMetric(metric); 913 if (status != B_OK) { 914 fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName, 915 strerror(status)); 916 } 917 } 918 919 if (media != -1) { 920 status_t status = interface.SetMedia(media); 921 if (status != B_OK) { 922 fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName, 923 strerror(status)); 924 } 925 } 926 927 // start auto configuration, if asked for 928 929 if (doAutoConfig) { 930 status_t status = interface.AutoConfigure(family); 931 if (status == B_BAD_PORT_ID) { 932 fprintf(stderr, "%s: The net_server needs to run for the auto " 933 "configuration!\n", kProgramName); 934 } else if (status != B_OK) { 935 fprintf(stderr, "%s: Auto-configuring failed: %s\n", kProgramName, 936 strerror(status)); 937 } 938 } 939 } 940 941 942 // #pragma mark - 943 944 945 int 946 main(int argc, char** argv) 947 { 948 if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) 949 usage(0); 950 951 int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); 952 if (socket < 0) { 953 fprintf(stderr, "%s: The networking stack doesn't seem to be " 954 "available.\n", kProgramName); 955 return 1; 956 } 957 close(socket); 958 959 if (argc > 1 960 && (!strcmp(argv[1], "--delete") 961 || !strcmp(argv[1], "--del") 962 || !strcmp(argv[1], "-d") 963 || !strcmp(argv[1], "del") 964 || !strcmp(argv[1], "delete"))) { 965 // Delete interface (addresses) 966 967 if (argc < 3) 968 usage(1); 969 970 const char* name = argv[2]; 971 delete_interface(name, argv + 3, argc - 3); 972 return 0; 973 } 974 975 if (argc > 1 && !strcmp(argv[1], "-a")) { 976 // Accept an optional "-a" option to list all interfaces for those 977 // that are used to it from other platforms. 978 979 if (argc > 2) 980 usage(1); 981 982 list_interfaces(NULL); 983 return 0; 984 } 985 986 const char* name = argv[1]; 987 if (argc > 2) { 988 if (configure_wireless(name, argv + 2, argc - 2)) 989 return 0; 990 991 // Add or configure an interface 992 993 configure_interface(name, argv + 2, argc - 2); 994 return 0; 995 } 996 997 // list interfaces 998 999 list_interfaces(name); 1000 return 0; 1001 } 1002