blob: 65d7c4e7147fcd7830004f711b2d2ba0588d20c1 [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
Rob Landley93983042005-05-03 21:30:26 +0000891#ifdef CONFIG_FEATURE_CLEAN_UP
892static void sockets_close(void)
893{
894 struct aftype **aft;
895 for (aft = aftypes; *aft != NULL; aft++) {
896 struct aftype *af = *aft;
897 if( af->fd != -1 ) {
898 close(af->fd);
899 af->fd = -1;
900 }
901 }
902}
903#endif
904
Eric Andersenf15d4da2001-03-06 00:48:59 +0000905/* like strcmp(), but knows about numbers */
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000906static int nstrcmp(const char *a, const char *b)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000907{
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000908 const char *a_ptr = a;
909 const char *b_ptr = b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000910
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000911 while (*a == *b) {
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000912 if (*a == '\0') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000913 return 0;
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000914 }
915 if (!isdigit(*a) && isdigit(*(a+1))) {
916 a_ptr = a+1;
917 b_ptr = b+1;
918 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000919 a++;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000920 b++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000921 }
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000922
923 if (isdigit(*a) && isdigit(*b)) {
924 return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000925 }
926 return *a - *b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000927}
928
929static struct interface *add_interface(char *name)
930{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000931 struct interface *ife, **nextp, *new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000932
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000933 for (ife = int_last; ife; ife = ife->prev) {
934 int n = nstrcmp(ife->name, name);
935
936 if (n == 0)
937 return ife;
938 if (n < 0)
939 break;
940 }
941 new(new);
942 safe_strncpy(new->name, name, IFNAMSIZ);
943 nextp = ife ? &ife->next : &int_list;
944 new->prev = ife;
945 new->next = *nextp;
946 if (new->next)
947 new->next->prev = new;
948 else
949 int_last = new;
950 *nextp = new;
951 return new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000952}
953
954
955static int if_readconf(void)
956{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000957 int numreqs = 30;
958 struct ifconf ifc;
959 struct ifreq *ifr;
960 int n, err = -1;
961 int skfd2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000962
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000963 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
964 (as of 2.1.128) */
965 skfd2 = get_socket_for_af(AF_INET);
966 if (skfd2 < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000967 bb_perror_msg(("warning: no inet socket available"));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000968 /* Try to soldier on with whatever socket we can get hold of. */
969 skfd2 = sockets_open(0);
970 if (skfd2 < 0)
971 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000972 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000973
974 ifc.ifc_buf = NULL;
975 for (;;) {
976 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
977 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
978
979 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
980 perror("SIOCGIFCONF");
981 goto out;
982 }
983 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
984 /* assume it overflowed and try again */
985 numreqs += 10;
986 continue;
987 }
988 break;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000989 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000990
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000991 ifr = ifc.ifc_req;
992 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
993 add_interface(ifr->ifr_name);
994 ifr++;
995 }
996 err = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000997
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000998 out:
999 free(ifc.ifc_buf);
1000 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001001}
1002
Eric Andersen14f5c8d2005-04-16 19:39:00 +00001003static char *get_name(char *name, char *p)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001004{
Eric Andersen9940e082004-08-12 16:52:00 +00001005 /* Extract <name>[:<alias>] from nul-terminated p where p matches
1006 <name>[:<alias>]: after leading whitespace.
1007 If match is not made, set name empty and return unchanged p */
1008 int namestart=0, nameend=0, aliasend;
1009 while (isspace(p[namestart]))
1010 namestart++;
1011 nameend=namestart;
1012 while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
1013 nameend++;
1014 if (p[nameend]==':') {
1015 aliasend=nameend+1;
1016 while (p[aliasend] && isdigit(p[aliasend]))
1017 aliasend++;
1018 if (p[aliasend]==':') {
1019 nameend=aliasend;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001020 }
Eric Andersen9940e082004-08-12 16:52:00 +00001021 if ((nameend-namestart)<IFNAMSIZ) {
1022 memcpy(name,&p[namestart],nameend-namestart);
1023 name[nameend-namestart]='\0';
1024 p=&p[nameend];
1025 } else {
1026 /* Interface name too large */
1027 name[0]='\0';
1028 }
1029 } else {
1030 /* first ':' not found - return empty */
1031 name[0]='\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +00001032 }
Eric Andersen6fea7322004-08-26 21:45:21 +00001033 return p + 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001034}
1035
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001036/* If scanf supports size qualifiers for %n conversions, then we can
1037 * use a modified fmt that simply stores the position in the fields
1038 * having no associated fields in the proc string. Of course, we need
1039 * to zero them again when we're done. But that is smaller than the
1040 * old approach of multiple scanf occurrences with large numbers of
1041 * args. */
1042
1043/* static const char *ss_fmt[] = { */
1044/* "%Ln%Lu%lu%lu%lu%lu%ln%ln%Ln%Lu%lu%lu%lu%lu%lu", */
1045/* "%Lu%Lu%lu%lu%lu%lu%ln%ln%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 /* Lie about the size of the int pointed to for %n. */
1050#if INT_MAX == LONG_MAX
1051static const char *ss_fmt[] = {
1052 "%n%Lu%u%u%u%u%n%n%n%Lu%u%u%u%u%u",
1053 "%Lu%Lu%u%u%u%u%n%n%Lu%Lu%u%u%u%u%u",
1054 "%Lu%Lu%u%u%u%u%u%u%Lu%Lu%u%u%u%u%u%u"
1055};
1056#else
1057static const char *ss_fmt[] = {
1058 "%n%Lu%lu%lu%lu%lu%n%n%n%Lu%lu%lu%lu%lu%lu",
1059 "%Lu%Lu%lu%lu%lu%lu%n%n%Lu%Lu%lu%lu%lu%lu%lu",
1060 "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu"
1061};
1062
1063#endif
1064
1065static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001066{
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001067 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
1068
1069 sscanf(bp, ss_fmt[procnetdev_vsn],
1070 &ife->stats.rx_bytes, /* missing for 0 */
1071 &ife->stats.rx_packets,
1072 &ife->stats.rx_errors,
1073 &ife->stats.rx_dropped,
1074 &ife->stats.rx_fifo_errors,
1075 &ife->stats.rx_frame_errors,
1076 &ife->stats.rx_compressed, /* missing for <= 1 */
1077 &ife->stats.rx_multicast, /* missing for <= 1 */
1078 &ife->stats.tx_bytes, /* missing for 0 */
1079 &ife->stats.tx_packets,
1080 &ife->stats.tx_errors,
1081 &ife->stats.tx_dropped,
1082 &ife->stats.tx_fifo_errors,
1083 &ife->stats.collisions,
1084 &ife->stats.tx_carrier_errors,
1085 &ife->stats.tx_compressed /* missing for <= 1 */
1086 );
1087
1088 if (procnetdev_vsn <= 1) {
1089 if (procnetdev_vsn == 0) {
1090 ife->stats.rx_bytes = 0;
1091 ife->stats.tx_bytes = 0;
1092 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001093 ife->stats.rx_multicast = 0;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001094 ife->stats.rx_compressed = 0;
1095 ife->stats.tx_compressed = 0;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001096 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001097}
1098
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001099static inline int procnetdev_version(char *buf)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001100{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001101 if (strstr(buf, "compressed"))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001102 return 2;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001103 if (strstr(buf, "bytes"))
1104 return 1;
1105 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001106}
1107
1108static int if_readlist_proc(char *target)
1109{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001110 static int proc_read;
1111 FILE *fh;
1112 char buf[512];
1113 struct interface *ife;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001114 int err, procnetdev_vsn;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001115
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001116 if (proc_read)
1117 return 0;
1118 if (!target)
1119 proc_read = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001120
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001121 fh = fopen(_PATH_PROCNET_DEV, "r");
1122 if (!fh) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001123 bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001124 return if_readconf();
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001125 }
1126 fgets(buf, sizeof buf, fh); /* eat line */
1127 fgets(buf, sizeof buf, fh);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001128
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001129 procnetdev_vsn = procnetdev_version(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001130
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001131 err = 0;
1132 while (fgets(buf, sizeof buf, fh)) {
Eric Andersenf96675b2003-07-28 06:37:04 +00001133 char *s, name[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001134
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001135 s = get_name(name, buf);
1136 ife = add_interface(name);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001137 get_dev_fields(s, ife, procnetdev_vsn);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001138 ife->statistics_valid = 1;
1139 if (target && !strcmp(target, name))
1140 break;
1141 }
1142 if (ferror(fh)) {
1143 perror(_PATH_PROCNET_DEV);
1144 err = -1;
1145 proc_read = 0;
1146 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001147 fclose(fh);
1148 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001149}
1150
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001151static int if_readlist(void)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001152{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001153 int err = if_readlist_proc(NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001154
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001155 if (!err)
1156 err = if_readconf();
1157 return err;
1158}
1159
1160static int for_all_interfaces(int (*doit) (struct interface *, void *),
1161 void *cookie)
1162{
1163 struct interface *ife;
1164
1165 if (!int_list && (if_readlist() < 0))
1166 return -1;
1167 for (ife = int_list; ife; ife = ife->next) {
1168 int err = doit(ife, cookie);
1169
1170 if (err)
1171 return err;
1172 }
1173 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001174}
1175
1176/* Support for fetching an IPX address */
1177
1178#if HAVE_AFIPX
1179static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
1180{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001181 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
1182 return ioctl(sock, SIOCGIFADDR, ifr);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001183}
1184#endif
1185
1186
1187/* Fetch the interface configuration from the kernel. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001188static int if_fetch(struct interface *ife)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001189{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001190 struct ifreq ifr;
1191 int fd;
1192 char *ifname = ife->name;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001193
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001194 strcpy(ifr.ifr_name, ifname);
1195 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
1196 return (-1);
1197 ife->flags = ifr.ifr_flags;
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, SIOCGIFHWADDR, &ifr) < 0)
1201 memset(ife->hwaddr, 0, 32);
1202 else
1203 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001204
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001205 ife->type = ifr.ifr_hwaddr.sa_family;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001206
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001207 strcpy(ifr.ifr_name, ifname);
1208 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
1209 ife->metric = 0;
1210 else
1211 ife->metric = ifr.ifr_metric;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001212
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001213 strcpy(ifr.ifr_name, ifname);
1214 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
1215 ife->mtu = 0;
1216 else
1217 ife->mtu = ifr.ifr_mtu;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001218
1219#ifdef HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001220 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
1221 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
1222 ife->type == ARPHRD_ADAPT) {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001223#ifdef SIOCGOUTFILL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001224 strcpy(ifr.ifr_name, ifname);
1225 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
1226 ife->outfill = 0;
1227 else
1228 ife->outfill = (unsigned int) ifr.ifr_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001229#endif
1230#ifdef SIOCGKEEPALIVE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001231 strcpy(ifr.ifr_name, ifname);
1232 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
1233 ife->keepalive = 0;
1234 else
1235 ife->keepalive = (unsigned int) ifr.ifr_data;
1236#endif
1237 }
1238#endif
1239
Rob Landley93983042005-05-03 21:30:26 +00001240#ifdef SIOCGIFMAP
Eric Andersenf15d4da2001-03-06 00:48:59 +00001241 strcpy(ifr.ifr_name, ifname);
Rob Landley93983042005-05-03 21:30:26 +00001242 if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001243 ife->map = ifr.ifr_map;
Rob Landley93983042005-05-03 21:30:26 +00001244 else
1245#endif
1246 memset(&ife->map, 0, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001247
1248#ifdef HAVE_TXQUEUELEN
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001249 strcpy(ifr.ifr_name, ifname);
1250 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
1251 ife->tx_queue_len = -1; /* unknown value */
1252 else
1253 ife->tx_queue_len = ifr.ifr_qlen;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001254#else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001255 ife->tx_queue_len = -1; /* unknown value */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001256#endif
1257
1258#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001259 /* IPv4 address? */
1260 fd = get_socket_for_af(AF_INET);
1261 if (fd >= 0) {
1262 strcpy(ifr.ifr_name, ifname);
1263 ifr.ifr_addr.sa_family = AF_INET;
1264 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1265 ife->has_ip = 1;
1266 ife->addr = ifr.ifr_addr;
1267 strcpy(ifr.ifr_name, ifname);
1268 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
1269 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
1270 else
1271 ife->dstaddr = ifr.ifr_dstaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001272
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001273 strcpy(ifr.ifr_name, ifname);
1274 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
1275 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
1276 else
1277 ife->broadaddr = ifr.ifr_broadaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001278
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001279 strcpy(ifr.ifr_name, ifname);
1280 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
1281 memset(&ife->netmask, 0, sizeof(struct sockaddr));
1282 else
1283 ife->netmask = ifr.ifr_netmask;
1284 } else
1285 memset(&ife->addr, 0, sizeof(struct sockaddr));
1286 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001287#endif
1288
1289#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001290 /* DDP address maybe ? */
1291 fd = get_socket_for_af(AF_APPLETALK);
1292 if (fd >= 0) {
1293 strcpy(ifr.ifr_name, ifname);
1294 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1295 ife->ddpaddr = ifr.ifr_addr;
1296 ife->has_ddp = 1;
1297 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001298 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001299#endif
1300
1301#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001302 /* Look for IPX addresses with all framing types */
1303 fd = get_socket_for_af(AF_IPX);
1304 if (fd >= 0) {
1305 strcpy(ifr.ifr_name, ifname);
1306 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
1307 ife->has_ipx_bb = 1;
1308 ife->ipxaddr_bb = ifr.ifr_addr;
1309 }
1310 strcpy(ifr.ifr_name, ifname);
1311 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
1312 ife->has_ipx_sn = 1;
1313 ife->ipxaddr_sn = ifr.ifr_addr;
1314 }
1315 strcpy(ifr.ifr_name, ifname);
1316 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
1317 ife->has_ipx_e3 = 1;
1318 ife->ipxaddr_e3 = ifr.ifr_addr;
1319 }
1320 strcpy(ifr.ifr_name, ifname);
1321 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
1322 ife->has_ipx_e2 = 1;
1323 ife->ipxaddr_e2 = ifr.ifr_addr;
1324 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001325 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001326#endif
1327
1328#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001329 /* Econet address maybe? */
1330 fd = get_socket_for_af(AF_ECONET);
1331 if (fd >= 0) {
1332 strcpy(ifr.ifr_name, ifname);
1333 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1334 ife->ecaddr = ifr.ifr_addr;
1335 ife->has_econet = 1;
1336 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001337 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001338#endif
1339
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001340 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001341}
1342
1343
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001344static int do_if_fetch(struct interface *ife)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001345{
1346 if (if_fetch(ife) < 0) {
1347 char *errmsg;
1348
1349 if (errno == ENODEV) {
1350 /* Give better error message for this case. */
1351 errmsg = _("Device not found");
1352 } else {
1353 errmsg = strerror(errno);
1354 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001355 bb_error_msg(_("%s: error fetching interface information: %s\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001356 ife->name, errmsg);
1357 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001358 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001359 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001360}
1361
1362/* This structure defines hardware protocols and their handlers. */
1363struct hwtype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001364 const char *name;
1365 const char *title;
1366 int type;
1367 int alen;
1368 char *(*print) (unsigned char *);
1369 int (*input) (char *, struct sockaddr *);
1370 int (*activate) (int fd);
1371 int suppress_null_addr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001372};
1373
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001374static struct hwtype unspec_hwtype = {
1375 "unspec", "UNSPEC", -1, 0,
1376 UNSPEC_print, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001377};
1378
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001379static struct hwtype loop_hwtype = {
1380 "loop", "Local Loopback", ARPHRD_LOOPBACK, 0,
1381 NULL, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001382};
1383
1384#if HAVE_HWETHER
1385#include <net/if_arp.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001386
Mike Frysinger3b05b802005-03-04 01:10:56 +00001387#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION)
Eric Andersenab4e19a2003-01-14 08:54:08 +00001388#include <net/ethernet.h>
1389#else
Eric Andersenf15d4da2001-03-06 00:48:59 +00001390#include <linux/if_ether.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001391#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001392
Eric Andersenf15d4da2001-03-06 00:48:59 +00001393/* Display an Ethernet address in readable format. */
1394static char *pr_ether(unsigned char *ptr)
1395{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001396 static char buff[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001397
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001398 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
1399 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
1400 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
1401 );
1402 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001403}
1404
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001405#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001406/* Input an Ethernet address and convert to binary. */
1407static int in_ether(char *bufp, struct sockaddr *sap)
1408{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001409 unsigned char *ptr;
1410 char c, *orig;
1411 int i;
1412 unsigned val;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001413
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001414 sap->sa_family = ether_hwtype.type;
1415 ptr = sap->sa_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001416
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001417 i = 0;
1418 orig = bufp;
1419 while ((*bufp != '\0') && (i < ETH_ALEN)) {
1420 val = 0;
1421 c = *bufp++;
1422 if (isdigit(c))
1423 val = c - '0';
1424 else if (c >= 'a' && c <= 'f')
1425 val = c - 'a' + 10;
1426 else if (c >= 'A' && c <= 'F')
1427 val = c - 'A' + 10;
1428 else {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001429#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001430 bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001431#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001432 errno = EINVAL;
1433 return (-1);
1434 }
1435 val <<= 4;
1436 c = *bufp;
1437 if (isdigit(c))
1438 val |= c - '0';
1439 else if (c >= 'a' && c <= 'f')
1440 val |= c - 'a' + 10;
1441 else if (c >= 'A' && c <= 'F')
1442 val |= c - 'A' + 10;
1443 else if (c == ':' || c == 0)
1444 val >>= 4;
1445 else {
1446#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001447 bb_error_msg(_("in_ether(%s): invalid ether address!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001448#endif
1449 errno = EINVAL;
1450 return (-1);
1451 }
1452 if (c != 0)
1453 bufp++;
1454 *ptr++ = (unsigned char) (val & 0377);
1455 i++;
1456
1457 /* We might get a semicolon here - not required. */
1458 if (*bufp == ':') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001459#ifdef DEBUG
Glenn L McGrath642f2892002-11-28 10:20:45 +00001460 if (i == ETH_ALEN) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001461 bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001462 }
Glenn L McGrath642f2892002-11-28 10:20:45 +00001463#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001464 bufp++;
1465 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001466 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001467
Glenn L McGrath642f2892002-11-28 10:20:45 +00001468#ifdef DEBUG
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001469 /* That's it. Any trailing junk? */
1470 if ((i == ETH_ALEN) && (*bufp != '\0')) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001471 bb_error_msg(_("in_ether(%s): trailing junk!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001472 errno = EINVAL;
1473 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001474 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001475 bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001476#endif
1477
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001478 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001479}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001480#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001481
1482
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001483static struct hwtype ether_hwtype = {
1484 "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN,
1485 pr_ether, NULL /* UNUSED in_ether */ , NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001486};
1487
1488
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001489#endif /* HAVE_HWETHER */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001490
1491
1492#if HAVE_HWPPP
1493
1494#include <net/if_arp.h>
1495
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001496#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001497/* Start the PPP encapsulation on the file descriptor. */
1498static int do_ppp(int fd)
1499{
Manuel Novoa III cad53642003-03-19 09:13:01 +00001500 bb_error_msg(_("You cannot start PPP with this program."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001501 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001502}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001503#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001504
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001505static struct hwtype ppp_hwtype = {
1506 "ppp", "Point-Point Protocol", ARPHRD_PPP, 0,
1507 NULL, NULL, NULL /* UNUSED do_ppp */ , 0
Eric Andersenf15d4da2001-03-06 00:48:59 +00001508};
1509
1510
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001511#endif /* HAVE_PPP */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001512
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001513static struct hwtype *hwtypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001514
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001515 &loop_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001516
1517#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001518 &slip_hwtype,
1519 &cslip_hwtype,
1520 &slip6_hwtype,
1521 &cslip6_hwtype,
1522 &adaptive_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001523#endif
1524#if HAVE_HWSTRIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001525 &strip_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001526#endif
1527#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001528 &ash_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001529#endif
1530#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001531 &ether_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001532#endif
1533#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001534 &tr_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001535#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001536 &tr_hwtype1,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001537#endif
1538#endif
1539#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001540 &ax25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001541#endif
1542#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001543 &netrom_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001544#endif
1545#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001546 &rose_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001547#endif
1548#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001549 &tunnel_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001550#endif
1551#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001552 &ppp_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001553#endif
1554#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001555 &hdlc_hwtype,
1556 &lapb_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001557#endif
1558#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001559 &arcnet_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001560#endif
1561#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001562 &dlci_hwtype,
1563 &frad_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001564#endif
1565#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001566 &sit_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001567#endif
1568#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001569 &fddi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001570#endif
1571#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001572 &hippi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001573#endif
1574#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001575 &irda_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001576#endif
1577#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001578 &ec_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001579#endif
1580#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001581 &x25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001582#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001583 &unspec_hwtype,
1584 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001585};
1586
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001587#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001588static short sVhwinit = 0;
1589
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001590static void hwinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +00001591{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001592 loop_hwtype.title = _("Local Loopback");
1593 unspec_hwtype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001594#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001595 slip_hwtype.title = _("Serial Line IP");
1596 cslip_hwtype.title = _("VJ Serial Line IP");
1597 slip6_hwtype.title = _("6-bit Serial Line IP");
1598 cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
1599 adaptive_hwtype.title = _("Adaptive Serial Line IP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001600#endif
1601#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001602 ether_hwtype.title = _("Ethernet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001603#endif
1604#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001605 ash_hwtype.title = _("Ash");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001606#endif
1607#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001608 fddi_hwtype.title = _("Fiber Distributed Data Interface");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001609#endif
1610#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001611 hippi_hwtype.title = _("HIPPI");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001612#endif
1613#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001614 ax25_hwtype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001615#endif
1616#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001617 rose_hwtype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001618#endif
1619#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001620 netrom_hwtype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001621#endif
1622#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001623 x25_hwtype.title = _("generic X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001624#endif
1625#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001626 tunnel_hwtype.title = _("IPIP Tunnel");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001627#endif
1628#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001629 ppp_hwtype.title = _("Point-to-Point Protocol");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001630#endif
1631#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001632 hdlc_hwtype.title = _("(Cisco)-HDLC");
1633 lapb_hwtype.title = _("LAPB");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001634#endif
1635#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001636 arcnet_hwtype.title = _("ARCnet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001637#endif
1638#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001639 dlci_hwtype.title = _("Frame Relay DLCI");
1640 frad_hwtype.title = _("Frame Relay Access Device");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001641#endif
1642#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001643 sit_hwtype.title = _("IPv6-in-IPv4");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001644#endif
1645#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001646 irda_hwtype.title = _("IrLAP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001647#endif
1648#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001649 tr_hwtype.title = _("16/4 Mbps Token Ring");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001650#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001651 tr_hwtype1.title = _("16/4 Mbps Token Ring (New)");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001652#endif
1653#endif
1654#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001655 ec_hwtype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001656#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001657 sVhwinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001658}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001659#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001660
1661#ifdef IFF_PORTSEL
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001662#if 0
1663static const char * const if_port_text[][4] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001664 /* Keep in step with <linux/netdevice.h> */
1665 {"unknown", NULL, NULL, NULL},
1666 {"10base2", "bnc", "coax", NULL},
1667 {"10baseT", "utp", "tpe", NULL},
1668 {"AUI", "thick", "db15", NULL},
1669 {"100baseT", NULL, NULL, NULL},
1670 {"100baseTX", NULL, NULL, NULL},
1671 {"100baseFX", NULL, NULL, NULL},
1672 {NULL, NULL, NULL, NULL},
Eric Andersenf15d4da2001-03-06 00:48:59 +00001673};
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001674#else
1675static const char * const if_port_text[] = {
1676 /* Keep in step with <linux/netdevice.h> */
1677 "unknown",
1678 "10base2",
1679 "10baseT",
1680 "AUI",
1681 "100baseT",
1682 "100baseTX",
1683 "100baseFX",
1684 NULL
1685};
1686#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001687#endif
1688
1689/* Check our hardware type table for this type. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001690static struct hwtype *get_hwntype(int type)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001691{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001692 struct hwtype **hwp;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001693
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001694#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001695 if (!sVhwinit)
1696 hwinit();
1697#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001698
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001699 hwp = hwtypes;
1700 while (*hwp != NULL) {
1701 if ((*hwp)->type == type)
1702 return (*hwp);
1703 hwp++;
1704 }
1705 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001706}
1707
1708/* return 1 if address is all zeros */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001709static int hw_null_address(struct hwtype *hw, void *ap)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001710{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001711 unsigned int i;
1712 unsigned char *address = (unsigned char *) ap;
1713
1714 for (i = 0; i < hw->alen; i++)
1715 if (address[i])
1716 return 0;
1717 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001718}
1719
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001720static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001721
1722static void print_bytes_scaled(unsigned long long ull, const char *end)
1723{
1724 unsigned long long int_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001725 const char *ext;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001726 unsigned int frac_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001727 int i;
1728
1729 frac_part = 0;
1730 ext = TRext;
1731 int_part = ull;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001732 i = 4;
1733 do {
1734#if 0
1735 /* This does correct rounding and is a little larger. But it
1736 * uses KiB as the smallest displayed unit. */
1737 if ((int_part < (1024*1024 - 51)) || !--i) {
1738 i = 0;
1739 int_part += 51; /* 1024*.05 = 51.2 */
1740 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001741 }
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001742 int_part /= 1024;
1743 ext += 3; /* KiB, MiB, GiB, TiB */
1744#else
1745 if (int_part >= 1024) {
1746 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
1747 int_part /= 1024;
1748 ext += 3; /* KiB, MiB, GiB, TiB */
1749 }
1750 --i;
1751#endif
1752 } while (i);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001753
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001754 printf("X bytes:%Lu (%Lu.%u %sB)%s", ull, int_part, frac_part, ext, end);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001755}
1756
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001757static const char * const ife_print_flags_strs[] = {
1758 "UP ",
1759 "BROADCAST ",
1760 "DEBUG ",
1761 "LOOPBACK ",
1762 "POINTOPOINT ",
1763 "NOTRAILERS ",
1764 "RUNNING ",
1765 "NOARP ",
1766 "PROMISC ",
1767 "ALLMULTI ",
1768 "SLAVE ",
1769 "MASTER ",
1770 "MULTICAST ",
1771#ifdef HAVE_DYNAMIC
1772 "DYNAMIC "
1773#endif
1774};
1775
1776static const unsigned short ife_print_flags_mask[] = {
1777 IFF_UP,
1778 IFF_BROADCAST,
1779 IFF_DEBUG,
1780 IFF_LOOPBACK,
1781 IFF_POINTOPOINT,
1782 IFF_NOTRAILERS,
1783 IFF_RUNNING,
1784 IFF_NOARP,
1785 IFF_PROMISC,
1786 IFF_ALLMULTI,
1787 IFF_SLAVE,
1788 IFF_MASTER,
1789 IFF_MULTICAST,
1790#ifdef HAVE_DYNAMIC
1791 IFF_DYNAMIC
1792#endif
1793 0
1794};
1795
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001796static void ife_print(struct interface *ptr)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001797{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001798 struct aftype *ap;
1799 struct hwtype *hw;
1800 int hf;
1801 int can_compress = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001802
1803#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001804 static struct aftype *ipxtype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001805#endif
1806#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001807 static struct aftype *ectype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001808#endif
1809#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001810 static struct aftype *ddptype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001811#endif
1812#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001813 FILE *f;
1814 char addr6[40], devname[20];
1815 struct sockaddr_in6 sap;
1816 int plen, scope, dad_status, if_idx;
1817 char addr6p[8][5];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001818#endif
1819
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001820 ap = get_afntype(ptr->addr.sa_family);
1821 if (ap == NULL)
1822 ap = get_afntype(0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001823
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001824 hf = ptr->type;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001825
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001826 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
1827 can_compress = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001828
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001829 hw = get_hwntype(hf);
1830 if (hw == NULL)
1831 hw = get_hwntype(-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001832
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001833 printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title));
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001834 /* For some hardware types (eg Ash, ATM) we don't print the
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001835 hardware address if it's null. */
1836 if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
1837 hw->suppress_null_addr)))
1838 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001839#ifdef IFF_PORTSEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001840 if (ptr->flags & IFF_PORTSEL) {
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001841 printf(_("Media:%s"), if_port_text[ptr->map.port] /* [0] */);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001842 if (ptr->flags & IFF_AUTOMEDIA)
1843 printf(_("(auto)"));
1844 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001845#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001846 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001847
1848#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001849 if (ptr->has_ip) {
1850 printf(_(" %s addr:%s "), ap->name,
1851 ap->sprint(&ptr->addr, 1));
1852 if (ptr->flags & IFF_POINTOPOINT) {
1853 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
1854 }
1855 if (ptr->flags & IFF_BROADCAST) {
1856 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
1857 }
1858 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001859 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001860#endif
1861
1862#if HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +00001863
Eric Andersen51b8bd62002-07-03 11:46:38 +00001864#define IPV6_ADDR_ANY 0x0000U
1865
1866#define IPV6_ADDR_UNICAST 0x0001U
1867#define IPV6_ADDR_MULTICAST 0x0002U
1868#define IPV6_ADDR_ANYCAST 0x0004U
1869
1870#define IPV6_ADDR_LOOPBACK 0x0010U
1871#define IPV6_ADDR_LINKLOCAL 0x0020U
1872#define IPV6_ADDR_SITELOCAL 0x0040U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001873
Eric Andersen51b8bd62002-07-03 11:46:38 +00001874#define IPV6_ADDR_COMPATv4 0x0080U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001875
Eric Andersen51b8bd62002-07-03 11:46:38 +00001876#define IPV6_ADDR_SCOPE_MASK 0x00f0U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001877
Eric Andersen51b8bd62002-07-03 11:46:38 +00001878#define IPV6_ADDR_MAPPED 0x1000U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001879#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
1880
1881 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1882 while (fscanf
1883 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
1884 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
1885 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
1886 &dad_status, devname) != EOF) {
1887 if (!strcmp(devname, ptr->name)) {
1888 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1889 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1890 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1891 inet_pton(AF_INET6, addr6,
1892 (struct sockaddr *) &sap.sin6_addr);
1893 sap.sin6_family = AF_INET6;
1894 printf(_(" inet6 addr: %s/%d"),
1895 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
1896 plen);
1897 printf(_(" Scope:"));
1898 switch (scope & IPV6_ADDR_SCOPE_MASK) {
1899 case 0:
1900 printf(_("Global"));
1901 break;
1902 case IPV6_ADDR_LINKLOCAL:
1903 printf(_("Link"));
1904 break;
1905 case IPV6_ADDR_SITELOCAL:
1906 printf(_("Site"));
1907 break;
1908 case IPV6_ADDR_COMPATv4:
1909 printf(_("Compat"));
1910 break;
1911 case IPV6_ADDR_LOOPBACK:
1912 printf(_("Host"));
1913 break;
1914 default:
1915 printf(_("Unknown"));
1916 }
1917 printf("\n");
1918 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001919 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001920 fclose(f);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001921 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001922#endif
1923
1924#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001925 if (ipxtype == NULL)
1926 ipxtype = get_afntype(AF_IPX);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001927
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001928 if (ipxtype != NULL) {
1929 if (ptr->has_ipx_bb)
1930 printf(_(" IPX/Ethernet II addr:%s\n"),
1931 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
1932 if (ptr->has_ipx_sn)
1933 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
1934 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
1935 if (ptr->has_ipx_e2)
1936 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
1937 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
1938 if (ptr->has_ipx_e3)
1939 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
1940 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
1941 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001942#endif
1943
1944#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001945 if (ddptype == NULL)
1946 ddptype = get_afntype(AF_APPLETALK);
1947 if (ddptype != NULL) {
1948 if (ptr->has_ddp)
1949 printf(_(" EtherTalk Phase 2 addr:%s\n"),
1950 ddptype->sprint(&ptr->ddpaddr, 1));
1951 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001952#endif
1953
1954#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001955 if (ectype == NULL)
1956 ectype = get_afntype(AF_ECONET);
1957 if (ectype != NULL) {
1958 if (ptr->has_econet)
1959 printf(_(" econet addr:%s\n"),
1960 ectype->sprint(&ptr->ecaddr, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001961 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001962#endif
1963
1964 printf(" ");
1965 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001966
1967 if (ptr->flags == 0) {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001968 printf(_("[NO FLAGS] "));
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001969 } else {
1970 int i = 0;
1971 do {
1972 if (ptr->flags & ife_print_flags_mask[i]) {
1973 printf(_(ife_print_flags_strs[i]));
1974 }
1975 } while (ife_print_flags_mask[++i]);
1976 }
1977
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001978 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1979 printf(_(" MTU:%d Metric:%d"), ptr->mtu, ptr->metric ? ptr->metric : 1);
1980#ifdef SIOCSKEEPALIVE
1981 if (ptr->outfill || ptr->keepalive)
1982 printf(_(" Outfill:%d Keepalive:%d"), ptr->outfill, ptr->keepalive);
1983#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001984 printf("\n");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001985
1986 /* If needed, display the interface statistics. */
1987
1988 if (ptr->statistics_valid) {
1989 /* XXX: statistics are currently only printed for the primary address,
1990 * not for the aliases, although strictly speaking they're shared
1991 * by all addresses.
1992 */
1993 printf(" ");
1994
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001995 printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001996 ptr->stats.rx_packets, ptr->stats.rx_errors,
1997 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1998 ptr->stats.rx_frame_errors);
1999 if (can_compress)
2000 printf(_(" compressed:%lu\n"),
2001 ptr->stats.rx_compressed);
2002 printf(" ");
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00002003 printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002004 ptr->stats.tx_packets, ptr->stats.tx_errors,
2005 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
2006 ptr->stats.tx_carrier_errors);
2007 printf(_(" collisions:%lu "), ptr->stats.collisions);
2008 if (can_compress)
2009 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
2010 if (ptr->tx_queue_len != -1)
2011 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
2012 printf("\n R");
2013 print_bytes_scaled(ptr->stats.rx_bytes, " T");
2014 print_bytes_scaled(ptr->stats.tx_bytes, "\n");
2015
2016 }
2017
2018 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
2019 ptr->map.base_addr)) {
2020 printf(" ");
2021 if (ptr->map.irq)
2022 printf(_("Interrupt:%d "), ptr->map.irq);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002023 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002024 I/O maps */
2025 printf(_("Base address:0x%lx "),
2026 (unsigned long) ptr->map.base_addr);
2027 if (ptr->map.mem_start) {
2028 printf(_("Memory:%lx-%lx "), ptr->map.mem_start,
2029 ptr->map.mem_end);
2030 }
2031 if (ptr->map.dma)
2032 printf(_("DMA chan:%x "), ptr->map.dma);
2033 printf("\n");
2034 }
2035 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00002036}
2037
2038
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002039static int do_if_print(struct interface *ife, void *cookie)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002040{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002041 int *opt_a = (int *) cookie;
2042 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002043
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002044 res = do_if_fetch(ife);
2045 if (res >= 0) {
2046 if ((ife->flags & IFF_UP) || *opt_a)
2047 ife_print(ife);
2048 }
2049 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002050}
2051
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002052static struct interface *lookup_interface(char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002053{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002054 struct interface *ife = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002055
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002056 if (if_readlist_proc(name) < 0)
2057 return NULL;
2058 ife = add_interface(name);
2059 return ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002060}
2061
2062/* for ipv4 add/del modes */
2063static int if_print(char *ifname)
2064{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002065 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002066
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002067 if (!ifname) {
2068 res = for_all_interfaces(do_if_print, &interface_opt_a);
2069 } else {
2070 struct interface *ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002071
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002072 ife = lookup_interface(ifname);
2073 res = do_if_fetch(ife);
2074 if (res >= 0)
2075 ife_print(ife);
2076 }
2077 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002078}
2079
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002080int display_interfaces(char *ifname)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002081{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002082 int status;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002083
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002084 /* Create a channel to the NET kernel. */
2085 if ((skfd = sockets_open(0)) < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002086 bb_perror_msg_and_die("socket");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002087 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00002088
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002089 /* Do we have to show the current setup? */
2090 status = if_print(ifname);
Rob Landley93983042005-05-03 21:30:26 +00002091#ifdef CONFIG_FEATURE_CLEAN_UP
2092 sockets_close();
2093#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002094 exit(status < 0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00002095}