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