blob: 39fd44cc2c1a2a7176aa7da9304f7253a3a5f18c [file] [log] [blame]
Eric Andersenf15d4da2001-03-06 00:48:59 +00001/*
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002 * stolen from net-tools-1.59 and stripped down for busybox by
Eric Andersencb81e642003-07-14 21:21:08 +00003 * Erik Andersen <andersen@codepoet.org>
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004 *
5 * Heavily modified by Manuel Novoa III Mar 12, 2001
6 *
7 * Pruned unused code using KEEP_UNUSED define.
8 * Added print_bytes_scaled function to reduce code size.
9 * Added some (potentially) missing defines.
10 * Improved display support for -a and for a named interface.
11 *
12 * -----------------------------------------------------------
13 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000014 * ifconfig This file contains an implementation of the command
15 * that either displays or sets the characteristics of
16 * one or more of the system's networking interfaces.
17 *
Eric Andersen6fea7322004-08-26 21:45:21 +000018 * Version: $Id: interface.c,v 1.25 2004/08/26 21:45:21 andersen Exp $
Eric Andersenf15d4da2001-03-06 00:48:59 +000019 *
20 * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
21 * and others. Copyright 1993 MicroWalt Corporation
22 *
23 * This program is free software; you can redistribute it
24 * and/or modify it under the terms of the GNU General
25 * Public License as published by the Free Software
26 * Foundation; either version 2 of the License, or (at
27 * your option) any later version.
28 *
29 * Patched to support 'add' and 'del' keywords for INET(4) addresses
30 * by Mrs. Brisby <mrs.brisby@nimh.org>
31 *
32 * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
33 * - gettext instead of catgets for i18n
Eric Andersenc7bda1c2004-03-15 08:29:22 +000034 * 10/1998 - Andi Kleen. Use interface list primitives.
35 * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
Eric Andersenf15d4da2001-03-06 00:48:59 +000036 * (default AF was wrong)
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +000037 */
38
39/* #define KEEP_UNUSED */
40
Eric Andersenc7bda1c2004-03-15 08:29:22 +000041/*
42 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000043 * Protocol Families.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000044 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000045 */
46#define HAVE_AFINET 1
Eric Andersenf15d4da2001-03-06 00:48:59 +000047#undef HAVE_AFIPX
48#undef HAVE_AFATALK
49#undef HAVE_AFNETROM
50#undef HAVE_AFX25
51#undef HAVE_AFECONET
Eric Andersen8b113f92001-06-01 21:47:15 +000052#undef HAVE_AFASH
Eric Andersenf15d4da2001-03-06 00:48:59 +000053
Eric Andersenc7bda1c2004-03-15 08:29:22 +000054/*
55 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000056 * Device Hardware types.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000057 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000058 */
59#define HAVE_HWETHER 1
60#define HAVE_HWPPP 1
61#undef HAVE_HWSLIP
62
63
Eric Andersencd8c4362001-11-10 11:22:46 +000064#include "inet_common.h"
Eric Andersenf15d4da2001-03-06 00:48:59 +000065#include <stdio.h>
66#include <errno.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +000067#include <stdlib.h>
68#include <string.h>
69#include <unistd.h>
Eric Andersencd8c4362001-11-10 11:22:46 +000070#include <fcntl.h>
71#include <ctype.h>
72#include <sys/ioctl.h>
Eric Andersen85e5e722003-07-22 08:56:55 +000073#include <sys/types.h>
Eric Andersencd8c4362001-11-10 11:22:46 +000074#include <net/if.h>
75#include <net/if_arp.h>
Bernhard Reutner-Fischerfa939aa2006-04-05 16:21:37 +000076#include "busybox.h"
Eric Andersenf15d4da2001-03-06 00:48:59 +000077
Glenn L McGrathb54a7482003-08-29 11:34:08 +000078#ifdef CONFIG_FEATURE_IPV6
79# define HAVE_AFINET6 1
80#else
81# undef HAVE_AFINET6
82#endif
83
Eric Andersenf15d4da2001-03-06 00:48:59 +000084#define _PATH_PROCNET_DEV "/proc/net/dev"
Eric Andersen51b8bd62002-07-03 11:46:38 +000085#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
Eric Andersenf15d4da2001-03-06 00:48:59 +000086#define new(p) ((p) = xcalloc(1,sizeof(*(p))))
Eric Andersen8b113f92001-06-01 21:47:15 +000087#define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch))
Eric Andersenf15d4da2001-03-06 00:48:59 +000088
Eric Andersenf15d4da2001-03-06 00:48:59 +000089#ifdef HAVE_HWSLIP
Eric Andersenab4e19a2003-01-14 08:54:08 +000090#include <net/if_slip.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +000091#endif
92
93#if HAVE_AFINET6
94
95#ifndef _LINUX_IN6_H
96/*
97 * This is in linux/include/net/ipv6.h.
98 */
99
100struct in6_ifreq {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000101 struct in6_addr ifr6_addr;
Glenn L McGrathb54a7482003-08-29 11:34:08 +0000102 uint32_t ifr6_prefixlen;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000103 unsigned int ifr6_ifindex;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000104};
105
106#endif
107
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000108#endif /* HAVE_AFINET6 */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000109
110#if HAVE_AFIPX
Eric Andersenb6b519b2001-04-09 23:52:18 +0000111#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000112#include <netipx/ipx.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +0000113#endif
114#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000115
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000116/* Defines for glibc2.0 users. */
117#ifndef SIOCSIFTXQLEN
118#define SIOCSIFTXQLEN 0x8943
119#define SIOCGIFTXQLEN 0x8942
120#endif
121
122/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
123#ifndef ifr_qlen
124#define ifr_qlen ifr_ifru.ifru_mtu
125#endif
126
127#ifndef HAVE_TXQUEUELEN
128#define HAVE_TXQUEUELEN 1
129#endif
130
131#ifndef IFF_DYNAMIC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000132#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000133#endif
134
Eric Andersenf15d4da2001-03-06 00:48:59 +0000135/* This structure defines protocol families and their handlers. */
136struct aftype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000137 const char *name;
138 const char *title;
139 int af;
140 int alen;
141 char *(*print) (unsigned char *);
142 char *(*sprint) (struct sockaddr *, int numeric);
143 int (*input) (int type, char *bufp, struct sockaddr *);
144 void (*herror) (char *text);
145 int (*rprint) (int options);
146 int (*rinput) (int typ, int ext, char **argv);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000147
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000148 /* may modify src */
149 int (*getmask) (char *src, struct sockaddr * mask, char *name);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000150
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000151 int fd;
152 char *flag_file;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000153};
154
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000155#ifdef KEEP_UNUSED
156
157static int flag_unx;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000158
Eric Andersen8b113f92001-06-01 21:47:15 +0000159#ifdef HAVE_AFIPX
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000160static int flag_ipx;
Eric Andersen8b113f92001-06-01 21:47:15 +0000161#endif
162#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000163static int flag_ax25;
Eric Andersen8b113f92001-06-01 21:47:15 +0000164#endif
165#ifdef HAVE_AFATALK
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000166static int flag_ddp;
Eric Andersen8b113f92001-06-01 21:47:15 +0000167#endif
168#ifdef HAVE_AFNETROM
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000169static int flag_netrom;
Eric Andersen8b113f92001-06-01 21:47:15 +0000170#endif
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000171static int flag_inet;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000172
Eric Andersen8b113f92001-06-01 21:47:15 +0000173#ifdef HAVE_AFINET6
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000174static int flag_inet6;
Eric Andersen8b113f92001-06-01 21:47:15 +0000175#endif
176#ifdef HAVE_AFECONET
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000177static int flag_econet;
Eric Andersen8b113f92001-06-01 21:47:15 +0000178#endif
179#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000180static int flag_x25 = 0;
Eric Andersen8b113f92001-06-01 21:47:15 +0000181#endif
182#ifdef HAVE_AFASH
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000183static int flag_ash;
Eric Andersen8b113f92001-06-01 21:47:15 +0000184#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000185
186
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000187static struct aftrans_t {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000188 char *alias;
189 char *name;
190 int *flag;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000191} aftrans[] = {
192
Eric Andersen8b113f92001-06-01 21:47:15 +0000193#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000194 {
195 "ax25", "ax25", &flag_ax25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000196#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000197 {
198 "ip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000199#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000200 {
201 "ip6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000202#endif
203#ifdef HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000204 {
205 "ipx", "ipx", &flag_ipx},
Eric Andersen8b113f92001-06-01 21:47:15 +0000206#endif
207#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000208 {
209 "appletalk", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000210#endif
211#ifdef HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000212 {
213 "netrom", "netrom", &flag_netrom},
Eric Andersen8b113f92001-06-01 21:47:15 +0000214#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000215 {
216 "inet", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000217#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000218 {
219 "inet6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000220#endif
221#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000222 {
223 "ddp", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000224#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000225 {
226 "unix", "unix", &flag_unx}, {
227 "tcpip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000228#ifdef HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000229 {
230 "econet", "ec", &flag_econet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000231#endif
232#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000233 {
234 "x25", "x25", &flag_x25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000235#endif
236#ifdef HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000237 {
238 "ash", "ash", &flag_ash},
Eric Andersen8b113f92001-06-01 21:47:15 +0000239#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000240 {
241 0, 0, 0}
Eric Andersenf15d4da2001-03-06 00:48:59 +0000242};
243
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000244static char afname[256] = "";
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000245#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000246
247#if HAVE_AFUNIX
248
249/* Display a UNIX domain address. */
250static char *UNIX_print(unsigned char *ptr)
251{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000252 return (ptr);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000253}
254
255
256/* Display a UNIX domain address. */
257static char *UNIX_sprint(struct sockaddr *sap, int numeric)
258{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000259 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000260
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000261 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
262 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
263 return (UNIX_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000264}
265
266
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000267static struct aftype unix_aftype = {
268 "unix", "UNIX Domain", AF_UNIX, 0,
269 UNIX_print, UNIX_sprint, NULL, NULL,
270 NULL, NULL, NULL,
271 -1,
272 "/proc/net/unix"
Eric Andersenf15d4da2001-03-06 00:48:59 +0000273};
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000274#endif /* HAVE_AFUNIX */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000275
276#if HAVE_AFINET
277
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000278#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000279static void INET_reserror(char *text)
280{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000281 herror(text);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000282}
283
Eric Andersenf15d4da2001-03-06 00:48:59 +0000284/* Display an Internet socket address. */
285static char *INET_print(unsigned char *ptr)
286{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000287 return (inet_ntoa((*(struct in_addr *) ptr)));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000288}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000289#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000290
291/* Display an Internet socket address. */
292static char *INET_sprint(struct sockaddr *sap, int numeric)
293{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000294 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000295
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000296 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
297 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000298
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000299 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
300 numeric, 0xffffff00) != 0)
301 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000302
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000303 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000304}
305
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000306#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000307static char *INET_sprintmask(struct sockaddr *sap, int numeric,
308 unsigned int netmask)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000309{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000310 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000311
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000312 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
313 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
314 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
315 numeric, netmask) != 0)
316 return (NULL);
317 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000318}
319
Eric Andersenf15d4da2001-03-06 00:48:59 +0000320static int INET_getsock(char *bufp, struct sockaddr *sap)
321{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000322 char *sp = bufp, *bp;
323 unsigned int i;
324 unsigned val;
325 struct sockaddr_in *sin;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000326
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000327 sin = (struct sockaddr_in *) sap;
328 sin->sin_family = AF_INET;
329 sin->sin_port = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000330
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000331 val = 0;
332 bp = (char *) &val;
333 for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) {
334 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000335
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000336 if ((*sp >= 'A') && (*sp <= 'F'))
337 bp[i] |= (int) (*sp - 'A') + 10;
338 else if ((*sp >= '0') && (*sp <= '9'))
339 bp[i] |= (int) (*sp - '0');
340 else
341 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000342
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000343 bp[i] <<= 4;
344 sp++;
345 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000346
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000347 if ((*sp >= 'A') && (*sp <= 'F'))
348 bp[i] |= (int) (*sp - 'A') + 10;
349 else if ((*sp >= '0') && (*sp <= '9'))
350 bp[i] |= (int) (*sp - '0');
351 else
352 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000353
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000354 sp++;
355 }
356 sin->sin_addr.s_addr = htonl(val);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000357
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000358 return (sp - bufp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000359}
360
361static int INET_input(int type, char *bufp, struct sockaddr *sap)
362{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000363 switch (type) {
364 case 1:
365 return (INET_getsock(bufp, sap));
366 case 256:
367 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
368 default:
369 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
370 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000371}
372
373static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
374{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000375 struct sockaddr_in *mask = (struct sockaddr_in *) m;
376 char *slash, *end;
377 int prefix;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000378
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000379 if ((slash = strchr(adr, '/')) == NULL)
380 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000381
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000382 *slash++ = '\0';
383 prefix = strtoul(slash, &end, 0);
384 if (*end != '\0')
385 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000386
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000387 if (name) {
388 sprintf(name, "/%d", prefix);
389 }
390 mask->sin_family = AF_INET;
391 mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
392 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000393}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000394#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000395
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000396static struct aftype inet_aftype = {
397 "inet", "DARPA Internet", AF_INET, sizeof(unsigned long),
398 NULL /* UNUSED INET_print */ , INET_sprint,
399 NULL /* UNUSED INET_input */ , NULL /* UNUSED INET_reserror */ ,
400 NULL /*INET_rprint */ , NULL /*INET_rinput */ ,
401 NULL /* UNUSED INET_getnetmask */ ,
402 -1,
403 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000404};
405
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000406#endif /* HAVE_AFINET */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000407
Eric Andersen51b8bd62002-07-03 11:46:38 +0000408#if HAVE_AFINET6
409
410#ifdef KEEP_UNUSED
411static void INET6_reserror(char *text)
412{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000413 herror(text);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000414}
415
416/* Display an Internet socket address. */
417static char *INET6_print(unsigned char *ptr)
418{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000419 static char name[80];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000420
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000421 inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80);
422 return name;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000423}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000424#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000425
426/* Display an Internet socket address. */
427/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
428static char *INET6_sprint(struct sockaddr *sap, int numeric)
429{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000430 static char buff[128];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000431
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000432 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
433 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
434 if (INET6_rresolve
435 (buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)
436 return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff));
437 return (buff);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000438}
439
440#ifdef KEEP_UNUSED
441static int INET6_getsock(char *bufp, struct sockaddr *sap)
442{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000443 struct sockaddr_in6 *sin6;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000444
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000445 sin6 = (struct sockaddr_in6 *) sap;
446 sin6->sin6_family = AF_INET6;
447 sin6->sin6_port = 0;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000448
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000449 if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0)
450 return (-1);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000451
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000452 return 16; /* ?;) */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000453}
454
455static int INET6_input(int type, char *bufp, struct sockaddr *sap)
456{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000457 switch (type) {
458 case 1:
459 return (INET6_getsock(bufp, sap));
460 default:
461 return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));
462 }
Eric Andersen51b8bd62002-07-03 11:46:38 +0000463}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000464#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000465
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000466static struct aftype inet6_aftype = {
467 "inet6", "IPv6", AF_INET6, sizeof(struct in6_addr),
468 NULL /* UNUSED INET6_print */ , INET6_sprint,
469 NULL /* UNUSED INET6_input */ , NULL /* UNUSED INET6_reserror */ ,
470 NULL /*INET6_rprint */ , NULL /*INET6_rinput */ ,
471 NULL /* UNUSED INET6_getnetmask */ ,
472 -1,
473 NULL
Eric Andersen51b8bd62002-07-03 11:46:38 +0000474};
475
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000476#endif /* HAVE_AFINET6 */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000477
Eric Andersenf15d4da2001-03-06 00:48:59 +0000478/* Display an UNSPEC address. */
479static char *UNSPEC_print(unsigned char *ptr)
480{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000481 static char buff[sizeof(struct sockaddr) * 3 + 1];
482 char *pos;
483 unsigned int i;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000484
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000485 pos = buff;
486 for (i = 0; i < sizeof(struct sockaddr); i++) {
487 /* careful -- not every libc's sprintf returns # bytes written */
488 sprintf(pos, "%02X-", (*ptr++ & 0377));
489 pos += 3;
490 }
491 /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */
492 *--pos = '\0';
493 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000494}
495
496/* Display an UNSPEC socket address. */
497static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
498{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000499 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000500
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000501 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
502 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
Eric Andersen0cb6f352006-01-30 22:30:41 +0000503 return (UNSPEC_print((unsigned char *)sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000504}
505
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000506static struct aftype unspec_aftype = {
507 "unspec", "UNSPEC", AF_UNSPEC, 0,
508 UNSPEC_print, UNSPEC_sprint, NULL, NULL,
509 NULL,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000510};
511
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000512static struct aftype * const aftypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000513#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000514 &unix_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000515#endif
516#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000517 &inet_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000518#endif
519#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000520 &inet6_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000521#endif
522#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000523 &ax25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000524#endif
525#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000526 &netrom_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000527#endif
528#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000529 &rose_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000530#endif
531#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000532 &ipx_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000533#endif
534#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000535 &ddp_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000536#endif
537#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000538 &ec_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000539#endif
540#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000541 &ash_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000542#endif
543#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000544 &x25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000545#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000546 &unspec_aftype,
547 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000548};
549
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000550#ifdef KEEP_UNUSED
551static short sVafinit = 0;
552
553static void afinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +0000554{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000555 unspec_aftype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000556#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000557 unix_aftype.title = _("UNIX Domain");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000558#endif
559#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000560 inet_aftype.title = _("DARPA Internet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000561#endif
562#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000563 inet6_aftype.title = _("IPv6");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000564#endif
565#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000566 ax25_aftype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000567#endif
568#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000569 netrom_aftype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000570#endif
571#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000572 ipx_aftype.title = _("Novell IPX");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000573#endif
574#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000575 ddp_aftype.title = _("Appletalk DDP");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000576#endif
577#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000578 ec_aftype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000579#endif
580#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000581 x25_aftype.title = _("CCITT X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000582#endif
583#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000584 rose_aftype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000585#endif
586#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000587 ash_aftype.title = _("Ash");
588#endif
589 sVafinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000590}
591
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000592static int aftrans_opt(const char *arg)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000593{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000594 struct aftrans_t *paft;
595 char *tmp1, *tmp2;
596 char buf[256];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000597
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000598 safe_strncpy(buf, arg, sizeof(buf));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000599
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000600 tmp1 = buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000601
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000602 while (tmp1) {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000603
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000604 tmp2 = strchr(tmp1, ',');
Eric Andersenf15d4da2001-03-06 00:48:59 +0000605
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000606 if (tmp2)
607 *(tmp2++) = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000608
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000609 paft = aftrans;
610 for (paft = aftrans; paft->alias; paft++) {
611 if (strcmp(tmp1, paft->alias))
612 continue;
613 if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000614 bb_error_msg(_("Too many address family arguments."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000615 return (0);
616 }
617 if (paft->flag)
618 (*paft->flag)++;
619 if (afname[0])
620 strcat(afname, ",");
621 strcat(afname, paft->name);
622 break;
623 }
624 if (!paft->alias) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000625 bb_error_msg(_("Unknown address family `%s'."), tmp1);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000626 return (1);
627 }
628 tmp1 = tmp2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000629 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000630
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000631 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000632}
633
634/* set the default AF list from the program name or a constant value */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000635static void aftrans_def(char *tool, char *argv0, char *dflt)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000636{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000637 char *tmp;
638 char *buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000639
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000640 strcpy(afname, dflt);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000641
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000642 if (!(tmp = strrchr(argv0, '/')))
643 tmp = argv0; /* no slash?! */
644 else
645 tmp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000646
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000647 if (!(buf = strdup(tmp)))
648 return;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000649
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000650 if (strlen(tool) >= strlen(tmp)) {
651 free(buf);
652 return;
653 }
654 tmp = buf + (strlen(tmp) - strlen(tool));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000655
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000656 if (strcmp(tmp, tool) != 0) {
657 free(buf);
658 return;
659 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000660 *tmp = '\0';
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000661 if ((tmp = strchr(buf, '_')))
662 *tmp = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000663
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000664 afname[0] = '\0';
665 if (aftrans_opt(buf))
666 strcpy(afname, buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000667
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000668 free(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000669}
670
Eric Andersenf15d4da2001-03-06 00:48:59 +0000671/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000672static struct aftype *get_aftype(const char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000673{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000674 struct aftype * const *afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000675
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000676#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000677 if (!sVafinit)
678 afinit();
679#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000680
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000681 afp = aftypes;
682 while (*afp != NULL) {
683 if (!strcmp((*afp)->name, name))
684 return (*afp);
685 afp++;
686 }
687 if (strchr(name, ','))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000688 bb_error_msg(_("Please don't supply more than one address family."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000689 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000690}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000691#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000692
693/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000694static struct aftype *get_afntype(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000695{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000696 struct aftype * const *afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000697
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000698#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000699 if (!sVafinit)
700 afinit();
701#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000702
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000703 afp = aftypes;
704 while (*afp != NULL) {
705 if ((*afp)->af == af)
706 return (*afp);
707 afp++;
708 }
709 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000710}
711
712/* Check our protocol family table for this family and return its socket */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000713static int get_socket_for_af(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000714{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000715 struct aftype * const *afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000716
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000717#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000718 if (!sVafinit)
719 afinit();
720#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000721
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000722 afp = aftypes;
723 while (*afp != NULL) {
724 if ((*afp)->af == af)
725 return (*afp)->fd;
726 afp++;
727 }
728 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000729}
730
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000731#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000732/* type: 0=all, 1=getroute */
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000733static void print_aflist(int type)
734{
735 int count = 0;
736 char *txt;
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000737 struct aftype * const *afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000738
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000739#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000740 if (!sVafinit)
741 afinit();
742#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000743
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000744 afp = aftypes;
745 while (*afp != NULL) {
746 if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) {
747 afp++;
748 continue;
749 }
750 if ((count % 3) == 0)
751 fprintf(stderr, count ? "\n " : " ");
752 txt = (*afp)->name;
753 if (!txt)
754 txt = "..";
755 fprintf(stderr, "%s (%s) ", txt, _((*afp)->title));
756 count++;
757 afp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000758 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000759 fprintf(stderr, "\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000760}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000761#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000762
763struct user_net_device_stats {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000764 unsigned long long rx_packets; /* total packets received */
765 unsigned long long tx_packets; /* total packets transmitted */
766 unsigned long long rx_bytes; /* total bytes received */
767 unsigned long long tx_bytes; /* total bytes transmitted */
768 unsigned long rx_errors; /* bad packets received */
769 unsigned long tx_errors; /* packet transmit problems */
770 unsigned long rx_dropped; /* no space in linux buffers */
771 unsigned long tx_dropped; /* no space available in linux */
772 unsigned long rx_multicast; /* multicast packets received */
773 unsigned long rx_compressed;
774 unsigned long tx_compressed;
775 unsigned long collisions;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000776
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000777 /* detailed rx_errors: */
778 unsigned long rx_length_errors;
779 unsigned long rx_over_errors; /* receiver ring buff overflow */
780 unsigned long rx_crc_errors; /* recved pkt with crc error */
781 unsigned long rx_frame_errors; /* recv'd frame alignment error */
782 unsigned long rx_fifo_errors; /* recv'r fifo overrun */
783 unsigned long rx_missed_errors; /* receiver missed packet */
784 /* detailed tx_errors */
785 unsigned long tx_aborted_errors;
786 unsigned long tx_carrier_errors;
787 unsigned long tx_fifo_errors;
788 unsigned long tx_heartbeat_errors;
789 unsigned long tx_window_errors;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000790};
791
792struct interface {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000793 struct interface *next, *prev;
794 char name[IFNAMSIZ]; /* interface name */
795 short type; /* if type */
796 short flags; /* various flags */
797 int metric; /* routing metric */
798 int mtu; /* MTU value */
799 int tx_queue_len; /* transmit queue length */
800 struct ifmap map; /* hardware setup */
801 struct sockaddr addr; /* IP address */
802 struct sockaddr dstaddr; /* P-P IP address */
803 struct sockaddr broadaddr; /* IP broadcast address */
804 struct sockaddr netmask; /* IP network mask */
805 struct sockaddr ipxaddr_bb; /* IPX network address */
806 struct sockaddr ipxaddr_sn; /* IPX network address */
807 struct sockaddr ipxaddr_e3; /* IPX network address */
808 struct sockaddr ipxaddr_e2; /* IPX network address */
809 struct sockaddr ddpaddr; /* Appletalk DDP address */
810 struct sockaddr ecaddr; /* Econet address */
811 int has_ip;
812 int has_ipx_bb;
813 int has_ipx_sn;
814 int has_ipx_e3;
815 int has_ipx_e2;
816 int has_ax25;
817 int has_ddp;
818 int has_econet;
819 char hwaddr[32]; /* HW address */
820 int statistics_valid;
821 struct user_net_device_stats stats; /* statistics */
822 int keepalive; /* keepalive value for SLIP */
823 int outfill; /* outfill value for SLIP */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000824};
825
826
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000827int interface_opt_a = 0; /* show all interfaces */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000828
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000829#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000830static int opt_i = 0; /* show the statistics */
831static int opt_v = 0; /* debugging output flag */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000832
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000833static int addr_family = 0; /* currently selected AF */
834#endif /* KEEP_UNUSED */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000835
Eric Andersenf15d4da2001-03-06 00:48:59 +0000836static struct interface *int_list, *int_last;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000837static int skfd = -1; /* generic raw socket desc. */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000838
839
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000840static int sockets_open(int family)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000841{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000842 struct aftype * const *aft;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000843 int sfd = -1;
844 static int force = -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000845
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000846 if (force < 0) {
847 force = 0;
848 if (get_kernel_revision() < KRELEASE(2, 1, 0))
849 force = 1;
850 if (access("/proc/net", R_OK))
851 force = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000852 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000853 for (aft = aftypes; *aft; aft++) {
854 struct aftype *af = *aft;
855 int type = SOCK_DGRAM;
856
857 if (af->af == AF_UNSPEC)
858 continue;
859 if (family && family != af->af)
860 continue;
861 if (af->fd != -1) {
862 sfd = af->fd;
863 continue;
864 }
865 /* Check some /proc file first to not stress kmod */
866 if (!family && !force && af->flag_file) {
867 if (access(af->flag_file, R_OK))
868 continue;
869 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000870#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000871 if (af->af == AF_NETROM)
872 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000873#endif
874#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000875 if (af->af == AF_X25)
876 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000877#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000878 af->fd = socket(af->af, type, 0);
879 if (af->fd >= 0)
880 sfd = af->fd;
881 }
Glenn L McGrath642f2892002-11-28 10:20:45 +0000882 if (sfd < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000883 bb_error_msg(_("No usable address families found."));
Glenn L McGrath642f2892002-11-28 10:20:45 +0000884 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000885 return sfd;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000886}
887
Rob Landley93983042005-05-03 21:30:26 +0000888#ifdef CONFIG_FEATURE_CLEAN_UP
889static void sockets_close(void)
890{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000891 struct aftype * const *aft;
Rob Landley93983042005-05-03 21:30:26 +0000892 for (aft = aftypes; *aft != NULL; aft++) {
893 struct aftype *af = *aft;
894 if( af->fd != -1 ) {
895 close(af->fd);
896 af->fd = -1;
897 }
898 }
899}
900#endif
901
Eric Andersenf15d4da2001-03-06 00:48:59 +0000902/* like strcmp(), but knows about numbers */
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000903static int nstrcmp(const char *a, const char *b)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000904{
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000905 const char *a_ptr = a;
906 const char *b_ptr = b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000907
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000908 while (*a == *b) {
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000909 if (*a == '\0') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000910 return 0;
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000911 }
912 if (!isdigit(*a) && isdigit(*(a+1))) {
913 a_ptr = a+1;
914 b_ptr = b+1;
915 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000916 a++;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000917 b++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000918 }
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000919
920 if (isdigit(*a) && isdigit(*b)) {
921 return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000922 }
923 return *a - *b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000924}
925
926static struct interface *add_interface(char *name)
927{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000928 struct interface *ife, **nextp, *new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000929
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000930 for (ife = int_last; ife; ife = ife->prev) {
931 int n = nstrcmp(ife->name, name);
932
933 if (n == 0)
934 return ife;
935 if (n < 0)
936 break;
937 }
938 new(new);
939 safe_strncpy(new->name, name, IFNAMSIZ);
940 nextp = ife ? &ife->next : &int_list;
941 new->prev = ife;
942 new->next = *nextp;
943 if (new->next)
944 new->next->prev = new;
945 else
946 int_last = new;
947 *nextp = new;
948 return new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000949}
950
951
952static int if_readconf(void)
953{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000954 int numreqs = 30;
955 struct ifconf ifc;
956 struct ifreq *ifr;
957 int n, err = -1;
958 int skfd2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000959
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000960 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
961 (as of 2.1.128) */
962 skfd2 = get_socket_for_af(AF_INET);
963 if (skfd2 < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000964 bb_perror_msg(("warning: no inet socket available"));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000965 /* Try to soldier on with whatever socket we can get hold of. */
966 skfd2 = sockets_open(0);
967 if (skfd2 < 0)
968 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000969 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000970
971 ifc.ifc_buf = NULL;
972 for (;;) {
973 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
974 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
975
976 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
977 perror("SIOCGIFCONF");
978 goto out;
979 }
980 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
981 /* assume it overflowed and try again */
982 numreqs += 10;
983 continue;
984 }
985 break;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000986 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000987
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000988 ifr = ifc.ifc_req;
989 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
990 add_interface(ifr->ifr_name);
991 ifr++;
992 }
993 err = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000994
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000995 out:
996 free(ifc.ifc_buf);
997 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000998}
999
Eric Andersen14f5c8d2005-04-16 19:39:00 +00001000static char *get_name(char *name, char *p)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001001{
Eric Andersen9940e082004-08-12 16:52:00 +00001002 /* Extract <name>[:<alias>] from nul-terminated p where p matches
1003 <name>[:<alias>]: after leading whitespace.
1004 If match is not made, set name empty and return unchanged p */
1005 int namestart=0, nameend=0, aliasend;
1006 while (isspace(p[namestart]))
1007 namestart++;
1008 nameend=namestart;
1009 while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
1010 nameend++;
1011 if (p[nameend]==':') {
1012 aliasend=nameend+1;
1013 while (p[aliasend] && isdigit(p[aliasend]))
1014 aliasend++;
1015 if (p[aliasend]==':') {
1016 nameend=aliasend;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001017 }
Eric Andersen9940e082004-08-12 16:52:00 +00001018 if ((nameend-namestart)<IFNAMSIZ) {
1019 memcpy(name,&p[namestart],nameend-namestart);
1020 name[nameend-namestart]='\0';
1021 p=&p[nameend];
1022 } else {
1023 /* Interface name too large */
1024 name[0]='\0';
1025 }
1026 } else {
1027 /* first ':' not found - return empty */
1028 name[0]='\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +00001029 }
Eric Andersen6fea7322004-08-26 21:45:21 +00001030 return p + 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001031}
1032
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001033/* If scanf supports size qualifiers for %n conversions, then we can
1034 * use a modified fmt that simply stores the position in the fields
1035 * having no associated fields in the proc string. Of course, we need
1036 * to zero them again when we're done. But that is smaller than the
1037 * old approach of multiple scanf occurrences with large numbers of
1038 * args. */
1039
Bernhard Reutner-Fischera901b402006-01-19 14:51:17 +00001040/* static const char * const ss_fmt[] = { */
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001041/* "%lln%llu%lu%lu%lu%lu%ln%ln%lln%llu%lu%lu%lu%lu%lu", */
1042/* "%llu%llu%lu%lu%lu%lu%ln%ln%llu%llu%lu%lu%lu%lu%lu", */
1043/* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001044/* }; */
1045
1046 /* Lie about the size of the int pointed to for %n. */
1047#if INT_MAX == LONG_MAX
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001048static const char * const ss_fmt[] = {
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001049 "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u",
1050 "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u",
1051 "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u"
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001052};
1053#else
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001054static const char * const ss_fmt[] = {
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001055 "%n%llu%lu%lu%lu%lu%n%n%n%llu%lu%lu%lu%lu%lu",
1056 "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu",
1057 "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu"
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001058};
1059
1060#endif
1061
1062static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001063{
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001064 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
1065
1066 sscanf(bp, ss_fmt[procnetdev_vsn],
1067 &ife->stats.rx_bytes, /* missing for 0 */
1068 &ife->stats.rx_packets,
1069 &ife->stats.rx_errors,
1070 &ife->stats.rx_dropped,
1071 &ife->stats.rx_fifo_errors,
1072 &ife->stats.rx_frame_errors,
1073 &ife->stats.rx_compressed, /* missing for <= 1 */
1074 &ife->stats.rx_multicast, /* missing for <= 1 */
1075 &ife->stats.tx_bytes, /* missing for 0 */
1076 &ife->stats.tx_packets,
1077 &ife->stats.tx_errors,
1078 &ife->stats.tx_dropped,
1079 &ife->stats.tx_fifo_errors,
1080 &ife->stats.collisions,
1081 &ife->stats.tx_carrier_errors,
1082 &ife->stats.tx_compressed /* missing for <= 1 */
1083 );
1084
1085 if (procnetdev_vsn <= 1) {
1086 if (procnetdev_vsn == 0) {
1087 ife->stats.rx_bytes = 0;
1088 ife->stats.tx_bytes = 0;
1089 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001090 ife->stats.rx_multicast = 0;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001091 ife->stats.rx_compressed = 0;
1092 ife->stats.tx_compressed = 0;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001093 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001094}
1095
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001096static inline int procnetdev_version(char *buf)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001097{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001098 if (strstr(buf, "compressed"))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001099 return 2;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001100 if (strstr(buf, "bytes"))
1101 return 1;
1102 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001103}
1104
1105static int if_readlist_proc(char *target)
1106{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001107 static int proc_read;
1108 FILE *fh;
1109 char buf[512];
1110 struct interface *ife;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001111 int err, procnetdev_vsn;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001112
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001113 if (proc_read)
1114 return 0;
1115 if (!target)
1116 proc_read = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001117
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001118 fh = fopen(_PATH_PROCNET_DEV, "r");
1119 if (!fh) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001120 bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001121 return if_readconf();
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001122 }
1123 fgets(buf, sizeof buf, fh); /* eat line */
1124 fgets(buf, sizeof buf, fh);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001125
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001126 procnetdev_vsn = procnetdev_version(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001127
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001128 err = 0;
1129 while (fgets(buf, sizeof buf, fh)) {
Eric Andersenf96675b2003-07-28 06:37:04 +00001130 char *s, name[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001131
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001132 s = get_name(name, buf);
1133 ife = add_interface(name);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001134 get_dev_fields(s, ife, procnetdev_vsn);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001135 ife->statistics_valid = 1;
1136 if (target && !strcmp(target, name))
1137 break;
1138 }
1139 if (ferror(fh)) {
1140 perror(_PATH_PROCNET_DEV);
1141 err = -1;
1142 proc_read = 0;
1143 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001144 fclose(fh);
1145 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001146}
1147
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001148static int if_readlist(void)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001149{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001150 int err = if_readlist_proc(NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001151
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001152 if (!err)
1153 err = if_readconf();
1154 return err;
1155}
1156
1157static int for_all_interfaces(int (*doit) (struct interface *, void *),
1158 void *cookie)
1159{
1160 struct interface *ife;
1161
1162 if (!int_list && (if_readlist() < 0))
1163 return -1;
1164 for (ife = int_list; ife; ife = ife->next) {
1165 int err = doit(ife, cookie);
1166
1167 if (err)
1168 return err;
1169 }
1170 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001171}
1172
1173/* Support for fetching an IPX address */
1174
1175#if HAVE_AFIPX
1176static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
1177{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001178 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
1179 return ioctl(sock, SIOCGIFADDR, ifr);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001180}
1181#endif
1182
1183
1184/* Fetch the interface configuration from the kernel. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001185static int if_fetch(struct interface *ife)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001186{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001187 struct ifreq ifr;
1188 int fd;
1189 char *ifname = ife->name;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001190
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001191 strcpy(ifr.ifr_name, ifname);
1192 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
1193 return (-1);
1194 ife->flags = ifr.ifr_flags;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001195
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001196 strcpy(ifr.ifr_name, ifname);
1197 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
1198 memset(ife->hwaddr, 0, 32);
1199 else
1200 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001201
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001202 ife->type = ifr.ifr_hwaddr.sa_family;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001203
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001204 strcpy(ifr.ifr_name, ifname);
1205 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
1206 ife->metric = 0;
1207 else
1208 ife->metric = ifr.ifr_metric;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001209
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001210 strcpy(ifr.ifr_name, ifname);
1211 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
1212 ife->mtu = 0;
1213 else
1214 ife->mtu = ifr.ifr_mtu;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001215
1216#ifdef HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001217 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
1218 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
1219 ife->type == ARPHRD_ADAPT) {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001220#ifdef SIOCGOUTFILL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001221 strcpy(ifr.ifr_name, ifname);
1222 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
1223 ife->outfill = 0;
1224 else
1225 ife->outfill = (unsigned int) ifr.ifr_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001226#endif
1227#ifdef SIOCGKEEPALIVE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001228 strcpy(ifr.ifr_name, ifname);
1229 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
1230 ife->keepalive = 0;
1231 else
1232 ife->keepalive = (unsigned int) ifr.ifr_data;
1233#endif
1234 }
1235#endif
1236
Rob Landley93983042005-05-03 21:30:26 +00001237#ifdef SIOCGIFMAP
Eric Andersenf15d4da2001-03-06 00:48:59 +00001238 strcpy(ifr.ifr_name, ifname);
Rob Landley93983042005-05-03 21:30:26 +00001239 if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001240 ife->map = ifr.ifr_map;
Rob Landley93983042005-05-03 21:30:26 +00001241 else
1242#endif
1243 memset(&ife->map, 0, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001244
1245#ifdef HAVE_TXQUEUELEN
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001246 strcpy(ifr.ifr_name, ifname);
1247 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
1248 ife->tx_queue_len = -1; /* unknown value */
1249 else
1250 ife->tx_queue_len = ifr.ifr_qlen;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001251#else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001252 ife->tx_queue_len = -1; /* unknown value */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001253#endif
1254
1255#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001256 /* IPv4 address? */
1257 fd = get_socket_for_af(AF_INET);
1258 if (fd >= 0) {
1259 strcpy(ifr.ifr_name, ifname);
1260 ifr.ifr_addr.sa_family = AF_INET;
1261 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1262 ife->has_ip = 1;
1263 ife->addr = ifr.ifr_addr;
1264 strcpy(ifr.ifr_name, ifname);
1265 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
1266 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
1267 else
1268 ife->dstaddr = ifr.ifr_dstaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001269
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001270 strcpy(ifr.ifr_name, ifname);
1271 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
1272 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
1273 else
1274 ife->broadaddr = ifr.ifr_broadaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001275
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001276 strcpy(ifr.ifr_name, ifname);
1277 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
1278 memset(&ife->netmask, 0, sizeof(struct sockaddr));
1279 else
1280 ife->netmask = ifr.ifr_netmask;
1281 } else
1282 memset(&ife->addr, 0, sizeof(struct sockaddr));
1283 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001284#endif
1285
1286#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001287 /* DDP address maybe ? */
1288 fd = get_socket_for_af(AF_APPLETALK);
1289 if (fd >= 0) {
1290 strcpy(ifr.ifr_name, ifname);
1291 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1292 ife->ddpaddr = ifr.ifr_addr;
1293 ife->has_ddp = 1;
1294 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001295 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001296#endif
1297
1298#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001299 /* Look for IPX addresses with all framing types */
1300 fd = get_socket_for_af(AF_IPX);
1301 if (fd >= 0) {
1302 strcpy(ifr.ifr_name, ifname);
1303 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
1304 ife->has_ipx_bb = 1;
1305 ife->ipxaddr_bb = ifr.ifr_addr;
1306 }
1307 strcpy(ifr.ifr_name, ifname);
1308 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
1309 ife->has_ipx_sn = 1;
1310 ife->ipxaddr_sn = ifr.ifr_addr;
1311 }
1312 strcpy(ifr.ifr_name, ifname);
1313 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
1314 ife->has_ipx_e3 = 1;
1315 ife->ipxaddr_e3 = ifr.ifr_addr;
1316 }
1317 strcpy(ifr.ifr_name, ifname);
1318 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
1319 ife->has_ipx_e2 = 1;
1320 ife->ipxaddr_e2 = ifr.ifr_addr;
1321 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001322 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001323#endif
1324
1325#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001326 /* Econet address maybe? */
1327 fd = get_socket_for_af(AF_ECONET);
1328 if (fd >= 0) {
1329 strcpy(ifr.ifr_name, ifname);
1330 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1331 ife->ecaddr = ifr.ifr_addr;
1332 ife->has_econet = 1;
1333 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001334 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001335#endif
1336
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001337 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001338}
1339
1340
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001341static int do_if_fetch(struct interface *ife)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001342{
1343 if (if_fetch(ife) < 0) {
1344 char *errmsg;
1345
1346 if (errno == ENODEV) {
1347 /* Give better error message for this case. */
1348 errmsg = _("Device not found");
1349 } else {
1350 errmsg = strerror(errno);
1351 }
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001352 bb_error_msg(_("%s: error fetching interface information: %s"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001353 ife->name, errmsg);
1354 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001355 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001356 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001357}
1358
1359/* This structure defines hardware protocols and their handlers. */
1360struct hwtype {
Bernhard Reutner-Fischera901b402006-01-19 14:51:17 +00001361 const char * const name;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001362 const char *title;
1363 int type;
1364 int alen;
1365 char *(*print) (unsigned char *);
1366 int (*input) (char *, struct sockaddr *);
1367 int (*activate) (int fd);
1368 int suppress_null_addr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001369};
1370
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001371static const struct hwtype unspec_hwtype = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001372 "unspec", "UNSPEC", -1, 0,
1373 UNSPEC_print, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001374};
1375
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001376static const struct hwtype loop_hwtype = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001377 "loop", "Local Loopback", ARPHRD_LOOPBACK, 0,
1378 NULL, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001379};
1380
1381#if HAVE_HWETHER
1382#include <net/if_arp.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001383
Mike Frysinger3b05b802005-03-04 01:10:56 +00001384#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION)
Eric Andersenab4e19a2003-01-14 08:54:08 +00001385#include <net/ethernet.h>
1386#else
Eric Andersenf15d4da2001-03-06 00:48:59 +00001387#include <linux/if_ether.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001388#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001389
Eric Andersenf15d4da2001-03-06 00:48:59 +00001390/* Display an Ethernet address in readable format. */
1391static char *pr_ether(unsigned char *ptr)
1392{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001393 static char buff[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001394
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001395 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
1396 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
1397 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
1398 );
1399 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001400}
1401
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001402#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001403/* Input an Ethernet address and convert to binary. */
1404static int in_ether(char *bufp, struct sockaddr *sap)
1405{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001406 unsigned char *ptr;
1407 char c, *orig;
1408 int i;
1409 unsigned val;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001410
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001411 sap->sa_family = ether_hwtype.type;
1412 ptr = sap->sa_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001413
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001414 i = 0;
1415 orig = bufp;
1416 while ((*bufp != '\0') && (i < ETH_ALEN)) {
1417 val = 0;
1418 c = *bufp++;
1419 if (isdigit(c))
1420 val = c - '0';
1421 else if (c >= 'a' && c <= 'f')
1422 val = c - 'a' + 10;
1423 else if (c >= 'A' && c <= 'F')
1424 val = c - 'A' + 10;
1425 else {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001426#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001427 bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001428#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001429 errno = EINVAL;
1430 return (-1);
1431 }
1432 val <<= 4;
1433 c = *bufp;
1434 if (isdigit(c))
1435 val |= c - '0';
1436 else if (c >= 'a' && c <= 'f')
1437 val |= c - 'a' + 10;
1438 else if (c >= 'A' && c <= 'F')
1439 val |= c - 'A' + 10;
1440 else if (c == ':' || c == 0)
1441 val >>= 4;
1442 else {
1443#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001444 bb_error_msg(_("in_ether(%s): invalid ether address!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001445#endif
1446 errno = EINVAL;
1447 return (-1);
1448 }
1449 if (c != 0)
1450 bufp++;
1451 *ptr++ = (unsigned char) (val & 0377);
1452 i++;
1453
1454 /* We might get a semicolon here - not required. */
1455 if (*bufp == ':') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001456#ifdef DEBUG
Glenn L McGrath642f2892002-11-28 10:20:45 +00001457 if (i == ETH_ALEN) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001458 bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001459 }
Glenn L McGrath642f2892002-11-28 10:20:45 +00001460#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001461 bufp++;
1462 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001463 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001464
Glenn L McGrath642f2892002-11-28 10:20:45 +00001465#ifdef DEBUG
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001466 /* That's it. Any trailing junk? */
1467 if ((i == ETH_ALEN) && (*bufp != '\0')) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001468 bb_error_msg(_("in_ether(%s): trailing junk!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001469 errno = EINVAL;
1470 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001471 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001472 bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001473#endif
1474
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001475 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001476}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001477#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001478
1479
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001480static const struct hwtype ether_hwtype = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001481 "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN,
1482 pr_ether, NULL /* UNUSED in_ether */ , NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001483};
1484
1485
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001486#endif /* HAVE_HWETHER */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001487
1488
1489#if HAVE_HWPPP
1490
1491#include <net/if_arp.h>
1492
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001493#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001494/* Start the PPP encapsulation on the file descriptor. */
1495static int do_ppp(int fd)
1496{
Manuel Novoa III cad53642003-03-19 09:13:01 +00001497 bb_error_msg(_("You cannot start PPP with this program."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001498 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001499}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001500#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001501
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001502static const struct hwtype ppp_hwtype = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001503 "ppp", "Point-Point Protocol", ARPHRD_PPP, 0,
1504 NULL, NULL, NULL /* UNUSED do_ppp */ , 0
Eric Andersenf15d4da2001-03-06 00:48:59 +00001505};
1506
1507
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001508#endif /* HAVE_PPP */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001509
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001510static const struct hwtype * const hwtypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001511
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001512 &loop_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001513
1514#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001515 &slip_hwtype,
1516 &cslip_hwtype,
1517 &slip6_hwtype,
1518 &cslip6_hwtype,
1519 &adaptive_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001520#endif
1521#if HAVE_HWSTRIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001522 &strip_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001523#endif
1524#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001525 &ash_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001526#endif
1527#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001528 &ether_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001529#endif
1530#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001531 &tr_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001532#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001533 &tr_hwtype1,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001534#endif
1535#endif
1536#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001537 &ax25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001538#endif
1539#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001540 &netrom_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001541#endif
1542#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001543 &rose_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001544#endif
1545#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001546 &tunnel_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001547#endif
1548#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001549 &ppp_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001550#endif
1551#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001552 &hdlc_hwtype,
1553 &lapb_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001554#endif
1555#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001556 &arcnet_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001557#endif
1558#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001559 &dlci_hwtype,
1560 &frad_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001561#endif
1562#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001563 &sit_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001564#endif
1565#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001566 &fddi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001567#endif
1568#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001569 &hippi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001570#endif
1571#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001572 &irda_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001573#endif
1574#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001575 &ec_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001576#endif
1577#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001578 &x25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001579#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001580 &unspec_hwtype,
1581 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001582};
1583
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001584#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001585static short sVhwinit = 0;
1586
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001587static void hwinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +00001588{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001589 loop_hwtype.title = _("Local Loopback");
1590 unspec_hwtype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001591#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001592 slip_hwtype.title = _("Serial Line IP");
1593 cslip_hwtype.title = _("VJ Serial Line IP");
1594 slip6_hwtype.title = _("6-bit Serial Line IP");
1595 cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
1596 adaptive_hwtype.title = _("Adaptive Serial Line IP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001597#endif
1598#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001599 ether_hwtype.title = _("Ethernet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001600#endif
1601#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001602 ash_hwtype.title = _("Ash");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001603#endif
1604#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001605 fddi_hwtype.title = _("Fiber Distributed Data Interface");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001606#endif
1607#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001608 hippi_hwtype.title = _("HIPPI");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001609#endif
1610#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001611 ax25_hwtype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001612#endif
1613#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001614 rose_hwtype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001615#endif
1616#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001617 netrom_hwtype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001618#endif
1619#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001620 x25_hwtype.title = _("generic X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001621#endif
1622#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001623 tunnel_hwtype.title = _("IPIP Tunnel");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001624#endif
1625#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001626 ppp_hwtype.title = _("Point-to-Point Protocol");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001627#endif
1628#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001629 hdlc_hwtype.title = _("(Cisco)-HDLC");
1630 lapb_hwtype.title = _("LAPB");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001631#endif
1632#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001633 arcnet_hwtype.title = _("ARCnet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001634#endif
1635#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001636 dlci_hwtype.title = _("Frame Relay DLCI");
1637 frad_hwtype.title = _("Frame Relay Access Device");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001638#endif
1639#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001640 sit_hwtype.title = _("IPv6-in-IPv4");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001641#endif
1642#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001643 irda_hwtype.title = _("IrLAP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001644#endif
1645#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001646 tr_hwtype.title = _("16/4 Mbps Token Ring");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001647#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001648 tr_hwtype1.title = _("16/4 Mbps Token Ring (New)");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001649#endif
1650#endif
1651#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001652 ec_hwtype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001653#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001654 sVhwinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001655}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001656#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001657
1658#ifdef IFF_PORTSEL
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001659#if 0
1660static const char * const if_port_text[][4] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001661 /* Keep in step with <linux/netdevice.h> */
1662 {"unknown", NULL, NULL, NULL},
1663 {"10base2", "bnc", "coax", NULL},
1664 {"10baseT", "utp", "tpe", NULL},
1665 {"AUI", "thick", "db15", NULL},
1666 {"100baseT", NULL, NULL, NULL},
1667 {"100baseTX", NULL, NULL, NULL},
1668 {"100baseFX", NULL, NULL, NULL},
1669 {NULL, NULL, NULL, NULL},
Eric Andersenf15d4da2001-03-06 00:48:59 +00001670};
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001671#else
1672static const char * const if_port_text[] = {
1673 /* Keep in step with <linux/netdevice.h> */
1674 "unknown",
1675 "10base2",
1676 "10baseT",
1677 "AUI",
1678 "100baseT",
1679 "100baseTX",
1680 "100baseFX",
1681 NULL
1682};
1683#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001684#endif
1685
1686/* Check our hardware type table for this type. */
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001687static const struct hwtype *get_hwntype(int type)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001688{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001689 const struct hwtype * const *hwp;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001690
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001691#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001692 if (!sVhwinit)
1693 hwinit();
1694#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001695
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001696 hwp = hwtypes;
1697 while (*hwp != NULL) {
1698 if ((*hwp)->type == type)
1699 return (*hwp);
1700 hwp++;
1701 }
1702 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001703}
1704
1705/* return 1 if address is all zeros */
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001706static int hw_null_address(const struct hwtype *hw, void *ap)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001707{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001708 unsigned int i;
1709 unsigned char *address = (unsigned char *) ap;
1710
1711 for (i = 0; i < hw->alen; i++)
1712 if (address[i])
1713 return 0;
1714 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001715}
1716
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001717static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001718
1719static void print_bytes_scaled(unsigned long long ull, const char *end)
1720{
1721 unsigned long long int_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001722 const char *ext;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001723 unsigned int frac_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001724 int i;
1725
1726 frac_part = 0;
1727 ext = TRext;
1728 int_part = ull;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001729 i = 4;
1730 do {
1731#if 0
1732 /* This does correct rounding and is a little larger. But it
1733 * uses KiB as the smallest displayed unit. */
1734 if ((int_part < (1024*1024 - 51)) || !--i) {
1735 i = 0;
1736 int_part += 51; /* 1024*.05 = 51.2 */
1737 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001738 }
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001739 int_part /= 1024;
1740 ext += 3; /* KiB, MiB, GiB, TiB */
1741#else
1742 if (int_part >= 1024) {
1743 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
1744 int_part /= 1024;
1745 ext += 3; /* KiB, MiB, GiB, TiB */
1746 }
1747 --i;
1748#endif
1749 } while (i);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001750
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001751 printf("X bytes:%llu (%llu.%u %sB)%s", ull, int_part, frac_part, ext, end);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001752}
1753
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001754static const char * const ife_print_flags_strs[] = {
1755 "UP ",
1756 "BROADCAST ",
1757 "DEBUG ",
1758 "LOOPBACK ",
1759 "POINTOPOINT ",
1760 "NOTRAILERS ",
1761 "RUNNING ",
1762 "NOARP ",
1763 "PROMISC ",
1764 "ALLMULTI ",
1765 "SLAVE ",
1766 "MASTER ",
1767 "MULTICAST ",
1768#ifdef HAVE_DYNAMIC
1769 "DYNAMIC "
1770#endif
1771};
1772
1773static const unsigned short ife_print_flags_mask[] = {
1774 IFF_UP,
1775 IFF_BROADCAST,
1776 IFF_DEBUG,
1777 IFF_LOOPBACK,
1778 IFF_POINTOPOINT,
1779 IFF_NOTRAILERS,
1780 IFF_RUNNING,
1781 IFF_NOARP,
1782 IFF_PROMISC,
1783 IFF_ALLMULTI,
1784 IFF_SLAVE,
1785 IFF_MASTER,
1786 IFF_MULTICAST,
1787#ifdef HAVE_DYNAMIC
1788 IFF_DYNAMIC
1789#endif
1790 0
1791};
1792
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001793static void ife_print(struct interface *ptr)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001794{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001795 struct aftype *ap;
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +00001796 const struct hwtype *hw;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001797 int hf;
1798 int can_compress = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001799
1800#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001801 static struct aftype *ipxtype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001802#endif
1803#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001804 static struct aftype *ectype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001805#endif
1806#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001807 static struct aftype *ddptype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001808#endif
1809#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001810 FILE *f;
1811 char addr6[40], devname[20];
1812 struct sockaddr_in6 sap;
1813 int plen, scope, dad_status, if_idx;
1814 char addr6p[8][5];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001815#endif
1816
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001817 ap = get_afntype(ptr->addr.sa_family);
1818 if (ap == NULL)
1819 ap = get_afntype(0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001820
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001821 hf = ptr->type;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001822
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001823 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
1824 can_compress = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001825
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001826 hw = get_hwntype(hf);
1827 if (hw == NULL)
1828 hw = get_hwntype(-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001829
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001830 printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title));
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001831 /* For some hardware types (eg Ash, ATM) we don't print the
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001832 hardware address if it's null. */
1833 if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
1834 hw->suppress_null_addr)))
Eric Andersen0cb6f352006-01-30 22:30:41 +00001835 printf(_("HWaddr %s "), hw->print((unsigned char *)ptr->hwaddr));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001836#ifdef IFF_PORTSEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001837 if (ptr->flags & IFF_PORTSEL) {
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001838 printf(_("Media:%s"), if_port_text[ptr->map.port] /* [0] */);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001839 if (ptr->flags & IFF_AUTOMEDIA)
1840 printf(_("(auto)"));
1841 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001842#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001843 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001844
1845#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001846 if (ptr->has_ip) {
1847 printf(_(" %s addr:%s "), ap->name,
1848 ap->sprint(&ptr->addr, 1));
1849 if (ptr->flags & IFF_POINTOPOINT) {
1850 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
1851 }
1852 if (ptr->flags & IFF_BROADCAST) {
1853 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
1854 }
1855 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001856 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001857#endif
1858
1859#if HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +00001860
Eric Andersen51b8bd62002-07-03 11:46:38 +00001861#define IPV6_ADDR_ANY 0x0000U
1862
1863#define IPV6_ADDR_UNICAST 0x0001U
1864#define IPV6_ADDR_MULTICAST 0x0002U
1865#define IPV6_ADDR_ANYCAST 0x0004U
1866
1867#define IPV6_ADDR_LOOPBACK 0x0010U
1868#define IPV6_ADDR_LINKLOCAL 0x0020U
1869#define IPV6_ADDR_SITELOCAL 0x0040U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001870
Eric Andersen51b8bd62002-07-03 11:46:38 +00001871#define IPV6_ADDR_COMPATv4 0x0080U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001872
Eric Andersen51b8bd62002-07-03 11:46:38 +00001873#define IPV6_ADDR_SCOPE_MASK 0x00f0U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001874
Eric Andersen51b8bd62002-07-03 11:46:38 +00001875#define IPV6_ADDR_MAPPED 0x1000U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001876#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
1877
1878 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1879 while (fscanf
1880 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
1881 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
1882 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
1883 &dad_status, devname) != EOF) {
1884 if (!strcmp(devname, ptr->name)) {
1885 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1886 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1887 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1888 inet_pton(AF_INET6, addr6,
1889 (struct sockaddr *) &sap.sin6_addr);
1890 sap.sin6_family = AF_INET6;
1891 printf(_(" inet6 addr: %s/%d"),
1892 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
1893 plen);
1894 printf(_(" Scope:"));
1895 switch (scope & IPV6_ADDR_SCOPE_MASK) {
1896 case 0:
1897 printf(_("Global"));
1898 break;
1899 case IPV6_ADDR_LINKLOCAL:
1900 printf(_("Link"));
1901 break;
1902 case IPV6_ADDR_SITELOCAL:
1903 printf(_("Site"));
1904 break;
1905 case IPV6_ADDR_COMPATv4:
1906 printf(_("Compat"));
1907 break;
1908 case IPV6_ADDR_LOOPBACK:
1909 printf(_("Host"));
1910 break;
1911 default:
1912 printf(_("Unknown"));
1913 }
1914 printf("\n");
1915 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001916 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001917 fclose(f);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001918 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001919#endif
1920
1921#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001922 if (ipxtype == NULL)
1923 ipxtype = get_afntype(AF_IPX);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001924
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001925 if (ipxtype != NULL) {
1926 if (ptr->has_ipx_bb)
1927 printf(_(" IPX/Ethernet II addr:%s\n"),
1928 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
1929 if (ptr->has_ipx_sn)
1930 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
1931 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
1932 if (ptr->has_ipx_e2)
1933 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
1934 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
1935 if (ptr->has_ipx_e3)
1936 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
1937 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
1938 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001939#endif
1940
1941#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001942 if (ddptype == NULL)
1943 ddptype = get_afntype(AF_APPLETALK);
1944 if (ddptype != NULL) {
1945 if (ptr->has_ddp)
1946 printf(_(" EtherTalk Phase 2 addr:%s\n"),
1947 ddptype->sprint(&ptr->ddpaddr, 1));
1948 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001949#endif
1950
1951#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001952 if (ectype == NULL)
1953 ectype = get_afntype(AF_ECONET);
1954 if (ectype != NULL) {
1955 if (ptr->has_econet)
1956 printf(_(" econet addr:%s\n"),
1957 ectype->sprint(&ptr->ecaddr, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001958 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001959#endif
1960
1961 printf(" ");
1962 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001963
1964 if (ptr->flags == 0) {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001965 printf(_("[NO FLAGS] "));
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001966 } else {
1967 int i = 0;
1968 do {
1969 if (ptr->flags & ife_print_flags_mask[i]) {
1970 printf(_(ife_print_flags_strs[i]));
1971 }
1972 } while (ife_print_flags_mask[++i]);
1973 }
1974
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001975 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1976 printf(_(" MTU:%d Metric:%d"), ptr->mtu, ptr->metric ? ptr->metric : 1);
1977#ifdef SIOCSKEEPALIVE
1978 if (ptr->outfill || ptr->keepalive)
1979 printf(_(" Outfill:%d Keepalive:%d"), ptr->outfill, ptr->keepalive);
1980#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001981 printf("\n");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001982
1983 /* If needed, display the interface statistics. */
1984
1985 if (ptr->statistics_valid) {
1986 /* XXX: statistics are currently only printed for the primary address,
1987 * not for the aliases, although strictly speaking they're shared
1988 * by all addresses.
1989 */
1990 printf(" ");
1991
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001992 printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001993 ptr->stats.rx_packets, ptr->stats.rx_errors,
1994 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1995 ptr->stats.rx_frame_errors);
1996 if (can_compress)
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001997 printf(" compressed:%lu\n",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001998 ptr->stats.rx_compressed);
1999 printf(" ");
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00002000 printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002001 ptr->stats.tx_packets, ptr->stats.tx_errors,
2002 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
2003 ptr->stats.tx_carrier_errors);
Bernhard Reutner-Fischer214744d2006-03-30 13:38:19 +00002004 printf(" collisions:%lu ", ptr->stats.collisions);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002005 if (can_compress)
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00002006 printf("compressed:%lu ", ptr->stats.tx_compressed);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002007 if (ptr->tx_queue_len != -1)
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00002008 printf("txqueuelen:%d ", ptr->tx_queue_len);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002009 printf("\n R");
2010 print_bytes_scaled(ptr->stats.rx_bytes, " T");
2011 print_bytes_scaled(ptr->stats.tx_bytes, "\n");
2012
2013 }
2014
2015 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
2016 ptr->map.base_addr)) {
2017 printf(" ");
2018 if (ptr->map.irq)
2019 printf(_("Interrupt:%d "), ptr->map.irq);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002020 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002021 I/O maps */
2022 printf(_("Base address:0x%lx "),
2023 (unsigned long) ptr->map.base_addr);
2024 if (ptr->map.mem_start) {
2025 printf(_("Memory:%lx-%lx "), ptr->map.mem_start,
2026 ptr->map.mem_end);
2027 }
2028 if (ptr->map.dma)
2029 printf(_("DMA chan:%x "), ptr->map.dma);
2030 printf("\n");
2031 }
2032 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00002033}
2034
2035
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002036static int do_if_print(struct interface *ife, void *cookie)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002037{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002038 int *opt_a = (int *) cookie;
2039 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002040
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002041 res = do_if_fetch(ife);
2042 if (res >= 0) {
2043 if ((ife->flags & IFF_UP) || *opt_a)
2044 ife_print(ife);
2045 }
2046 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002047}
2048
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002049static struct interface *lookup_interface(char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002050{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002051 struct interface *ife = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002052
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002053 if (if_readlist_proc(name) < 0)
2054 return NULL;
2055 ife = add_interface(name);
2056 return ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002057}
2058
2059/* for ipv4 add/del modes */
2060static int if_print(char *ifname)
2061{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002062 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002063
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002064 if (!ifname) {
2065 res = for_all_interfaces(do_if_print, &interface_opt_a);
2066 } else {
2067 struct interface *ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002068
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002069 ife = lookup_interface(ifname);
2070 res = do_if_fetch(ife);
2071 if (res >= 0)
2072 ife_print(ife);
2073 }
2074 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002075}
2076
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002077int display_interfaces(char *ifname)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002078{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002079 int status;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002080
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002081 /* Create a channel to the NET kernel. */
2082 if ((skfd = sockets_open(0)) < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002083 bb_perror_msg_and_die("socket");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002084 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00002085
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002086 /* Do we have to show the current setup? */
2087 status = if_print(ifname);
Rob Landley93983042005-05-03 21:30:26 +00002088#ifdef CONFIG_FEATURE_CLEAN_UP
2089 sockets_close();
2090#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002091 exit(status < 0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00002092}