blob: f3655b0e08f1e1daa91dc176fb10c31d067fd994 [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 *
Glenn L McGrath2e99d432004-07-23 01:49:46 +000018 * Version: $Id: interface.c,v 1.23 2004/07/23 01:49:46 bug1 Exp $
Eric Andersenf15d4da2001-03-06 00:48:59 +000019 *
20 * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
21 * and others. Copyright 1993 MicroWalt Corporation
22 *
23 * This program is free software; you can redistribute it
24 * and/or modify it under the terms of the GNU General
25 * Public License as published by the Free Software
26 * Foundation; either version 2 of the License, or (at
27 * your option) any later version.
28 *
29 * Patched to support 'add' and 'del' keywords for INET(4) addresses
30 * by Mrs. Brisby <mrs.brisby@nimh.org>
31 *
32 * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
33 * - gettext instead of catgets for i18n
Eric Andersenc7bda1c2004-03-15 08:29:22 +000034 * 10/1998 - Andi Kleen. Use interface list primitives.
35 * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
Eric Andersenf15d4da2001-03-06 00:48:59 +000036 * (default AF was wrong)
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +000037 */
38
39/* #define KEEP_UNUSED */
40
Eric Andersenc7bda1c2004-03-15 08:29:22 +000041/*
42 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000043 * Protocol Families.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000044 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000045 */
46#define HAVE_AFINET 1
Eric Andersenf15d4da2001-03-06 00:48:59 +000047#undef HAVE_AFIPX
48#undef HAVE_AFATALK
49#undef HAVE_AFNETROM
50#undef HAVE_AFX25
51#undef HAVE_AFECONET
Eric Andersen8b113f92001-06-01 21:47:15 +000052#undef HAVE_AFASH
Eric Andersenf15d4da2001-03-06 00:48:59 +000053
Eric Andersenc7bda1c2004-03-15 08:29:22 +000054/*
55 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000056 * Device Hardware types.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000057 *
Eric Andersenf15d4da2001-03-06 00:48:59 +000058 */
59#define HAVE_HWETHER 1
60#define HAVE_HWPPP 1
61#undef HAVE_HWSLIP
62
63
Eric Andersencd8c4362001-11-10 11:22:46 +000064#include "inet_common.h"
Eric Andersenf15d4da2001-03-06 00:48:59 +000065#include <stdio.h>
66#include <errno.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +000067#include <stdlib.h>
68#include <string.h>
69#include <unistd.h>
Eric Andersencd8c4362001-11-10 11:22:46 +000070#include <fcntl.h>
71#include <ctype.h>
72#include <sys/ioctl.h>
Eric Andersen85e5e722003-07-22 08:56:55 +000073#include <sys/types.h>
Eric Andersencd8c4362001-11-10 11:22:46 +000074#include <net/if.h>
75#include <net/if_arp.h>
Glenn L McGrath6b8c5502001-05-05 03:19:12 +000076#include "libbb.h"
Eric Andersenf15d4da2001-03-06 00:48:59 +000077
Glenn L McGrathb54a7482003-08-29 11:34:08 +000078#ifdef CONFIG_FEATURE_IPV6
79# define HAVE_AFINET6 1
80#else
81# undef HAVE_AFINET6
82#endif
83
Eric Andersenf15d4da2001-03-06 00:48:59 +000084#define _(x) x
85#define _PATH_PROCNET_DEV "/proc/net/dev"
Eric Andersen51b8bd62002-07-03 11:46:38 +000086#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
Eric Andersenf15d4da2001-03-06 00:48:59 +000087#define new(p) ((p) = xcalloc(1,sizeof(*(p))))
Eric Andersen8b113f92001-06-01 21:47:15 +000088#define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch))
Eric Andersenf15d4da2001-03-06 00:48:59 +000089
Eric Andersenf15d4da2001-03-06 00:48:59 +000090#ifdef HAVE_HWSLIP
Eric Andersenab4e19a2003-01-14 08:54:08 +000091#include <net/if_slip.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +000092#endif
93
94#if HAVE_AFINET6
95
96#ifndef _LINUX_IN6_H
97/*
98 * This is in linux/include/net/ipv6.h.
99 */
100
101struct in6_ifreq {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000102 struct in6_addr ifr6_addr;
Glenn L McGrathb54a7482003-08-29 11:34:08 +0000103 uint32_t ifr6_prefixlen;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000104 unsigned int ifr6_ifindex;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000105};
106
107#endif
108
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000109#endif /* HAVE_AFINET6 */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000110
111#if HAVE_AFIPX
Eric Andersenb6b519b2001-04-09 23:52:18 +0000112#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000113#include <netipx/ipx.h>
114#else
115#include "ipx.h"
116#endif
117#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000118
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000119/* Defines for glibc2.0 users. */
120#ifndef SIOCSIFTXQLEN
121#define SIOCSIFTXQLEN 0x8943
122#define SIOCGIFTXQLEN 0x8942
123#endif
124
125/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
126#ifndef ifr_qlen
127#define ifr_qlen ifr_ifru.ifru_mtu
128#endif
129
130#ifndef HAVE_TXQUEUELEN
131#define HAVE_TXQUEUELEN 1
132#endif
133
134#ifndef IFF_DYNAMIC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000135#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000136#endif
137
Eric Andersenf15d4da2001-03-06 00:48:59 +0000138/* This structure defines protocol families and their handlers. */
139struct aftype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000140 const char *name;
141 const char *title;
142 int af;
143 int alen;
144 char *(*print) (unsigned char *);
145 char *(*sprint) (struct sockaddr *, int numeric);
146 int (*input) (int type, char *bufp, struct sockaddr *);
147 void (*herror) (char *text);
148 int (*rprint) (int options);
149 int (*rinput) (int typ, int ext, char **argv);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000150
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000151 /* may modify src */
152 int (*getmask) (char *src, struct sockaddr * mask, char *name);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000153
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000154 int fd;
155 char *flag_file;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000156};
157
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000158#ifdef KEEP_UNUSED
159
160static int flag_unx;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000161
Eric Andersen8b113f92001-06-01 21:47:15 +0000162#ifdef HAVE_AFIPX
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000163static int flag_ipx;
Eric Andersen8b113f92001-06-01 21:47:15 +0000164#endif
165#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000166static int flag_ax25;
Eric Andersen8b113f92001-06-01 21:47:15 +0000167#endif
168#ifdef HAVE_AFATALK
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000169static int flag_ddp;
Eric Andersen8b113f92001-06-01 21:47:15 +0000170#endif
171#ifdef HAVE_AFNETROM
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000172static int flag_netrom;
Eric Andersen8b113f92001-06-01 21:47:15 +0000173#endif
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000174static int flag_inet;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000175
Eric Andersen8b113f92001-06-01 21:47:15 +0000176#ifdef HAVE_AFINET6
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000177static int flag_inet6;
Eric Andersen8b113f92001-06-01 21:47:15 +0000178#endif
179#ifdef HAVE_AFECONET
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000180static int flag_econet;
Eric Andersen8b113f92001-06-01 21:47:15 +0000181#endif
182#ifdef HAVE_AFX25
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000183static int flag_x25 = 0;
Eric Andersen8b113f92001-06-01 21:47:15 +0000184#endif
185#ifdef HAVE_AFASH
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000186static int flag_ash;
Eric Andersen8b113f92001-06-01 21:47:15 +0000187#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000188
189
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000190static struct aftrans_t {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000191 char *alias;
192 char *name;
193 int *flag;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000194} aftrans[] = {
195
Eric Andersen8b113f92001-06-01 21:47:15 +0000196#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000197 {
198 "ax25", "ax25", &flag_ax25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000199#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000200 {
201 "ip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000202#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000203 {
204 "ip6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000205#endif
206#ifdef HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000207 {
208 "ipx", "ipx", &flag_ipx},
Eric Andersen8b113f92001-06-01 21:47:15 +0000209#endif
210#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000211 {
212 "appletalk", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000213#endif
214#ifdef HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000215 {
216 "netrom", "netrom", &flag_netrom},
Eric Andersen8b113f92001-06-01 21:47:15 +0000217#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000218 {
219 "inet", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000220#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000221 {
222 "inet6", "inet6", &flag_inet6},
Eric Andersen8b113f92001-06-01 21:47:15 +0000223#endif
224#ifdef HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000225 {
226 "ddp", "ddp", &flag_ddp},
Eric Andersen8b113f92001-06-01 21:47:15 +0000227#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000228 {
229 "unix", "unix", &flag_unx}, {
230 "tcpip", "inet", &flag_inet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000231#ifdef HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000232 {
233 "econet", "ec", &flag_econet},
Eric Andersen8b113f92001-06-01 21:47:15 +0000234#endif
235#ifdef HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000236 {
237 "x25", "x25", &flag_x25},
Eric Andersen8b113f92001-06-01 21:47:15 +0000238#endif
239#ifdef HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000240 {
241 "ash", "ash", &flag_ash},
Eric Andersen8b113f92001-06-01 21:47:15 +0000242#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000243 {
244 0, 0, 0}
Eric Andersenf15d4da2001-03-06 00:48:59 +0000245};
246
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000247static char afname[256] = "";
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000248#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000249
250#if HAVE_AFUNIX
251
252/* Display a UNIX domain address. */
253static char *UNIX_print(unsigned char *ptr)
254{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000255 return (ptr);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000256}
257
258
259/* Display a UNIX domain address. */
260static char *UNIX_sprint(struct sockaddr *sap, int numeric)
261{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000262 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000263
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000264 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
265 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
266 return (UNIX_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000267}
268
269
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000270static struct aftype unix_aftype = {
271 "unix", "UNIX Domain", AF_UNIX, 0,
272 UNIX_print, UNIX_sprint, NULL, NULL,
273 NULL, NULL, NULL,
274 -1,
275 "/proc/net/unix"
Eric Andersenf15d4da2001-03-06 00:48:59 +0000276};
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000277#endif /* HAVE_AFUNIX */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000278
279#if HAVE_AFINET
280
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000281#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000282static void INET_reserror(char *text)
283{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000284 herror(text);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000285}
286
Eric Andersenf15d4da2001-03-06 00:48:59 +0000287/* Display an Internet socket address. */
288static char *INET_print(unsigned char *ptr)
289{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000290 return (inet_ntoa((*(struct in_addr *) ptr)));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000291}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000292#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000293
294/* Display an Internet socket address. */
295static char *INET_sprint(struct sockaddr *sap, int numeric)
296{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000297 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000298
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000299 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
300 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000301
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000302 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
303 numeric, 0xffffff00) != 0)
304 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000305
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000306 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000307}
308
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000309#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000310static char *INET_sprintmask(struct sockaddr *sap, int numeric,
311 unsigned int netmask)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000312{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000313 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000314
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000315 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
316 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
317 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
318 numeric, netmask) != 0)
319 return (NULL);
320 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000321}
322
Eric Andersenf15d4da2001-03-06 00:48:59 +0000323static int INET_getsock(char *bufp, struct sockaddr *sap)
324{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000325 char *sp = bufp, *bp;
326 unsigned int i;
327 unsigned val;
328 struct sockaddr_in *sin;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000329
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000330 sin = (struct sockaddr_in *) sap;
331 sin->sin_family = AF_INET;
332 sin->sin_port = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000333
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000334 val = 0;
335 bp = (char *) &val;
336 for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) {
337 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000338
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000339 if ((*sp >= 'A') && (*sp <= 'F'))
340 bp[i] |= (int) (*sp - 'A') + 10;
341 else if ((*sp >= '0') && (*sp <= '9'))
342 bp[i] |= (int) (*sp - '0');
343 else
344 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000345
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000346 bp[i] <<= 4;
347 sp++;
348 *sp = toupper(*sp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000349
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000350 if ((*sp >= 'A') && (*sp <= 'F'))
351 bp[i] |= (int) (*sp - 'A') + 10;
352 else if ((*sp >= '0') && (*sp <= '9'))
353 bp[i] |= (int) (*sp - '0');
354 else
355 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000356
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000357 sp++;
358 }
359 sin->sin_addr.s_addr = htonl(val);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000360
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000361 return (sp - bufp);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000362}
363
364static int INET_input(int type, char *bufp, struct sockaddr *sap)
365{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000366 switch (type) {
367 case 1:
368 return (INET_getsock(bufp, sap));
369 case 256:
370 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
371 default:
372 return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
373 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000374}
375
376static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
377{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000378 struct sockaddr_in *mask = (struct sockaddr_in *) m;
379 char *slash, *end;
380 int prefix;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000381
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000382 if ((slash = strchr(adr, '/')) == NULL)
383 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000384
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000385 *slash++ = '\0';
386 prefix = strtoul(slash, &end, 0);
387 if (*end != '\0')
388 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000389
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000390 if (name) {
391 sprintf(name, "/%d", prefix);
392 }
393 mask->sin_family = AF_INET;
394 mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
395 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000396}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000397#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000398
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000399static struct aftype inet_aftype = {
400 "inet", "DARPA Internet", AF_INET, sizeof(unsigned long),
401 NULL /* UNUSED INET_print */ , INET_sprint,
402 NULL /* UNUSED INET_input */ , NULL /* UNUSED INET_reserror */ ,
403 NULL /*INET_rprint */ , NULL /*INET_rinput */ ,
404 NULL /* UNUSED INET_getnetmask */ ,
405 -1,
406 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000407};
408
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000409#endif /* HAVE_AFINET */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000410
Eric Andersen51b8bd62002-07-03 11:46:38 +0000411#if HAVE_AFINET6
412
413#ifdef KEEP_UNUSED
414static void INET6_reserror(char *text)
415{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000416 herror(text);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000417}
418
419/* Display an Internet socket address. */
420static char *INET6_print(unsigned char *ptr)
421{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000422 static char name[80];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000423
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000424 inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80);
425 return name;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000426}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000427#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000428
429/* Display an Internet socket address. */
430/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
431static char *INET6_sprint(struct sockaddr *sap, int numeric)
432{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000433 static char buff[128];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000434
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000435 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
436 return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
437 if (INET6_rresolve
438 (buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)
439 return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff));
440 return (buff);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000441}
442
443#ifdef KEEP_UNUSED
444static int INET6_getsock(char *bufp, struct sockaddr *sap)
445{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000446 struct sockaddr_in6 *sin6;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000447
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000448 sin6 = (struct sockaddr_in6 *) sap;
449 sin6->sin6_family = AF_INET6;
450 sin6->sin6_port = 0;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000451
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000452 if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0)
453 return (-1);
Eric Andersen51b8bd62002-07-03 11:46:38 +0000454
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000455 return 16; /* ?;) */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000456}
457
458static int INET6_input(int type, char *bufp, struct sockaddr *sap)
459{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000460 switch (type) {
461 case 1:
462 return (INET6_getsock(bufp, sap));
463 default:
464 return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));
465 }
Eric Andersen51b8bd62002-07-03 11:46:38 +0000466}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000467#endif /* KEEP_UNUSED */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000468
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000469static struct aftype inet6_aftype = {
470 "inet6", "IPv6", AF_INET6, sizeof(struct in6_addr),
471 NULL /* UNUSED INET6_print */ , INET6_sprint,
472 NULL /* UNUSED INET6_input */ , NULL /* UNUSED INET6_reserror */ ,
473 NULL /*INET6_rprint */ , NULL /*INET6_rinput */ ,
474 NULL /* UNUSED INET6_getnetmask */ ,
475 -1,
476 NULL
Eric Andersen51b8bd62002-07-03 11:46:38 +0000477};
478
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000479#endif /* HAVE_AFINET6 */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000480
Eric Andersenf15d4da2001-03-06 00:48:59 +0000481/* Display an UNSPEC address. */
482static char *UNSPEC_print(unsigned char *ptr)
483{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000484 static char buff[sizeof(struct sockaddr) * 3 + 1];
485 char *pos;
486 unsigned int i;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000487
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000488 pos = buff;
489 for (i = 0; i < sizeof(struct sockaddr); i++) {
490 /* careful -- not every libc's sprintf returns # bytes written */
491 sprintf(pos, "%02X-", (*ptr++ & 0377));
492 pos += 3;
493 }
494 /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */
495 *--pos = '\0';
496 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000497}
498
499/* Display an UNSPEC socket address. */
500static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
501{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000502 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000503
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000504 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
505 return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
506 return (UNSPEC_print(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000507}
508
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000509static struct aftype unspec_aftype = {
510 "unspec", "UNSPEC", AF_UNSPEC, 0,
511 UNSPEC_print, UNSPEC_sprint, NULL, NULL,
512 NULL,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000513};
514
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000515static struct aftype *aftypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000516#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000517 &unix_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000518#endif
519#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000520 &inet_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000521#endif
522#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000523 &inet6_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000524#endif
525#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000526 &ax25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000527#endif
528#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000529 &netrom_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000530#endif
531#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000532 &rose_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000533#endif
534#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000535 &ipx_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000536#endif
537#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000538 &ddp_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000539#endif
540#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000541 &ec_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000542#endif
543#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000544 &ash_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000545#endif
546#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000547 &x25_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000548#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000549 &unspec_aftype,
550 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000551};
552
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000553#ifdef KEEP_UNUSED
554static short sVafinit = 0;
555
556static void afinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +0000557{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000558 unspec_aftype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000559#if HAVE_AFUNIX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000560 unix_aftype.title = _("UNIX Domain");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000561#endif
562#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000563 inet_aftype.title = _("DARPA Internet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000564#endif
565#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000566 inet6_aftype.title = _("IPv6");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000567#endif
568#if HAVE_AFAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000569 ax25_aftype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000570#endif
571#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000572 netrom_aftype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000573#endif
574#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000575 ipx_aftype.title = _("Novell IPX");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000576#endif
577#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000578 ddp_aftype.title = _("Appletalk DDP");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000579#endif
580#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000581 ec_aftype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000582#endif
583#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000584 x25_aftype.title = _("CCITT X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000585#endif
586#if HAVE_AFROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000587 rose_aftype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000588#endif
589#if HAVE_AFASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000590 ash_aftype.title = _("Ash");
591#endif
592 sVafinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000593}
594
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000595static int aftrans_opt(const char *arg)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000596{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000597 struct aftrans_t *paft;
598 char *tmp1, *tmp2;
599 char buf[256];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000600
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000601 safe_strncpy(buf, arg, sizeof(buf));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000602
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000603 tmp1 = buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000604
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000605 while (tmp1) {
Eric Andersenf15d4da2001-03-06 00:48:59 +0000606
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000607 tmp2 = strchr(tmp1, ',');
Eric Andersenf15d4da2001-03-06 00:48:59 +0000608
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000609 if (tmp2)
610 *(tmp2++) = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000611
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000612 paft = aftrans;
613 for (paft = aftrans; paft->alias; paft++) {
614 if (strcmp(tmp1, paft->alias))
615 continue;
616 if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000617 bb_error_msg(_("Too many address family arguments."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000618 return (0);
619 }
620 if (paft->flag)
621 (*paft->flag)++;
622 if (afname[0])
623 strcat(afname, ",");
624 strcat(afname, paft->name);
625 break;
626 }
627 if (!paft->alias) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000628 bb_error_msg(_("Unknown address family `%s'."), tmp1);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000629 return (1);
630 }
631 tmp1 = tmp2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000632 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000633
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000634 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000635}
636
637/* set the default AF list from the program name or a constant value */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000638static void aftrans_def(char *tool, char *argv0, char *dflt)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000639{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000640 char *tmp;
641 char *buf;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000642
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000643 strcpy(afname, dflt);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000644
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000645 if (!(tmp = strrchr(argv0, '/')))
646 tmp = argv0; /* no slash?! */
647 else
648 tmp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000649
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000650 if (!(buf = strdup(tmp)))
651 return;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000652
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000653 if (strlen(tool) >= strlen(tmp)) {
654 free(buf);
655 return;
656 }
657 tmp = buf + (strlen(tmp) - strlen(tool));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000658
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000659 if (strcmp(tmp, tool) != 0) {
660 free(buf);
661 return;
662 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000663 *tmp = '\0';
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000664 if ((tmp = strchr(buf, '_')))
665 *tmp = '\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000666
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000667 afname[0] = '\0';
668 if (aftrans_opt(buf))
669 strcpy(afname, buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000670
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000671 free(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000672}
673
Eric Andersenf15d4da2001-03-06 00:48:59 +0000674/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000675static struct aftype *get_aftype(const char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000676{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000677 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000678
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000679#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000680 if (!sVafinit)
681 afinit();
682#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000683
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000684 afp = aftypes;
685 while (*afp != NULL) {
686 if (!strcmp((*afp)->name, name))
687 return (*afp);
688 afp++;
689 }
690 if (strchr(name, ','))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000691 bb_error_msg(_("Please don't supply more than one address family."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000692 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000693}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000694#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000695
696/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000697static struct aftype *get_afntype(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000698{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000699 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000700
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000701#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000702 if (!sVafinit)
703 afinit();
704#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000705
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000706 afp = aftypes;
707 while (*afp != NULL) {
708 if ((*afp)->af == af)
709 return (*afp);
710 afp++;
711 }
712 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000713}
714
715/* Check our protocol family table for this family and return its socket */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000716static int get_socket_for_af(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000717{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000718 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000719
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000720#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000721 if (!sVafinit)
722 afinit();
723#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000724
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000725 afp = aftypes;
726 while (*afp != NULL) {
727 if ((*afp)->af == af)
728 return (*afp)->fd;
729 afp++;
730 }
731 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000732}
733
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000734#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +0000735/* type: 0=all, 1=getroute */
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000736static void print_aflist(int type)
737{
738 int count = 0;
739 char *txt;
740 struct aftype **afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000741
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000742#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000743 if (!sVafinit)
744 afinit();
745#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000746
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000747 afp = aftypes;
748 while (*afp != NULL) {
749 if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) {
750 afp++;
751 continue;
752 }
753 if ((count % 3) == 0)
754 fprintf(stderr, count ? "\n " : " ");
755 txt = (*afp)->name;
756 if (!txt)
757 txt = "..";
758 fprintf(stderr, "%s (%s) ", txt, _((*afp)->title));
759 count++;
760 afp++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000761 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000762 fprintf(stderr, "\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000763}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000764#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000765
766struct user_net_device_stats {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000767 unsigned long long rx_packets; /* total packets received */
768 unsigned long long tx_packets; /* total packets transmitted */
769 unsigned long long rx_bytes; /* total bytes received */
770 unsigned long long tx_bytes; /* total bytes transmitted */
771 unsigned long rx_errors; /* bad packets received */
772 unsigned long tx_errors; /* packet transmit problems */
773 unsigned long rx_dropped; /* no space in linux buffers */
774 unsigned long tx_dropped; /* no space available in linux */
775 unsigned long rx_multicast; /* multicast packets received */
776 unsigned long rx_compressed;
777 unsigned long tx_compressed;
778 unsigned long collisions;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000779
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000780 /* detailed rx_errors: */
781 unsigned long rx_length_errors;
782 unsigned long rx_over_errors; /* receiver ring buff overflow */
783 unsigned long rx_crc_errors; /* recved pkt with crc error */
784 unsigned long rx_frame_errors; /* recv'd frame alignment error */
785 unsigned long rx_fifo_errors; /* recv'r fifo overrun */
786 unsigned long rx_missed_errors; /* receiver missed packet */
787 /* detailed tx_errors */
788 unsigned long tx_aborted_errors;
789 unsigned long tx_carrier_errors;
790 unsigned long tx_fifo_errors;
791 unsigned long tx_heartbeat_errors;
792 unsigned long tx_window_errors;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000793};
794
795struct interface {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000796 struct interface *next, *prev;
797 char name[IFNAMSIZ]; /* interface name */
798 short type; /* if type */
799 short flags; /* various flags */
800 int metric; /* routing metric */
801 int mtu; /* MTU value */
802 int tx_queue_len; /* transmit queue length */
803 struct ifmap map; /* hardware setup */
804 struct sockaddr addr; /* IP address */
805 struct sockaddr dstaddr; /* P-P IP address */
806 struct sockaddr broadaddr; /* IP broadcast address */
807 struct sockaddr netmask; /* IP network mask */
808 struct sockaddr ipxaddr_bb; /* IPX network address */
809 struct sockaddr ipxaddr_sn; /* IPX network address */
810 struct sockaddr ipxaddr_e3; /* IPX network address */
811 struct sockaddr ipxaddr_e2; /* IPX network address */
812 struct sockaddr ddpaddr; /* Appletalk DDP address */
813 struct sockaddr ecaddr; /* Econet address */
814 int has_ip;
815 int has_ipx_bb;
816 int has_ipx_sn;
817 int has_ipx_e3;
818 int has_ipx_e2;
819 int has_ax25;
820 int has_ddp;
821 int has_econet;
822 char hwaddr[32]; /* HW address */
823 int statistics_valid;
824 struct user_net_device_stats stats; /* statistics */
825 int keepalive; /* keepalive value for SLIP */
826 int outfill; /* outfill value for SLIP */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000827};
828
829
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000830int interface_opt_a = 0; /* show all interfaces */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000831
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000832#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000833static int opt_i = 0; /* show the statistics */
834static int opt_v = 0; /* debugging output flag */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000835
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000836static int addr_family = 0; /* currently selected AF */
837#endif /* KEEP_UNUSED */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000838
Eric Andersenf15d4da2001-03-06 00:48:59 +0000839static struct interface *int_list, *int_last;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000840static int skfd = -1; /* generic raw socket desc. */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000841
842
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000843static int sockets_open(int family)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000844{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000845 struct aftype **aft;
846 int sfd = -1;
847 static int force = -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000848
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000849 if (force < 0) {
850 force = 0;
851 if (get_kernel_revision() < KRELEASE(2, 1, 0))
852 force = 1;
853 if (access("/proc/net", R_OK))
854 force = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000855 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000856 for (aft = aftypes; *aft; aft++) {
857 struct aftype *af = *aft;
858 int type = SOCK_DGRAM;
859
860 if (af->af == AF_UNSPEC)
861 continue;
862 if (family && family != af->af)
863 continue;
864 if (af->fd != -1) {
865 sfd = af->fd;
866 continue;
867 }
868 /* Check some /proc file first to not stress kmod */
869 if (!family && !force && af->flag_file) {
870 if (access(af->flag_file, R_OK))
871 continue;
872 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000873#if HAVE_AFNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000874 if (af->af == AF_NETROM)
875 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000876#endif
877#if HAVE_AFX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000878 if (af->af == AF_X25)
879 type = SOCK_SEQPACKET;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000880#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000881 af->fd = socket(af->af, type, 0);
882 if (af->fd >= 0)
883 sfd = af->fd;
884 }
Glenn L McGrath642f2892002-11-28 10:20:45 +0000885 if (sfd < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000886 bb_error_msg(_("No usable address families found."));
Glenn L McGrath642f2892002-11-28 10:20:45 +0000887 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000888 return sfd;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000889}
890
891/* like strcmp(), but knows about numbers */
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000892static int nstrcmp(const char *a, const char *b)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000893{
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000894 const char *a_ptr = a;
895 const char *b_ptr = b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000896
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000897 while (*a == *b) {
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000898 if (*a == '\0') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000899 return 0;
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000900 }
901 if (!isdigit(*a) && isdigit(*(a+1))) {
902 a_ptr = a+1;
903 b_ptr = b+1;
904 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000905 a++;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000906 b++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000907 }
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000908
909 if (isdigit(*a) && isdigit(*b)) {
910 return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000911 }
912 return *a - *b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000913}
914
915static struct interface *add_interface(char *name)
916{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000917 struct interface *ife, **nextp, *new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000918
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000919 for (ife = int_last; ife; ife = ife->prev) {
920 int n = nstrcmp(ife->name, name);
921
922 if (n == 0)
923 return ife;
924 if (n < 0)
925 break;
926 }
927 new(new);
928 safe_strncpy(new->name, name, IFNAMSIZ);
929 nextp = ife ? &ife->next : &int_list;
930 new->prev = ife;
931 new->next = *nextp;
932 if (new->next)
933 new->next->prev = new;
934 else
935 int_last = new;
936 *nextp = new;
937 return new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000938}
939
940
941static int if_readconf(void)
942{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000943 int numreqs = 30;
944 struct ifconf ifc;
945 struct ifreq *ifr;
946 int n, err = -1;
947 int skfd2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000948
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000949 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
950 (as of 2.1.128) */
951 skfd2 = get_socket_for_af(AF_INET);
952 if (skfd2 < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000953 bb_perror_msg(("warning: no inet socket available"));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000954 /* Try to soldier on with whatever socket we can get hold of. */
955 skfd2 = sockets_open(0);
956 if (skfd2 < 0)
957 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000958 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000959
960 ifc.ifc_buf = NULL;
961 for (;;) {
962 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
963 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
964
965 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
966 perror("SIOCGIFCONF");
967 goto out;
968 }
969 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
970 /* assume it overflowed and try again */
971 numreqs += 10;
972 continue;
973 }
974 break;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000975 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000976
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000977 ifr = ifc.ifc_req;
978 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
979 add_interface(ifr->ifr_name);
980 ifr++;
981 }
982 err = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000983
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000984 out:
985 free(ifc.ifc_buf);
986 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000987}
988
989static char *get_name(char *name, char *p)
990{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000991 while (isspace(*p))
992 p++;
993 while (*p) {
994 if (isspace(*p))
995 break;
996 if (*p == ':') { /* could be an alias */
997 char *dot = p, *dotname = name;
998
999 *name++ = *p++;
1000 while (isdigit(*p))
1001 *name++ = *p++;
1002 if (*p != ':') { /* it wasn't, backup */
1003 p = dot;
1004 name = dotname;
1005 }
1006 if (*p == '\0')
1007 return NULL;
1008 p++;
1009 break;
1010 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001011 *name++ = *p++;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001012 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001013 *name++ = '\0';
1014 return p;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001015}
1016
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001017/* If scanf supports size qualifiers for %n conversions, then we can
1018 * use a modified fmt that simply stores the position in the fields
1019 * having no associated fields in the proc string. Of course, we need
1020 * to zero them again when we're done. But that is smaller than the
1021 * old approach of multiple scanf occurrences with large numbers of
1022 * args. */
1023
1024/* static const char *ss_fmt[] = { */
1025/* "%Ln%Lu%lu%lu%lu%lu%ln%ln%Ln%Lu%lu%lu%lu%lu%lu", */
1026/* "%Lu%Lu%lu%lu%lu%lu%ln%ln%Lu%Lu%lu%lu%lu%lu%lu", */
1027/* "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu" */
1028/* }; */
1029
1030 /* Lie about the size of the int pointed to for %n. */
1031#if INT_MAX == LONG_MAX
1032static const char *ss_fmt[] = {
1033 "%n%Lu%u%u%u%u%n%n%n%Lu%u%u%u%u%u",
1034 "%Lu%Lu%u%u%u%u%n%n%Lu%Lu%u%u%u%u%u",
1035 "%Lu%Lu%u%u%u%u%u%u%Lu%Lu%u%u%u%u%u%u"
1036};
1037#else
1038static const char *ss_fmt[] = {
1039 "%n%Lu%lu%lu%lu%lu%n%n%n%Lu%lu%lu%lu%lu%lu",
1040 "%Lu%Lu%lu%lu%lu%lu%n%n%Lu%Lu%lu%lu%lu%lu%lu",
1041 "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu"
1042};
1043
1044#endif
1045
1046static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001047{
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001048 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
1049
1050 sscanf(bp, ss_fmt[procnetdev_vsn],
1051 &ife->stats.rx_bytes, /* missing for 0 */
1052 &ife->stats.rx_packets,
1053 &ife->stats.rx_errors,
1054 &ife->stats.rx_dropped,
1055 &ife->stats.rx_fifo_errors,
1056 &ife->stats.rx_frame_errors,
1057 &ife->stats.rx_compressed, /* missing for <= 1 */
1058 &ife->stats.rx_multicast, /* missing for <= 1 */
1059 &ife->stats.tx_bytes, /* missing for 0 */
1060 &ife->stats.tx_packets,
1061 &ife->stats.tx_errors,
1062 &ife->stats.tx_dropped,
1063 &ife->stats.tx_fifo_errors,
1064 &ife->stats.collisions,
1065 &ife->stats.tx_carrier_errors,
1066 &ife->stats.tx_compressed /* missing for <= 1 */
1067 );
1068
1069 if (procnetdev_vsn <= 1) {
1070 if (procnetdev_vsn == 0) {
1071 ife->stats.rx_bytes = 0;
1072 ife->stats.tx_bytes = 0;
1073 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001074 ife->stats.rx_multicast = 0;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001075 ife->stats.rx_compressed = 0;
1076 ife->stats.tx_compressed = 0;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001077 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001078}
1079
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001080static inline int procnetdev_version(char *buf)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001081{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001082 if (strstr(buf, "compressed"))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001083 return 2;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001084 if (strstr(buf, "bytes"))
1085 return 1;
1086 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001087}
1088
1089static int if_readlist_proc(char *target)
1090{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001091 static int proc_read;
1092 FILE *fh;
1093 char buf[512];
1094 struct interface *ife;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001095 int err, procnetdev_vsn;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001096
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001097 if (proc_read)
1098 return 0;
1099 if (!target)
1100 proc_read = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001101
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001102 fh = fopen(_PATH_PROCNET_DEV, "r");
1103 if (!fh) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001104 bb_perror_msg(_("Warning: cannot open %s. Limited output."), _PATH_PROCNET_DEV);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001105 return if_readconf();
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001106 }
1107 fgets(buf, sizeof buf, fh); /* eat line */
1108 fgets(buf, sizeof buf, fh);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001109
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001110 procnetdev_vsn = procnetdev_version(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001111
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001112 err = 0;
1113 while (fgets(buf, sizeof buf, fh)) {
Eric Andersenf96675b2003-07-28 06:37:04 +00001114 char *s, name[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001115
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001116 s = get_name(name, buf);
1117 ife = add_interface(name);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001118 get_dev_fields(s, ife, procnetdev_vsn);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001119 ife->statistics_valid = 1;
1120 if (target && !strcmp(target, name))
1121 break;
1122 }
1123 if (ferror(fh)) {
1124 perror(_PATH_PROCNET_DEV);
1125 err = -1;
1126 proc_read = 0;
1127 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001128 fclose(fh);
1129 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001130}
1131
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001132static int if_readlist(void)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001133{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001134 int err = if_readlist_proc(NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001135
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001136 if (!err)
1137 err = if_readconf();
1138 return err;
1139}
1140
1141static int for_all_interfaces(int (*doit) (struct interface *, void *),
1142 void *cookie)
1143{
1144 struct interface *ife;
1145
1146 if (!int_list && (if_readlist() < 0))
1147 return -1;
1148 for (ife = int_list; ife; ife = ife->next) {
1149 int err = doit(ife, cookie);
1150
1151 if (err)
1152 return err;
1153 }
1154 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001155}
1156
1157/* Support for fetching an IPX address */
1158
1159#if HAVE_AFIPX
1160static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
1161{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001162 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
1163 return ioctl(sock, SIOCGIFADDR, ifr);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001164}
1165#endif
1166
1167
1168/* Fetch the interface configuration from the kernel. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001169static int if_fetch(struct interface *ife)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001170{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001171 struct ifreq ifr;
1172 int fd;
1173 char *ifname = ife->name;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001174
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001175 strcpy(ifr.ifr_name, ifname);
1176 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
1177 return (-1);
1178 ife->flags = ifr.ifr_flags;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001179
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001180 strcpy(ifr.ifr_name, ifname);
1181 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
1182 memset(ife->hwaddr, 0, 32);
1183 else
1184 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001185
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001186 ife->type = ifr.ifr_hwaddr.sa_family;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001187
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001188 strcpy(ifr.ifr_name, ifname);
1189 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
1190 ife->metric = 0;
1191 else
1192 ife->metric = ifr.ifr_metric;
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, SIOCGIFMTU, &ifr) < 0)
1196 ife->mtu = 0;
1197 else
1198 ife->mtu = ifr.ifr_mtu;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001199
1200#ifdef HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001201 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
1202 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
1203 ife->type == ARPHRD_ADAPT) {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001204#ifdef SIOCGOUTFILL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001205 strcpy(ifr.ifr_name, ifname);
1206 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
1207 ife->outfill = 0;
1208 else
1209 ife->outfill = (unsigned int) ifr.ifr_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001210#endif
1211#ifdef SIOCGKEEPALIVE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001212 strcpy(ifr.ifr_name, ifname);
1213 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
1214 ife->keepalive = 0;
1215 else
1216 ife->keepalive = (unsigned int) ifr.ifr_data;
1217#endif
1218 }
1219#endif
1220
Eric Andersenf15d4da2001-03-06 00:48:59 +00001221 strcpy(ifr.ifr_name, ifname);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001222 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
1223 memset(&ife->map, 0, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001224 else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001225 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001226
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001227 strcpy(ifr.ifr_name, ifname);
1228 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
1229 memset(&ife->map, 0, sizeof(struct ifmap));
1230 else
1231 ife->map = ifr.ifr_map;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001232
1233#ifdef HAVE_TXQUEUELEN
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001234 strcpy(ifr.ifr_name, ifname);
1235 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
1236 ife->tx_queue_len = -1; /* unknown value */
1237 else
1238 ife->tx_queue_len = ifr.ifr_qlen;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001239#else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001240 ife->tx_queue_len = -1; /* unknown value */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001241#endif
1242
1243#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001244 /* IPv4 address? */
1245 fd = get_socket_for_af(AF_INET);
1246 if (fd >= 0) {
1247 strcpy(ifr.ifr_name, ifname);
1248 ifr.ifr_addr.sa_family = AF_INET;
1249 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1250 ife->has_ip = 1;
1251 ife->addr = ifr.ifr_addr;
1252 strcpy(ifr.ifr_name, ifname);
1253 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
1254 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
1255 else
1256 ife->dstaddr = ifr.ifr_dstaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001257
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001258 strcpy(ifr.ifr_name, ifname);
1259 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
1260 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
1261 else
1262 ife->broadaddr = ifr.ifr_broadaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001263
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001264 strcpy(ifr.ifr_name, ifname);
1265 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
1266 memset(&ife->netmask, 0, sizeof(struct sockaddr));
1267 else
1268 ife->netmask = ifr.ifr_netmask;
1269 } else
1270 memset(&ife->addr, 0, sizeof(struct sockaddr));
1271 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001272#endif
1273
1274#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001275 /* DDP address maybe ? */
1276 fd = get_socket_for_af(AF_APPLETALK);
1277 if (fd >= 0) {
1278 strcpy(ifr.ifr_name, ifname);
1279 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1280 ife->ddpaddr = ifr.ifr_addr;
1281 ife->has_ddp = 1;
1282 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001283 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001284#endif
1285
1286#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001287 /* Look for IPX addresses with all framing types */
1288 fd = get_socket_for_af(AF_IPX);
1289 if (fd >= 0) {
1290 strcpy(ifr.ifr_name, ifname);
1291 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
1292 ife->has_ipx_bb = 1;
1293 ife->ipxaddr_bb = ifr.ifr_addr;
1294 }
1295 strcpy(ifr.ifr_name, ifname);
1296 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
1297 ife->has_ipx_sn = 1;
1298 ife->ipxaddr_sn = ifr.ifr_addr;
1299 }
1300 strcpy(ifr.ifr_name, ifname);
1301 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
1302 ife->has_ipx_e3 = 1;
1303 ife->ipxaddr_e3 = ifr.ifr_addr;
1304 }
1305 strcpy(ifr.ifr_name, ifname);
1306 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
1307 ife->has_ipx_e2 = 1;
1308 ife->ipxaddr_e2 = ifr.ifr_addr;
1309 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001310 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001311#endif
1312
1313#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001314 /* Econet address maybe? */
1315 fd = get_socket_for_af(AF_ECONET);
1316 if (fd >= 0) {
1317 strcpy(ifr.ifr_name, ifname);
1318 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1319 ife->ecaddr = ifr.ifr_addr;
1320 ife->has_econet = 1;
1321 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001322 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001323#endif
1324
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001325 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001326}
1327
1328
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001329static int do_if_fetch(struct interface *ife)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001330{
1331 if (if_fetch(ife) < 0) {
1332 char *errmsg;
1333
1334 if (errno == ENODEV) {
1335 /* Give better error message for this case. */
1336 errmsg = _("Device not found");
1337 } else {
1338 errmsg = strerror(errno);
1339 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001340 bb_error_msg(_("%s: error fetching interface information: %s\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001341 ife->name, errmsg);
1342 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001343 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001344 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001345}
1346
1347/* This structure defines hardware protocols and their handlers. */
1348struct hwtype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001349 const char *name;
1350 const char *title;
1351 int type;
1352 int alen;
1353 char *(*print) (unsigned char *);
1354 int (*input) (char *, struct sockaddr *);
1355 int (*activate) (int fd);
1356 int suppress_null_addr;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001357};
1358
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001359static struct hwtype unspec_hwtype = {
1360 "unspec", "UNSPEC", -1, 0,
1361 UNSPEC_print, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001362};
1363
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001364static struct hwtype loop_hwtype = {
1365 "loop", "Local Loopback", ARPHRD_LOOPBACK, 0,
1366 NULL, NULL, NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001367};
1368
1369#if HAVE_HWETHER
1370#include <net/if_arp.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001371
1372#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
1373#include <net/ethernet.h>
1374#else
Eric Andersenf15d4da2001-03-06 00:48:59 +00001375#include <linux/if_ether.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +00001376#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001377
Eric Andersenf15d4da2001-03-06 00:48:59 +00001378/* Display an Ethernet address in readable format. */
1379static char *pr_ether(unsigned char *ptr)
1380{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001381 static char buff[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001382
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001383 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
1384 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
1385 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
1386 );
1387 return (buff);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001388}
1389
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001390#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001391/* Input an Ethernet address and convert to binary. */
1392static int in_ether(char *bufp, struct sockaddr *sap)
1393{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001394 unsigned char *ptr;
1395 char c, *orig;
1396 int i;
1397 unsigned val;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001398
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001399 sap->sa_family = ether_hwtype.type;
1400 ptr = sap->sa_data;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001401
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001402 i = 0;
1403 orig = bufp;
1404 while ((*bufp != '\0') && (i < ETH_ALEN)) {
1405 val = 0;
1406 c = *bufp++;
1407 if (isdigit(c))
1408 val = c - '0';
1409 else if (c >= 'a' && c <= 'f')
1410 val = c - 'a' + 10;
1411 else if (c >= 'A' && c <= 'F')
1412 val = c - 'A' + 10;
1413 else {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001414#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001415 bb_error_msg(_("in_ether(%s): invalid ether address!\n"), orig);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001416#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001417 errno = EINVAL;
1418 return (-1);
1419 }
1420 val <<= 4;
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 if (c == ':' || c == 0)
1429 val >>= 4;
1430 else {
1431#ifdef DEBUG
Manuel Novoa III cad53642003-03-19 09:13:01 +00001432 bb_error_msg(_("in_ether(%s): invalid ether address!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001433#endif
1434 errno = EINVAL;
1435 return (-1);
1436 }
1437 if (c != 0)
1438 bufp++;
1439 *ptr++ = (unsigned char) (val & 0377);
1440 i++;
1441
1442 /* We might get a semicolon here - not required. */
1443 if (*bufp == ':') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001444#ifdef DEBUG
Glenn L McGrath642f2892002-11-28 10:20:45 +00001445 if (i == ETH_ALEN) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001446 bb_error_msg(_("in_ether(%s): trailing : ignored!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001447 }
Glenn L McGrath642f2892002-11-28 10:20:45 +00001448#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001449 bufp++;
1450 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001451 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001452
Glenn L McGrath642f2892002-11-28 10:20:45 +00001453#ifdef DEBUG
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001454 /* That's it. Any trailing junk? */
1455 if ((i == ETH_ALEN) && (*bufp != '\0')) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001456 bb_error_msg(_("in_ether(%s): trailing junk!"), orig);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001457 errno = EINVAL;
1458 return (-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001459 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00001460 bb_error_msg("in_ether(%s): %s", orig, pr_ether(sap->sa_data));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001461#endif
1462
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001463 return (0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001464}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001465#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001466
1467
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001468static struct hwtype ether_hwtype = {
1469 "ether", "Ethernet", ARPHRD_ETHER, ETH_ALEN,
1470 pr_ether, NULL /* UNUSED in_ether */ , NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001471};
1472
1473
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001474#endif /* HAVE_HWETHER */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001475
1476
1477#if HAVE_HWPPP
1478
1479#include <net/if_arp.h>
1480
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001481#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001482/* Start the PPP encapsulation on the file descriptor. */
1483static int do_ppp(int fd)
1484{
Manuel Novoa III cad53642003-03-19 09:13:01 +00001485 bb_error_msg(_("You cannot start PPP with this program."));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001486 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001487}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001488#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001489
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001490static struct hwtype ppp_hwtype = {
1491 "ppp", "Point-Point Protocol", ARPHRD_PPP, 0,
1492 NULL, NULL, NULL /* UNUSED do_ppp */ , 0
Eric Andersenf15d4da2001-03-06 00:48:59 +00001493};
1494
1495
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001496#endif /* HAVE_PPP */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001497
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001498static struct hwtype *hwtypes[] = {
Eric Andersenf15d4da2001-03-06 00:48:59 +00001499
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001500 &loop_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001501
1502#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001503 &slip_hwtype,
1504 &cslip_hwtype,
1505 &slip6_hwtype,
1506 &cslip6_hwtype,
1507 &adaptive_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001508#endif
1509#if HAVE_HWSTRIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001510 &strip_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001511#endif
1512#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001513 &ash_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001514#endif
1515#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001516 &ether_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001517#endif
1518#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001519 &tr_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001520#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001521 &tr_hwtype1,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001522#endif
1523#endif
1524#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001525 &ax25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001526#endif
1527#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001528 &netrom_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001529#endif
1530#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001531 &rose_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001532#endif
1533#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001534 &tunnel_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001535#endif
1536#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001537 &ppp_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001538#endif
1539#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001540 &hdlc_hwtype,
1541 &lapb_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001542#endif
1543#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001544 &arcnet_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001545#endif
1546#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001547 &dlci_hwtype,
1548 &frad_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001549#endif
1550#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001551 &sit_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001552#endif
1553#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001554 &fddi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001555#endif
1556#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001557 &hippi_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001558#endif
1559#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001560 &irda_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001561#endif
1562#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001563 &ec_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001564#endif
1565#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001566 &x25_hwtype,
Eric Andersenf15d4da2001-03-06 00:48:59 +00001567#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001568 &unspec_hwtype,
1569 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +00001570};
1571
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001572#ifdef KEEP_UNUSED
Eric Andersenf15d4da2001-03-06 00:48:59 +00001573static short sVhwinit = 0;
1574
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001575static void hwinit()
Eric Andersenf15d4da2001-03-06 00:48:59 +00001576{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001577 loop_hwtype.title = _("Local Loopback");
1578 unspec_hwtype.title = _("UNSPEC");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001579#if HAVE_HWSLIP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001580 slip_hwtype.title = _("Serial Line IP");
1581 cslip_hwtype.title = _("VJ Serial Line IP");
1582 slip6_hwtype.title = _("6-bit Serial Line IP");
1583 cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
1584 adaptive_hwtype.title = _("Adaptive Serial Line IP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001585#endif
1586#if HAVE_HWETHER
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001587 ether_hwtype.title = _("Ethernet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001588#endif
1589#if HAVE_HWASH
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001590 ash_hwtype.title = _("Ash");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001591#endif
1592#if HAVE_HWFDDI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001593 fddi_hwtype.title = _("Fiber Distributed Data Interface");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001594#endif
1595#if HAVE_HWHIPPI
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001596 hippi_hwtype.title = _("HIPPI");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001597#endif
1598#if HAVE_HWAX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001599 ax25_hwtype.title = _("AMPR AX.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001600#endif
1601#if HAVE_HWROSE
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001602 rose_hwtype.title = _("AMPR ROSE");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001603#endif
1604#if HAVE_HWNETROM
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001605 netrom_hwtype.title = _("AMPR NET/ROM");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001606#endif
1607#if HAVE_HWX25
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001608 x25_hwtype.title = _("generic X.25");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001609#endif
1610#if HAVE_HWTUNNEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001611 tunnel_hwtype.title = _("IPIP Tunnel");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001612#endif
1613#if HAVE_HWPPP
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001614 ppp_hwtype.title = _("Point-to-Point Protocol");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001615#endif
1616#if HAVE_HWHDLCLAPB
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001617 hdlc_hwtype.title = _("(Cisco)-HDLC");
1618 lapb_hwtype.title = _("LAPB");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001619#endif
1620#if HAVE_HWARC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001621 arcnet_hwtype.title = _("ARCnet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001622#endif
1623#if HAVE_HWFR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001624 dlci_hwtype.title = _("Frame Relay DLCI");
1625 frad_hwtype.title = _("Frame Relay Access Device");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001626#endif
1627#if HAVE_HWSIT
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001628 sit_hwtype.title = _("IPv6-in-IPv4");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001629#endif
1630#if HAVE_HWIRDA
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001631 irda_hwtype.title = _("IrLAP");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001632#endif
1633#if HAVE_HWTR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001634 tr_hwtype.title = _("16/4 Mbps Token Ring");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001635#ifdef ARPHRD_IEEE802_TR
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001636 tr_hwtype1.title = _("16/4 Mbps Token Ring (New)");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001637#endif
1638#endif
1639#if HAVE_HWEC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001640 ec_hwtype.title = _("Econet");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001641#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001642 sVhwinit = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001643}
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001644#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001645
1646#ifdef IFF_PORTSEL
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001647#if 0
1648static const char * const if_port_text[][4] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001649 /* Keep in step with <linux/netdevice.h> */
1650 {"unknown", NULL, NULL, NULL},
1651 {"10base2", "bnc", "coax", NULL},
1652 {"10baseT", "utp", "tpe", NULL},
1653 {"AUI", "thick", "db15", NULL},
1654 {"100baseT", NULL, NULL, NULL},
1655 {"100baseTX", NULL, NULL, NULL},
1656 {"100baseFX", NULL, NULL, NULL},
1657 {NULL, NULL, NULL, NULL},
Eric Andersenf15d4da2001-03-06 00:48:59 +00001658};
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001659#else
1660static const char * const if_port_text[] = {
1661 /* Keep in step with <linux/netdevice.h> */
1662 "unknown",
1663 "10base2",
1664 "10baseT",
1665 "AUI",
1666 "100baseT",
1667 "100baseTX",
1668 "100baseFX",
1669 NULL
1670};
1671#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001672#endif
1673
1674/* Check our hardware type table for this type. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001675static struct hwtype *get_hwntype(int type)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001676{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001677 struct hwtype **hwp;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001678
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001679#ifdef KEEP_UNUSED
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001680 if (!sVhwinit)
1681 hwinit();
1682#endif /* KEEP_UNUSED */
Eric Andersenf15d4da2001-03-06 00:48:59 +00001683
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001684 hwp = hwtypes;
1685 while (*hwp != NULL) {
1686 if ((*hwp)->type == type)
1687 return (*hwp);
1688 hwp++;
1689 }
1690 return (NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001691}
1692
1693/* return 1 if address is all zeros */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001694static int hw_null_address(struct hwtype *hw, void *ap)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001695{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001696 unsigned int i;
1697 unsigned char *address = (unsigned char *) ap;
1698
1699 for (i = 0; i < hw->alen; i++)
1700 if (address[i])
1701 return 0;
1702 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001703}
1704
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001705static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001706
1707static void print_bytes_scaled(unsigned long long ull, const char *end)
1708{
1709 unsigned long long int_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001710 const char *ext;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001711 unsigned int frac_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001712 int i;
1713
1714 frac_part = 0;
1715 ext = TRext;
1716 int_part = ull;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001717 i = 4;
1718 do {
1719#if 0
1720 /* This does correct rounding and is a little larger. But it
1721 * uses KiB as the smallest displayed unit. */
1722 if ((int_part < (1024*1024 - 51)) || !--i) {
1723 i = 0;
1724 int_part += 51; /* 1024*.05 = 51.2 */
1725 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001726 }
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001727 int_part /= 1024;
1728 ext += 3; /* KiB, MiB, GiB, TiB */
1729#else
1730 if (int_part >= 1024) {
1731 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
1732 int_part /= 1024;
1733 ext += 3; /* KiB, MiB, GiB, TiB */
1734 }
1735 --i;
1736#endif
1737 } while (i);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001738
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001739 printf("X bytes:%Lu (%Lu.%u %sB)%s", ull, int_part, frac_part, ext, end);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001740}
1741
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001742static const char * const ife_print_flags_strs[] = {
1743 "UP ",
1744 "BROADCAST ",
1745 "DEBUG ",
1746 "LOOPBACK ",
1747 "POINTOPOINT ",
1748 "NOTRAILERS ",
1749 "RUNNING ",
1750 "NOARP ",
1751 "PROMISC ",
1752 "ALLMULTI ",
1753 "SLAVE ",
1754 "MASTER ",
1755 "MULTICAST ",
1756#ifdef HAVE_DYNAMIC
1757 "DYNAMIC "
1758#endif
1759};
1760
1761static const unsigned short ife_print_flags_mask[] = {
1762 IFF_UP,
1763 IFF_BROADCAST,
1764 IFF_DEBUG,
1765 IFF_LOOPBACK,
1766 IFF_POINTOPOINT,
1767 IFF_NOTRAILERS,
1768 IFF_RUNNING,
1769 IFF_NOARP,
1770 IFF_PROMISC,
1771 IFF_ALLMULTI,
1772 IFF_SLAVE,
1773 IFF_MASTER,
1774 IFF_MULTICAST,
1775#ifdef HAVE_DYNAMIC
1776 IFF_DYNAMIC
1777#endif
1778 0
1779};
1780
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001781static void ife_print(struct interface *ptr)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001782{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001783 struct aftype *ap;
1784 struct hwtype *hw;
1785 int hf;
1786 int can_compress = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001787
1788#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001789 static struct aftype *ipxtype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001790#endif
1791#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001792 static struct aftype *ectype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001793#endif
1794#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001795 static struct aftype *ddptype = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001796#endif
1797#if HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001798 FILE *f;
1799 char addr6[40], devname[20];
1800 struct sockaddr_in6 sap;
1801 int plen, scope, dad_status, if_idx;
1802 char addr6p[8][5];
Eric Andersenf15d4da2001-03-06 00:48:59 +00001803#endif
1804
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001805 ap = get_afntype(ptr->addr.sa_family);
1806 if (ap == NULL)
1807 ap = get_afntype(0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001808
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001809 hf = ptr->type;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001810
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001811 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
1812 can_compress = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001813
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001814 hw = get_hwntype(hf);
1815 if (hw == NULL)
1816 hw = get_hwntype(-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001817
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001818 printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title));
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001819 /* For some hardware types (eg Ash, ATM) we don't print the
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001820 hardware address if it's null. */
1821 if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
1822 hw->suppress_null_addr)))
1823 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001824#ifdef IFF_PORTSEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001825 if (ptr->flags & IFF_PORTSEL) {
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001826 printf(_("Media:%s"), if_port_text[ptr->map.port] /* [0] */);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001827 if (ptr->flags & IFF_AUTOMEDIA)
1828 printf(_("(auto)"));
1829 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001830#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001831 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001832
1833#if HAVE_AFINET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001834 if (ptr->has_ip) {
1835 printf(_(" %s addr:%s "), ap->name,
1836 ap->sprint(&ptr->addr, 1));
1837 if (ptr->flags & IFF_POINTOPOINT) {
1838 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
1839 }
1840 if (ptr->flags & IFF_BROADCAST) {
1841 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
1842 }
1843 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001844 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001845#endif
1846
1847#if HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +00001848
Eric Andersen51b8bd62002-07-03 11:46:38 +00001849#define IPV6_ADDR_ANY 0x0000U
1850
1851#define IPV6_ADDR_UNICAST 0x0001U
1852#define IPV6_ADDR_MULTICAST 0x0002U
1853#define IPV6_ADDR_ANYCAST 0x0004U
1854
1855#define IPV6_ADDR_LOOPBACK 0x0010U
1856#define IPV6_ADDR_LINKLOCAL 0x0020U
1857#define IPV6_ADDR_SITELOCAL 0x0040U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001858
Eric Andersen51b8bd62002-07-03 11:46:38 +00001859#define IPV6_ADDR_COMPATv4 0x0080U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001860
Eric Andersen51b8bd62002-07-03 11:46:38 +00001861#define IPV6_ADDR_SCOPE_MASK 0x00f0U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001862
Eric Andersen51b8bd62002-07-03 11:46:38 +00001863#define IPV6_ADDR_MAPPED 0x1000U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001864#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
1865
1866 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1867 while (fscanf
1868 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
1869 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
1870 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
1871 &dad_status, devname) != EOF) {
1872 if (!strcmp(devname, ptr->name)) {
1873 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1874 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1875 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1876 inet_pton(AF_INET6, addr6,
1877 (struct sockaddr *) &sap.sin6_addr);
1878 sap.sin6_family = AF_INET6;
1879 printf(_(" inet6 addr: %s/%d"),
1880 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
1881 plen);
1882 printf(_(" Scope:"));
1883 switch (scope & IPV6_ADDR_SCOPE_MASK) {
1884 case 0:
1885 printf(_("Global"));
1886 break;
1887 case IPV6_ADDR_LINKLOCAL:
1888 printf(_("Link"));
1889 break;
1890 case IPV6_ADDR_SITELOCAL:
1891 printf(_("Site"));
1892 break;
1893 case IPV6_ADDR_COMPATv4:
1894 printf(_("Compat"));
1895 break;
1896 case IPV6_ADDR_LOOPBACK:
1897 printf(_("Host"));
1898 break;
1899 default:
1900 printf(_("Unknown"));
1901 }
1902 printf("\n");
1903 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001904 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001905 fclose(f);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001906 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001907#endif
1908
1909#if HAVE_AFIPX
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001910 if (ipxtype == NULL)
1911 ipxtype = get_afntype(AF_IPX);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001912
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001913 if (ipxtype != NULL) {
1914 if (ptr->has_ipx_bb)
1915 printf(_(" IPX/Ethernet II addr:%s\n"),
1916 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
1917 if (ptr->has_ipx_sn)
1918 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
1919 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
1920 if (ptr->has_ipx_e2)
1921 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
1922 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
1923 if (ptr->has_ipx_e3)
1924 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
1925 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
1926 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001927#endif
1928
1929#if HAVE_AFATALK
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001930 if (ddptype == NULL)
1931 ddptype = get_afntype(AF_APPLETALK);
1932 if (ddptype != NULL) {
1933 if (ptr->has_ddp)
1934 printf(_(" EtherTalk Phase 2 addr:%s\n"),
1935 ddptype->sprint(&ptr->ddpaddr, 1));
1936 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001937#endif
1938
1939#if HAVE_AFECONET
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001940 if (ectype == NULL)
1941 ectype = get_afntype(AF_ECONET);
1942 if (ectype != NULL) {
1943 if (ptr->has_econet)
1944 printf(_(" econet addr:%s\n"),
1945 ectype->sprint(&ptr->ecaddr, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +00001946 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001947#endif
1948
1949 printf(" ");
1950 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001951
1952 if (ptr->flags == 0) {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001953 printf(_("[NO FLAGS] "));
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001954 } else {
1955 int i = 0;
1956 do {
1957 if (ptr->flags & ife_print_flags_mask[i]) {
1958 printf(_(ife_print_flags_strs[i]));
1959 }
1960 } while (ife_print_flags_mask[++i]);
1961 }
1962
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001963 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1964 printf(_(" MTU:%d Metric:%d"), ptr->mtu, ptr->metric ? ptr->metric : 1);
1965#ifdef SIOCSKEEPALIVE
1966 if (ptr->outfill || ptr->keepalive)
1967 printf(_(" Outfill:%d Keepalive:%d"), ptr->outfill, ptr->keepalive);
1968#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +00001969 printf("\n");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001970
1971 /* If needed, display the interface statistics. */
1972
1973 if (ptr->statistics_valid) {
1974 /* XXX: statistics are currently only printed for the primary address,
1975 * not for the aliases, although strictly speaking they're shared
1976 * by all addresses.
1977 */
1978 printf(" ");
1979
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001980 printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001981 ptr->stats.rx_packets, ptr->stats.rx_errors,
1982 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1983 ptr->stats.rx_frame_errors);
1984 if (can_compress)
1985 printf(_(" compressed:%lu\n"),
1986 ptr->stats.rx_compressed);
1987 printf(" ");
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001988 printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001989 ptr->stats.tx_packets, ptr->stats.tx_errors,
1990 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
1991 ptr->stats.tx_carrier_errors);
1992 printf(_(" collisions:%lu "), ptr->stats.collisions);
1993 if (can_compress)
1994 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
1995 if (ptr->tx_queue_len != -1)
1996 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
1997 printf("\n R");
1998 print_bytes_scaled(ptr->stats.rx_bytes, " T");
1999 print_bytes_scaled(ptr->stats.tx_bytes, "\n");
2000
2001 }
2002
2003 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
2004 ptr->map.base_addr)) {
2005 printf(" ");
2006 if (ptr->map.irq)
2007 printf(_("Interrupt:%d "), ptr->map.irq);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002008 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002009 I/O maps */
2010 printf(_("Base address:0x%lx "),
2011 (unsigned long) ptr->map.base_addr);
2012 if (ptr->map.mem_start) {
2013 printf(_("Memory:%lx-%lx "), ptr->map.mem_start,
2014 ptr->map.mem_end);
2015 }
2016 if (ptr->map.dma)
2017 printf(_("DMA chan:%x "), ptr->map.dma);
2018 printf("\n");
2019 }
2020 printf("\n");
Eric Andersenf15d4da2001-03-06 00:48:59 +00002021}
2022
2023
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002024static int do_if_print(struct interface *ife, void *cookie)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002025{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002026 int *opt_a = (int *) cookie;
2027 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002028
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002029 res = do_if_fetch(ife);
2030 if (res >= 0) {
2031 if ((ife->flags & IFF_UP) || *opt_a)
2032 ife_print(ife);
2033 }
2034 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002035}
2036
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002037static struct interface *lookup_interface(char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002038{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002039 struct interface *ife = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002040
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002041 if (if_readlist_proc(name) < 0)
2042 return NULL;
2043 ife = add_interface(name);
2044 return ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002045}
2046
2047/* for ipv4 add/del modes */
2048static int if_print(char *ifname)
2049{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002050 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002051
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002052 if (!ifname) {
2053 res = for_all_interfaces(do_if_print, &interface_opt_a);
2054 } else {
2055 struct interface *ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002056
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002057 ife = lookup_interface(ifname);
2058 res = do_if_fetch(ife);
2059 if (res >= 0)
2060 ife_print(ife);
2061 }
2062 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002063}
2064
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00002065int display_interfaces(char *ifname)
Eric Andersenf15d4da2001-03-06 00:48:59 +00002066{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002067 int status;
Eric Andersenf15d4da2001-03-06 00:48:59 +00002068
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002069 /* Create a channel to the NET kernel. */
2070 if ((skfd = sockets_open(0)) < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002071 bb_perror_msg_and_die("socket");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002072 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00002073
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00002074 /* Do we have to show the current setup? */
2075 status = if_print(ifname);
2076 close(skfd);
2077 exit(status < 0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00002078}