1/* 2 * ifconfig This file contains an implementation of the command 3 * that either displays or sets the characteristics of 4 * one or more of the system's networking interfaces. 5 * 6 * Version: $Id: interface.c,v 1.1.1.1 2008/10/15 03:28:34 james26_jang Exp $ 7 * 8 * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> 9 * and others. Copyright 1993 MicroWalt Corporation 10 * 11 * This program is free software; you can redistribute it 12 * and/or modify it under the terms of the GNU General 13 * Public License as published by the Free Software 14 * Foundation; either version 2 of the License, or (at 15 * your option) any later version. 16 * 17 * Patched to support 'add' and 'del' keywords for INET(4) addresses 18 * by Mrs. Brisby <mrs.brisby@nimh.org> 19 * 20 * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> 21 * - gettext instead of catgets for i18n 22 * 10/1998 - Andi Kleen. Use interface list primitives. 23 * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu 24 * (default AF was wrong) 25 * stolen from net-tools-1.59 and stripped down for busybox by 26 * Erik Andersen <andersee@debian.org> 27 */ 28 29/* 30 * Heavily modified by Manuel Novoa III Mar 12, 2001 31 * 32 * Pruned unused code using KEEP_UNUSED define. 33 * Added print_bytes_scaled function to reduce code size. 34 * Added some (potentially) missing defines. 35 * Improved display support for -a and for a named interface. 36 */ 37 38/* #define KEEP_UNUSED */ 39 40/* 41 * 42 * Protocol Families. 43 * 44 */ 45#define HAVE_AFINET 1 46#undef HAVE_AFINET6 47#undef HAVE_AFIPX 48#undef HAVE_AFATALK 49#undef HAVE_AFNETROM 50#undef HAVE_AFX25 51#undef HAVE_AFECONET 52#undef HAVE_AFASH 53 54/* 55 * 56 * Device Hardware types. 57 * 58 */ 59#define HAVE_HWETHER 1 60#define HAVE_HWPPP 1 61#undef HAVE_HWSLIP 62 63 64#include <features.h> 65#include <sys/types.h> 66#include <sys/socket.h> 67#include <sys/ioctl.h> 68#include <netinet/in.h> 69#include <net/if.h> 70#include <net/if_arp.h> 71#include <stdio.h> 72#include <errno.h> 73#include <fcntl.h> 74#include <ctype.h> 75#include <stdlib.h> 76#include <string.h> 77#include <unistd.h> 78#include <netdb.h> 79#include <netinet/in.h> 80#include <arpa/inet.h> 81#include "libbb.h" 82 83#define _(x) x 84#define _PATH_PROCNET_DEV "/proc/net/dev" 85#define new(p) ((p) = xcalloc(1,sizeof(*(p)))) 86#define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch)) 87 88static int procnetdev_vsn = 1; 89 90 91/* Ugh. But libc5 doesn't provide POSIX types. */ 92#include <asm/types.h> 93 94 95#ifdef HAVE_HWSLIP 96#include <linux/if_slip.h> 97#endif 98 99#if HAVE_AFINET6 100 101#ifndef _LINUX_IN6_H 102/* 103 * This is in linux/include/net/ipv6.h. 104 */ 105 106struct in6_ifreq { 107 struct in6_addr ifr6_addr; 108 __u32 ifr6_prefixlen; 109 unsigned int ifr6_ifindex; 110}; 111 112#endif 113 114#endif /* HAVE_AFINET6 */ 115 116#if HAVE_AFIPX 117#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) 118#include <netipx/ipx.h> 119#else 120#include "ipx.h" 121#endif 122#endif 123 124/* Defines for glibc2.0 users. */ 125#ifndef SIOCSIFTXQLEN 126#define SIOCSIFTXQLEN 0x8943 127#define SIOCGIFTXQLEN 0x8942 128#endif 129 130/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */ 131#ifndef ifr_qlen 132#define ifr_qlen ifr_ifru.ifru_mtu 133#endif 134 135#ifndef HAVE_TXQUEUELEN 136#define HAVE_TXQUEUELEN 1 137#endif 138 139#ifndef IFF_DYNAMIC 140#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ 141#endif 142 143/* This structure defines protocol families and their handlers. */ 144struct aftype { 145 const char *name; 146 const char *title; 147 int af; 148 int alen; 149 char *(*print) (unsigned char *); 150 char *(*sprint) (struct sockaddr *, int numeric); 151 int (*input) (int type, char *bufp, struct sockaddr *); 152 void (*herror) (char *text); 153 int (*rprint) (int options); 154 int (*rinput) (int typ, int ext, char **argv); 155 156 /* may modify src */ 157 int (*getmask) (char *src, struct sockaddr * mask, char *name); 158 159 int fd; 160 char *flag_file; 161}; 162 163static struct aftype *aftypes[]; 164 165#ifdef KEEP_UNUSED 166 167static int flag_unx; 168#ifdef HAVE_AFIPX 169static int flag_ipx; 170#endif 171#ifdef HAVE_AFX25 172static int flag_ax25; 173#endif 174#ifdef HAVE_AFATALK 175static int flag_ddp; 176#endif 177#ifdef HAVE_AFNETROM 178static int flag_netrom; 179#endif 180static int flag_inet; 181#ifdef HAVE_AFINET6 182static int flag_inet6; 183#endif 184#ifdef HAVE_AFECONET 185static int flag_econet; 186#endif 187#ifdef HAVE_AFX25 188static int flag_x25 = 0; 189#endif 190#ifdef HAVE_AFASH 191static int flag_ash; 192#endif 193 194 195static struct aftrans_t { 196 char *alias; 197 char *name; 198 int *flag; 199} aftrans[] = { 200 201#ifdef HAVE_AFX25 202 { 203 "ax25", "ax25", &flag_ax25 204 }, 205#endif 206 { 207 "ip", "inet", &flag_inet 208 }, 209#ifdef HAVE_AFINET6 210 { 211 "ip6", "inet6", &flag_inet6 212 }, 213#endif 214#ifdef HAVE_AFIPX 215 { 216 "ipx", "ipx", &flag_ipx 217 }, 218#endif 219#ifdef HAVE_AFATALK 220 { 221 "appletalk", "ddp", &flag_ddp 222 }, 223#endif 224#ifdef HAVE_AFNETROM 225 { 226 "netrom", "netrom", &flag_netrom 227 }, 228#endif 229 { 230 "inet", "inet", &flag_inet 231 }, 232#ifdef HAVE_AFINET6 233 { 234 "inet6", "inet6", &flag_inet6 235 }, 236#endif 237#ifdef HAVE_AFATALK 238 { 239 "ddp", "ddp", &flag_ddp 240 }, 241#endif 242 { 243 "unix", "unix", &flag_unx 244 }, 245 { 246 "tcpip", "inet", &flag_inet 247 }, 248#ifdef HAVE_AFECONET 249 { 250 "econet", "ec", &flag_econet 251 }, 252#endif 253#ifdef HAVE_AFX25 254 { 255 "x25", "x25", &flag_x25 256 }, 257#endif 258#ifdef HAVE_AFASH 259 { 260 "ash", "ash", &flag_ash 261 }, 262#endif 263 { 264 0, 0, 0 265 } 266}; 267 268static char afname[256] = ""; 269#endif /* KEEP_UNUSED */ 270 271#if HAVE_AFUNIX 272 273/* Display a UNIX domain address. */ 274static char *UNIX_print(unsigned char *ptr) 275{ 276 return (ptr); 277} 278 279 280/* Display a UNIX domain address. */ 281static char *UNIX_sprint(struct sockaddr *sap, int numeric) 282{ 283 static char buf[64]; 284 285 if (sap->sa_family == 0xFFFF || sap->sa_family == 0) 286 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf)); 287 return (UNIX_print(sap->sa_data)); 288} 289 290 291static struct aftype unix_aftype = 292{ 293 "unix", "UNIX Domain", AF_UNIX, 0, 294 UNIX_print, UNIX_sprint, NULL, NULL, 295 NULL, NULL, NULL, 296 -1, 297 "/proc/net/unix" 298}; 299#endif /* HAVE_AFUNIX */ 300 301#if HAVE_AFINET 302 303 304/* cache */ 305struct addr { 306 struct sockaddr_in addr; 307 char *name; 308 int host; 309 struct addr *next; 310}; 311 312static struct addr *INET_nn = NULL; /* addr-to-name cache */ 313 314#ifdef KEEP_UNUSED 315static int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst) 316{ 317 struct hostent *hp; 318 struct netent *np; 319 320 /* Grmpf. -FvK */ 321 sin->sin_family = AF_INET; 322 sin->sin_port = 0; 323 324 /* Default is special, meaning 0.0.0.0. */ 325 if (!strcmp(name, "default")) { 326 sin->sin_addr.s_addr = INADDR_ANY; 327 return (1); 328 } 329 /* Look to see if it's a dotted quad. */ 330 if (inet_aton(name, &sin->sin_addr)) { 331 return 0; 332 } 333 /* If we expect this to be a hostname, try hostname database first */ 334#ifdef DEBUG 335 if (hostfirst) fprintf (stderr, "gethostbyname (%s)\n", name); 336#endif 337 if (hostfirst && 338 (hp = gethostbyname(name)) != (struct hostent *) NULL) { 339 memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], 340 sizeof(struct in_addr)); 341 return 0; 342 } 343 /* Try the NETWORKS database to see if this is a known network. */ 344#ifdef DEBUG 345 fprintf (stderr, "getnetbyname (%s)\n", name); 346#endif 347 if ((np = getnetbyname(name)) != (struct netent *) NULL) { 348 sin->sin_addr.s_addr = htonl(np->n_net); 349 return 1; 350 } 351 if (hostfirst) { 352 /* Don't try again */ 353 errno = h_errno; 354 return -1; 355 } 356#ifdef DEBUG 357 res_init(); 358 _res.options |= RES_DEBUG; 359#endif 360 361#ifdef DEBUG 362 fprintf (stderr, "gethostbyname (%s)\n", name); 363#endif 364 if ((hp = gethostbyname(name)) == (struct hostent *) NULL) { 365 errno = h_errno; 366 return -1; 367 } 368 memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], 369 sizeof(struct in_addr)); 370 371 return 0; 372} 373#endif /* KEEP_UNUSED */ 374 375/* numeric: & 0x8000: default instead of *, 376 * & 0x4000: host instead of net, 377 * & 0x0fff: don't resolve 378 */ 379static int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, 380 int numeric, unsigned int netmask) 381{ 382 struct hostent *ent; 383 struct netent *np; 384 struct addr *pn; 385 unsigned long ad, host_ad; 386 int host = 0; 387 388 /* Grmpf. -FvK */ 389 if (s_in->sin_family != AF_INET) { 390#ifdef DEBUG 391 fprintf(stderr, _("rresolve: unsupport address family %d !\n"), s_in->sin_family); 392#endif 393 errno = EAFNOSUPPORT; 394 return (-1); 395 } 396 ad = (unsigned long) s_in->sin_addr.s_addr; 397#ifdef DEBUG 398 fprintf (stderr, "rresolve: %08lx, mask %08x, num %08x \n", ad, netmask, numeric); 399#endif 400 if (ad == INADDR_ANY) { 401 if ((numeric & 0x0FFF) == 0) { 402 if (numeric & 0x8000) 403 safe_strncpy(name, "default", len); 404 else 405 safe_strncpy(name, "*", len); 406 return (0); 407 } 408 } 409 if (numeric & 0x0FFF) { 410 safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); 411 return (0); 412 } 413 414 if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) 415 host = 1; 416 pn = INET_nn; 417 while (pn != NULL) { 418 if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { 419 safe_strncpy(name, pn->name, len); 420#ifdef DEBUG 421 fprintf (stderr, "rresolve: found %s %08lx in cache\n", (host? "host": "net"), ad); 422#endif 423 return (0); 424 } 425 pn = pn->next; 426 } 427 428 host_ad = ntohl(ad); 429 np = NULL; 430 ent = NULL; 431 if (host) { 432#ifdef DEBUG 433 fprintf (stderr, "gethostbyaddr (%08lx)\n", ad); 434#endif 435 ent = gethostbyaddr((char *) &ad, 4, AF_INET); 436 if (ent != NULL) 437 safe_strncpy(name, ent->h_name, len); 438 } else { 439#ifdef DEBUG 440 fprintf (stderr, "getnetbyaddr (%08lx)\n", host_ad); 441#endif 442 } 443 if ((ent == NULL) && (np == NULL)) 444 safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); 445 pn = (struct addr *) xmalloc(sizeof(struct addr)); 446 pn->addr = *s_in; 447 pn->next = INET_nn; 448 pn->host = host; 449 pn->name = (char *) xmalloc(strlen(name) + 1); 450 strcpy(pn->name, name); 451 INET_nn = pn; 452 453 return (0); 454} 455 456#ifdef KEEP_UNUSED 457static void INET_reserror(char *text) 458{ 459 herror(text); 460} 461 462/* Display an Internet socket address. */ 463static char *INET_print(unsigned char *ptr) 464{ 465 return (inet_ntoa((*(struct in_addr *) ptr))); 466} 467#endif /* KEEP_UNUSED */ 468 469/* Display an Internet socket address. */ 470static char *INET_sprint(struct sockaddr *sap, int numeric) 471{ 472 static char buff[128]; 473 474 if (sap->sa_family == 0xFFFF || sap->sa_family == 0) 475 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); 476 477 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, 478 numeric, 0xffffff00) != 0) 479 return (NULL); 480 481 return (buff); 482} 483 484#ifdef KEEP_UNUSED 485static char *INET_sprintmask(struct sockaddr *sap, int numeric, 486 unsigned int netmask) 487{ 488 static char buff[128]; 489 490 if (sap->sa_family == 0xFFFF || sap->sa_family == 0) 491 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); 492 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, 493 numeric, netmask) != 0) 494 return (NULL); 495 return (buff); 496} 497 498static int INET_getsock(char *bufp, struct sockaddr *sap) 499{ 500 char *sp = bufp, *bp; 501 unsigned int i; 502 unsigned val; 503 struct sockaddr_in *sin; 504 505 sin = (struct sockaddr_in *) sap; 506 sin->sin_family = AF_INET; 507 sin->sin_port = 0; 508 509 val = 0; 510 bp = (char *) &val; 511 for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) { 512 *sp = toupper(*sp); 513 514 if ((*sp >= 'A') && (*sp <= 'F')) 515 bp[i] |= (int) (*sp - 'A') + 10; 516 else if ((*sp >= '0') && (*sp <= '9')) 517 bp[i] |= (int) (*sp - '0'); 518 else 519 return (-1); 520 521 bp[i] <<= 4; 522 sp++; 523 *sp = toupper(*sp); 524 525 if ((*sp >= 'A') && (*sp <= 'F')) 526 bp[i] |= (int) (*sp - 'A') + 10; 527 else if ((*sp >= '0') && (*sp <= '9')) 528 bp[i] |= (int) (*sp - '0'); 529 else 530 return (-1); 531 532 sp++; 533 } 534 sin->sin_addr.s_addr = htonl(val); 535 536 return (sp - bufp); 537} 538 539static int INET_input(int type, char *bufp, struct sockaddr *sap) 540{ 541 switch (type) { 542 case 1: 543 return (INET_getsock(bufp, sap)); 544 case 256: 545 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1)); 546 default: 547 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0)); 548 } 549} 550 551static int INET_getnetmask(char *adr, struct sockaddr *m, char *name) 552{ 553 struct sockaddr_in *mask = (struct sockaddr_in *) m; 554 char *slash, *end; 555 int prefix; 556 557 if ((slash = strchr(adr, '/')) == NULL) 558 return 0; 559 560 *slash++ = '\0'; 561 prefix = strtoul(slash, &end, 0); 562 if (*end != '\0') 563 return -1; 564 565 if (name) { 566 sprintf(name, "/%d", prefix); 567 } 568 mask->sin_family = AF_INET; 569 mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix)); 570 return 1; 571} 572#endif /* KEEP_UNUSED */ 573 574static struct aftype inet_aftype = 575{ 576 "inet", "DARPA Internet", AF_INET, sizeof(unsigned long), 577 NULL /* UNUSED INET_print */, INET_sprint, 578 NULL /* UNUSED INET_input */, NULL /* UNUSED INET_reserror */, 579 NULL /*INET_rprint */ , NULL /*INET_rinput */ , 580 NULL /* UNUSED INET_getnetmask */, 581 -1, 582 NULL 583}; 584 585#endif /* HAVE_AFINET */ 586 587/* Display an UNSPEC address. */ 588static char *UNSPEC_print(unsigned char *ptr) 589{ 590 static char buff[sizeof(struct sockaddr)*3+1]; 591 char *pos; 592 unsigned int i; 593 594 pos = buff; 595 for (i = 0; i < sizeof(struct sockaddr); i++) { 596 /* careful -- not every libc's sprintf returns # bytes written */ 597 sprintf(pos, "%02X-", (*ptr++ & 0377)); 598 pos += 3; 599 } 600 /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */ 601 *--pos = '\0'; 602 return (buff); 603} 604 605/* Display an UNSPEC socket address. */ 606static char *UNSPEC_sprint(struct sockaddr *sap, int numeric) 607{ 608 static char buf[64]; 609 610 if (sap->sa_family == 0xFFFF || sap->sa_family == 0) 611 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf)); 612 return (UNSPEC_print(sap->sa_data)); 613} 614 615static struct aftype unspec_aftype = 616{ 617 "unspec", "UNSPEC", AF_UNSPEC, 0, 618 UNSPEC_print, UNSPEC_sprint, NULL, NULL, 619 NULL, 620}; 621 622static struct aftype *aftypes[] = 623{ 624#if HAVE_AFUNIX 625 &unix_aftype, 626#endif 627#if HAVE_AFINET 628 &inet_aftype, 629#endif 630#if HAVE_AFINET6 631 &inet6_aftype, 632#endif 633#if HAVE_AFAX25 634 &ax25_aftype, 635#endif 636#if HAVE_AFNETROM 637 &netrom_aftype, 638#endif 639#if HAVE_AFROSE 640 &rose_aftype, 641#endif 642#if HAVE_AFIPX 643 &ipx_aftype, 644#endif 645#if HAVE_AFATALK 646 &ddp_aftype, 647#endif 648#if HAVE_AFECONET 649 &ec_aftype, 650#endif 651#if HAVE_AFASH 652 &ash_aftype, 653#endif 654#if HAVE_AFX25 655 &x25_aftype, 656#endif 657 &unspec_aftype, 658 NULL 659}; 660 661#ifdef KEEP_UNUSED 662static short sVafinit = 0; 663 664static void afinit() 665{ 666 unspec_aftype.title = _("UNSPEC"); 667#if HAVE_AFUNIX 668 unix_aftype.title = _("UNIX Domain"); 669#endif 670#if HAVE_AFINET 671 inet_aftype.title = _("DARPA Internet"); 672#endif 673#if HAVE_AFINET6 674 inet6_aftype.title = _("IPv6"); 675#endif 676#if HAVE_AFAX25 677 ax25_aftype.title = _("AMPR AX.25"); 678#endif 679#if HAVE_AFNETROM 680 netrom_aftype.title = _("AMPR NET/ROM"); 681#endif 682#if HAVE_AFIPX 683 ipx_aftype.title = _("Novell IPX"); 684#endif 685#if HAVE_AFATALK 686 ddp_aftype.title = _("Appletalk DDP"); 687#endif 688#if HAVE_AFECONET 689 ec_aftype.title = _("Econet"); 690#endif 691#if HAVE_AFX25 692 x25_aftype.title = _("CCITT X.25"); 693#endif 694#if HAVE_AFROSE 695 rose_aftype.title = _("AMPR ROSE"); 696#endif 697#if HAVE_AFASH 698 ash_aftype.title = _("Ash"); 699#endif 700 sVafinit = 1; 701} 702 703static int aftrans_opt(const char *arg) 704{ 705 struct aftrans_t *paft; 706 char *tmp1, *tmp2; 707 char buf[256]; 708 709 safe_strncpy(buf, arg, sizeof(buf)); 710 711 tmp1 = buf; 712 713 while (tmp1) { 714 715 tmp2 = strchr(tmp1, ','); 716 717 if (tmp2) 718 *(tmp2++) = '\0'; 719 720 paft = aftrans; 721 for (paft = aftrans; paft->alias; paft++) { 722 if (strcmp(tmp1, paft->alias)) 723 continue; 724 if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) { 725 fprintf(stderr, _("Too much address family arguments.\n")); 726 return (0); 727 } 728 if (paft->flag) 729 (*paft->flag)++; 730 if (afname[0]) 731 strcat(afname, ","); 732 strcat(afname, paft->name); 733 break; 734 } 735 if (!paft->alias) { 736 fprintf(stderr, _("Unknown address family `%s'.\n"), tmp1); 737 return (1); 738 } 739 tmp1 = tmp2; 740 } 741 742 return (0); 743} 744 745/* set the default AF list from the program name or a constant value */ 746static void aftrans_def(char *tool, char *argv0, char *dflt) 747{ 748 char *tmp; 749 char *buf; 750 751 strcpy(afname, dflt); 752 753 if (!(tmp = strrchr(argv0, '/'))) 754 tmp = argv0; /* no slash?! */ 755 else 756 tmp++; 757 758 if (!(buf = strdup(tmp))) 759 return; 760 761 if (strlen(tool) >= strlen(tmp)) { 762 free(buf); 763 return; 764 } 765 tmp = buf + (strlen(tmp) - strlen(tool)); 766 767 if (strcmp(tmp, tool) != 0) { 768 free(buf); 769 return; 770 } 771 *tmp = '\0'; 772 if ((tmp = strchr(buf, '_'))) 773 *tmp = '\0'; 774 775 afname[0] = '\0'; 776 if (aftrans_opt(buf)) 777 strcpy(afname, buf); 778 779 free(buf); 780} 781 782/* Check our protocol family table for this family. */ 783static struct aftype *get_aftype(const char *name) 784{ 785 struct aftype **afp; 786 787#ifdef KEEP_UNUSED 788 if (!sVafinit) 789 afinit(); 790#endif /* KEEP_UNUSED */ 791 792 afp = aftypes; 793 while (*afp != NULL) { 794 if (!strcmp((*afp)->name, name)) 795 return (*afp); 796 afp++; 797 } 798 if (strchr(name, ',')) 799 fprintf(stderr, _("Please don't supply more than one address family.\n")); 800 return (NULL); 801} 802#endif /* KEEP_UNUSED */ 803 804/* Check our protocol family table for this family. */ 805static struct aftype *get_afntype(int af) 806{ 807 struct aftype **afp; 808 809#ifdef KEEP_UNUSED 810 if (!sVafinit) 811 afinit(); 812#endif /* KEEP_UNUSED */ 813 814 afp = aftypes; 815 while (*afp != NULL) { 816 if ((*afp)->af == af) 817 return (*afp); 818 afp++; 819 } 820 return (NULL); 821} 822 823/* Check our protocol family table for this family and return its socket */ 824static int get_socket_for_af(int af) 825{ 826 struct aftype **afp; 827 828#ifdef KEEP_UNUSED 829 if (!sVafinit) 830 afinit(); 831#endif /* KEEP_UNUSED */ 832 833 afp = aftypes; 834 while (*afp != NULL) { 835 if ((*afp)->af == af) 836 return (*afp)->fd; 837 afp++; 838 } 839 return -1; 840} 841 842#ifdef KEEP_UNUSED 843/* type: 0=all, 1=getroute */ 844static void print_aflist(int type) { 845 int count = 0; 846 char * txt; 847 struct aftype **afp; 848 849#ifdef KEEP_UNUSED 850 if (!sVafinit) 851 afinit(); 852#endif /* KEEP_UNUSED */ 853 854 afp = aftypes; 855 while (*afp != NULL) { 856 if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) { 857 afp++; continue; 858 } 859 if ((count % 3) == 0) fprintf(stderr,count?"\n ":" "); 860 txt = (*afp)->name; if (!txt) txt = ".."; 861 fprintf(stderr,"%s (%s) ",txt,_((*afp)->title)); 862 count++; 863 afp++; 864 } 865 fprintf(stderr,"\n"); 866} 867#endif /* KEEP_UNUSED */ 868 869struct user_net_device_stats { 870 unsigned long long rx_packets; /* total packets received */ 871 unsigned long long tx_packets; /* total packets transmitted */ 872 unsigned long long rx_bytes; /* total bytes received */ 873 unsigned long long tx_bytes; /* total bytes transmitted */ 874 unsigned long rx_errors; /* bad packets received */ 875 unsigned long tx_errors; /* packet transmit problems */ 876 unsigned long rx_dropped; /* no space in linux buffers */ 877 unsigned long tx_dropped; /* no space available in linux */ 878 unsigned long rx_multicast; /* multicast packets received */ 879 unsigned long rx_compressed; 880 unsigned long tx_compressed; 881 unsigned long collisions; 882 883 /* detailed rx_errors: */ 884 unsigned long rx_length_errors; 885 unsigned long rx_over_errors; /* receiver ring buff overflow */ 886 unsigned long rx_crc_errors; /* recved pkt with crc error */ 887 unsigned long rx_frame_errors; /* recv'd frame alignment error */ 888 unsigned long rx_fifo_errors; /* recv'r fifo overrun */ 889 unsigned long rx_missed_errors; /* receiver missed packet */ 890 /* detailed tx_errors */ 891 unsigned long tx_aborted_errors; 892 unsigned long tx_carrier_errors; 893 unsigned long tx_fifo_errors; 894 unsigned long tx_heartbeat_errors; 895 unsigned long tx_window_errors; 896}; 897 898struct interface { 899 struct interface *next, *prev; 900 char name[IFNAMSIZ]; /* interface name */ 901 short type; /* if type */ 902 short flags; /* various flags */ 903 int metric; /* routing metric */ 904 int mtu; /* MTU value */ 905 int tx_queue_len; /* transmit queue length */ 906 struct ifmap map; /* hardware setup */ 907 struct sockaddr addr; /* IP address */ 908 struct sockaddr dstaddr; /* P-P IP address */ 909 struct sockaddr broadaddr; /* IP broadcast address */ 910 struct sockaddr netmask; /* IP network mask */ 911 struct sockaddr ipxaddr_bb; /* IPX network address */ 912 struct sockaddr ipxaddr_sn; /* IPX network address */ 913 struct sockaddr ipxaddr_e3; /* IPX network address */ 914 struct sockaddr ipxaddr_e2; /* IPX network address */ 915 struct sockaddr ddpaddr; /* Appletalk DDP address */ 916 struct sockaddr ecaddr; /* Econet address */ 917 int has_ip; 918 int has_ipx_bb; 919 int has_ipx_sn; 920 int has_ipx_e3; 921 int has_ipx_e2; 922 int has_ax25; 923 int has_ddp; 924 int has_econet; 925 char hwaddr[32]; /* HW address */ 926 int statistics_valid; 927 struct user_net_device_stats stats; /* statistics */ 928 int keepalive; /* keepalive value for SLIP */ 929 int outfill; /* outfill value for SLIP */ 930}; 931 932 933int interface_opt_a = 0; /* show all interfaces */ 934 935#ifdef KEEP_UNUSED 936static int opt_i = 0; /* show the statistics */ 937static int opt_v = 0; /* debugging output flag */ 938 939static int addr_family = 0; /* currently selected AF */ 940#endif /* KEEP_UNUSED */ 941 942static struct interface *int_list, *int_last; 943static int skfd = -1; /* generic raw socket desc. */ 944 945 946static int sockets_open(int family) 947{ 948 struct aftype **aft; 949 int sfd = -1; 950 static int force = -1; 951 952 if (force < 0) { 953 force = 0; 954 if (get_kernel_revision() < KRELEASE(2, 1, 0)) 955 force = 1; 956 if (access("/proc/net", R_OK)) 957 force = 1; 958 } 959 for (aft = aftypes; *aft; aft++) { 960 struct aftype *af = *aft; 961 int type = SOCK_DGRAM; 962 if (af->af == AF_UNSPEC) 963 continue; 964 if (family && family != af->af) 965 continue; 966 if (af->fd != -1) { 967 sfd = af->fd; 968 continue; 969 } 970 /* Check some /proc file first to not stress kmod */ 971 if (!family && !force && af->flag_file) { 972 if (access(af->flag_file, R_OK)) 973 continue; 974 } 975#if HAVE_AFNETROM 976 if (af->af == AF_NETROM) 977 type = SOCK_SEQPACKET; 978#endif 979#if HAVE_AFX25 980 if (af->af == AF_X25) 981 type = SOCK_SEQPACKET; 982#endif 983 af->fd = socket(af->af, type, 0); 984 if (af->fd >= 0) 985 sfd = af->fd; 986 } 987 if (sfd < 0) 988 fprintf(stderr, _("No usable address families found.\n")); 989 return sfd; 990} 991 992/* like strcmp(), but knows about numbers */ 993static int nstrcmp(const char *astr, const char *b) 994{ 995 const char *a = astr; 996 997 while (*a == *b) { 998 if (*a == '\0') 999 return 0; 1000 a++; 1001 b++; 1002 } 1003 if (isdigit(*a)) { 1004 if (!isdigit(*b)) 1005 return -1; 1006 while (a > astr) { 1007 a--; 1008 if (!isdigit(*a)) { 1009 a++; 1010 break; 1011 } 1012 if (!isdigit(*b)) 1013 return -1; 1014 b--; 1015 } 1016 return atoi(a) > atoi(b) ? 1 : -1; 1017 } 1018 return *a - *b; 1019} 1020 1021static struct interface *add_interface(char *name) 1022{ 1023 struct interface *ife, **nextp, *new; 1024 1025 for (ife = int_last; ife; ife = ife->prev) { 1026 int n = nstrcmp(ife->name, name); 1027 if (n == 0) 1028 return ife; 1029 if (n < 0) 1030 break; 1031 } 1032 new(new); 1033 safe_strncpy(new->name, name, IFNAMSIZ); 1034 nextp = ife ? &ife->next : &int_list; 1035 new->prev = ife; 1036 new->next = *nextp; 1037 if (new->next) 1038 new->next->prev = new; 1039 else 1040 int_last = new; 1041 *nextp = new; 1042 return new; 1043} 1044 1045 1046static int if_readconf(void) 1047{ 1048 int numreqs = 30; 1049 struct ifconf ifc; 1050 struct ifreq *ifr; 1051 int n, err = -1; 1052 int skfd2; 1053 1054 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets 1055 (as of 2.1.128) */ 1056 skfd2 = get_socket_for_af(AF_INET); 1057 if (skfd2 < 0) { 1058 fprintf(stderr, _("warning: no inet socket available: %s\n"), 1059 strerror(errno)); 1060 /* Try to soldier on with whatever socket we can get hold of. */ 1061 skfd2 = sockets_open(0); 1062 if (skfd2 < 0) 1063 return -1; 1064 } 1065 1066 ifc.ifc_buf = NULL; 1067 for (;;) { 1068 ifc.ifc_len = sizeof(struct ifreq) * numreqs; 1069 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); 1070 1071 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) { 1072 perror("SIOCGIFCONF"); 1073 goto out; 1074 } 1075 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) { 1076 /* assume it overflowed and try again */ 1077 numreqs += 10; 1078 continue; 1079 } 1080 break; 1081 } 1082 1083 ifr = ifc.ifc_req; 1084 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { 1085 add_interface(ifr->ifr_name); 1086 ifr++; 1087 } 1088 err = 0; 1089 1090out: 1091 free(ifc.ifc_buf); 1092 return err; 1093} 1094 1095static char *get_name(char *name, char *p) 1096{ 1097 while (isspace(*p)) 1098 p++; 1099 while (*p) { 1100 if (isspace(*p)) 1101 break; 1102 if (*p == ':') { /* could be an alias */ 1103 char *dot = p, *dotname = name; 1104 *name++ = *p++; 1105 while (isdigit(*p)) 1106 *name++ = *p++; 1107 if (*p != ':') { /* it wasn't, backup */ 1108 p = dot; 1109 name = dotname; 1110 } 1111 if (*p == '\0') 1112 return NULL; 1113 p++; 1114 break; 1115 } 1116 *name++ = *p++; 1117 } 1118 *name++ = '\0'; 1119 return p; 1120} 1121 1122static int get_dev_fields(char *bp, struct interface *ife) 1123{ 1124 switch (procnetdev_vsn) { 1125 case 3: 1126 sscanf(bp, 1127 "%Lu %Lu %lu %lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu %lu", 1128 &ife->stats.rx_bytes, 1129 &ife->stats.rx_packets, 1130 &ife->stats.rx_errors, 1131 &ife->stats.rx_dropped, 1132 &ife->stats.rx_fifo_errors, 1133 &ife->stats.rx_frame_errors, 1134 &ife->stats.rx_compressed, 1135 &ife->stats.rx_multicast, 1136 1137 &ife->stats.tx_bytes, 1138 &ife->stats.tx_packets, 1139 &ife->stats.tx_errors, 1140 &ife->stats.tx_dropped, 1141 &ife->stats.tx_fifo_errors, 1142 &ife->stats.collisions, 1143 &ife->stats.tx_carrier_errors, 1144 &ife->stats.tx_compressed); 1145 break; 1146 case 2: 1147 sscanf(bp, "%Lu %Lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu", 1148 &ife->stats.rx_bytes, 1149 &ife->stats.rx_packets, 1150 &ife->stats.rx_errors, 1151 &ife->stats.rx_dropped, 1152 &ife->stats.rx_fifo_errors, 1153 &ife->stats.rx_frame_errors, 1154 1155 &ife->stats.tx_bytes, 1156 &ife->stats.tx_packets, 1157 &ife->stats.tx_errors, 1158 &ife->stats.tx_dropped, 1159 &ife->stats.tx_fifo_errors, 1160 &ife->stats.collisions, 1161 &ife->stats.tx_carrier_errors); 1162 ife->stats.rx_multicast = 0; 1163 break; 1164 case 1: 1165 sscanf(bp, "%Lu %lu %lu %lu %lu %Lu %lu %lu %lu %lu %lu", 1166 &ife->stats.rx_packets, 1167 &ife->stats.rx_errors, 1168 &ife->stats.rx_dropped, 1169 &ife->stats.rx_fifo_errors, 1170 &ife->stats.rx_frame_errors, 1171 1172 &ife->stats.tx_packets, 1173 &ife->stats.tx_errors, 1174 &ife->stats.tx_dropped, 1175 &ife->stats.tx_fifo_errors, 1176 &ife->stats.collisions, 1177 &ife->stats.tx_carrier_errors); 1178 ife->stats.rx_bytes = 0; 1179 ife->stats.tx_bytes = 0; 1180 ife->stats.rx_multicast = 0; 1181 break; 1182 } 1183 return 0; 1184} 1185 1186static inline int procnetdev_version(char *buf) 1187{ 1188 if (strstr(buf, "compressed")) 1189 return 3; 1190 if (strstr(buf, "bytes")) 1191 return 2; 1192 return 1; 1193} 1194 1195static int if_readlist_proc(char *target) 1196{ 1197 static int proc_read; 1198 FILE *fh; 1199 char buf[512]; 1200 struct interface *ife; 1201 int err; 1202 1203 if (proc_read) 1204 return 0; 1205 if (!target) 1206 proc_read = 1; 1207 1208 fh = fopen(_PATH_PROCNET_DEV, "r"); 1209 if (!fh) { 1210 fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"), 1211 _PATH_PROCNET_DEV, strerror(errno)); 1212 return if_readconf(); 1213 } 1214 fgets(buf, sizeof buf, fh); /* eat line */ 1215 fgets(buf, sizeof buf, fh); 1216 1217 procnetdev_vsn = procnetdev_version(buf); 1218 1219 err = 0; 1220 while (fgets(buf, sizeof buf, fh)) { 1221 char *s, name[IFNAMSIZ]; 1222 s = get_name(name, buf); 1223 ife = add_interface(name); 1224 get_dev_fields(s, ife); 1225 ife->statistics_valid = 1; 1226 if (target && !strcmp(target,name)) 1227 break; 1228 } 1229 if (ferror(fh)) { 1230 perror(_PATH_PROCNET_DEV); 1231 err = -1; 1232 proc_read = 0; 1233 } 1234 1235 fclose(fh); 1236 return err; 1237} 1238 1239static int if_readlist(void) 1240{ 1241 int err = if_readlist_proc(NULL); 1242 if (!err) 1243 err = if_readconf(); 1244 return err; 1245} 1246 1247static int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie) 1248{ 1249 struct interface *ife; 1250 1251 if (!int_list && (if_readlist() < 0)) 1252 return -1; 1253 for (ife = int_list; ife; ife = ife->next) { 1254 int err = doit(ife, cookie); 1255 if (err) 1256 return err; 1257 } 1258 return 0; 1259} 1260 1261/* Support for fetching an IPX address */ 1262 1263#if HAVE_AFIPX 1264static int ipx_getaddr(int sock, int ft, struct ifreq *ifr) 1265{ 1266 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft; 1267 return ioctl(sock, SIOCGIFADDR, ifr); 1268} 1269#endif 1270 1271 1272/* Fetch the interface configuration from the kernel. */ 1273static int if_fetch(struct interface *ife) 1274{ 1275 struct ifreq ifr; 1276 int fd; 1277 char *ifname = ife->name; 1278 1279 strcpy(ifr.ifr_name, ifname); 1280 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) 1281 return (-1); 1282 ife->flags = ifr.ifr_flags; 1283 1284 strcpy(ifr.ifr_name, ifname); 1285 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) 1286 memset(ife->hwaddr, 0, 32); 1287 else 1288 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); 1289 1290 ife->type = ifr.ifr_hwaddr.sa_family; 1291 1292 strcpy(ifr.ifr_name, ifname); 1293 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) 1294 ife->metric = 0; 1295 else 1296 ife->metric = ifr.ifr_metric; 1297 1298 strcpy(ifr.ifr_name, ifname); 1299 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0) 1300 ife->mtu = 0; 1301 else 1302 ife->mtu = ifr.ifr_mtu; 1303 1304#ifdef HAVE_HWSLIP 1305 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP || 1306 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 || 1307 ife->type == ARPHRD_ADAPT) { 1308#ifdef SIOCGOUTFILL 1309 strcpy(ifr.ifr_name, ifname); 1310 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0) 1311 ife->outfill = 0; 1312 else 1313 ife->outfill = (unsigned int) ifr.ifr_data; 1314#endif 1315#ifdef SIOCGKEEPALIVE 1316 strcpy(ifr.ifr_name, ifname); 1317 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0) 1318 ife->keepalive = 0; 1319 else 1320 ife->keepalive = (unsigned int) ifr.ifr_data; 1321#endif 1322 } 1323#endif 1324 1325 strcpy(ifr.ifr_name, ifname); 1326 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) 1327 memset(&ife->map, 0, sizeof(struct ifmap)); 1328 else 1329 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap)); 1330 1331 strcpy(ifr.ifr_name, ifname); 1332 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) 1333 memset(&ife->map, 0, sizeof(struct ifmap)); 1334 else 1335 ife->map = ifr.ifr_map; 1336 1337#ifdef HAVE_TXQUEUELEN 1338 strcpy(ifr.ifr_name, ifname); 1339 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0) 1340 ife->tx_queue_len = -1; /* unknown value */ 1341 else 1342 ife->tx_queue_len = ifr.ifr_qlen; 1343#else 1344 ife->tx_queue_len = -1; /* unknown value */ 1345#endif 1346 1347#if HAVE_AFINET 1348 /* IPv4 address? */ 1349 fd = get_socket_for_af(AF_INET); 1350 if (fd >= 0) { 1351 strcpy(ifr.ifr_name, ifname); 1352 ifr.ifr_addr.sa_family = AF_INET; 1353 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { 1354 ife->has_ip = 1; 1355 ife->addr = ifr.ifr_addr; 1356 strcpy(ifr.ifr_name, ifname); 1357 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0) 1358 memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); 1359 else 1360 ife->dstaddr = ifr.ifr_dstaddr; 1361 1362 strcpy(ifr.ifr_name, ifname); 1363 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0) 1364 memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); 1365 else 1366 ife->broadaddr = ifr.ifr_broadaddr; 1367 1368 strcpy(ifr.ifr_name, ifname); 1369 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) 1370 memset(&ife->netmask, 0, sizeof(struct sockaddr)); 1371 else 1372 ife->netmask = ifr.ifr_netmask; 1373 } else 1374 memset(&ife->addr, 0, sizeof(struct sockaddr)); 1375 } 1376#endif 1377 1378#if HAVE_AFATALK 1379 /* DDP address maybe ? */ 1380 fd = get_socket_for_af(AF_APPLETALK); 1381 if (fd >= 0) { 1382 strcpy(ifr.ifr_name, ifname); 1383 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { 1384 ife->ddpaddr = ifr.ifr_addr; 1385 ife->has_ddp = 1; 1386 } 1387 } 1388#endif 1389 1390#if HAVE_AFIPX 1391 /* Look for IPX addresses with all framing types */ 1392 fd = get_socket_for_af(AF_IPX); 1393 if (fd >= 0) { 1394 strcpy(ifr.ifr_name, ifname); 1395 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) { 1396 ife->has_ipx_bb = 1; 1397 ife->ipxaddr_bb = ifr.ifr_addr; 1398 } 1399 strcpy(ifr.ifr_name, ifname); 1400 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) { 1401 ife->has_ipx_sn = 1; 1402 ife->ipxaddr_sn = ifr.ifr_addr; 1403 } 1404 strcpy(ifr.ifr_name, ifname); 1405 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) { 1406 ife->has_ipx_e3 = 1; 1407 ife->ipxaddr_e3 = ifr.ifr_addr; 1408 } 1409 strcpy(ifr.ifr_name, ifname); 1410 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) { 1411 ife->has_ipx_e2 = 1; 1412 ife->ipxaddr_e2 = ifr.ifr_addr; 1413 } 1414 } 1415#endif 1416 1417#if HAVE_AFECONET 1418 /* Econet address maybe? */ 1419 fd = get_socket_for_af(AF_ECONET); 1420 if (fd >= 0) { 1421 strcpy(ifr.ifr_name, ifname); 1422 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { 1423 ife->ecaddr = ifr.ifr_addr; 1424 ife->has_econet = 1; 1425 } 1426 } 1427#endif 1428 1429 return 0; 1430} 1431 1432 1433static int do_if_fetch(struct interface *ife) 1434{ 1435 if (if_fetch(ife) < 0) { 1436 char *errmsg; 1437 if (errno == ENODEV) { 1438 /* Give better error message for this case. */ 1439 errmsg = _("Device not found"); 1440 } else { 1441 errmsg = strerror(errno); 1442 } 1443 fprintf(stderr, _("%s: error fetching interface information: %s\n"), 1444 ife->name, errmsg); 1445 return -1; 1446 } 1447 return 0; 1448} 1449 1450/* This structure defines hardware protocols and their handlers. */ 1451struct hwtype { 1452 const char *name; 1453 const char *title; 1454 int type; 1455 int alen; 1456 char *(*print) (unsigned char *); 1457 int (*input) (char *, struct sockaddr *); 1458 int (*activate) (int fd); 1459 int suppress_null_addr; 1460}; 1461 1462static struct hwtype unspec_hwtype = 1463{ 1464 "unspec", "UNSPEC", -1, 0, 1465 UNSPEC_print, NULL, NULL 1466}; 1467 1468static struct hwtype loop_hwtype = 1469{ 1470 "loop", "Local Loopback", ARPHRD_LOOPBACK, 0, 1471 NULL, NULL, NULL 1472}; 1473 1474#if HAVE_HWETHER 1475#include <net/if_arp.h> 1476#include <linux/if_ether.h> 1477 1478static struct hwtype ether_hwtype; 1479 1480/* Display an Ethernet address in readable format. */ 1481static char *pr_ether(unsigned char *ptr) 1482{ 1483 static char buff[64]; 1484 1485 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X", 1486 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377), 1487 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377) 1488 ); 1489 return (buff); 1490} 1491 1492#ifdef KEEP_UNUSED 1493/* Input an Ethernet address and convert to binary. */ 1494static int in_ether(char *bufp, struct sockaddr *sap) 1495{ 1496 unsigned char *ptr; 1497 char c, *orig; 1498 int i; 1499 unsigned val; 1500 1501 sap->sa_family = ether_hwtype.type; 1502 ptr = sap->sa_data; 1503 1504 i = 0; 1505 orig = bufp; 1506 while ((*bufp != '\0') && (i < ETH_ALEN)) { 1507 val = 0; 1508 c = *bufp++; 1509 if (isdigit(c)) 1510 val = c - '0'; 1511 else if (c >= 'a' && c <= 'f') 1512 val = c - 'a' + 10; 1513 else if (c >= 'A' && c <= 'F') 1514 val = c - 'A' + 10; 1515 else { 1516#ifdef DEBUG 1517 fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig); 1518#endif 1519 errno = EINVAL; 1520 return (-1); 1521 } 1522 val <<= 4; 1523 c = *bufp; 1524 if (isdigit(c)) 1525 val |= c - '0'; 1526 else if (c >= 'a' && c <= 'f') 1527 val |= c - 'a' + 10; 1528 else if (c >= 'A' && c <= 'F') 1529 val |= c - 'A' + 10; 1530 else if (c == ':' || c == 0) 1531 val >>= 4; 1532 else { 1533#ifdef DEBUG 1534 fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig); 1535#endif 1536 errno = EINVAL; 1537 return (-1); 1538 } 1539 if (c != 0) 1540 bufp++; 1541 *ptr++ = (unsigned char) (val & 0377); 1542 i++; 1543 1544 /* We might get a semicolon here - not required. */ 1545 if (*bufp == ':') { 1546 if (i == ETH_ALEN) { 1547#ifdef DEBUG 1548 fprintf(stderr, _("in_ether(%s): trailing : ignored!\n"), 1549 orig) 1550#endif 1551 ; /* nothing */ 1552 } 1553 bufp++; 1554 } 1555 } 1556 1557 /* That's it. Any trailing junk? */ 1558 if ((i == ETH_ALEN) && (*bufp != '\0')) { 1559#ifdef DEBUG 1560 fprintf(stderr, _("in_ether(%s): trailing junk!\n"), orig); 1561 errno = EINVAL; 1562 return (-1); 1563#endif 1564 } 1565#ifdef DEBUG 1566 fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data)); 1567#endif 1568 1569 return (0); 1570} 1571#endif /* KEEP_UNUSED */ 1572 1573 1574static struct hwtype ether_hwtype = 1575{ 1576 "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN, 1577 pr_ether, NULL /* UNUSED in_ether */, NULL 1578}; 1579 1580 1581#endif /* HAVE_HWETHER */ 1582 1583 1584#if HAVE_HWPPP 1585 1586#include <net/if_arp.h> 1587 1588#ifdef KEEP_UNUSED 1589/* Start the PPP encapsulation on the file descriptor. */ 1590static int do_ppp(int fd) 1591{ 1592 fprintf(stderr, _("You cannot start PPP with this program.\n")); 1593 return -1; 1594} 1595#endif /* KEEP_UNUSED */ 1596 1597static struct hwtype ppp_hwtype = 1598{ 1599 "ppp", "Point-Point Protocol", ARPHRD_PPP, 0, 1600 NULL, NULL, NULL /* UNUSED do_ppp */, 0 1601}; 1602 1603 1604#endif /* HAVE_PPP */ 1605 1606static struct hwtype *hwtypes[] = 1607{ 1608 1609 &loop_hwtype, 1610 1611#if HAVE_HWSLIP 1612 &slip_hwtype, 1613 &cslip_hwtype, 1614 &slip6_hwtype, 1615 &cslip6_hwtype, 1616 &adaptive_hwtype, 1617#endif 1618#if HAVE_HWSTRIP 1619 &strip_hwtype, 1620#endif 1621#if HAVE_HWASH 1622 &ash_hwtype, 1623#endif 1624#if HAVE_HWETHER 1625 ðer_hwtype, 1626#endif 1627#if HAVE_HWTR 1628 &tr_hwtype, 1629#ifdef ARPHRD_IEEE802_TR 1630 &tr_hwtype1, 1631#endif 1632#endif 1633#if HAVE_HWAX25 1634 &ax25_hwtype, 1635#endif 1636#if HAVE_HWNETROM 1637 &netrom_hwtype, 1638#endif 1639#if HAVE_HWROSE 1640 &rose_hwtype, 1641#endif 1642#if HAVE_HWTUNNEL 1643 &tunnel_hwtype, 1644#endif 1645#if HAVE_HWPPP 1646 &ppp_hwtype, 1647#endif 1648#if HAVE_HWHDLCLAPB 1649 &hdlc_hwtype, 1650 &lapb_hwtype, 1651#endif 1652#if HAVE_HWARC 1653 &arcnet_hwtype, 1654#endif 1655#if HAVE_HWFR 1656 &dlci_hwtype, 1657 &frad_hwtype, 1658#endif 1659#if HAVE_HWSIT 1660 &sit_hwtype, 1661#endif 1662#if HAVE_HWFDDI 1663 &fddi_hwtype, 1664#endif 1665#if HAVE_HWHIPPI 1666 &hippi_hwtype, 1667#endif 1668#if HAVE_HWIRDA 1669 &irda_hwtype, 1670#endif 1671#if HAVE_HWEC 1672 &ec_hwtype, 1673#endif 1674#if HAVE_HWX25 1675 &x25_hwtype, 1676#endif 1677 &unspec_hwtype, 1678 NULL 1679}; 1680 1681#ifdef KEEP_UNUSED 1682static short sVhwinit = 0; 1683 1684static void hwinit() 1685{ 1686 loop_hwtype.title = _("Local Loopback"); 1687 unspec_hwtype.title = _("UNSPEC"); 1688#if HAVE_HWSLIP 1689 slip_hwtype.title = _("Serial Line IP"); 1690 cslip_hwtype.title = _("VJ Serial Line IP"); 1691 slip6_hwtype.title = _("6-bit Serial Line IP"); 1692 cslip6_hwtype.title = _("VJ 6-bit Serial Line IP"); 1693 adaptive_hwtype.title = _("Adaptive Serial Line IP"); 1694#endif 1695#if HAVE_HWETHER 1696 ether_hwtype.title = _("Ethernet"); 1697#endif 1698#if HAVE_HWASH 1699 ash_hwtype.title = _("Ash"); 1700#endif 1701#if HAVE_HWFDDI 1702 fddi_hwtype.title = _("Fiber Distributed Data Interface"); 1703#endif 1704#if HAVE_HWHIPPI 1705 hippi_hwtype.title = _("HIPPI"); 1706#endif 1707#if HAVE_HWAX25 1708 ax25_hwtype.title = _("AMPR AX.25"); 1709#endif 1710#if HAVE_HWROSE 1711 rose_hwtype.title = _("AMPR ROSE"); 1712#endif 1713#if HAVE_HWNETROM 1714 netrom_hwtype.title = _("AMPR NET/ROM"); 1715#endif 1716#if HAVE_HWX25 1717 x25_hwtype.title = _("generic X.25"); 1718#endif 1719#if HAVE_HWTUNNEL 1720 tunnel_hwtype.title = _("IPIP Tunnel"); 1721#endif 1722#if HAVE_HWPPP 1723 ppp_hwtype.title = _("Point-to-Point Protocol"); 1724#endif 1725#if HAVE_HWHDLCLAPB 1726 hdlc_hwtype.title = _("(Cisco)-HDLC"); 1727 lapb_hwtype.title = _("LAPB"); 1728#endif 1729#if HAVE_HWARC 1730 arcnet_hwtype.title = _("ARCnet"); 1731#endif 1732#if HAVE_HWFR 1733 dlci_hwtype.title = _("Frame Relay DLCI"); 1734 frad_hwtype.title = _("Frame Relay Access Device"); 1735#endif 1736#if HAVE_HWSIT 1737 sit_hwtype.title = _("IPv6-in-IPv4"); 1738#endif 1739#if HAVE_HWIRDA 1740 irda_hwtype.title = _("IrLAP"); 1741#endif 1742#if HAVE_HWTR 1743 tr_hwtype.title = _("16/4 Mbps Token Ring"); 1744#ifdef ARPHRD_IEEE802_TR 1745 tr_hwtype1.title = _("16/4 Mbps Token Ring (New)") ; 1746#endif 1747#endif 1748#if HAVE_HWEC 1749 ec_hwtype.title = _("Econet"); 1750#endif 1751 sVhwinit = 1; 1752} 1753#endif /* KEEP_UNUSED */ 1754 1755#ifdef IFF_PORTSEL 1756static const char *if_port_text[][4] = 1757{ 1758 /* Keep in step with <linux/netdevice.h> */ 1759 {"unknown", NULL, NULL, NULL}, 1760 {"10base2", "bnc", "coax", NULL}, 1761 {"10baseT", "utp", "tpe", NULL}, 1762 {"AUI", "thick", "db15", NULL}, 1763 {"100baseT", NULL, NULL, NULL}, 1764 {"100baseTX", NULL, NULL, NULL}, 1765 {"100baseFX", NULL, NULL, NULL}, 1766 {NULL, NULL, NULL, NULL}, 1767}; 1768#endif 1769 1770/* Check our hardware type table for this type. */ 1771static struct hwtype *get_hwntype(int type) 1772{ 1773 struct hwtype **hwp; 1774 1775#ifdef KEEP_UNUSED 1776 if (!sVhwinit) 1777 hwinit(); 1778#endif /* KEEP_UNUSED */ 1779 1780 hwp = hwtypes; 1781 while (*hwp != NULL) { 1782 if ((*hwp)->type == type) 1783 return (*hwp); 1784 hwp++; 1785 } 1786 return (NULL); 1787} 1788 1789/* return 1 if address is all zeros */ 1790static int hw_null_address(struct hwtype *hw, void *ap) 1791{ 1792 unsigned int i; 1793 unsigned char *address = (unsigned char *)ap; 1794 for (i = 0; i < hw->alen; i++) 1795 if (address[i]) 1796 return 0; 1797 return 1; 1798} 1799 1800static const char TRext[] = "\0\0k\0M"; 1801 1802static void print_bytes_scaled(unsigned long long ull, const char *end) 1803{ 1804 unsigned long long int_part; 1805 unsigned long frac_part; 1806 const char *ext; 1807 int i; 1808 1809 frac_part = 0; 1810 ext = TRext; 1811 int_part = ull; 1812 for (i=0 ; i<2 ; i++) { 1813 if (int_part >= 1024) { 1814 frac_part = ((int_part % 1024) * 10) / 1024; 1815 int_part /= 1024; 1816 ext += 2; /* Kb, Mb */ 1817 } 1818 } 1819 1820 printf("X bytes:%Lu (%Lu.%lu %sb)%s", ull, int_part, frac_part, ext, end); 1821} 1822 1823static void ife_print(struct interface *ptr) 1824{ 1825 struct aftype *ap; 1826 struct hwtype *hw; 1827 int hf; 1828 int can_compress = 0; 1829 1830#if HAVE_AFIPX 1831 static struct aftype *ipxtype = NULL; 1832#endif 1833#if HAVE_AFECONET 1834 static struct aftype *ectype = NULL; 1835#endif 1836#if HAVE_AFATALK 1837 static struct aftype *ddptype = NULL; 1838#endif 1839#if HAVE_AFINET6 1840 FILE *f; 1841 char addr6[40], devname[20]; 1842 struct sockaddr_in6 sap; 1843 int plen, scope, dad_status, if_idx; 1844 extern struct aftype inet6_aftype; 1845 char addr6p[8][5]; 1846#endif 1847 1848 ap = get_afntype(ptr->addr.sa_family); 1849 if (ap == NULL) 1850 ap = get_afntype(0); 1851 1852 hf = ptr->type; 1853 1854 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6) 1855 can_compress = 1; 1856 1857 hw = get_hwntype(hf); 1858 if (hw == NULL) 1859 hw = get_hwntype(-1); 1860 1861 printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title)); 1862 /* For some hardware types (eg Ash, ATM) we don't print the 1863 hardware address if it's null. */ 1864 if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) && 1865 hw->suppress_null_addr))) 1866 printf(_("HWaddr %s "), hw->print(ptr->hwaddr)); 1867#ifdef IFF_PORTSEL 1868 if (ptr->flags & IFF_PORTSEL) { 1869 printf(_("Media:%s"), if_port_text[ptr->map.port][0]); 1870 if (ptr->flags & IFF_AUTOMEDIA) 1871 printf(_("(auto)")); 1872 } 1873#endif 1874 printf("\n"); 1875 1876#if HAVE_AFINET 1877 if (ptr->has_ip) { 1878 printf(_(" %s addr:%s "), ap->name, 1879 ap->sprint(&ptr->addr, 1)); 1880 if (ptr->flags & IFF_POINTOPOINT) { 1881 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1)); 1882 } 1883 if (ptr->flags & IFF_BROADCAST) { 1884 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1)); 1885 } 1886 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1)); 1887 } 1888#endif 1889 1890#if HAVE_AFINET6 1891 1892 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { 1893 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", 1894 addr6p[0], addr6p[1], addr6p[2], addr6p[3], 1895 addr6p[4], addr6p[5], addr6p[6], addr6p[7], 1896 &if_idx, &plen, &scope, &dad_status, devname) != EOF) { 1897 if (!strcmp(devname, ptr->name)) { 1898 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", 1899 addr6p[0], addr6p[1], addr6p[2], addr6p[3], 1900 addr6p[4], addr6p[5], addr6p[6], addr6p[7]); 1901 inet6_aftype.input(1, addr6, (struct sockaddr *) &sap); 1902 printf(_(" inet6 addr: %s/%d"), 1903 inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen); 1904 printf(_(" Scope:")); 1905 switch (scope) { 1906 case 0: 1907 printf(_("Global")); 1908 break; 1909 case IPV6_ADDR_LINKLOCAL: 1910 printf(_("Link")); 1911 break; 1912 case IPV6_ADDR_SITELOCAL: 1913 printf(_("Site")); 1914 break; 1915 case IPV6_ADDR_COMPATv4: 1916 printf(_("Compat")); 1917 break; 1918 case IPV6_ADDR_LOOPBACK: 1919 printf(_("Host")); 1920 break; 1921 default: 1922 printf(_("Unknown")); 1923 } 1924 printf("\n"); 1925 } 1926 } 1927 fclose(f); 1928 } 1929#endif 1930 1931#if HAVE_AFIPX 1932 if (ipxtype == NULL) 1933 ipxtype = get_afntype(AF_IPX); 1934 1935 if (ipxtype != NULL) { 1936 if (ptr->has_ipx_bb) 1937 printf(_(" IPX/Ethernet II addr:%s\n"), 1938 ipxtype->sprint(&ptr->ipxaddr_bb, 1)); 1939 if (ptr->has_ipx_sn) 1940 printf(_(" IPX/Ethernet SNAP addr:%s\n"), 1941 ipxtype->sprint(&ptr->ipxaddr_sn, 1)); 1942 if (ptr->has_ipx_e2) 1943 printf(_(" IPX/Ethernet 802.2 addr:%s\n"), 1944 ipxtype->sprint(&ptr->ipxaddr_e2, 1)); 1945 if (ptr->has_ipx_e3) 1946 printf(_(" IPX/Ethernet 802.3 addr:%s\n"), 1947 ipxtype->sprint(&ptr->ipxaddr_e3, 1)); 1948 } 1949#endif 1950 1951#if HAVE_AFATALK 1952 if (ddptype == NULL) 1953 ddptype = get_afntype(AF_APPLETALK); 1954 if (ddptype != NULL) { 1955 if (ptr->has_ddp) 1956 printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1)); 1957 } 1958#endif 1959 1960#if HAVE_AFECONET 1961 if (ectype == NULL) 1962 ectype = get_afntype(AF_ECONET); 1963 if (ectype != NULL) { 1964 if (ptr->has_econet) 1965 printf(_(" econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1)); 1966 } 1967#endif 1968 1969 printf(" "); 1970 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */ 1971 if (ptr->flags == 0) 1972 printf(_("[NO FLAGS] ")); 1973 if (ptr->flags & IFF_UP) 1974 printf(_("UP ")); 1975 if (ptr->flags & IFF_BROADCAST) 1976 printf(_("BROADCAST ")); 1977 if (ptr->flags & IFF_DEBUG) 1978 printf(_("DEBUG ")); 1979 if (ptr->flags & IFF_LOOPBACK) 1980 printf(_("LOOPBACK ")); 1981 if (ptr->flags & IFF_POINTOPOINT) 1982 printf(_("POINTOPOINT ")); 1983 if (ptr->flags & IFF_NOTRAILERS) 1984 printf(_("NOTRAILERS ")); 1985 if (ptr->flags & IFF_RUNNING) 1986 printf(_("RUNNING ")); 1987 if (ptr->flags & IFF_NOARP) 1988 printf(_("NOARP ")); 1989 if (ptr->flags & IFF_PROMISC) 1990 printf(_("PROMISC ")); 1991 if (ptr->flags & IFF_ALLMULTI) 1992 printf(_("ALLMULTI ")); 1993 if (ptr->flags & IFF_SLAVE) 1994 printf(_("SLAVE ")); 1995 if (ptr->flags & IFF_MASTER) 1996 printf(_("MASTER ")); 1997 if (ptr->flags & IFF_MULTICAST) 1998 printf(_("MULTICAST ")); 1999#ifdef HAVE_DYNAMIC 2000 if (ptr->flags & IFF_DYNAMIC) 2001 printf(_("DYNAMIC ")); 2002#endif 2003 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ 2004 printf(_(" MTU:%d Metric:%d"), 2005 ptr->mtu, ptr->metric ? ptr->metric : 1); 2006#ifdef SIOCSKEEPALIVE 2007 if (ptr->outfill || ptr->keepalive) 2008 printf(_(" Outfill:%d Keepalive:%d"), 2009 ptr->outfill, ptr->keepalive); 2010#endif 2011 printf("\n"); 2012 2013 /* If needed, display the interface statistics. */ 2014 2015 if (ptr->statistics_valid) { 2016 printf(" "); 2017 2018 printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"), 2019 ptr->stats.rx_packets, ptr->stats.rx_errors, 2020 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors, 2021 ptr->stats.rx_frame_errors); 2022 if (can_compress) 2023 printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed); 2024 printf(" "); 2025 printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"), 2026 ptr->stats.tx_packets, ptr->stats.tx_errors, 2027 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors, 2028 ptr->stats.tx_carrier_errors); 2029 printf(_(" collisions:%lu "), ptr->stats.collisions); 2030 if (can_compress) 2031 printf(_("compressed:%lu "), ptr->stats.tx_compressed); 2032 if (ptr->tx_queue_len != -1) 2033 printf(_("txqueuelen:%d "), ptr->tx_queue_len); 2034 printf("\n R"); 2035 print_bytes_scaled(ptr->stats.rx_bytes, " T"); 2036 print_bytes_scaled(ptr->stats.tx_bytes, "\n"); 2037 2038 } 2039 2040 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma || 2041 ptr->map.base_addr)) { 2042 printf(" "); 2043 if (ptr->map.irq) 2044 printf(_("Interrupt:%d "), ptr->map.irq); 2045 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for 2046 I/O maps */ 2047 printf(_("Base address:0x%x "), ptr->map.base_addr); 2048 if (ptr->map.mem_start) { 2049 printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end); 2050 } 2051 if (ptr->map.dma) 2052 printf(_("DMA chan:%x "), ptr->map.dma); 2053 printf("\n"); 2054 } 2055 printf("\n"); 2056} 2057 2058 2059static int do_if_print(struct interface *ife, void *cookie) 2060{ 2061 int *opt_a = (int *) cookie; 2062 int res; 2063 2064 res = do_if_fetch(ife); 2065 if (res >= 0) { 2066 if ((ife->flags & IFF_UP) || *opt_a) 2067 ife_print(ife); 2068 } 2069 return res; 2070} 2071 2072static struct interface *lookup_interface(char *name) 2073{ 2074 struct interface *ife = NULL; 2075 2076 if (if_readlist_proc(name) < 0) 2077 return NULL; 2078 ife = add_interface(name); 2079 return ife; 2080} 2081 2082/* for ipv4 add/del modes */ 2083static int if_print(char *ifname) 2084{ 2085 int res; 2086 2087 if (!ifname) { 2088 res = for_all_interfaces(do_if_print, &interface_opt_a); 2089 } else { 2090 struct interface *ife; 2091 2092 ife = lookup_interface(ifname); 2093 res = do_if_fetch(ife); 2094 if (res >= 0) 2095 ife_print(ife); 2096 } 2097 return res; 2098} 2099 2100int display_interfaces(char *ifname) 2101{ 2102 int status; 2103 2104 /* Create a channel to the NET kernel. */ 2105 if ((skfd = sockets_open(0)) < 0) { 2106 perror_msg_and_die("socket"); 2107 } 2108 2109 /* Do we have to show the current setup? */ 2110 status = if_print(ifname); 2111 close(skfd); 2112 exit(status < 0); 2113} 2114