blob: 37a5f6405a668e17d2561c3c268d86cff3dac939 [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>
Glenn L McGrath6b8c5502001-05-05 03:19:12 +000076#include "libbb.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 _(x) x
85#define _PATH_PROCNET_DEV "/proc/net/dev"
Eric Andersen51b8bd62002-07-03 11:46:38 +000086#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
Eric Andersenf15d4da2001-03-06 00:48:59 +000087#define new(p) ((p) = xcalloc(1,sizeof(*(p))))
Eric Andersen8b113f92001-06-01 21:47:15 +000088#define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch))
Eric Andersenf15d4da2001-03-06 00:48:59 +000089
Eric Andersenf15d4da2001-03-06 00:48:59 +000090#ifdef HAVE_HWSLIP
Eric Andersenab4e19a2003-01-14 08:54:08 +000091#include <net/if_slip.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +000092#endif
93
94#if HAVE_AFINET6
95
96#ifndef _LINUX_IN6_H
97/*
98 * This is in linux/include/net/ipv6.h.
99 */
100
101struct in6_ifreq {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000102 struct in6_addr ifr6_addr;
Glenn L McGrathb54a7482003-08-29 11:34:08 +0000103 uint32_t ifr6_prefixlen;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000104 unsigned int ifr6_ifindex;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000105};
106
107#endif
108
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000109#endif /* HAVE_AFINET6 */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000110
111#if HAVE_AFIPX
Eric Andersenb6b519b2001-04-09 23:52:18 +0000112#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000113#include <netipx/ipx.h>
114#else
115#include "ipx.h"
116#endif
117#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000118
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000119/* Defines for glibc2.0 users. */
120#ifndef SIOCSIFTXQLEN
121#define SIOCSIFTXQLEN 0x8943
122#define SIOCGIFTXQLEN 0x8942
123#endif
124
125/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
126#ifndef ifr_qlen
127#define ifr_qlen ifr_ifru.ifru_mtu
128#endif
129
130#ifndef HAVE_TXQUEUELEN
131#define HAVE_TXQUEUELEN 1
132#endif
133
134#ifndef IFF_DYNAMIC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000135#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000136#endif
137
Eric Andersenf15d4da2001-03-06 00:48:59 +0000138/* This structure defines protocol families and their handlers. */
139struct aftype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000140 const char *name;
141 const char *title;
142 int af;
143 int alen;
144 char *(*print) (unsigned char *);
145 char *(*sprint) (struct sockaddr *, int numeric);
146 int (*input) (int type, char *bufp, struct sockaddr *);
147 void (*herror) (char *text);
148 int (*rprint) (int options);
149 int (*rinput) (int typ, int ext, char **argv);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000150
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000151 /* may modify src */
152 int (*getmask) (char *src, struct sockaddr * mask, char *name);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000153
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000154 int fd;
155 char *flag_file;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000156};
157
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000158#ifdef KEEP_UNUSED
159
160static int flag_unx;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000161
Eric Andersen8b113f92001-06-01 21:47:15 +0000162#ifdef HAVE_AFIPX
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000163static int flag_ipx;
Eric Andersen8b113f92001-06-01 21:47:15 +0000164#endif
165#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000166static int flag_ax25;
Eric Andersen8b113f92001-06-01 21:47:15 +0000167#endif
168#ifdef HAVE_AFATALK
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000169static int flag_ddp;
Eric Andersen8b113f92001-06-01 21:47:15 +0000170#endif
171#ifdef HAVE_AFNETROM
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000172static int flag_netrom;
Eric Andersen8b113f92001-06-01 21:47:15 +0000173#endif
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000174static int flag_inet;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000175
Eric Andersen8b113f92001-06-01 21:47:15 +0000176#ifdef HAVE_AFINET6
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000177static int flag_inet6;
Eric Andersen8b113f92001-06-01 21:47:15 +0000178#endif
179#ifdef HAVE_AFECONET
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000180static int flag_econet;
Eric Andersen8b113f92001-06-01 21:47:15 +0000181#endif
182#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000183static int flag_x25 = 0;
Eric Andersen8b113f92001-06-01 21:47:15 +0000184#endif
185#ifdef HAVE_AFASH
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000186static int flag_ash;
Eric Andersen8b113f92001-06-01 21:47:15 +0000187#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000188
189
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000190static struct aftrans_t {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000191 char *alias;
192 char *name;
193 int *flag;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000194} aftrans[] = {
195
Eric Andersen8b113f92001-06-01 21:47:15 +0000196#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000197 {
198 "ax25", "ax25", &flag_ax25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000199#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000200 {
201 "ip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000202#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000203 {
204 "ip6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000205#endif
206#ifdef HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000207 {
208 "ipx", "ipx", &flag_ipx},
Eric Andersen8b113f92001-06-01 21:47:15 +0000209#endif
210#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000211 {
212 "appletalk", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000213#endif
214#ifdef HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000215 {
216 "netrom", "netrom", &flag_netrom},
Eric Andersen8b113f92001-06-01 21:47:15 +0000217#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000218 {
219 "inet", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000220#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000221 {
222 "inet6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000223#endif
224#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000225 {
226 "ddp", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000227#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000228 {
229 "unix", "unix", &flag_unx}, {
230 "tcpip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000231#ifdef HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000232 {
233 "econet", "ec", &flag_econet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000234#endif
235#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000236 {
237 "x25", "x25", &flag_x25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000238#endif
239#ifdef HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000240 {
241 "ash", "ash", &flag_ash},
Eric Andersen8b113f92001-06-01 21:47:15 +0000242#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000243 {
244 0, 0, 0}
Eric Andersenf15d4da2001-03-06 00:48:59 +0000245};
246
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000247static char afname[256] = "";
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000248#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000249
250#if HAVE_AFUNIX
251
252/* Display a UNIX domain address. */
253static char *UNIX_print(unsigned char *ptr)
254{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000255 return (ptr);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000256}
257
258
259/* Display a UNIX domain address. */
260static char *UNIX_sprint(struct sockaddr *sap, int numeric)
261{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000262 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000263
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000264 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
265 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
266 return (UNIX_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000267}
268
269
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000270static struct aftype unix_aftype = {
271 "unix", "UNIX Domain", AF_UNIX, 0,
272 UNIX_print, UNIX_sprint, NULL, NULL,
273 NULL, NULL, NULL,
274 -1,
275 "/proc/net/unix"
Eric Andersenf15d4da2001-03-06 00:48:59 +0000276};
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000277#endif /* HAVE_AFUNIX */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000278
279#if HAVE_AFINET
280
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000281#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000282static void INET_reserror(char *text)
283{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000284 herror(text);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000285}
286
Eric Andersenf15d4da2001-03-06 00:48:59 +0000287/* Display an Internet socket address. */
288static char *INET_print(unsigned char *ptr)
289{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000290 return (inet_ntoa((*(struct in_addr *) ptr)));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000291}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000292#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000293
294/* Display an Internet socket address. */
295static char *INET_sprint(struct sockaddr *sap, int numeric)
296{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000297 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000298
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000299 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
300 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000301
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000302 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
303 numeric, 0xffffff00) != 0)
304 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000305
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000306 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000307}
308
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000309#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000310static char *INET_sprintmask(struct sockaddr *sap, int numeric,
311 unsigned int netmask)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000312{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000313 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000314
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000315 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
316 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
317 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
318 numeric, netmask) != 0)
319 return (NULL);
320 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000321}
322
Eric Andersenf15d4da2001-03-06 00:48:59 +0000323static int INET_getsock(char *bufp, struct sockaddr *sap)
324{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000325 char *sp = bufp, *bp;
326 unsigned int i;
327 unsigned val;
328 struct sockaddr_in *sin;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000329
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000330 sin = (struct sockaddr_in *) sap;
331 sin->sin_family = AF_INET;
332 sin->sin_port = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000333
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000334 val = 0;
335 bp = (char *) &val;
336 for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) {
337 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000338
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000339 if ((*sp >= 'A') && (*sp <= 'F'))
340 bp[i] |= (int) (*sp - 'A') + 10;
341 else if ((*sp >= '0') && (*sp <= '9'))
342 bp[i] |= (int) (*sp - '0');
343 else
344 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000345
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000346 bp[i] <<= 4;
347 sp++;
348 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000349
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000350 if ((*sp >= 'A') && (*sp <= 'F'))
351 bp[i] |= (int) (*sp - 'A') + 10;
352 else if ((*sp >= '0') && (*sp <= '9'))
353 bp[i] |= (int) (*sp - '0');
354 else
355 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000356
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000357 sp++;
358 }
359 sin->sin_addr.s_addr = htonl(val);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000360
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000361 return (sp - bufp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000362}
363
364static int INET_input(int type, char *bufp, struct sockaddr *sap)
365{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000366 switch (type) {
367 case 1:
368 return (INET_getsock(bufp, sap));
369 case 256:
370 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
371 default:
372 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
373 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000374}
375
376static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
377{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000378 struct sockaddr_in *mask = (struct sockaddr_in *) m;
379 char *slash, *end;
380 int prefix;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000381
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000382 if ((slash = strchr(adr, '/')) == NULL)
383 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000384
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000385 *slash++ = '\0';
386 prefix = strtoul(slash, &end, 0);
387 if (*end != '\0')
388 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000389
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000390 if (name) {
391 sprintf(name, "/%d", prefix);
392 }
393 mask->sin_family = AF_INET;
394 mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
395 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000396}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000397#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000398
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000399static struct aftype inet_aftype = {
400 "inet", "DARPA Internet", AF_INET, sizeof(unsigned long),
401 NULL /* UNUSED INET_print */ , INET_sprint,
402 NULL /* UNUSED INET_input */ , NULL /* UNUSED INET_reserror */ ,
403 NULL /*INET_rprint */ , NULL /*INET_rinput */ ,
404 NULL /* UNUSED INET_getnetmask */ ,
405 -1,
406 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000407};
408
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000409#endif /* HAVE_AFINET */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000410
Eric Andersen51b8bd62002-07-03 11:46:38 +0000411#if HAVE_AFINET6
412
413#ifdef KEEP_UNUSED
414static void INET6_reserror(char *text)
415{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000416 herror(text);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000417}
418
419/* Display an Internet socket address. */
420static char *INET6_print(unsigned char *ptr)
421{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000422 static char name[80];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000423
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000424 inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80);
425 return name;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000426}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000427#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000428
429/* Display an Internet socket address. */
430/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
431static char *INET6_sprint(struct sockaddr *sap, int numeric)
432{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000433 static char buff[128];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000434
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000435 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
436 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
437 if (INET6_rresolve
438 (buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)
439 return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff));
440 return (buff);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000441}
442
443#ifdef KEEP_UNUSED
444static int INET6_getsock(char *bufp, struct sockaddr *sap)
445{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000446 struct sockaddr_in6 *sin6;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000447
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000448 sin6 = (struct sockaddr_in6 *) sap;
449 sin6->sin6_family = AF_INET6;
450 sin6->sin6_port = 0;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000451
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000452 if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0)
453 return (-1);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000454
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000455 return 16; /* ?;) */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000456}
457
458static int INET6_input(int type, char *bufp, struct sockaddr *sap)
459{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000460 switch (type) {
461 case 1:
462 return (INET6_getsock(bufp, sap));
463 default:
464 return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));
465 }
Eric Andersen51b8bd62002-07-03 11:46:38 +0000466}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000467#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000468
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000469static struct aftype inet6_aftype = {
470 "inet6", "IPv6", AF_INET6, sizeof(struct in6_addr),
471 NULL /* UNUSED INET6_print */ , INET6_sprint,
472 NULL /* UNUSED INET6_input */ , NULL /* UNUSED INET6_reserror */ ,
473 NULL /*INET6_rprint */ , NULL /*INET6_rinput */ ,
474 NULL /* UNUSED INET6_getnetmask */ ,
475 -1,
476 NULL
Eric Andersen51b8bd62002-07-03 11:46:38 +0000477};
478
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000479#endif /* HAVE_AFINET6 */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000480
Eric Andersenf15d4da2001-03-06 00:48:59 +0000481/* Display an UNSPEC address. */
482static char *UNSPEC_print(unsigned char *ptr)
483{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000484 static char buff[sizeof(struct sockaddr) * 3 + 1];
485 char *pos;
486 unsigned int i;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000487
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000488 pos = buff;
489 for (i = 0; i < sizeof(struct sockaddr); i++) {
490 /* careful -- not every libc's sprintf returns # bytes written */
491 sprintf(pos, "%02X-", (*ptr++ & 0377));
492 pos += 3;
493 }
494 /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */
495 *--pos = '\0';
496 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000497}
498
499/* Display an UNSPEC socket address. */
500static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
501{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000502 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000503
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000504 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
505 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
506 return (UNSPEC_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000507}
508
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000509static struct aftype unspec_aftype = {
510 "unspec", "UNSPEC", AF_UNSPEC, 0,
511 UNSPEC_print, UNSPEC_sprint, NULL, NULL,
512 NULL,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000513};
514
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000515static struct aftype *aftypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000516#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000517 &unix_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000518#endif
519#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000520 &inet_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000521#endif
522#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000523 &inet6_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000524#endif
525#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000526 &ax25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000527#endif
528#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000529 &netrom_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000530#endif
531#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000532 &rose_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000533#endif
534#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000535 &ipx_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000536#endif
537#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000538 &ddp_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000539#endif
540#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000541 &ec_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000542#endif
543#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000544 &ash_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000545#endif
546#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000547 &x25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000548#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000549 &unspec_aftype,
550 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000551};
552
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000553#ifdef KEEP_UNUSED
554static short sVafinit = 0;
555
556static void afinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +0000557{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000558 unspec_aftype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000559#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000560 unix_aftype.title = _("UNIX Domain");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000561#endif
562#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000563 inet_aftype.title = _("DARPA Internet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000564#endif
565#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000566 inet6_aftype.title = _("IPv6");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000567#endif
568#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000569 ax25_aftype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000570#endif
571#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000572 netrom_aftype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000573#endif
574#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000575 ipx_aftype.title = _("Novell IPX");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000576#endif
577#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000578 ddp_aftype.title = _("Appletalk DDP");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000579#endif
580#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000581 ec_aftype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000582#endif
583#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000584 x25_aftype.title = _("CCITT X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000585#endif
586#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000587 rose_aftype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000588#endif
589#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000590 ash_aftype.title = _("Ash");
591#endif
592 sVafinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000593}
594
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000595static int aftrans_opt(const char *arg)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000596{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000597 struct aftrans_t *paft;
598 char *tmp1, *tmp2;
599 char buf[256];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000600
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000601 safe_strncpy(buf, arg, sizeof(buf));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000602
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000603 tmp1 = buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000604
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000605 while (tmp1) {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000606
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000607 tmp2 = strchr(tmp1, ',');
Eric Andersenf15d4da2001-03-06 00:48:59 +0000608
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000609 if (tmp2)
610 *(tmp2++) = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000611
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000612 paft = aftrans;
613 for (paft = aftrans; paft->alias; paft++) {
614 if (strcmp(tmp1, paft->alias))
615 continue;
616 if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000617 bb_error_msg(_("Too many address family arguments."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000618 return (0);
619 }
620 if (paft->flag)
621 (*paft->flag)++;
622 if (afname[0])
623 strcat(afname, ",");
624 strcat(afname, paft->name);
625 break;
626 }
627 if (!paft->alias) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000628 bb_error_msg(_("Unknown address family `%s'."), tmp1);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000629 return (1);
630 }
631 tmp1 = tmp2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000632 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000633
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000634 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000635}
636
637/* set the default AF list from the program name or a constant value */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000638static void aftrans_def(char *tool, char *argv0, char *dflt)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000639{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000640 char *tmp;
641 char *buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000642
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000643 strcpy(afname, dflt);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000644
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000645 if (!(tmp = strrchr(argv0, '/')))
646 tmp = argv0; /* no slash?! */
647 else
648 tmp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000649
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000650 if (!(buf = strdup(tmp)))
651 return;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000652
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000653 if (strlen(tool) >= strlen(tmp)) {
654 free(buf);
655 return;
656 }
657 tmp = buf + (strlen(tmp) - strlen(tool));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000658
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000659 if (strcmp(tmp, tool) != 0) {
660 free(buf);
661 return;
662 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000663 *tmp = '\0';
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000664 if ((tmp = strchr(buf, '_')))
665 *tmp = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000666
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000667 afname[0] = '\0';
668 if (aftrans_opt(buf))
669 strcpy(afname, buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000670
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000671 free(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000672}
673
Eric Andersenf15d4da2001-03-06 00:48:59 +0000674/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000675static struct aftype *get_aftype(const char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000676{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000677 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000678
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000679#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000680 if (!sVafinit)
681 afinit();
682#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000683
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000684 afp = aftypes;
685 while (*afp != NULL) {
686 if (!strcmp((*afp)->name, name))
687 return (*afp);
688 afp++;
689 }
690 if (strchr(name, ','))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000691 bb_error_msg(_("Please don't supply more than one address family."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000692 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000693}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000694#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000695
696/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000697static struct aftype *get_afntype(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000698{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000699 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000700
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000701#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000702 if (!sVafinit)
703 afinit();
704#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000705
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000706 afp = aftypes;
707 while (*afp != NULL) {
708 if ((*afp)->af == af)
709 return (*afp);
710 afp++;
711 }
712 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000713}
714
715/* Check our protocol family table for this family and return its socket */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000716static int get_socket_for_af(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000717{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000718 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000719
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000720#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000721 if (!sVafinit)
722 afinit();
723#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000724
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000725 afp = aftypes;
726 while (*afp != NULL) {
727 if ((*afp)->af == af)
728 return (*afp)->fd;
729 afp++;
730 }
731 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000732}
733
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000734#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000735/* type: 0=all, 1=getroute */
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000736static void print_aflist(int type)
737{
738 int count = 0;
739 char *txt;
740 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000741
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000742#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000743 if (!sVafinit)
744 afinit();
745#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000746
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000747 afp = aftypes;
748 while (*afp != NULL) {
749 if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) {
750 afp++;
751 continue;
752 }
753 if ((count % 3) == 0)
754 fprintf(stderr, count ? "\n " : " ");
755 txt = (*afp)->name;
756 if (!txt)
757 txt = "..";
758 fprintf(stderr, "%s (%s) ", txt, _((*afp)->title));
759 count++;
760 afp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000761 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000762 fprintf(stderr, "\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000763}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000764#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000765
766struct user_net_device_stats {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000767 unsigned long long rx_packets; /* total packets received */
768 unsigned long long tx_packets; /* total packets transmitted */
769 unsigned long long rx_bytes; /* total bytes received */
770 unsigned long long tx_bytes; /* total bytes transmitted */
771 unsigned long rx_errors; /* bad packets received */
772 unsigned long tx_errors; /* packet transmit problems */
773 unsigned long rx_dropped; /* no space in linux buffers */
774 unsigned long tx_dropped; /* no space available in linux */
775 unsigned long rx_multicast; /* multicast packets received */
776 unsigned long rx_compressed;
777 unsigned long tx_compressed;
778 unsigned long collisions;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000779
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000780 /* detailed rx_errors: */
781 unsigned long rx_length_errors;
782 unsigned long rx_over_errors; /* receiver ring buff overflow */
783 unsigned long rx_crc_errors; /* recved pkt with crc error */
784 unsigned long rx_frame_errors; /* recv'd frame alignment error */
785 unsigned long rx_fifo_errors; /* recv'r fifo overrun */
786 unsigned long rx_missed_errors; /* receiver missed packet */
787 /* detailed tx_errors */
788 unsigned long tx_aborted_errors;
789 unsigned long tx_carrier_errors;
790 unsigned long tx_fifo_errors;
791 unsigned long tx_heartbeat_errors;
792 unsigned long tx_window_errors;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000793};
794
795struct interface {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000796 struct interface *next, *prev;
797 char name[IFNAMSIZ]; /* interface name */
798 short type; /* if type */
799 short flags; /* various flags */
800 int metric; /* routing metric */
801 int mtu; /* MTU value */
802 int tx_queue_len; /* transmit queue length */
803 struct ifmap map; /* hardware setup */
804 struct sockaddr addr; /* IP address */
805 struct sockaddr dstaddr; /* P-P IP address */
806 struct sockaddr broadaddr; /* IP broadcast address */
807 struct sockaddr netmask; /* IP network mask */
808 struct sockaddr ipxaddr_bb; /* IPX network address */
809 struct sockaddr ipxaddr_sn; /* IPX network address */
810 struct sockaddr ipxaddr_e3; /* IPX network address */
811 struct sockaddr ipxaddr_e2; /* IPX network address */
812 struct sockaddr ddpaddr; /* Appletalk DDP address */
813 struct sockaddr ecaddr; /* Econet address */
814 int has_ip;
815 int has_ipx_bb;
816 int has_ipx_sn;
817 int has_ipx_e3;
818 int has_ipx_e2;
819 int has_ax25;
820 int has_ddp;
821 int has_econet;
822 char hwaddr[32]; /* HW address */
823 int statistics_valid;
824 struct user_net_device_stats stats; /* statistics */
825 int keepalive; /* keepalive value for SLIP */
826 int outfill; /* outfill value for SLIP */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000827};
828
829
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000830int interface_opt_a = 0; /* show all interfaces */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000831
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000832#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000833static int opt_i = 0; /* show the statistics */
834static int opt_v = 0; /* debugging output flag */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000835
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000836static int addr_family = 0; /* currently selected AF */
837#endif /* KEEP_UNUSED */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000838
Eric Andersenf15d4da2001-03-06 00:48:59 +0000839static struct interface *int_list, *int_last;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000840static int skfd = -1; /* generic raw socket desc. */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000841
842
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000843static int sockets_open(int family)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000844{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000845 struct aftype **aft;
846 int sfd = -1;
847 static int force = -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000848
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000849 if (force < 0) {
850 force = 0;
851 if (get_kernel_revision() < KRELEASE(2, 1, 0))
852 force = 1;
853 if (access("/proc/net", R_OK))
854 force = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000855 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000856 for (aft = aftypes; *aft; aft++) {
857 struct aftype *af = *aft;
858 int type = SOCK_DGRAM;
859
860 if (af->af == AF_UNSPEC)
861 continue;
862 if (family && family != af->af)
863 continue;
864 if (af->fd != -1) {
865 sfd = af->fd;
866 continue;
867 }
868 /* Check some /proc file first to not stress kmod */
869 if (!family && !force && af->flag_file) {
870 if (access(af->flag_file, R_OK))
871 continue;
872 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000873#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000874 if (af->af == AF_NETROM)
875 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000876#endif
877#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000878 if (af->af == AF_X25)
879 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000880#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000881 af->fd = socket(af->af, type, 0);
882 if (af->fd >= 0)
883 sfd = af->fd;
884 }
Glenn L McGrath642f2892002-11-28 10:20:45 +0000885 if (sfd < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000886 bb_error_msg(_("No usable address families found."));
Glenn L McGrath642f2892002-11-28 10:20:45 +0000887 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000888 return sfd;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000889}
890
891/* like strcmp(), but knows about numbers */
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000892static int nstrcmp(const char *a, const char *b)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000893{
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000894 const char *a_ptr = a;
895 const char *b_ptr = b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000896
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000897 while (*a == *b) {
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000898 if (*a == '\0') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000899 return 0;
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000900 }
901 if (!isdigit(*a) && isdigit(*(a+1))) {
902 a_ptr = a+1;
903 b_ptr = b+1;
904 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000905 a++;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000906 b++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000907 }
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000908
909 if (isdigit(*a) && isdigit(*b)) {
910 return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000911 }
912 return *a - *b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000913}
914
915static struct interface *add_interface(char *name)
916{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000917 struct interface *ife, **nextp, *new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000918
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000919 for (ife = int_last; ife; ife = ife->prev) {
920 int n = nstrcmp(ife->name, name);
921
922 if (n == 0)
923 return ife;
924 if (n < 0)
925 break;
926 }
927 new(new);
928 safe_strncpy(new->name, name, IFNAMSIZ);
929 nextp = ife ? &ife->next : &int_list;
930 new->prev = ife;
931 new->next = *nextp;
932 if (new->next)
933 new->next->prev = new;
934 else
935 int_last = new;
936 *nextp = new;
937 return new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000938}
939
940
941static int if_readconf(void)
942{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000943 int numreqs = 30;
944 struct ifconf ifc;
945 struct ifreq *ifr;
946 int n, err = -1;
947 int skfd2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000948
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000949 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
950 (as of 2.1.128) */
951 skfd2 = get_socket_for_af(AF_INET);
952 if (skfd2 < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000953 bb_perror_msg(("warning: no inet socket available"));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000954 /* Try to soldier on with whatever socket we can get hold of. */
955 skfd2 = sockets_open(0);
956 if (skfd2 < 0)
957 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000958 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000959
960 ifc.ifc_buf = NULL;
961 for (;;) {
962 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
963 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
964
965 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
966 perror("SIOCGIFCONF");
967 goto out;
968 }
969 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
970 /* assume it overflowed and try again */
971 numreqs += 10;
972 continue;
973 }
974 break;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000975 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000976
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000977 ifr = ifc.ifc_req;
978 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
979 add_interface(ifr->ifr_name);
980 ifr++;
981 }
982 err = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000983
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000984 out:
985 free(ifc.ifc_buf);
986 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000987}
988
Eric Andersen14f5c8d2005-04-16 19:39:00 +0000989static char *get_name(char *name, char *p)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000990{
Eric Andersen9940e082004-08-12 16:52:00 +0000991 /* Extract <name>[:<alias>] from nul-terminated p where p matches
992 <name>[:<alias>]: after leading whitespace.
993 If match is not made, set name empty and return unchanged p */
994 int namestart=0, nameend=0, aliasend;
995 while (isspace(p[namestart]))
996 namestart++;
997 nameend=namestart;
998 while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
999 nameend++;
1000 if (p[nameend]==':') {
1001 aliasend=nameend+1;
1002 while (p[aliasend] && isdigit(p[aliasend]))
1003 aliasend++;
1004 if (p[aliasend]==':') {
1005 nameend=aliasend;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001006 }
Eric Andersen9940e082004-08-12 16:52:00 +00001007 if ((nameend-namestart)<IFNAMSIZ) {
1008 memcpy(name,&p[namestart],nameend-namestart);
1009 name[nameend-namestart]='\0';
1010 p=&p[nameend];
1011 } else {
1012 /* Interface name too large */
1013 name[0]='\0';
1014 }
1015 } else {
1016 /* first ':' not found - return empty */
1017 name[0]='\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +00001018 }
Eric Andersen6fea7322004-08-26 21:45:21 +00001019 return p + 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001020}
1021
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001022/* If scanf supports size qualifiers for %n conversions, then we can
1023 * use a modified fmt that simply stores the position in the fields
1024 * having no associated fields in the proc string. Of course, we need
1025 * to zero them again when we're done. But that is smaller than the
1026 * old approach of multiple scanf occurrences with large numbers of
1027 * args. */
1028
1029/* static const char *ss_fmt[] = { */
1030/* "%Ln%Lu%lu%lu%lu%lu%ln%ln%Ln%Lu%lu%lu%lu%lu%lu", */
1031/* "%Lu%Lu%lu%lu%lu%lu%ln%ln%Lu%Lu%lu%lu%lu%lu%lu", */
1032/* "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu" */
1033/* }; */
1034
1035 /* Lie about the size of the int pointed to for %n. */
1036#if INT_MAX == LONG_MAX
1037static const char *ss_fmt[] = {
1038 "%n%Lu%u%u%u%u%n%n%n%Lu%u%u%u%u%u",
1039 "%Lu%Lu%u%u%u%u%n%n%Lu%Lu%u%u%u%u%u",
1040 "%Lu%Lu%u%u%u%u%u%u%Lu%Lu%u%u%u%u%u%u"
1041};
1042#else
1043static const char *ss_fmt[] = {
1044 "%n%Lu%lu%lu%lu%lu%n%n%n%Lu%lu%lu%lu%lu%lu",
1045 "%Lu%Lu%lu%lu%lu%lu%n%n%Lu%Lu%lu%lu%lu%lu%lu",
1046 "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu"
1047};
1048
1049#endif
1050
1051static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001052{
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001053 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
1054
1055 sscanf(bp, ss_fmt[procnetdev_vsn],
1056 &ife->stats.rx_bytes, /* missing for 0 */
1057 &ife->stats.rx_packets,
1058 &ife->stats.rx_errors,
1059 &ife->stats.rx_dropped,
1060 &ife->stats.rx_fifo_errors,
1061 &ife->stats.rx_frame_errors,
1062 &ife->stats.rx_compressed, /* missing for <= 1 */
1063 &ife->stats.rx_multicast, /* missing for <= 1 */
1064 &ife->stats.tx_bytes, /* missing for 0 */
1065 &ife->stats.tx_packets,
1066 &ife->stats.tx_errors,
1067 &ife->stats.tx_dropped,
1068 &ife->stats.tx_fifo_errors,
1069 &ife->stats.collisions,
1070 &ife->stats.tx_carrier_errors,
1071 &ife->stats.tx_compressed /* missing for <= 1 */
1072 );
1073
1074 if (procnetdev_vsn <= 1) {
1075 if (procnetdev_vsn == 0) {
1076 ife->stats.rx_bytes = 0;
1077 ife->stats.tx_bytes = 0;
1078 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001079 ife->stats.rx_multicast = 0;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001080 ife->stats.rx_compressed = 0;
1081 ife->stats.tx_compressed = 0;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001082 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001083}
1084
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001085static inline int procnetdev_version(char *buf)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001086{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001087 if (strstr(buf, "compressed"))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001088 return 2;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001089 if (strstr(buf, "bytes"))
1090 return 1;
1091 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001092}
1093
1094static int if_readlist_proc(char *target)
1095{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001096 static int proc_read;
1097 FILE *fh;
1098 char buf[512];
1099 struct interface *ife;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001100 int err, procnetdev_vsn;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001101
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001102 if (proc_read)
1103 return 0;
1104 if (!target)
1105 proc_read = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001106
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001107 fh = fopen(_PATH_PROCNET_DEV, "r");
1108 if (!fh) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001109 bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001110 return if_readconf();
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001111 }
1112 fgets(buf, sizeof buf, fh); /* eat line */
1113 fgets(buf, sizeof buf, fh);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001114
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001115 procnetdev_vsn = procnetdev_version(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001116
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001117 err = 0;
1118 while (fgets(buf, sizeof buf, fh)) {
Eric Andersenf96675b2003-07-28 06:37:04 +00001119 char *s, name[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001120
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001121 s = get_name(name, buf);
1122 ife = add_interface(name);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001123 get_dev_fields(s, ife, procnetdev_vsn);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001124 ife->statistics_valid = 1;
1125 if (target && !strcmp(target, name))
1126 break;
1127 }
1128 if (ferror(fh)) {
1129 perror(_PATH_PROCNET_DEV);
1130 err = -1;
1131 proc_read = 0;
1132 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001133 fclose(fh);
1134 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001135}
1136
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001137static int if_readlist(void)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001138{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001139 int err = if_readlist_proc(NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001140
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001141 if (!err)
1142 err = if_readconf();
1143 return err;
1144}
1145
1146static int for_all_interfaces(int (*doit) (struct interface *, void *),
1147 void *cookie)
1148{
1149 struct interface *ife;
1150
1151 if (!int_list && (if_readlist() < 0))
1152 return -1;
1153 for (ife = int_list; ife; ife = ife->next) {
1154 int err = doit(ife, cookie);
1155
1156 if (err)
1157 return err;
1158 }
1159 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001160}
1161
1162/* Support for fetching an IPX address */
1163
1164#if HAVE_AFIPX
1165static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
1166{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001167 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
1168 return ioctl(sock, SIOCGIFADDR, ifr);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001169}
1170#endif
1171
1172
1173/* Fetch the interface configuration from the kernel. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001174static int if_fetch(struct interface *ife)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001175{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001176 struct ifreq ifr;
1177 int fd;
1178 char *ifname = ife->name;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001179
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001180 strcpy(ifr.ifr_name, ifname);
1181 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
1182 return (-1);
1183 ife->flags = ifr.ifr_flags;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001184
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001185 strcpy(ifr.ifr_name, ifname);
1186 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
1187 memset(ife->hwaddr, 0, 32);
1188 else
1189 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001190
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001191 ife->type = ifr.ifr_hwaddr.sa_family;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001192
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001193 strcpy(ifr.ifr_name, ifname);
1194 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
1195 ife->metric = 0;
1196 else
1197 ife->metric = ifr.ifr_metric;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001198
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001199 strcpy(ifr.ifr_name, ifname);
1200 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
1201 ife->mtu = 0;
1202 else
1203 ife->mtu = ifr.ifr_mtu;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001204
1205#ifdef HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001206 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
1207 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
1208 ife->type == ARPHRD_ADAPT) {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001209#ifdef SIOCGOUTFILL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001210 strcpy(ifr.ifr_name, ifname);
1211 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
1212 ife->outfill = 0;
1213 else
1214 ife->outfill = (unsigned int) ifr.ifr_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001215#endif
1216#ifdef SIOCGKEEPALIVE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001217 strcpy(ifr.ifr_name, ifname);
1218 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
1219 ife->keepalive = 0;
1220 else
1221 ife->keepalive = (unsigned int) ifr.ifr_data;
1222#endif
1223 }
1224#endif
1225
Eric Andersenf15d4da2001-03-06 00:48:59 +00001226 strcpy(ifr.ifr_name, ifname);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001227 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
1228 memset(&ife->map, 0, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001229 else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001230 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001231
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001232 strcpy(ifr.ifr_name, ifname);
1233 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
1234 memset(&ife->map, 0, sizeof(struct ifmap));
1235 else
1236 ife->map = ifr.ifr_map;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001237
1238#ifdef HAVE_TXQUEUELEN
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001239 strcpy(ifr.ifr_name, ifname);
1240 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
1241 ife->tx_queue_len = -1; /* unknown value */
1242 else
1243 ife->tx_queue_len = ifr.ifr_qlen;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001244#else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001245 ife->tx_queue_len = -1; /* unknown value */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001246#endif
1247
1248#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001249 /* IPv4 address? */
1250 fd = get_socket_for_af(AF_INET);
1251 if (fd >= 0) {
1252 strcpy(ifr.ifr_name, ifname);
1253 ifr.ifr_addr.sa_family = AF_INET;
1254 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1255 ife->has_ip = 1;
1256 ife->addr = ifr.ifr_addr;
1257 strcpy(ifr.ifr_name, ifname);
1258 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
1259 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
1260 else
1261 ife->dstaddr = ifr.ifr_dstaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001262
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001263 strcpy(ifr.ifr_name, ifname);
1264 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
1265 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
1266 else
1267 ife->broadaddr = ifr.ifr_broadaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001268
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001269 strcpy(ifr.ifr_name, ifname);
1270 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
1271 memset(&ife->netmask, 0, sizeof(struct sockaddr));
1272 else
1273 ife->netmask = ifr.ifr_netmask;
1274 } else
1275 memset(&ife->addr, 0, sizeof(struct sockaddr));
1276 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001277#endif
1278
1279#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001280 /* DDP address maybe ? */
1281 fd = get_socket_for_af(AF_APPLETALK);
1282 if (fd >= 0) {
1283 strcpy(ifr.ifr_name, ifname);
1284 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1285 ife->ddpaddr = ifr.ifr_addr;
1286 ife->has_ddp = 1;
1287 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001288 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001289#endif
1290
1291#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001292 /* Look for IPX addresses with all framing types */
1293 fd = get_socket_for_af(AF_IPX);
1294 if (fd >= 0) {
1295 strcpy(ifr.ifr_name, ifname);
1296 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
1297 ife->has_ipx_bb = 1;
1298 ife->ipxaddr_bb = ifr.ifr_addr;
1299 }
1300 strcpy(ifr.ifr_name, ifname);
1301 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
1302 ife->has_ipx_sn = 1;
1303 ife->ipxaddr_sn = ifr.ifr_addr;
1304 }
1305 strcpy(ifr.ifr_name, ifname);
1306 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
1307 ife->has_ipx_e3 = 1;
1308 ife->ipxaddr_e3 = ifr.ifr_addr;
1309 }
1310 strcpy(ifr.ifr_name, ifname);
1311 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
1312 ife->has_ipx_e2 = 1;
1313 ife->ipxaddr_e2 = ifr.ifr_addr;
1314 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001315 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001316#endif
1317
1318#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001319 /* Econet address maybe? */
1320 fd = get_socket_for_af(AF_ECONET);
1321 if (fd >= 0) {
1322 strcpy(ifr.ifr_name, ifname);
1323 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1324 ife->ecaddr = ifr.ifr_addr;
1325 ife->has_econet = 1;
1326 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001327 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001328#endif
1329
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001330 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001331}
1332
1333
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001334static int do_if_fetch(struct interface *ife)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001335{
1336 if (if_fetch(ife) < 0) {
1337 char *errmsg;
1338
1339 if (errno == ENODEV) {
1340 /* Give better error message for this case. */
1341 errmsg = _("Device not found");
1342 } else {
1343 errmsg = strerror(errno);
1344 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001345 bb_error_msg(_("%s: error fetching interface information: %s\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001346 ife->name, errmsg);
1347 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001348 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001349 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001350}
1351
1352/* This structure defines hardware protocols and their handlers. */
1353struct hwtype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001354 const char *name;
1355 const char *title;
1356 int type;
1357 int alen;
1358 char *(*print) (unsigned char *);
1359 int (*input) (char *, struct sockaddr *);
1360 int (*activate) (int fd);
1361 int suppress_null_addr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001362};
1363
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001364static struct hwtype unspec_hwtype = {
1365 "unspec", "UNSPEC", -1, 0,
1366 UNSPEC_print, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001367};
1368
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001369static struct hwtype loop_hwtype = {
1370 "loop", "Local Loopback", ARPHRD_LOOPBACK, 0,
1371 NULL, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001372};
1373
1374#if HAVE_HWETHER
1375#include <net/if_arp.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001376
Mike Frysinger3b05b802005-03-04 01:10:56 +00001377#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION)
Eric Andersenab4e19a2003-01-14 08:54:08 +00001378#include <net/ethernet.h>
1379#else
Eric Andersenf15d4da2001-03-06 00:48:59 +00001380#include <linux/if_ether.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001381#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001382
Eric Andersenf15d4da2001-03-06 00:48:59 +00001383/* Display an Ethernet address in readable format. */
1384static char *pr_ether(unsigned char *ptr)
1385{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001386 static char buff[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001387
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001388 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
1389 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
1390 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
1391 );
1392 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001393}
1394
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001395#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001396/* Input an Ethernet address and convert to binary. */
1397static int in_ether(char *bufp, struct sockaddr *sap)
1398{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001399 unsigned char *ptr;
1400 char c, *orig;
1401 int i;
1402 unsigned val;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001403
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001404 sap->sa_family = ether_hwtype.type;
1405 ptr = sap->sa_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001406
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001407 i = 0;
1408 orig = bufp;
1409 while ((*bufp != '\0') && (i < ETH_ALEN)) {
1410 val = 0;
1411 c = *bufp++;
1412 if (isdigit(c))
1413 val = c - '0';
1414 else if (c >= 'a' && c <= 'f')
1415 val = c - 'a' + 10;
1416 else if (c >= 'A' && c <= 'F')
1417 val = c - 'A' + 10;
1418 else {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001419#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001420 bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001421#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001422 errno = EINVAL;
1423 return (-1);
1424 }
1425 val <<= 4;
1426 c = *bufp;
1427 if (isdigit(c))
1428 val |= c - '0';
1429 else if (c >= 'a' && c <= 'f')
1430 val |= c - 'a' + 10;
1431 else if (c >= 'A' && c <= 'F')
1432 val |= c - 'A' + 10;
1433 else if (c == ':' || c == 0)
1434 val >>= 4;
1435 else {
1436#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001437 bb_error_msg(_("in_ether(%s): invalid ether address!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001438#endif
1439 errno = EINVAL;
1440 return (-1);
1441 }
1442 if (c != 0)
1443 bufp++;
1444 *ptr++ = (unsigned char) (val & 0377);
1445 i++;
1446
1447 /* We might get a semicolon here - not required. */
1448 if (*bufp == ':') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001449#ifdef DEBUG
Glenn L McGrath642f2892002-11-28 10:20:45 +00001450 if (i == ETH_ALEN) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001451 bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001452 }
Glenn L McGrath642f2892002-11-28 10:20:45 +00001453#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001454 bufp++;
1455 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001456 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001457
Glenn L McGrath642f2892002-11-28 10:20:45 +00001458#ifdef DEBUG
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001459 /* That's it. Any trailing junk? */
1460 if ((i == ETH_ALEN) && (*bufp != '\0')) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001461 bb_error_msg(_("in_ether(%s): trailing junk!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001462 errno = EINVAL;
1463 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001464 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001465 bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001466#endif
1467
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001468 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001469}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001470#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001471
1472
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001473static struct hwtype ether_hwtype = {
1474 "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN,
1475 pr_ether, NULL /* UNUSED in_ether */ , NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001476};
1477
1478
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001479#endif /* HAVE_HWETHER */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001480
1481
1482#if HAVE_HWPPP
1483
1484#include <net/if_arp.h>
1485
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001486#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001487/* Start the PPP encapsulation on the file descriptor. */
1488static int do_ppp(int fd)
1489{
Manuel Novoa III cad53642003-03-19 09:13:01 +00001490 bb_error_msg(_("You cannot start PPP with this program."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001491 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001492}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001493#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001494
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001495static struct hwtype ppp_hwtype = {
1496 "ppp", "Point-Point Protocol", ARPHRD_PPP, 0,
1497 NULL, NULL, NULL /* UNUSED do_ppp */ , 0
Eric Andersenf15d4da2001-03-06 00:48:59 +00001498};
1499
1500
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001501#endif /* HAVE_PPP */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001502
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001503static struct hwtype *hwtypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001504
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001505 &loop_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001506
1507#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001508 &slip_hwtype,
1509 &cslip_hwtype,
1510 &slip6_hwtype,
1511 &cslip6_hwtype,
1512 &adaptive_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001513#endif
1514#if HAVE_HWSTRIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001515 &strip_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001516#endif
1517#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001518 &ash_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001519#endif
1520#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001521 &ether_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001522#endif
1523#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001524 &tr_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001525#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001526 &tr_hwtype1,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001527#endif
1528#endif
1529#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001530 &ax25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001531#endif
1532#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001533 &netrom_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001534#endif
1535#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001536 &rose_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001537#endif
1538#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001539 &tunnel_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001540#endif
1541#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001542 &ppp_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001543#endif
1544#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001545 &hdlc_hwtype,
1546 &lapb_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001547#endif
1548#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001549 &arcnet_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001550#endif
1551#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001552 &dlci_hwtype,
1553 &frad_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001554#endif
1555#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001556 &sit_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001557#endif
1558#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001559 &fddi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001560#endif
1561#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001562 &hippi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001563#endif
1564#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001565 &irda_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001566#endif
1567#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001568 &ec_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001569#endif
1570#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001571 &x25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001572#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001573 &unspec_hwtype,
1574 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001575};
1576
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001577#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001578static short sVhwinit = 0;
1579
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001580static void hwinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +00001581{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001582 loop_hwtype.title = _("Local Loopback");
1583 unspec_hwtype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001584#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001585 slip_hwtype.title = _("Serial Line IP");
1586 cslip_hwtype.title = _("VJ Serial Line IP");
1587 slip6_hwtype.title = _("6-bit Serial Line IP");
1588 cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
1589 adaptive_hwtype.title = _("Adaptive Serial Line IP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001590#endif
1591#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001592 ether_hwtype.title = _("Ethernet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001593#endif
1594#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001595 ash_hwtype.title = _("Ash");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001596#endif
1597#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001598 fddi_hwtype.title = _("Fiber Distributed Data Interface");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001599#endif
1600#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001601 hippi_hwtype.title = _("HIPPI");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001602#endif
1603#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001604 ax25_hwtype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001605#endif
1606#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001607 rose_hwtype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001608#endif
1609#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001610 netrom_hwtype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001611#endif
1612#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001613 x25_hwtype.title = _("generic X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001614#endif
1615#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001616 tunnel_hwtype.title = _("IPIP Tunnel");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001617#endif
1618#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001619 ppp_hwtype.title = _("Point-to-Point Protocol");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001620#endif
1621#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001622 hdlc_hwtype.title = _("(Cisco)-HDLC");
1623 lapb_hwtype.title = _("LAPB");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001624#endif
1625#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001626 arcnet_hwtype.title = _("ARCnet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001627#endif
1628#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001629 dlci_hwtype.title = _("Frame Relay DLCI");
1630 frad_hwtype.title = _("Frame Relay Access Device");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001631#endif
1632#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001633 sit_hwtype.title = _("IPv6-in-IPv4");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001634#endif
1635#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001636 irda_hwtype.title = _("IrLAP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001637#endif
1638#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001639 tr_hwtype.title = _("16/4 Mbps Token Ring");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001640#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001641 tr_hwtype1.title = _("16/4 Mbps Token Ring (New)");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001642#endif
1643#endif
1644#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001645 ec_hwtype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001646#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001647 sVhwinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001648}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001649#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001650
1651#ifdef IFF_PORTSEL
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001652#if 0
1653static const char * const if_port_text[][4] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001654 /* Keep in step with <linux/netdevice.h> */
1655 {"unknown", NULL, NULL, NULL},
1656 {"10base2", "bnc", "coax", NULL},
1657 {"10baseT", "utp", "tpe", NULL},
1658 {"AUI", "thick", "db15", NULL},
1659 {"100baseT", NULL, NULL, NULL},
1660 {"100baseTX", NULL, NULL, NULL},
1661 {"100baseFX", NULL, NULL, NULL},
1662 {NULL, NULL, NULL, NULL},
Eric Andersenf15d4da2001-03-06 00:48:59 +00001663};
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001664#else
1665static const char * const if_port_text[] = {
1666 /* Keep in step with <linux/netdevice.h> */
1667 "unknown",
1668 "10base2",
1669 "10baseT",
1670 "AUI",
1671 "100baseT",
1672 "100baseTX",
1673 "100baseFX",
1674 NULL
1675};
1676#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001677#endif
1678
1679/* Check our hardware type table for this type. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001680static struct hwtype *get_hwntype(int type)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001681{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001682 struct hwtype **hwp;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001683
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001684#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001685 if (!sVhwinit)
1686 hwinit();
1687#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001688
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001689 hwp = hwtypes;
1690 while (*hwp != NULL) {
1691 if ((*hwp)->type == type)
1692 return (*hwp);
1693 hwp++;
1694 }
1695 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001696}
1697
1698/* return 1 if address is all zeros */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001699static int hw_null_address(struct hwtype *hw, void *ap)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001700{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001701 unsigned int i;
1702 unsigned char *address = (unsigned char *) ap;
1703
1704 for (i = 0; i < hw->alen; i++)
1705 if (address[i])
1706 return 0;
1707 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001708}
1709
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001710static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001711
1712static void print_bytes_scaled(unsigned long long ull, const char *end)
1713{
1714 unsigned long long int_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001715 const char *ext;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001716 unsigned int frac_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001717 int i;
1718
1719 frac_part = 0;
1720 ext = TRext;
1721 int_part = ull;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001722 i = 4;
1723 do {
1724#if 0
1725 /* This does correct rounding and is a little larger. But it
1726 * uses KiB as the smallest displayed unit. */
1727 if ((int_part < (1024*1024 - 51)) || !--i) {
1728 i = 0;
1729 int_part += 51; /* 1024*.05 = 51.2 */
1730 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001731 }
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001732 int_part /= 1024;
1733 ext += 3; /* KiB, MiB, GiB, TiB */
1734#else
1735 if (int_part >= 1024) {
1736 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
1737 int_part /= 1024;
1738 ext += 3; /* KiB, MiB, GiB, TiB */
1739 }
1740 --i;
1741#endif
1742 } while (i);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001743
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001744 printf("X bytes:%Lu (%Lu.%u %sB)%s", ull, int_part, frac_part, ext, end);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001745}
1746
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001747static const char * const ife_print_flags_strs[] = {
1748 "UP ",
1749 "BROADCAST ",
1750 "DEBUG ",
1751 "LOOPBACK ",
1752 "POINTOPOINT ",
1753 "NOTRAILERS ",
1754 "RUNNING ",
1755 "NOARP ",
1756 "PROMISC ",
1757 "ALLMULTI ",
1758 "SLAVE ",
1759 "MASTER ",
1760 "MULTICAST ",
1761#ifdef HAVE_DYNAMIC
1762 "DYNAMIC "
1763#endif
1764};
1765
1766static const unsigned short ife_print_flags_mask[] = {
1767 IFF_UP,
1768 IFF_BROADCAST,
1769 IFF_DEBUG,
1770 IFF_LOOPBACK,
1771 IFF_POINTOPOINT,
1772 IFF_NOTRAILERS,
1773 IFF_RUNNING,
1774 IFF_NOARP,
1775 IFF_PROMISC,
1776 IFF_ALLMULTI,
1777 IFF_SLAVE,
1778 IFF_MASTER,
1779 IFF_MULTICAST,
1780#ifdef HAVE_DYNAMIC
1781 IFF_DYNAMIC
1782#endif
1783 0
1784};
1785
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001786static void ife_print(struct interface *ptr)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001787{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001788 struct aftype *ap;
1789 struct hwtype *hw;
1790 int hf;
1791 int can_compress = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001792
1793#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001794 static struct aftype *ipxtype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001795#endif
1796#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001797 static struct aftype *ectype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001798#endif
1799#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001800 static struct aftype *ddptype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001801#endif
1802#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001803 FILE *f;
1804 char addr6[40], devname[20];
1805 struct sockaddr_in6 sap;
1806 int plen, scope, dad_status, if_idx;
1807 char addr6p[8][5];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001808#endif
1809
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001810 ap = get_afntype(ptr->addr.sa_family);
1811 if (ap == NULL)
1812 ap = get_afntype(0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001813
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001814 hf = ptr->type;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001815
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001816 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
1817 can_compress = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001818
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001819 hw = get_hwntype(hf);
1820 if (hw == NULL)
1821 hw = get_hwntype(-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001822
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001823 printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title));
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001824 /* For some hardware types (eg Ash, ATM) we don't print the
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001825 hardware address if it's null. */
1826 if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
1827 hw->suppress_null_addr)))
1828 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001829#ifdef IFF_PORTSEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001830 if (ptr->flags & IFF_PORTSEL) {
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001831 printf(_("Media:%s"), if_port_text[ptr->map.port] /* [0] */);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001832 if (ptr->flags & IFF_AUTOMEDIA)
1833 printf(_("(auto)"));
1834 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001835#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001836 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001837
1838#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001839 if (ptr->has_ip) {
1840 printf(_(" %s addr:%s "), ap->name,
1841 ap->sprint(&ptr->addr, 1));
1842 if (ptr->flags & IFF_POINTOPOINT) {
1843 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
1844 }
1845 if (ptr->flags & IFF_BROADCAST) {
1846 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
1847 }
1848 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001849 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001850#endif
1851
1852#if HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +00001853
Eric Andersen51b8bd62002-07-03 11:46:38 +00001854#define IPV6_ADDR_ANY 0x0000U
1855
1856#define IPV6_ADDR_UNICAST 0x0001U
1857#define IPV6_ADDR_MULTICAST 0x0002U
1858#define IPV6_ADDR_ANYCAST 0x0004U
1859
1860#define IPV6_ADDR_LOOPBACK 0x0010U
1861#define IPV6_ADDR_LINKLOCAL 0x0020U
1862#define IPV6_ADDR_SITELOCAL 0x0040U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001863
Eric Andersen51b8bd62002-07-03 11:46:38 +00001864#define IPV6_ADDR_COMPATv4 0x0080U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001865
Eric Andersen51b8bd62002-07-03 11:46:38 +00001866#define IPV6_ADDR_SCOPE_MASK 0x00f0U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001867
Eric Andersen51b8bd62002-07-03 11:46:38 +00001868#define IPV6_ADDR_MAPPED 0x1000U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001869#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
1870
1871 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1872 while (fscanf
1873 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
1874 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
1875 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
1876 &dad_status, devname) != EOF) {
1877 if (!strcmp(devname, ptr->name)) {
1878 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1879 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1880 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1881 inet_pton(AF_INET6, addr6,
1882 (struct sockaddr *) &sap.sin6_addr);
1883 sap.sin6_family = AF_INET6;
1884 printf(_(" inet6 addr: %s/%d"),
1885 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
1886 plen);
1887 printf(_(" Scope:"));
1888 switch (scope & IPV6_ADDR_SCOPE_MASK) {
1889 case 0:
1890 printf(_("Global"));
1891 break;
1892 case IPV6_ADDR_LINKLOCAL:
1893 printf(_("Link"));
1894 break;
1895 case IPV6_ADDR_SITELOCAL:
1896 printf(_("Site"));
1897 break;
1898 case IPV6_ADDR_COMPATv4:
1899 printf(_("Compat"));
1900 break;
1901 case IPV6_ADDR_LOOPBACK:
1902 printf(_("Host"));
1903 break;
1904 default:
1905 printf(_("Unknown"));
1906 }
1907 printf("\n");
1908 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001909 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001910 fclose(f);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001911 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001912#endif
1913
1914#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001915 if (ipxtype == NULL)
1916 ipxtype = get_afntype(AF_IPX);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001917
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001918 if (ipxtype != NULL) {
1919 if (ptr->has_ipx_bb)
1920 printf(_(" IPX/Ethernet II addr:%s\n"),
1921 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
1922 if (ptr->has_ipx_sn)
1923 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
1924 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
1925 if (ptr->has_ipx_e2)
1926 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
1927 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
1928 if (ptr->has_ipx_e3)
1929 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
1930 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
1931 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001932#endif
1933
1934#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001935 if (ddptype == NULL)
1936 ddptype = get_afntype(AF_APPLETALK);
1937 if (ddptype != NULL) {
1938 if (ptr->has_ddp)
1939 printf(_(" EtherTalk Phase 2 addr:%s\n"),
1940 ddptype->sprint(&ptr->ddpaddr, 1));
1941 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001942#endif
1943
1944#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001945 if (ectype == NULL)
1946 ectype = get_afntype(AF_ECONET);
1947 if (ectype != NULL) {
1948 if (ptr->has_econet)
1949 printf(_(" econet addr:%s\n"),
1950 ectype->sprint(&ptr->ecaddr, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001951 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001952#endif
1953
1954 printf(" ");
1955 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001956
1957 if (ptr->flags == 0) {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001958 printf(_("[NO FLAGS] "));
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001959 } else {
1960 int i = 0;
1961 do {
1962 if (ptr->flags & ife_print_flags_mask[i]) {
1963 printf(_(ife_print_flags_strs[i]));
1964 }
1965 } while (ife_print_flags_mask[++i]);
1966 }
1967
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001968 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1969 printf(_(" MTU:%d Metric:%d"), ptr->mtu, ptr->metric ? ptr->metric : 1);
1970#ifdef SIOCSKEEPALIVE
1971 if (ptr->outfill || ptr->keepalive)
1972 printf(_(" Outfill:%d Keepalive:%d"), ptr->outfill, ptr->keepalive);
1973#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001974 printf("\n");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001975
1976 /* If needed, display the interface statistics. */
1977
1978 if (ptr->statistics_valid) {
1979 /* XXX: statistics are currently only printed for the primary address,
1980 * not for the aliases, although strictly speaking they're shared
1981 * by all addresses.
1982 */
1983 printf(" ");
1984
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001985 printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001986 ptr->stats.rx_packets, ptr->stats.rx_errors,
1987 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1988 ptr->stats.rx_frame_errors);
1989 if (can_compress)
1990 printf(_(" compressed:%lu\n"),
1991 ptr->stats.rx_compressed);
1992 printf(" ");
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001993 printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001994 ptr->stats.tx_packets, ptr->stats.tx_errors,
1995 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
1996 ptr->stats.tx_carrier_errors);
1997 printf(_(" collisions:%lu "), ptr->stats.collisions);
1998 if (can_compress)
1999 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
2000 if (ptr->tx_queue_len != -1)
2001 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
2002 printf("\n R");
2003 print_bytes_scaled(ptr->stats.rx_bytes, " T");
2004 print_bytes_scaled(ptr->stats.tx_bytes, "\n");
2005
2006 }
2007
2008 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
2009 ptr->map.base_addr)) {
2010 printf(" ");
2011 if (ptr->map.irq)
2012 printf(_("Interrupt:%d "), ptr->map.irq);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002013 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002014 I/O maps */
2015 printf(_("Base address:0x%lx "),
2016 (unsigned long) ptr->map.base_addr);
2017 if (ptr->map.mem_start) {
2018 printf(_("Memory:%lx-%lx "), ptr->map.mem_start,
2019 ptr->map.mem_end);
2020 }
2021 if (ptr->map.dma)
2022 printf(_("DMA chan:%x "), ptr->map.dma);
2023 printf("\n");
2024 }
2025 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00002026}
2027
2028
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002029static int do_if_print(struct interface *ife, void *cookie)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002030{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002031 int *opt_a = (int *) cookie;
2032 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002033
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002034 res = do_if_fetch(ife);
2035 if (res >= 0) {
2036 if ((ife->flags & IFF_UP) || *opt_a)
2037 ife_print(ife);
2038 }
2039 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002040}
2041
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002042static struct interface *lookup_interface(char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002043{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002044 struct interface *ife = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002045
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002046 if (if_readlist_proc(name) < 0)
2047 return NULL;
2048 ife = add_interface(name);
2049 return ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002050}
2051
2052/* for ipv4 add/del modes */
2053static int if_print(char *ifname)
2054{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002055 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002056
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002057 if (!ifname) {
2058 res = for_all_interfaces(do_if_print, &interface_opt_a);
2059 } else {
2060 struct interface *ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002061
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002062 ife = lookup_interface(ifname);
2063 res = do_if_fetch(ife);
2064 if (res >= 0)
2065 ife_print(ife);
2066 }
2067 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002068}
2069
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002070int display_interfaces(char *ifname)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002071{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002072 int status;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002073
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002074 /* Create a channel to the NET kernel. */
2075 if ((skfd = sockets_open(0)) < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002076 bb_perror_msg_and_die("socket");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002077 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00002078
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002079 /* Do we have to show the current setup? */
2080 status = if_print(ifname);
2081 close(skfd);
2082 exit(status < 0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00002083}