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, %Ld 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, %Ld 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 // try to parse address 701 702 BNetworkAddress address; 703 BNetworkAddress mask; 704 705 if (parse_address(family, args[i], address)) { 706 i++; 707 708 if (parse_address(family, args[i], mask)) 709 i++; 710 } 711 712 BNetworkInterface interface(name); 713 if (!interface.Exists()) { 714 // the interface does not exist yet, we have to add it first 715 BNetworkRoster& roster = BNetworkRoster::Default(); 716 717 status_t status = roster.AddInterface(interface); 718 if (status != B_OK) { 719 fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName, 720 strerror(status)); 721 exit(1); 722 } 723 } 724 725 BNetworkAddress broadcast; 726 BNetworkAddress peer; 727 int mtu = -1, metric = -1, media = -1; 728 int addFlags = 0, currentFlags = 0, removeFlags = 0; 729 bool doAutoConfig = false; 730 731 // parse parameters and flags 732 733 while (i < argCount) { 734 if (!strcmp(args[i], "peer")) { 735 if (!parse_address(family, args[i + 1], peer)) { 736 fprintf(stderr, "%s: Option 'peer' needs valid address " 737 "parameter\n", kProgramName); 738 exit(1); 739 } 740 i++; 741 } else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) { 742 if (!mask.IsEmpty()) { 743 fprintf(stderr, "%s: Netmask or prefix length is specified " 744 "twice\n", kProgramName); 745 exit(1); 746 } 747 if (!parse_address(family, args[i + 1], mask)) { 748 fprintf(stderr, "%s: Option 'netmask' needs valid address " 749 "parameter\n", kProgramName); 750 exit(1); 751 } 752 i++; 753 } else if (!strcmp(args[i], "prefixlen") || !strcmp(args[i], "plen") 754 || !strcmp(args[i], "prefix-length")) { 755 if (!mask.IsEmpty()) { 756 fprintf(stderr, "%s: Netmask or prefix length is specified " 757 "twice\n", kProgramName); 758 exit(1); 759 } 760 761 // default to AF_INET if no address family has been specified yet 762 if (family == AF_UNSPEC) 763 family = AF_INET; 764 765 if (!prefix_length_to_mask(family, args[i + 1], mask)) { 766 fprintf(stderr, "%s: Option 'prefix-length %s' is invalid for " 767 "this address family\n", kProgramName, args[i + 1]); 768 exit(1); 769 } 770 i++; 771 } else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) { 772 if (!broadcast.IsEmpty()) { 773 fprintf(stderr, "%s: broadcast address is specified twice\n", 774 kProgramName); 775 exit(1); 776 } 777 if (!parse_address(family, args[i + 1], broadcast)) { 778 fprintf(stderr, "%s: Option 'broadcast' needs valid address " 779 "parameter\n", kProgramName); 780 exit(1); 781 } 782 addFlags |= IFF_BROADCAST; 783 i++; 784 } else if (!strcmp(args[i], "mtu")) { 785 mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0; 786 if (mtu <= 500) { 787 fprintf(stderr, "%s: Option 'mtu' expected valid max transfer " 788 "unit size\n", kProgramName); 789 exit(1); 790 } 791 i++; 792 } else if (!strcmp(args[i], "metric")) { 793 if (i + 1 >= argCount) { 794 fprintf(stderr, "%s: Option 'metric' expected parameter\n", 795 kProgramName); 796 exit(1); 797 } 798 metric = strtol(args[i + 1], NULL, 0); 799 i++; 800 } else if (!strcmp(args[i], "media")) { 801 media = interface.Media(); 802 if (media < 0) { 803 fprintf(stderr, "%s: Unable to detect media type\n", 804 kProgramName); 805 exit(1); 806 } 807 if (i + 1 >= argCount) { 808 fprintf(stderr, "%s: Option 'media' expected parameter\n", 809 kProgramName); 810 exit(1); 811 } 812 if (!media_parse_subtype(args[i + 1], IFM_TYPE(media), &media)) { 813 fprintf(stderr, "%s: Invalid parameter for option 'media': " 814 "'%s'\n", kProgramName, args[i + 1]); 815 exit(1); 816 } 817 i++; 818 } else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) { 819 addFlags |= IFF_UP; 820 } else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) { 821 removeFlags |= IFF_UP; 822 } else if (!strcmp(args[i], "bcast")) { 823 addFlags |= IFF_BROADCAST; 824 } else if (!strcmp(args[i], "-bcast")) { 825 removeFlags |= IFF_BROADCAST; 826 } else if (!strcmp(args[i], "promisc")) { 827 addFlags |= IFF_PROMISC; 828 } else if (!strcmp(args[i], "-promisc")) { 829 removeFlags |= IFF_PROMISC; 830 } else if (!strcmp(args[i], "allmulti")) { 831 addFlags |= IFF_ALLMULTI; 832 } else if (!strcmp(args[i], "-allmulti")) { 833 removeFlags |= IFF_ALLMULTI; 834 } else if (!strcmp(args[i], "loopback")) { 835 addFlags |= IFF_LOOPBACK; 836 } else if (!strcmp(args[i], "auto-config")) { 837 doAutoConfig = true; 838 } else 839 usage(1); 840 841 i++; 842 } 843 844 if ((addFlags & removeFlags) != 0) { 845 fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName); 846 exit(1); 847 } 848 849 if (doAutoConfig && (!address.IsEmpty() || !mask.IsEmpty() 850 || !broadcast.IsEmpty() || !peer.IsEmpty())) { 851 fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName); 852 exit(1); 853 } 854 855 // set address/mask/broadcast/peer 856 857 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) { 858 BNetworkInterfaceAddress interfaceAddress; 859 interfaceAddress.SetAddress(address); 860 interfaceAddress.SetMask(mask); 861 if (!broadcast.IsEmpty()) 862 interfaceAddress.SetBroadcast(broadcast); 863 else if (!peer.IsEmpty()) 864 interfaceAddress.SetDestination(peer); 865 866 status_t status = interface.SetAddress(interfaceAddress); 867 if (status != B_OK) { 868 fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName, 869 strerror(status)); 870 exit(1); 871 } 872 } 873 874 currentFlags = interface.Flags(); 875 876 // set flags 877 878 if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty() 879 || !peer.IsEmpty()) 880 removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING; 881 882 if (addFlags || removeFlags) { 883 status_t status 884 = interface.SetFlags((currentFlags & ~removeFlags) | addFlags); 885 if (status != B_OK) { 886 fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName, 887 strerror(status)); 888 } 889 } 890 891 // set options 892 893 if (mtu != -1) { 894 status_t status = interface.SetMTU(mtu); 895 if (status != B_OK) { 896 fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName, 897 strerror(status)); 898 } 899 } 900 901 if (metric != -1) { 902 status_t status = interface.SetMetric(metric); 903 if (status != B_OK) { 904 fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName, 905 strerror(status)); 906 } 907 } 908 909 if (media != -1) { 910 status_t status = interface.SetMedia(media); 911 if (status != B_OK) { 912 fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName, 913 strerror(status)); 914 } 915 } 916 917 // start auto configuration, if asked for 918 919 if (doAutoConfig) { 920 status_t status = interface.AutoConfigure(family); 921 if (status == B_BAD_PORT_ID) { 922 fprintf(stderr, "%s: The net_server needs to run for the auto " 923 "configuration!\n", kProgramName); 924 } else if (status != B_OK) { 925 fprintf(stderr, "%s: Auto-configuring failed: %s\n", kProgramName, 926 strerror(status)); 927 } 928 } 929 } 930 931 932 // #pragma mark - 933 934 935 int 936 main(int argc, char** argv) 937 { 938 if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) 939 usage(0); 940 941 int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); 942 if (socket < 0) { 943 fprintf(stderr, "%s: The networking stack doesn't seem to be " 944 "available.\n", kProgramName); 945 return 1; 946 } 947 close(socket); 948 949 if (argc > 1 950 && (!strcmp(argv[1], "--delete") 951 || !strcmp(argv[1], "--del") 952 || !strcmp(argv[1], "-d") 953 || !strcmp(argv[1], "del") 954 || !strcmp(argv[1], "delete"))) { 955 // Delete interface (addresses) 956 957 if (argc < 3) 958 usage(1); 959 960 const char* name = argv[2]; 961 delete_interface(name, argv + 3, argc - 3); 962 return 0; 963 } 964 965 if (argc > 1 && !strcmp(argv[1], "-a")) { 966 // Accept an optional "-a" option to list all interfaces for those 967 // that are used to it from other platforms. 968 969 if (argc > 2) 970 usage(1); 971 972 list_interfaces(NULL); 973 return 0; 974 } 975 976 const char* name = argv[1]; 977 if (argc > 2) { 978 if (configure_wireless(name, argv + 2, argc - 2)) 979 return 0; 980 981 // Add or configure an interface 982 983 configure_interface(name, argv + 2, argc - 2); 984 return 0; 985 } 986 987 // list interfaces 988 989 list_interfaces(name); 990 return 0; 991 } 992