blob: 7b7d9def0d097a265c687218f59527359daf433e [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>
Eric Andersenf15d4da2001-03-06 00:48:59 +0000114#endif
115#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000116
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000117/* Defines for glibc2.0 users. */
118#ifndef SIOCSIFTXQLEN
119#define SIOCSIFTXQLEN 0x8943
120#define SIOCGIFTXQLEN 0x8942
121#endif
122
123/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
124#ifndef ifr_qlen
125#define ifr_qlen ifr_ifru.ifru_mtu
126#endif
127
128#ifndef HAVE_TXQUEUELEN
129#define HAVE_TXQUEUELEN 1
130#endif
131
132#ifndef IFF_DYNAMIC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000133#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000134#endif
135
Eric Andersenf15d4da2001-03-06 00:48:59 +0000136/* This structure defines protocol families and their handlers. */
137struct aftype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000138 const char *name;
139 const char *title;
140 int af;
141 int alen;
142 char *(*print) (unsigned char *);
143 char *(*sprint) (struct sockaddr *, int numeric);
144 int (*input) (int type, char *bufp, struct sockaddr *);
145 void (*herror) (char *text);
146 int (*rprint) (int options);
147 int (*rinput) (int typ, int ext, char **argv);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000148
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000149 /* may modify src */
150 int (*getmask) (char *src, struct sockaddr * mask, char *name);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000151
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000152 int fd;
153 char *flag_file;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000154};
155
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000156#ifdef KEEP_UNUSED
157
158static int flag_unx;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000159
Eric Andersen8b113f92001-06-01 21:47:15 +0000160#ifdef HAVE_AFIPX
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000161static int flag_ipx;
Eric Andersen8b113f92001-06-01 21:47:15 +0000162#endif
163#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000164static int flag_ax25;
Eric Andersen8b113f92001-06-01 21:47:15 +0000165#endif
166#ifdef HAVE_AFATALK
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000167static int flag_ddp;
Eric Andersen8b113f92001-06-01 21:47:15 +0000168#endif
169#ifdef HAVE_AFNETROM
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000170static int flag_netrom;
Eric Andersen8b113f92001-06-01 21:47:15 +0000171#endif
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000172static int flag_inet;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000173
Eric Andersen8b113f92001-06-01 21:47:15 +0000174#ifdef HAVE_AFINET6
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000175static int flag_inet6;
Eric Andersen8b113f92001-06-01 21:47:15 +0000176#endif
177#ifdef HAVE_AFECONET
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000178static int flag_econet;
Eric Andersen8b113f92001-06-01 21:47:15 +0000179#endif
180#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000181static int flag_x25 = 0;
Eric Andersen8b113f92001-06-01 21:47:15 +0000182#endif
183#ifdef HAVE_AFASH
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000184static int flag_ash;
Eric Andersen8b113f92001-06-01 21:47:15 +0000185#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000186
187
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000188static struct aftrans_t {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000189 char *alias;
190 char *name;
191 int *flag;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000192} aftrans[] = {
193
Eric Andersen8b113f92001-06-01 21:47:15 +0000194#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000195 {
196 "ax25", "ax25", &flag_ax25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000197#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000198 {
199 "ip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000200#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000201 {
202 "ip6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000203#endif
204#ifdef HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000205 {
206 "ipx", "ipx", &flag_ipx},
Eric Andersen8b113f92001-06-01 21:47:15 +0000207#endif
208#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000209 {
210 "appletalk", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000211#endif
212#ifdef HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000213 {
214 "netrom", "netrom", &flag_netrom},
Eric Andersen8b113f92001-06-01 21:47:15 +0000215#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000216 {
217 "inet", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000218#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000219 {
220 "inet6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000221#endif
222#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000223 {
224 "ddp", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000225#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000226 {
227 "unix", "unix", &flag_unx}, {
228 "tcpip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000229#ifdef HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000230 {
231 "econet", "ec", &flag_econet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000232#endif
233#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000234 {
235 "x25", "x25", &flag_x25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000236#endif
237#ifdef HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000238 {
239 "ash", "ash", &flag_ash},
Eric Andersen8b113f92001-06-01 21:47:15 +0000240#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000241 {
242 0, 0, 0}
Eric Andersenf15d4da2001-03-06 00:48:59 +0000243};
244
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000245static char afname[256] = "";
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000246#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000247
248#if HAVE_AFUNIX
249
250/* Display a UNIX domain address. */
251static char *UNIX_print(unsigned char *ptr)
252{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000253 return (ptr);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000254}
255
256
257/* Display a UNIX domain address. */
258static char *UNIX_sprint(struct sockaddr *sap, int numeric)
259{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000260 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000261
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000262 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
263 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
264 return (UNIX_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000265}
266
267
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000268static struct aftype unix_aftype = {
269 "unix", "UNIX Domain", AF_UNIX, 0,
270 UNIX_print, UNIX_sprint, NULL, NULL,
271 NULL, NULL, NULL,
272 -1,
273 "/proc/net/unix"
Eric Andersenf15d4da2001-03-06 00:48:59 +0000274};
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000275#endif /* HAVE_AFUNIX */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000276
277#if HAVE_AFINET
278
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000279#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000280static void INET_reserror(char *text)
281{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000282 herror(text);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000283}
284
Eric Andersenf15d4da2001-03-06 00:48:59 +0000285/* Display an Internet socket address. */
286static char *INET_print(unsigned char *ptr)
287{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000288 return (inet_ntoa((*(struct in_addr *) ptr)));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000289}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000290#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000291
292/* Display an Internet socket address. */
293static char *INET_sprint(struct sockaddr *sap, int numeric)
294{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000295 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000296
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000297 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
298 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000299
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000300 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
301 numeric, 0xffffff00) != 0)
302 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000303
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000304 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000305}
306
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000307#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000308static char *INET_sprintmask(struct sockaddr *sap, int numeric,
309 unsigned int netmask)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000310{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000311 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000312
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000313 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
314 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
315 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
316 numeric, netmask) != 0)
317 return (NULL);
318 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000319}
320
Eric Andersenf15d4da2001-03-06 00:48:59 +0000321static int INET_getsock(char *bufp, struct sockaddr *sap)
322{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000323 char *sp = bufp, *bp;
324 unsigned int i;
325 unsigned val;
326 struct sockaddr_in *sin;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000327
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000328 sin = (struct sockaddr_in *) sap;
329 sin->sin_family = AF_INET;
330 sin->sin_port = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000331
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000332 val = 0;
333 bp = (char *) &val;
334 for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) {
335 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000336
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000337 if ((*sp >= 'A') && (*sp <= 'F'))
338 bp[i] |= (int) (*sp - 'A') + 10;
339 else if ((*sp >= '0') && (*sp <= '9'))
340 bp[i] |= (int) (*sp - '0');
341 else
342 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000343
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000344 bp[i] <<= 4;
345 sp++;
346 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000347
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000348 if ((*sp >= 'A') && (*sp <= 'F'))
349 bp[i] |= (int) (*sp - 'A') + 10;
350 else if ((*sp >= '0') && (*sp <= '9'))
351 bp[i] |= (int) (*sp - '0');
352 else
353 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000354
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000355 sp++;
356 }
357 sin->sin_addr.s_addr = htonl(val);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000358
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000359 return (sp - bufp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000360}
361
362static int INET_input(int type, char *bufp, struct sockaddr *sap)
363{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000364 switch (type) {
365 case 1:
366 return (INET_getsock(bufp, sap));
367 case 256:
368 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
369 default:
370 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
371 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000372}
373
374static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
375{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000376 struct sockaddr_in *mask = (struct sockaddr_in *) m;
377 char *slash, *end;
378 int prefix;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000379
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000380 if ((slash = strchr(adr, '/')) == NULL)
381 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000382
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000383 *slash++ = '\0';
384 prefix = strtoul(slash, &end, 0);
385 if (*end != '\0')
386 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000387
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000388 if (name) {
389 sprintf(name, "/%d", prefix);
390 }
391 mask->sin_family = AF_INET;
392 mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
393 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000394}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000395#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000396
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000397static struct aftype inet_aftype = {
398 "inet", "DARPA Internet", AF_INET, sizeof(unsigned long),
399 NULL /* UNUSED INET_print */ , INET_sprint,
400 NULL /* UNUSED INET_input */ , NULL /* UNUSED INET_reserror */ ,
401 NULL /*INET_rprint */ , NULL /*INET_rinput */ ,
402 NULL /* UNUSED INET_getnetmask */ ,
403 -1,
404 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000405};
406
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000407#endif /* HAVE_AFINET */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000408
Eric Andersen51b8bd62002-07-03 11:46:38 +0000409#if HAVE_AFINET6
410
411#ifdef KEEP_UNUSED
412static void INET6_reserror(char *text)
413{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000414 herror(text);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000415}
416
417/* Display an Internet socket address. */
418static char *INET6_print(unsigned char *ptr)
419{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000420 static char name[80];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000421
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000422 inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80);
423 return name;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000424}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000425#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000426
427/* Display an Internet socket address. */
428/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
429static char *INET6_sprint(struct sockaddr *sap, int numeric)
430{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000431 static char buff[128];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000432
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000433 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
434 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
435 if (INET6_rresolve
436 (buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)
437 return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff));
438 return (buff);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000439}
440
441#ifdef KEEP_UNUSED
442static int INET6_getsock(char *bufp, struct sockaddr *sap)
443{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000444 struct sockaddr_in6 *sin6;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000445
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000446 sin6 = (struct sockaddr_in6 *) sap;
447 sin6->sin6_family = AF_INET6;
448 sin6->sin6_port = 0;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000449
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000450 if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0)
451 return (-1);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000452
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000453 return 16; /* ?;) */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000454}
455
456static int INET6_input(int type, char *bufp, struct sockaddr *sap)
457{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000458 switch (type) {
459 case 1:
460 return (INET6_getsock(bufp, sap));
461 default:
462 return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));
463 }
Eric Andersen51b8bd62002-07-03 11:46:38 +0000464}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000465#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000466
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000467static struct aftype inet6_aftype = {
468 "inet6", "IPv6", AF_INET6, sizeof(struct in6_addr),
469 NULL /* UNUSED INET6_print */ , INET6_sprint,
470 NULL /* UNUSED INET6_input */ , NULL /* UNUSED INET6_reserror */ ,
471 NULL /*INET6_rprint */ , NULL /*INET6_rinput */ ,
472 NULL /* UNUSED INET6_getnetmask */ ,
473 -1,
474 NULL
Eric Andersen51b8bd62002-07-03 11:46:38 +0000475};
476
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000477#endif /* HAVE_AFINET6 */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000478
Eric Andersenf15d4da2001-03-06 00:48:59 +0000479/* Display an UNSPEC address. */
480static char *UNSPEC_print(unsigned char *ptr)
481{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000482 static char buff[sizeof(struct sockaddr) * 3 + 1];
483 char *pos;
484 unsigned int i;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000485
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000486 pos = buff;
487 for (i = 0; i < sizeof(struct sockaddr); i++) {
488 /* careful -- not every libc's sprintf returns # bytes written */
489 sprintf(pos, "%02X-", (*ptr++ & 0377));
490 pos += 3;
491 }
492 /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */
493 *--pos = '\0';
494 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000495}
496
497/* Display an UNSPEC socket address. */
498static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
499{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000500 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000501
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000502 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
503 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
504 return (UNSPEC_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000505}
506
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000507static struct aftype unspec_aftype = {
508 "unspec", "UNSPEC", AF_UNSPEC, 0,
509 UNSPEC_print, UNSPEC_sprint, NULL, NULL,
510 NULL,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000511};
512
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000513static struct aftype *aftypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000514#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000515 &unix_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000516#endif
517#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000518 &inet_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000519#endif
520#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000521 &inet6_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000522#endif
523#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000524 &ax25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000525#endif
526#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000527 &netrom_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000528#endif
529#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000530 &rose_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000531#endif
532#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000533 &ipx_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000534#endif
535#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000536 &ddp_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000537#endif
538#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000539 &ec_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000540#endif
541#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000542 &ash_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000543#endif
544#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000545 &x25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000546#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000547 &unspec_aftype,
548 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000549};
550
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000551#ifdef KEEP_UNUSED
552static short sVafinit = 0;
553
554static void afinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +0000555{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000556 unspec_aftype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000557#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000558 unix_aftype.title = _("UNIX Domain");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000559#endif
560#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000561 inet_aftype.title = _("DARPA Internet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000562#endif
563#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000564 inet6_aftype.title = _("IPv6");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000565#endif
566#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000567 ax25_aftype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000568#endif
569#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000570 netrom_aftype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000571#endif
572#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000573 ipx_aftype.title = _("Novell IPX");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000574#endif
575#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000576 ddp_aftype.title = _("Appletalk DDP");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000577#endif
578#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000579 ec_aftype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000580#endif
581#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000582 x25_aftype.title = _("CCITT X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000583#endif
584#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000585 rose_aftype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000586#endif
587#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000588 ash_aftype.title = _("Ash");
589#endif
590 sVafinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000591}
592
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000593static int aftrans_opt(const char *arg)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000594{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000595 struct aftrans_t *paft;
596 char *tmp1, *tmp2;
597 char buf[256];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000598
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000599 safe_strncpy(buf, arg, sizeof(buf));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000600
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000601 tmp1 = buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000602
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000603 while (tmp1) {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000604
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000605 tmp2 = strchr(tmp1, ',');
Eric Andersenf15d4da2001-03-06 00:48:59 +0000606
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000607 if (tmp2)
608 *(tmp2++) = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000609
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000610 paft = aftrans;
611 for (paft = aftrans; paft->alias; paft++) {
612 if (strcmp(tmp1, paft->alias))
613 continue;
614 if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000615 bb_error_msg(_("Too many address family arguments."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000616 return (0);
617 }
618 if (paft->flag)
619 (*paft->flag)++;
620 if (afname[0])
621 strcat(afname, ",");
622 strcat(afname, paft->name);
623 break;
624 }
625 if (!paft->alias) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000626 bb_error_msg(_("Unknown address family `%s'."), tmp1);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000627 return (1);
628 }
629 tmp1 = tmp2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000630 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000631
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000632 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000633}
634
635/* set the default AF list from the program name or a constant value */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000636static void aftrans_def(char *tool, char *argv0, char *dflt)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000637{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000638 char *tmp;
639 char *buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000640
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000641 strcpy(afname, dflt);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000642
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000643 if (!(tmp = strrchr(argv0, '/')))
644 tmp = argv0; /* no slash?! */
645 else
646 tmp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000647
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000648 if (!(buf = strdup(tmp)))
649 return;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000650
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000651 if (strlen(tool) >= strlen(tmp)) {
652 free(buf);
653 return;
654 }
655 tmp = buf + (strlen(tmp) - strlen(tool));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000656
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000657 if (strcmp(tmp, tool) != 0) {
658 free(buf);
659 return;
660 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000661 *tmp = '\0';
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000662 if ((tmp = strchr(buf, '_')))
663 *tmp = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000664
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000665 afname[0] = '\0';
666 if (aftrans_opt(buf))
667 strcpy(afname, buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000668
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000669 free(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000670}
671
Eric Andersenf15d4da2001-03-06 00:48:59 +0000672/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000673static struct aftype *get_aftype(const char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000674{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000675 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000676
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000677#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000678 if (!sVafinit)
679 afinit();
680#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000681
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000682 afp = aftypes;
683 while (*afp != NULL) {
684 if (!strcmp((*afp)->name, name))
685 return (*afp);
686 afp++;
687 }
688 if (strchr(name, ','))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000689 bb_error_msg(_("Please don't supply more than one address family."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000690 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000691}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000692#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000693
694/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000695static struct aftype *get_afntype(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000696{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000697 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000698
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000699#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000700 if (!sVafinit)
701 afinit();
702#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000703
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000704 afp = aftypes;
705 while (*afp != NULL) {
706 if ((*afp)->af == af)
707 return (*afp);
708 afp++;
709 }
710 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000711}
712
713/* Check our protocol family table for this family and return its socket */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000714static int get_socket_for_af(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000715{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000716 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000717
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000718#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000719 if (!sVafinit)
720 afinit();
721#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000722
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000723 afp = aftypes;
724 while (*afp != NULL) {
725 if ((*afp)->af == af)
726 return (*afp)->fd;
727 afp++;
728 }
729 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000730}
731
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000732#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000733/* type: 0=all, 1=getroute */
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000734static void print_aflist(int type)
735{
736 int count = 0;
737 char *txt;
738 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000739
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000740#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000741 if (!sVafinit)
742 afinit();
743#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000744
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000745 afp = aftypes;
746 while (*afp != NULL) {
747 if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) {
748 afp++;
749 continue;
750 }
751 if ((count % 3) == 0)
752 fprintf(stderr, count ? "\n " : " ");
753 txt = (*afp)->name;
754 if (!txt)
755 txt = "..";
756 fprintf(stderr, "%s (%s) ", txt, _((*afp)->title));
757 count++;
758 afp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000759 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000760 fprintf(stderr, "\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000761}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000762#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000763
764struct user_net_device_stats {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000765 unsigned long long rx_packets; /* total packets received */
766 unsigned long long tx_packets; /* total packets transmitted */
767 unsigned long long rx_bytes; /* total bytes received */
768 unsigned long long tx_bytes; /* total bytes transmitted */
769 unsigned long rx_errors; /* bad packets received */
770 unsigned long tx_errors; /* packet transmit problems */
771 unsigned long rx_dropped; /* no space in linux buffers */
772 unsigned long tx_dropped; /* no space available in linux */
773 unsigned long rx_multicast; /* multicast packets received */
774 unsigned long rx_compressed;
775 unsigned long tx_compressed;
776 unsigned long collisions;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000777
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000778 /* detailed rx_errors: */
779 unsigned long rx_length_errors;
780 unsigned long rx_over_errors; /* receiver ring buff overflow */
781 unsigned long rx_crc_errors; /* recved pkt with crc error */
782 unsigned long rx_frame_errors; /* recv'd frame alignment error */
783 unsigned long rx_fifo_errors; /* recv'r fifo overrun */
784 unsigned long rx_missed_errors; /* receiver missed packet */
785 /* detailed tx_errors */
786 unsigned long tx_aborted_errors;
787 unsigned long tx_carrier_errors;
788 unsigned long tx_fifo_errors;
789 unsigned long tx_heartbeat_errors;
790 unsigned long tx_window_errors;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000791};
792
793struct interface {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000794 struct interface *next, *prev;
795 char name[IFNAMSIZ]; /* interface name */
796 short type; /* if type */
797 short flags; /* various flags */
798 int metric; /* routing metric */
799 int mtu; /* MTU value */
800 int tx_queue_len; /* transmit queue length */
801 struct ifmap map; /* hardware setup */
802 struct sockaddr addr; /* IP address */
803 struct sockaddr dstaddr; /* P-P IP address */
804 struct sockaddr broadaddr; /* IP broadcast address */
805 struct sockaddr netmask; /* IP network mask */
806 struct sockaddr ipxaddr_bb; /* IPX network address */
807 struct sockaddr ipxaddr_sn; /* IPX network address */
808 struct sockaddr ipxaddr_e3; /* IPX network address */
809 struct sockaddr ipxaddr_e2; /* IPX network address */
810 struct sockaddr ddpaddr; /* Appletalk DDP address */
811 struct sockaddr ecaddr; /* Econet address */
812 int has_ip;
813 int has_ipx_bb;
814 int has_ipx_sn;
815 int has_ipx_e3;
816 int has_ipx_e2;
817 int has_ax25;
818 int has_ddp;
819 int has_econet;
820 char hwaddr[32]; /* HW address */
821 int statistics_valid;
822 struct user_net_device_stats stats; /* statistics */
823 int keepalive; /* keepalive value for SLIP */
824 int outfill; /* outfill value for SLIP */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000825};
826
827
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000828int interface_opt_a = 0; /* show all interfaces */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000829
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000830#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000831static int opt_i = 0; /* show the statistics */
832static int opt_v = 0; /* debugging output flag */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000833
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000834static int addr_family = 0; /* currently selected AF */
835#endif /* KEEP_UNUSED */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000836
Eric Andersenf15d4da2001-03-06 00:48:59 +0000837static struct interface *int_list, *int_last;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000838static int skfd = -1; /* generic raw socket desc. */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000839
840
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000841static int sockets_open(int family)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000842{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000843 struct aftype **aft;
844 int sfd = -1;
845 static int force = -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000846
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000847 if (force < 0) {
848 force = 0;
849 if (get_kernel_revision() < KRELEASE(2, 1, 0))
850 force = 1;
851 if (access("/proc/net", R_OK))
852 force = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000853 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000854 for (aft = aftypes; *aft; aft++) {
855 struct aftype *af = *aft;
856 int type = SOCK_DGRAM;
857
858 if (af->af == AF_UNSPEC)
859 continue;
860 if (family && family != af->af)
861 continue;
862 if (af->fd != -1) {
863 sfd = af->fd;
864 continue;
865 }
866 /* Check some /proc file first to not stress kmod */
867 if (!family && !force && af->flag_file) {
868 if (access(af->flag_file, R_OK))
869 continue;
870 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000871#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000872 if (af->af == AF_NETROM)
873 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000874#endif
875#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000876 if (af->af == AF_X25)
877 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000878#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000879 af->fd = socket(af->af, type, 0);
880 if (af->fd >= 0)
881 sfd = af->fd;
882 }
Glenn L McGrath642f2892002-11-28 10:20:45 +0000883 if (sfd < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000884 bb_error_msg(_("No usable address families found."));
Glenn L McGrath642f2892002-11-28 10:20:45 +0000885 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000886 return sfd;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000887}
888
Rob Landley93983042005-05-03 21:30:26 +0000889#ifdef CONFIG_FEATURE_CLEAN_UP
890static void sockets_close(void)
891{
892 struct aftype **aft;
893 for (aft = aftypes; *aft != NULL; aft++) {
894 struct aftype *af = *aft;
895 if( af->fd != -1 ) {
896 close(af->fd);
897 af->fd = -1;
898 }
899 }
900}
901#endif
902
Eric Andersenf15d4da2001-03-06 00:48:59 +0000903/* like strcmp(), but knows about numbers */
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000904static int nstrcmp(const char *a, const char *b)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000905{
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000906 const char *a_ptr = a;
907 const char *b_ptr = b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000908
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000909 while (*a == *b) {
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000910 if (*a == '\0') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000911 return 0;
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000912 }
913 if (!isdigit(*a) && isdigit(*(a+1))) {
914 a_ptr = a+1;
915 b_ptr = b+1;
916 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000917 a++;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000918 b++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000919 }
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000920
921 if (isdigit(*a) && isdigit(*b)) {
922 return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000923 }
924 return *a - *b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000925}
926
927static struct interface *add_interface(char *name)
928{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000929 struct interface *ife, **nextp, *new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000930
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000931 for (ife = int_last; ife; ife = ife->prev) {
932 int n = nstrcmp(ife->name, name);
933
934 if (n == 0)
935 return ife;
936 if (n < 0)
937 break;
938 }
939 new(new);
940 safe_strncpy(new->name, name, IFNAMSIZ);
941 nextp = ife ? &ife->next : &int_list;
942 new->prev = ife;
943 new->next = *nextp;
944 if (new->next)
945 new->next->prev = new;
946 else
947 int_last = new;
948 *nextp = new;
949 return new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000950}
951
952
953static int if_readconf(void)
954{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000955 int numreqs = 30;
956 struct ifconf ifc;
957 struct ifreq *ifr;
958 int n, err = -1;
959 int skfd2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000960
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000961 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
962 (as of 2.1.128) */
963 skfd2 = get_socket_for_af(AF_INET);
964 if (skfd2 < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000965 bb_perror_msg(("warning: no inet socket available"));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000966 /* Try to soldier on with whatever socket we can get hold of. */
967 skfd2 = sockets_open(0);
968 if (skfd2 < 0)
969 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000970 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000971
972 ifc.ifc_buf = NULL;
973 for (;;) {
974 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
975 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
976
977 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
978 perror("SIOCGIFCONF");
979 goto out;
980 }
981 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
982 /* assume it overflowed and try again */
983 numreqs += 10;
984 continue;
985 }
986 break;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000987 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000988
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000989 ifr = ifc.ifc_req;
990 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
991 add_interface(ifr->ifr_name);
992 ifr++;
993 }
994 err = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000995
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000996 out:
997 free(ifc.ifc_buf);
998 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000999}
1000
Eric Andersen14f5c8d2005-04-16 19:39:00 +00001001static char *get_name(char *name, char *p)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001002{
Eric Andersen9940e082004-08-12 16:52:00 +00001003 /* Extract <name>[:<alias>] from nul-terminated p where p matches
1004 <name>[:<alias>]: after leading whitespace.
1005 If match is not made, set name empty and return unchanged p */
1006 int namestart=0, nameend=0, aliasend;
1007 while (isspace(p[namestart]))
1008 namestart++;
1009 nameend=namestart;
1010 while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
1011 nameend++;
1012 if (p[nameend]==':') {
1013 aliasend=nameend+1;
1014 while (p[aliasend] && isdigit(p[aliasend]))
1015 aliasend++;
1016 if (p[aliasend]==':') {
1017 nameend=aliasend;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001018 }
Eric Andersen9940e082004-08-12 16:52:00 +00001019 if ((nameend-namestart)<IFNAMSIZ) {
1020 memcpy(name,&p[namestart],nameend-namestart);
1021 name[nameend-namestart]='\0';
1022 p=&p[nameend];
1023 } else {
1024 /* Interface name too large */
1025 name[0]='\0';
1026 }
1027 } else {
1028 /* first ':' not found - return empty */
1029 name[0]='\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +00001030 }
Eric Andersen6fea7322004-08-26 21:45:21 +00001031 return p + 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001032}
1033
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001034/* If scanf supports size qualifiers for %n conversions, then we can
1035 * use a modified fmt that simply stores the position in the fields
1036 * having no associated fields in the proc string. Of course, we need
1037 * to zero them again when we're done. But that is smaller than the
1038 * old approach of multiple scanf occurrences with large numbers of
1039 * args. */
1040
1041/* static const char *ss_fmt[] = { */
1042/* "%Ln%Lu%lu%lu%lu%lu%ln%ln%Ln%Lu%lu%lu%lu%lu%lu", */
1043/* "%Lu%Lu%lu%lu%lu%lu%ln%ln%Lu%Lu%lu%lu%lu%lu%lu", */
1044/* "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu" */
1045/* }; */
1046
1047 /* Lie about the size of the int pointed to for %n. */
1048#if INT_MAX == LONG_MAX
1049static const char *ss_fmt[] = {
1050 "%n%Lu%u%u%u%u%n%n%n%Lu%u%u%u%u%u",
1051 "%Lu%Lu%u%u%u%u%n%n%Lu%Lu%u%u%u%u%u",
1052 "%Lu%Lu%u%u%u%u%u%u%Lu%Lu%u%u%u%u%u%u"
1053};
1054#else
1055static const char *ss_fmt[] = {
1056 "%n%Lu%lu%lu%lu%lu%n%n%n%Lu%lu%lu%lu%lu%lu",
1057 "%Lu%Lu%lu%lu%lu%lu%n%n%Lu%Lu%lu%lu%lu%lu%lu",
1058 "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu"
1059};
1060
1061#endif
1062
1063static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001064{
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001065 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
1066
1067 sscanf(bp, ss_fmt[procnetdev_vsn],
1068 &ife->stats.rx_bytes, /* missing for 0 */
1069 &ife->stats.rx_packets,
1070 &ife->stats.rx_errors,
1071 &ife->stats.rx_dropped,
1072 &ife->stats.rx_fifo_errors,
1073 &ife->stats.rx_frame_errors,
1074 &ife->stats.rx_compressed, /* missing for <= 1 */
1075 &ife->stats.rx_multicast, /* missing for <= 1 */
1076 &ife->stats.tx_bytes, /* missing for 0 */
1077 &ife->stats.tx_packets,
1078 &ife->stats.tx_errors,
1079 &ife->stats.tx_dropped,
1080 &ife->stats.tx_fifo_errors,
1081 &ife->stats.collisions,
1082 &ife->stats.tx_carrier_errors,
1083 &ife->stats.tx_compressed /* missing for <= 1 */
1084 );
1085
1086 if (procnetdev_vsn <= 1) {
1087 if (procnetdev_vsn == 0) {
1088 ife->stats.rx_bytes = 0;
1089 ife->stats.tx_bytes = 0;
1090 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001091 ife->stats.rx_multicast = 0;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001092 ife->stats.rx_compressed = 0;
1093 ife->stats.tx_compressed = 0;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001094 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001095}
1096
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001097static inline int procnetdev_version(char *buf)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001098{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001099 if (strstr(buf, "compressed"))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001100 return 2;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001101 if (strstr(buf, "bytes"))
1102 return 1;
1103 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001104}
1105
1106static int if_readlist_proc(char *target)
1107{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001108 static int proc_read;
1109 FILE *fh;
1110 char buf[512];
1111 struct interface *ife;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001112 int err, procnetdev_vsn;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001113
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001114 if (proc_read)
1115 return 0;
1116 if (!target)
1117 proc_read = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001118
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001119 fh = fopen(_PATH_PROCNET_DEV, "r");
1120 if (!fh) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001121 bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001122 return if_readconf();
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001123 }
1124 fgets(buf, sizeof buf, fh); /* eat line */
1125 fgets(buf, sizeof buf, fh);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001126
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001127 procnetdev_vsn = procnetdev_version(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001128
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001129 err = 0;
1130 while (fgets(buf, sizeof buf, fh)) {
Eric Andersenf96675b2003-07-28 06:37:04 +00001131 char *s, name[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001132
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001133 s = get_name(name, buf);
1134 ife = add_interface(name);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001135 get_dev_fields(s, ife, procnetdev_vsn);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001136 ife->statistics_valid = 1;
1137 if (target && !strcmp(target, name))
1138 break;
1139 }
1140 if (ferror(fh)) {
1141 perror(_PATH_PROCNET_DEV);
1142 err = -1;
1143 proc_read = 0;
1144 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001145 fclose(fh);
1146 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001147}
1148
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001149static int if_readlist(void)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001150{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001151 int err = if_readlist_proc(NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001152
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001153 if (!err)
1154 err = if_readconf();
1155 return err;
1156}
1157
1158static int for_all_interfaces(int (*doit) (struct interface *, void *),
1159 void *cookie)
1160{
1161 struct interface *ife;
1162
1163 if (!int_list && (if_readlist() < 0))
1164 return -1;
1165 for (ife = int_list; ife; ife = ife->next) {
1166 int err = doit(ife, cookie);
1167
1168 if (err)
1169 return err;
1170 }
1171 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001172}
1173
1174/* Support for fetching an IPX address */
1175
1176#if HAVE_AFIPX
1177static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
1178{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001179 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
1180 return ioctl(sock, SIOCGIFADDR, ifr);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001181}
1182#endif
1183
1184
1185/* Fetch the interface configuration from the kernel. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001186static int if_fetch(struct interface *ife)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001187{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001188 struct ifreq ifr;
1189 int fd;
1190 char *ifname = ife->name;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001191
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001192 strcpy(ifr.ifr_name, ifname);
1193 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
1194 return (-1);
1195 ife->flags = ifr.ifr_flags;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001196
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001197 strcpy(ifr.ifr_name, ifname);
1198 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
1199 memset(ife->hwaddr, 0, 32);
1200 else
1201 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001202
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001203 ife->type = ifr.ifr_hwaddr.sa_family;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001204
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001205 strcpy(ifr.ifr_name, ifname);
1206 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
1207 ife->metric = 0;
1208 else
1209 ife->metric = ifr.ifr_metric;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001210
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001211 strcpy(ifr.ifr_name, ifname);
1212 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
1213 ife->mtu = 0;
1214 else
1215 ife->mtu = ifr.ifr_mtu;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001216
1217#ifdef HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001218 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
1219 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
1220 ife->type == ARPHRD_ADAPT) {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001221#ifdef SIOCGOUTFILL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001222 strcpy(ifr.ifr_name, ifname);
1223 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
1224 ife->outfill = 0;
1225 else
1226 ife->outfill = (unsigned int) ifr.ifr_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001227#endif
1228#ifdef SIOCGKEEPALIVE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001229 strcpy(ifr.ifr_name, ifname);
1230 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
1231 ife->keepalive = 0;
1232 else
1233 ife->keepalive = (unsigned int) ifr.ifr_data;
1234#endif
1235 }
1236#endif
1237
Rob Landley93983042005-05-03 21:30:26 +00001238#ifdef SIOCGIFMAP
Eric Andersenf15d4da2001-03-06 00:48:59 +00001239 strcpy(ifr.ifr_name, ifname);
Rob Landley93983042005-05-03 21:30:26 +00001240 if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001241 ife->map = ifr.ifr_map;
Rob Landley93983042005-05-03 21:30:26 +00001242 else
1243#endif
1244 memset(&ife->map, 0, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001245
1246#ifdef HAVE_TXQUEUELEN
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001247 strcpy(ifr.ifr_name, ifname);
1248 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
1249 ife->tx_queue_len = -1; /* unknown value */
1250 else
1251 ife->tx_queue_len = ifr.ifr_qlen;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001252#else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001253 ife->tx_queue_len = -1; /* unknown value */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001254#endif
1255
1256#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001257 /* IPv4 address? */
1258 fd = get_socket_for_af(AF_INET);
1259 if (fd >= 0) {
1260 strcpy(ifr.ifr_name, ifname);
1261 ifr.ifr_addr.sa_family = AF_INET;
1262 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1263 ife->has_ip = 1;
1264 ife->addr = ifr.ifr_addr;
1265 strcpy(ifr.ifr_name, ifname);
1266 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
1267 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
1268 else
1269 ife->dstaddr = ifr.ifr_dstaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001270
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001271 strcpy(ifr.ifr_name, ifname);
1272 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
1273 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
1274 else
1275 ife->broadaddr = ifr.ifr_broadaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001276
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001277 strcpy(ifr.ifr_name, ifname);
1278 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
1279 memset(&ife->netmask, 0, sizeof(struct sockaddr));
1280 else
1281 ife->netmask = ifr.ifr_netmask;
1282 } else
1283 memset(&ife->addr, 0, sizeof(struct sockaddr));
1284 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001285#endif
1286
1287#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001288 /* DDP address maybe ? */
1289 fd = get_socket_for_af(AF_APPLETALK);
1290 if (fd >= 0) {
1291 strcpy(ifr.ifr_name, ifname);
1292 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1293 ife->ddpaddr = ifr.ifr_addr;
1294 ife->has_ddp = 1;
1295 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001296 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001297#endif
1298
1299#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001300 /* Look for IPX addresses with all framing types */
1301 fd = get_socket_for_af(AF_IPX);
1302 if (fd >= 0) {
1303 strcpy(ifr.ifr_name, ifname);
1304 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
1305 ife->has_ipx_bb = 1;
1306 ife->ipxaddr_bb = ifr.ifr_addr;
1307 }
1308 strcpy(ifr.ifr_name, ifname);
1309 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
1310 ife->has_ipx_sn = 1;
1311 ife->ipxaddr_sn = ifr.ifr_addr;
1312 }
1313 strcpy(ifr.ifr_name, ifname);
1314 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
1315 ife->has_ipx_e3 = 1;
1316 ife->ipxaddr_e3 = ifr.ifr_addr;
1317 }
1318 strcpy(ifr.ifr_name, ifname);
1319 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
1320 ife->has_ipx_e2 = 1;
1321 ife->ipxaddr_e2 = ifr.ifr_addr;
1322 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001323 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001324#endif
1325
1326#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001327 /* Econet address maybe? */
1328 fd = get_socket_for_af(AF_ECONET);
1329 if (fd >= 0) {
1330 strcpy(ifr.ifr_name, ifname);
1331 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1332 ife->ecaddr = ifr.ifr_addr;
1333 ife->has_econet = 1;
1334 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001335 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001336#endif
1337
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001338 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001339}
1340
1341
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001342static int do_if_fetch(struct interface *ife)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001343{
1344 if (if_fetch(ife) < 0) {
1345 char *errmsg;
1346
1347 if (errno == ENODEV) {
1348 /* Give better error message for this case. */
1349 errmsg = _("Device not found");
1350 } else {
1351 errmsg = strerror(errno);
1352 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001353 bb_error_msg(_("%s: error fetching interface information: %s\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001354 ife->name, errmsg);
1355 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001356 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001357 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001358}
1359
1360/* This structure defines hardware protocols and their handlers. */
1361struct hwtype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001362 const char *name;
1363 const char *title;
1364 int type;
1365 int alen;
1366 char *(*print) (unsigned char *);
1367 int (*input) (char *, struct sockaddr *);
1368 int (*activate) (int fd);
1369 int suppress_null_addr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001370};
1371
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001372static struct hwtype unspec_hwtype = {
1373 "unspec", "UNSPEC", -1, 0,
1374 UNSPEC_print, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001375};
1376
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001377static struct hwtype loop_hwtype = {
1378 "loop", "Local Loopback", ARPHRD_LOOPBACK, 0,
1379 NULL, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001380};
1381
1382#if HAVE_HWETHER
1383#include <net/if_arp.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001384
Mike Frysinger3b05b802005-03-04 01:10:56 +00001385#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION)
Eric Andersenab4e19a2003-01-14 08:54:08 +00001386#include <net/ethernet.h>
1387#else
Eric Andersenf15d4da2001-03-06 00:48:59 +00001388#include <linux/if_ether.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001389#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001390
Eric Andersenf15d4da2001-03-06 00:48:59 +00001391/* Display an Ethernet address in readable format. */
1392static char *pr_ether(unsigned char *ptr)
1393{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001394 static char buff[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001395
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001396 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
1397 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
1398 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
1399 );
1400 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001401}
1402
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001403#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001404/* Input an Ethernet address and convert to binary. */
1405static int in_ether(char *bufp, struct sockaddr *sap)
1406{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001407 unsigned char *ptr;
1408 char c, *orig;
1409 int i;
1410 unsigned val;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001411
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001412 sap->sa_family = ether_hwtype.type;
1413 ptr = sap->sa_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001414
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001415 i = 0;
1416 orig = bufp;
1417 while ((*bufp != '\0') && (i < ETH_ALEN)) {
1418 val = 0;
1419 c = *bufp++;
1420 if (isdigit(c))
1421 val = c - '0';
1422 else if (c >= 'a' && c <= 'f')
1423 val = c - 'a' + 10;
1424 else if (c >= 'A' && c <= 'F')
1425 val = c - 'A' + 10;
1426 else {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001427#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001428 bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001429#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001430 errno = EINVAL;
1431 return (-1);
1432 }
1433 val <<= 4;
1434 c = *bufp;
1435 if (isdigit(c))
1436 val |= c - '0';
1437 else if (c >= 'a' && c <= 'f')
1438 val |= c - 'a' + 10;
1439 else if (c >= 'A' && c <= 'F')
1440 val |= c - 'A' + 10;
1441 else if (c == ':' || c == 0)
1442 val >>= 4;
1443 else {
1444#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001445 bb_error_msg(_("in_ether(%s): invalid ether address!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001446#endif
1447 errno = EINVAL;
1448 return (-1);
1449 }
1450 if (c != 0)
1451 bufp++;
1452 *ptr++ = (unsigned char) (val & 0377);
1453 i++;
1454
1455 /* We might get a semicolon here - not required. */
1456 if (*bufp == ':') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001457#ifdef DEBUG
Glenn L McGrath642f2892002-11-28 10:20:45 +00001458 if (i == ETH_ALEN) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001459 bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001460 }
Glenn L McGrath642f2892002-11-28 10:20:45 +00001461#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001462 bufp++;
1463 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001464 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001465
Glenn L McGrath642f2892002-11-28 10:20:45 +00001466#ifdef DEBUG
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001467 /* That's it. Any trailing junk? */
1468 if ((i == ETH_ALEN) && (*bufp != '\0')) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001469 bb_error_msg(_("in_ether(%s): trailing junk!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001470 errno = EINVAL;
1471 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001472 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001473 bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001474#endif
1475
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001476 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001477}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001478#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001479
1480
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001481static struct hwtype ether_hwtype = {
1482 "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN,
1483 pr_ether, NULL /* UNUSED in_ether */ , NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001484};
1485
1486
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001487#endif /* HAVE_HWETHER */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001488
1489
1490#if HAVE_HWPPP
1491
1492#include <net/if_arp.h>
1493
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001494#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001495/* Start the PPP encapsulation on the file descriptor. */
1496static int do_ppp(int fd)
1497{
Manuel Novoa III cad53642003-03-19 09:13:01 +00001498 bb_error_msg(_("You cannot start PPP with this program."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001499 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001500}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001501#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001502
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001503static struct hwtype ppp_hwtype = {
1504 "ppp", "Point-Point Protocol", ARPHRD_PPP, 0,
1505 NULL, NULL, NULL /* UNUSED do_ppp */ , 0
Eric Andersenf15d4da2001-03-06 00:48:59 +00001506};
1507
1508
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001509#endif /* HAVE_PPP */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001510
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001511static struct hwtype *hwtypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001512
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001513 &loop_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001514
1515#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001516 &slip_hwtype,
1517 &cslip_hwtype,
1518 &slip6_hwtype,
1519 &cslip6_hwtype,
1520 &adaptive_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001521#endif
1522#if HAVE_HWSTRIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001523 &strip_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001524#endif
1525#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001526 &ash_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001527#endif
1528#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001529 &ether_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001530#endif
1531#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001532 &tr_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001533#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001534 &tr_hwtype1,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001535#endif
1536#endif
1537#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001538 &ax25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001539#endif
1540#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001541 &netrom_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001542#endif
1543#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001544 &rose_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001545#endif
1546#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001547 &tunnel_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001548#endif
1549#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001550 &ppp_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001551#endif
1552#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001553 &hdlc_hwtype,
1554 &lapb_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001555#endif
1556#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001557 &arcnet_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001558#endif
1559#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001560 &dlci_hwtype,
1561 &frad_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001562#endif
1563#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001564 &sit_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001565#endif
1566#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001567 &fddi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001568#endif
1569#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001570 &hippi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001571#endif
1572#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001573 &irda_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001574#endif
1575#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001576 &ec_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001577#endif
1578#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001579 &x25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001580#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001581 &unspec_hwtype,
1582 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001583};
1584
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001585#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001586static short sVhwinit = 0;
1587
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001588static void hwinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +00001589{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001590 loop_hwtype.title = _("Local Loopback");
1591 unspec_hwtype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001592#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001593 slip_hwtype.title = _("Serial Line IP");
1594 cslip_hwtype.title = _("VJ Serial Line IP");
1595 slip6_hwtype.title = _("6-bit Serial Line IP");
1596 cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
1597 adaptive_hwtype.title = _("Adaptive Serial Line IP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001598#endif
1599#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001600 ether_hwtype.title = _("Ethernet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001601#endif
1602#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001603 ash_hwtype.title = _("Ash");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001604#endif
1605#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001606 fddi_hwtype.title = _("Fiber Distributed Data Interface");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001607#endif
1608#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001609 hippi_hwtype.title = _("HIPPI");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001610#endif
1611#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001612 ax25_hwtype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001613#endif
1614#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001615 rose_hwtype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001616#endif
1617#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001618 netrom_hwtype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001619#endif
1620#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001621 x25_hwtype.title = _("generic X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001622#endif
1623#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001624 tunnel_hwtype.title = _("IPIP Tunnel");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001625#endif
1626#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001627 ppp_hwtype.title = _("Point-to-Point Protocol");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001628#endif
1629#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001630 hdlc_hwtype.title = _("(Cisco)-HDLC");
1631 lapb_hwtype.title = _("LAPB");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001632#endif
1633#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001634 arcnet_hwtype.title = _("ARCnet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001635#endif
1636#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001637 dlci_hwtype.title = _("Frame Relay DLCI");
1638 frad_hwtype.title = _("Frame Relay Access Device");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001639#endif
1640#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001641 sit_hwtype.title = _("IPv6-in-IPv4");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001642#endif
1643#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001644 irda_hwtype.title = _("IrLAP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001645#endif
1646#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001647 tr_hwtype.title = _("16/4 Mbps Token Ring");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001648#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001649 tr_hwtype1.title = _("16/4 Mbps Token Ring (New)");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001650#endif
1651#endif
1652#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001653 ec_hwtype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001654#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001655 sVhwinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001656}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001657#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001658
1659#ifdef IFF_PORTSEL
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001660#if 0
1661static const char * const if_port_text[][4] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001662 /* Keep in step with <linux/netdevice.h> */
1663 {"unknown", NULL, NULL, NULL},
1664 {"10base2", "bnc", "coax", NULL},
1665 {"10baseT", "utp", "tpe", NULL},
1666 {"AUI", "thick", "db15", NULL},
1667 {"100baseT", NULL, NULL, NULL},
1668 {"100baseTX", NULL, NULL, NULL},
1669 {"100baseFX", NULL, NULL, NULL},
1670 {NULL, NULL, NULL, NULL},
Eric Andersenf15d4da2001-03-06 00:48:59 +00001671};
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001672#else
1673static const char * const if_port_text[] = {
1674 /* Keep in step with <linux/netdevice.h> */
1675 "unknown",
1676 "10base2",
1677 "10baseT",
1678 "AUI",
1679 "100baseT",
1680 "100baseTX",
1681 "100baseFX",
1682 NULL
1683};
1684#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001685#endif
1686
1687/* Check our hardware type table for this type. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001688static struct hwtype *get_hwntype(int type)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001689{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001690 struct hwtype **hwp;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001691
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001692#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001693 if (!sVhwinit)
1694 hwinit();
1695#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001696
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001697 hwp = hwtypes;
1698 while (*hwp != NULL) {
1699 if ((*hwp)->type == type)
1700 return (*hwp);
1701 hwp++;
1702 }
1703 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001704}
1705
1706/* return 1 if address is all zeros */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001707static int hw_null_address(struct hwtype *hw, void *ap)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001708{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001709 unsigned int i;
1710 unsigned char *address = (unsigned char *) ap;
1711
1712 for (i = 0; i < hw->alen; i++)
1713 if (address[i])
1714 return 0;
1715 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001716}
1717
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001718static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001719
1720static void print_bytes_scaled(unsigned long long ull, const char *end)
1721{
1722 unsigned long long int_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001723 const char *ext;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001724 unsigned int frac_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001725 int i;
1726
1727 frac_part = 0;
1728 ext = TRext;
1729 int_part = ull;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001730 i = 4;
1731 do {
1732#if 0
1733 /* This does correct rounding and is a little larger. But it
1734 * uses KiB as the smallest displayed unit. */
1735 if ((int_part < (1024*1024 - 51)) || !--i) {
1736 i = 0;
1737 int_part += 51; /* 1024*.05 = 51.2 */
1738 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001739 }
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001740 int_part /= 1024;
1741 ext += 3; /* KiB, MiB, GiB, TiB */
1742#else
1743 if (int_part >= 1024) {
1744 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
1745 int_part /= 1024;
1746 ext += 3; /* KiB, MiB, GiB, TiB */
1747 }
1748 --i;
1749#endif
1750 } while (i);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001751
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001752 printf("X bytes:%Lu (%Lu.%u %sB)%s", ull, int_part, frac_part, ext, end);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001753}
1754
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001755static const char * const ife_print_flags_strs[] = {
1756 "UP ",
1757 "BROADCAST ",
1758 "DEBUG ",
1759 "LOOPBACK ",
1760 "POINTOPOINT ",
1761 "NOTRAILERS ",
1762 "RUNNING ",
1763 "NOARP ",
1764 "PROMISC ",
1765 "ALLMULTI ",
1766 "SLAVE ",
1767 "MASTER ",
1768 "MULTICAST ",
1769#ifdef HAVE_DYNAMIC
1770 "DYNAMIC "
1771#endif
1772};
1773
1774static const unsigned short ife_print_flags_mask[] = {
1775 IFF_UP,
1776 IFF_BROADCAST,
1777 IFF_DEBUG,
1778 IFF_LOOPBACK,
1779 IFF_POINTOPOINT,
1780 IFF_NOTRAILERS,
1781 IFF_RUNNING,
1782 IFF_NOARP,
1783 IFF_PROMISC,
1784 IFF_ALLMULTI,
1785 IFF_SLAVE,
1786 IFF_MASTER,
1787 IFF_MULTICAST,
1788#ifdef HAVE_DYNAMIC
1789 IFF_DYNAMIC
1790#endif
1791 0
1792};
1793
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001794static void ife_print(struct interface *ptr)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001795{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001796 struct aftype *ap;
1797 struct hwtype *hw;
1798 int hf;
1799 int can_compress = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001800
1801#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001802 static struct aftype *ipxtype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001803#endif
1804#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001805 static struct aftype *ectype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001806#endif
1807#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001808 static struct aftype *ddptype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001809#endif
1810#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001811 FILE *f;
1812 char addr6[40], devname[20];
1813 struct sockaddr_in6 sap;
1814 int plen, scope, dad_status, if_idx;
1815 char addr6p[8][5];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001816#endif
1817
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001818 ap = get_afntype(ptr->addr.sa_family);
1819 if (ap == NULL)
1820 ap = get_afntype(0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001821
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001822 hf = ptr->type;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001823
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001824 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
1825 can_compress = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001826
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001827 hw = get_hwntype(hf);
1828 if (hw == NULL)
1829 hw = get_hwntype(-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001830
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001831 printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title));
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001832 /* For some hardware types (eg Ash, ATM) we don't print the
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001833 hardware address if it's null. */
1834 if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
1835 hw->suppress_null_addr)))
1836 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001837#ifdef IFF_PORTSEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001838 if (ptr->flags & IFF_PORTSEL) {
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001839 printf(_("Media:%s"), if_port_text[ptr->map.port] /* [0] */);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001840 if (ptr->flags & IFF_AUTOMEDIA)
1841 printf(_("(auto)"));
1842 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001843#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001844 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001845
1846#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001847 if (ptr->has_ip) {
1848 printf(_(" %s addr:%s "), ap->name,
1849 ap->sprint(&ptr->addr, 1));
1850 if (ptr->flags & IFF_POINTOPOINT) {
1851 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
1852 }
1853 if (ptr->flags & IFF_BROADCAST) {
1854 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
1855 }
1856 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001857 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001858#endif
1859
1860#if HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +00001861
Eric Andersen51b8bd62002-07-03 11:46:38 +00001862#define IPV6_ADDR_ANY 0x0000U
1863
1864#define IPV6_ADDR_UNICAST 0x0001U
1865#define IPV6_ADDR_MULTICAST 0x0002U
1866#define IPV6_ADDR_ANYCAST 0x0004U
1867
1868#define IPV6_ADDR_LOOPBACK 0x0010U
1869#define IPV6_ADDR_LINKLOCAL 0x0020U
1870#define IPV6_ADDR_SITELOCAL 0x0040U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001871
Eric Andersen51b8bd62002-07-03 11:46:38 +00001872#define IPV6_ADDR_COMPATv4 0x0080U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001873
Eric Andersen51b8bd62002-07-03 11:46:38 +00001874#define IPV6_ADDR_SCOPE_MASK 0x00f0U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001875
Eric Andersen51b8bd62002-07-03 11:46:38 +00001876#define IPV6_ADDR_MAPPED 0x1000U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001877#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
1878
1879 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1880 while (fscanf
1881 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
1882 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
1883 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
1884 &dad_status, devname) != EOF) {
1885 if (!strcmp(devname, ptr->name)) {
1886 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1887 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1888 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1889 inet_pton(AF_INET6, addr6,
1890 (struct sockaddr *) &sap.sin6_addr);
1891 sap.sin6_family = AF_INET6;
1892 printf(_(" inet6 addr: %s/%d"),
1893 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
1894 plen);
1895 printf(_(" Scope:"));
1896 switch (scope & IPV6_ADDR_SCOPE_MASK) {
1897 case 0:
1898 printf(_("Global"));
1899 break;
1900 case IPV6_ADDR_LINKLOCAL:
1901 printf(_("Link"));
1902 break;
1903 case IPV6_ADDR_SITELOCAL:
1904 printf(_("Site"));
1905 break;
1906 case IPV6_ADDR_COMPATv4:
1907 printf(_("Compat"));
1908 break;
1909 case IPV6_ADDR_LOOPBACK:
1910 printf(_("Host"));
1911 break;
1912 default:
1913 printf(_("Unknown"));
1914 }
1915 printf("\n");
1916 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001917 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001918 fclose(f);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001919 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001920#endif
1921
1922#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001923 if (ipxtype == NULL)
1924 ipxtype = get_afntype(AF_IPX);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001925
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001926 if (ipxtype != NULL) {
1927 if (ptr->has_ipx_bb)
1928 printf(_(" IPX/Ethernet II addr:%s\n"),
1929 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
1930 if (ptr->has_ipx_sn)
1931 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
1932 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
1933 if (ptr->has_ipx_e2)
1934 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
1935 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
1936 if (ptr->has_ipx_e3)
1937 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
1938 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
1939 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001940#endif
1941
1942#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001943 if (ddptype == NULL)
1944 ddptype = get_afntype(AF_APPLETALK);
1945 if (ddptype != NULL) {
1946 if (ptr->has_ddp)
1947 printf(_(" EtherTalk Phase 2 addr:%s\n"),
1948 ddptype->sprint(&ptr->ddpaddr, 1));
1949 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001950#endif
1951
1952#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001953 if (ectype == NULL)
1954 ectype = get_afntype(AF_ECONET);
1955 if (ectype != NULL) {
1956 if (ptr->has_econet)
1957 printf(_(" econet addr:%s\n"),
1958 ectype->sprint(&ptr->ecaddr, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001959 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001960#endif
1961
1962 printf(" ");
1963 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001964
1965 if (ptr->flags == 0) {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001966 printf(_("[NO FLAGS] "));
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001967 } else {
1968 int i = 0;
1969 do {
1970 if (ptr->flags & ife_print_flags_mask[i]) {
1971 printf(_(ife_print_flags_strs[i]));
1972 }
1973 } while (ife_print_flags_mask[++i]);
1974 }
1975
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001976 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1977 printf(_(" MTU:%d Metric:%d"), ptr->mtu, ptr->metric ? ptr->metric : 1);
1978#ifdef SIOCSKEEPALIVE
1979 if (ptr->outfill || ptr->keepalive)
1980 printf(_(" Outfill:%d Keepalive:%d"), ptr->outfill, ptr->keepalive);
1981#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001982 printf("\n");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001983
1984 /* If needed, display the interface statistics. */
1985
1986 if (ptr->statistics_valid) {
1987 /* XXX: statistics are currently only printed for the primary address,
1988 * not for the aliases, although strictly speaking they're shared
1989 * by all addresses.
1990 */
1991 printf(" ");
1992
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001993 printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001994 ptr->stats.rx_packets, ptr->stats.rx_errors,
1995 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1996 ptr->stats.rx_frame_errors);
1997 if (can_compress)
1998 printf(_(" compressed:%lu\n"),
1999 ptr->stats.rx_compressed);
2000 printf(" ");
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00002001 printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002002 ptr->stats.tx_packets, ptr->stats.tx_errors,
2003 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
2004 ptr->stats.tx_carrier_errors);
2005 printf(_(" collisions:%lu "), ptr->stats.collisions);
2006 if (can_compress)
2007 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
2008 if (ptr->tx_queue_len != -1)
2009 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
2010 printf("\n R");
2011 print_bytes_scaled(ptr->stats.rx_bytes, " T");
2012 print_bytes_scaled(ptr->stats.tx_bytes, "\n");
2013
2014 }
2015
2016 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
2017 ptr->map.base_addr)) {
2018 printf(" ");
2019 if (ptr->map.irq)
2020 printf(_("Interrupt:%d "), ptr->map.irq);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002021 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002022 I/O maps */
2023 printf(_("Base address:0x%lx "),
2024 (unsigned long) ptr->map.base_addr);
2025 if (ptr->map.mem_start) {
2026 printf(_("Memory:%lx-%lx "), ptr->map.mem_start,
2027 ptr->map.mem_end);
2028 }
2029 if (ptr->map.dma)
2030 printf(_("DMA chan:%x "), ptr->map.dma);
2031 printf("\n");
2032 }
2033 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00002034}
2035
2036
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002037static int do_if_print(struct interface *ife, void *cookie)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002038{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002039 int *opt_a = (int *) cookie;
2040 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002041
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002042 res = do_if_fetch(ife);
2043 if (res >= 0) {
2044 if ((ife->flags & IFF_UP) || *opt_a)
2045 ife_print(ife);
2046 }
2047 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002048}
2049
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002050static struct interface *lookup_interface(char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002051{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002052 struct interface *ife = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002053
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002054 if (if_readlist_proc(name) < 0)
2055 return NULL;
2056 ife = add_interface(name);
2057 return ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002058}
2059
2060/* for ipv4 add/del modes */
2061static int if_print(char *ifname)
2062{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002063 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002064
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002065 if (!ifname) {
2066 res = for_all_interfaces(do_if_print, &interface_opt_a);
2067 } else {
2068 struct interface *ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002069
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002070 ife = lookup_interface(ifname);
2071 res = do_if_fetch(ife);
2072 if (res >= 0)
2073 ife_print(ife);
2074 }
2075 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002076}
2077
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002078int display_interfaces(char *ifname)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002079{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002080 int status;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002081
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002082 /* Create a channel to the NET kernel. */
2083 if ((skfd = sockets_open(0)) < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002084 bb_perror_msg_and_die("socket");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002085 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00002086
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002087 /* Do we have to show the current setup? */
2088 status = if_print(ifname);
Rob Landley93983042005-05-03 21:30:26 +00002089#ifdef CONFIG_FEATURE_CLEAN_UP
2090 sockets_close();
2091#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002092 exit(status < 0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00002093}