blob: 1d194f38e4541185fb4a374f03237e47e451cb12 [file] [log] [blame]
"Robert P. J. Day"63fc1a92006-07-02 19:47:05 +00001/* vi: set sw=4 ts=4: */
Eric Andersenf15d4da2001-03-06 00:48:59 +00002/*
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003 * stolen from net-tools-1.59 and stripped down for busybox by
Eric Andersencb81e642003-07-14 21:21:08 +00004 * Erik Andersen <andersen@codepoet.org>
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005 *
6 * Heavily modified by Manuel Novoa III Mar 12, 2001
7 *
Eric Andersenbdfd0d72001-10-24 05:00:29 +00008 * 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 *
Rob Landleye84f4342006-06-03 21:23:20 +000023 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersenf15d4da2001-03-06 00:48:59 +000024 *
25 * Patched to support 'add' and 'del' keywords for INET(4) addresses
26 * by Mrs. Brisby <mrs.brisby@nimh.org>
27 *
28 * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
29 * - gettext instead of catgets for i18n
Eric Andersenc7bda1c2004-03-15 08:29:22 +000030 * 10/1998 - Andi Kleen. Use interface list primitives.
31 * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
Eric Andersenf15d4da2001-03-06 00:48:59 +000032 * (default AF was wrong)
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +000033 */
34
Eric Andersencd8c4362001-11-10 11:22:46 +000035#include "inet_common.h"
Eric Andersenf15d4da2001-03-06 00:48:59 +000036#include <stdio.h>
37#include <errno.h>
Eric Andersenf15d4da2001-03-06 00:48:59 +000038#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
Eric Andersencd8c4362001-11-10 11:22:46 +000041#include <fcntl.h>
42#include <ctype.h>
43#include <sys/ioctl.h>
Eric Andersen85e5e722003-07-22 08:56:55 +000044#include <sys/types.h>
Eric Andersencd8c4362001-11-10 11:22:46 +000045#include <net/if.h>
46#include <net/if_arp.h>
Bernhard Reutner-Fischerfa939aa2006-04-05 16:21:37 +000047#include "busybox.h"
Eric Andersenf15d4da2001-03-06 00:48:59 +000048
Glenn L McGrathb54a7482003-08-29 11:34:08 +000049#ifdef CONFIG_FEATURE_IPV6
50# define HAVE_AFINET6 1
51#else
52# undef HAVE_AFINET6
53#endif
54
Eric Andersenf15d4da2001-03-06 00:48:59 +000055#define _PATH_PROCNET_DEV "/proc/net/dev"
Eric Andersen51b8bd62002-07-03 11:46:38 +000056#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
Eric Andersenf15d4da2001-03-06 00:48:59 +000057
Denis Vlasenkoaad49992006-11-22 02:12:07 +000058#ifdef HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +000059
60#ifndef _LINUX_IN6_H
61/*
62 * This is in linux/include/net/ipv6.h.
63 */
64
65struct in6_ifreq {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +000066 struct in6_addr ifr6_addr;
Glenn L McGrathb54a7482003-08-29 11:34:08 +000067 uint32_t ifr6_prefixlen;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +000068 unsigned int ifr6_ifindex;
Eric Andersenf15d4da2001-03-06 00:48:59 +000069};
70
71#endif
72
Denis Vlasenkoaad49992006-11-22 02:12:07 +000073#endif /* HAVE_AFINET6 */
Eric Andersenf15d4da2001-03-06 00:48:59 +000074
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +000075/* Defines for glibc2.0 users. */
76#ifndef SIOCSIFTXQLEN
77#define SIOCSIFTXQLEN 0x8943
78#define SIOCGIFTXQLEN 0x8942
79#endif
80
81/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
82#ifndef ifr_qlen
83#define ifr_qlen ifr_ifru.ifru_mtu
84#endif
85
86#ifndef HAVE_TXQUEUELEN
87#define HAVE_TXQUEUELEN 1
88#endif
89
90#ifndef IFF_DYNAMIC
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +000091#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +000092#endif
93
Eric Andersenf15d4da2001-03-06 00:48:59 +000094/* This structure defines protocol families and their handlers. */
95struct aftype {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +000096 const char *name;
97 const char *title;
98 int af;
99 int alen;
100 char *(*print) (unsigned char *);
101 char *(*sprint) (struct sockaddr *, int numeric);
102 int (*input) (int type, char *bufp, struct sockaddr *);
103 void (*herror) (char *text);
104 int (*rprint) (int options);
105 int (*rinput) (int typ, int ext, char **argv);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000106
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000107 /* may modify src */
108 int (*getmask) (char *src, struct sockaddr * mask, char *name);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000109
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000110 int fd;
111 char *flag_file;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000112};
113
Eric Andersenf15d4da2001-03-06 00:48:59 +0000114/* Display an Internet socket address. */
115static char *INET_sprint(struct sockaddr *sap, int numeric)
116{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000117 static char buff[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000118
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000119 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
Rob Landley4e3aff32006-05-29 04:37:28 +0000120 return safe_strncpy(buff, "[NONE SET]", sizeof(buff));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000121
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000122 if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
123 numeric, 0xffffff00) != 0)
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000124 return NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000125
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000126 return buff;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000127}
128
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000129static struct aftype inet_aftype = {
Rob Landley2818b292006-06-20 15:52:52 +0000130 .name = "inet",
131 .title = "DARPA Internet",
132 .af = AF_INET,
Rob Landley9fe801e2006-06-20 21:13:29 +0000133 .alen = 4,
Rob Landley2818b292006-06-20 15:52:52 +0000134 .sprint = INET_sprint,
135 .fd = -1
Eric Andersenf15d4da2001-03-06 00:48:59 +0000136};
137
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000138#ifdef HAVE_AFINET6
Eric Andersen51b8bd62002-07-03 11:46:38 +0000139
Eric Andersen51b8bd62002-07-03 11:46:38 +0000140/* Display an Internet socket address. */
141/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
142static char *INET6_sprint(struct sockaddr *sap, int numeric)
143{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000144 static char buff[128];
Eric Andersen51b8bd62002-07-03 11:46:38 +0000145
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000146 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
Rob Landley4e3aff32006-05-29 04:37:28 +0000147 return safe_strncpy(buff, "[NONE SET]", sizeof(buff));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000148 if (INET6_rresolve
149 (buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)
Rob Landley4e3aff32006-05-29 04:37:28 +0000150 return safe_strncpy(buff, "[UNKNOWN]", sizeof(buff));
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000151 return buff;
Eric Andersen51b8bd62002-07-03 11:46:38 +0000152}
153
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000154static struct aftype inet6_aftype = {
Rob Landley2818b292006-06-20 15:52:52 +0000155 .name = "inet6",
156 .title = "IPv6",
157 .af = AF_INET6,
158 .alen = sizeof(struct in6_addr),
159 .sprint = INET6_sprint,
160 .fd = -1
Eric Andersen51b8bd62002-07-03 11:46:38 +0000161};
162
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000163#endif /* HAVE_AFINET6 */
Eric Andersen51b8bd62002-07-03 11:46:38 +0000164
Eric Andersenf15d4da2001-03-06 00:48:59 +0000165/* Display an UNSPEC address. */
166static char *UNSPEC_print(unsigned char *ptr)
167{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000168 static char buff[sizeof(struct sockaddr) * 3 + 1];
169 char *pos;
170 unsigned int i;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000171
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000172 pos = buff;
173 for (i = 0; i < sizeof(struct sockaddr); i++) {
174 /* careful -- not every libc's sprintf returns # bytes written */
175 sprintf(pos, "%02X-", (*ptr++ & 0377));
176 pos += 3;
177 }
178 /* Erase trailing "-". Works as long as sizeof(struct sockaddr) != 0 */
179 *--pos = '\0';
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000180 return buff;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000181}
182
183/* Display an UNSPEC socket address. */
184static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
185{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000186 static char buf[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000187
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000188 if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
Rob Landley4e3aff32006-05-29 04:37:28 +0000189 return safe_strncpy(buf, "[NONE SET]", sizeof(buf));
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000190 return UNSPEC_print((unsigned char *)sap->sa_data);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000191}
192
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000193static struct aftype unspec_aftype = {
194 "unspec", "UNSPEC", AF_UNSPEC, 0,
195 UNSPEC_print, UNSPEC_sprint, NULL, NULL,
196 NULL,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000197};
198
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000199static struct aftype * const aftypes[] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000200 &inet_aftype,
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000201#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000202 &inet6_aftype,
Eric Andersenf15d4da2001-03-06 00:48:59 +0000203#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000204 &unspec_aftype,
205 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000206};
207
Eric Andersenf15d4da2001-03-06 00:48:59 +0000208/* Check our protocol family table for this family. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000209static struct aftype *get_afntype(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000210{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000211 struct aftype * const *afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000212
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000213 afp = aftypes;
214 while (*afp != NULL) {
215 if ((*afp)->af == af)
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000216 return *afp;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000217 afp++;
218 }
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000219 return NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000220}
221
222/* Check our protocol family table for this family and return its socket */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000223static int get_socket_for_af(int af)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000224{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000225 struct aftype * const *afp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000226
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000227 afp = aftypes;
228 while (*afp != NULL) {
229 if ((*afp)->af == af)
230 return (*afp)->fd;
231 afp++;
232 }
233 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000234}
235
Eric Andersenf15d4da2001-03-06 00:48:59 +0000236struct user_net_device_stats {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000237 unsigned long long rx_packets; /* total packets received */
238 unsigned long long tx_packets; /* total packets transmitted */
239 unsigned long long rx_bytes; /* total bytes received */
240 unsigned long long tx_bytes; /* total bytes transmitted */
241 unsigned long rx_errors; /* bad packets received */
242 unsigned long tx_errors; /* packet transmit problems */
243 unsigned long rx_dropped; /* no space in linux buffers */
244 unsigned long tx_dropped; /* no space available in linux */
245 unsigned long rx_multicast; /* multicast packets received */
246 unsigned long rx_compressed;
247 unsigned long tx_compressed;
248 unsigned long collisions;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000249
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000250 /* detailed rx_errors: */
251 unsigned long rx_length_errors;
252 unsigned long rx_over_errors; /* receiver ring buff overflow */
253 unsigned long rx_crc_errors; /* recved pkt with crc error */
254 unsigned long rx_frame_errors; /* recv'd frame alignment error */
255 unsigned long rx_fifo_errors; /* recv'r fifo overrun */
256 unsigned long rx_missed_errors; /* receiver missed packet */
257 /* detailed tx_errors */
258 unsigned long tx_aborted_errors;
259 unsigned long tx_carrier_errors;
260 unsigned long tx_fifo_errors;
261 unsigned long tx_heartbeat_errors;
262 unsigned long tx_window_errors;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000263};
264
265struct interface {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000266 struct interface *next, *prev;
267 char name[IFNAMSIZ]; /* interface name */
268 short type; /* if type */
269 short flags; /* various flags */
270 int metric; /* routing metric */
271 int mtu; /* MTU value */
272 int tx_queue_len; /* transmit queue length */
273 struct ifmap map; /* hardware setup */
274 struct sockaddr addr; /* IP address */
275 struct sockaddr dstaddr; /* P-P IP address */
276 struct sockaddr broadaddr; /* IP broadcast address */
277 struct sockaddr netmask; /* IP network mask */
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000278 int has_ip;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000279 char hwaddr[32]; /* HW address */
280 int statistics_valid;
281 struct user_net_device_stats stats; /* statistics */
282 int keepalive; /* keepalive value for SLIP */
283 int outfill; /* outfill value for SLIP */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000284};
285
286
Denis Vlasenko04b30ba2006-11-21 14:26:37 +0000287int interface_opt_a; /* show all interfaces */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000288
Eric Andersenf15d4da2001-03-06 00:48:59 +0000289static struct interface *int_list, *int_last;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000290static int skfd = -1; /* generic raw socket desc. */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000291
292
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000293static int sockets_open(int family)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000294{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000295 struct aftype * const *aft;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000296 int sfd = -1;
297 static int force = -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000298
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000299 if (force < 0) {
300 force = 0;
Bernhard Reutner-Fischere2e56c72006-05-19 11:54:02 +0000301 if (get_linux_version_code() < KERNEL_VERSION(2,1,0))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000302 force = 1;
303 if (access("/proc/net", R_OK))
304 force = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000305 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000306 for (aft = aftypes; *aft; aft++) {
307 struct aftype *af = *aft;
308 int type = SOCK_DGRAM;
309
310 if (af->af == AF_UNSPEC)
311 continue;
312 if (family && family != af->af)
313 continue;
314 if (af->fd != -1) {
315 sfd = af->fd;
316 continue;
317 }
318 /* Check some /proc file first to not stress kmod */
319 if (!family && !force && af->flag_file) {
320 if (access(af->flag_file, R_OK))
321 continue;
322 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000323 af->fd = socket(af->af, type, 0);
324 if (af->fd >= 0)
325 sfd = af->fd;
326 }
Glenn L McGrath642f2892002-11-28 10:20:45 +0000327 if (sfd < 0) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +0000328 bb_error_msg("no usable address families found");
Glenn L McGrath642f2892002-11-28 10:20:45 +0000329 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000330 return sfd;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000331}
332
Rob Landley93983042005-05-03 21:30:26 +0000333#ifdef CONFIG_FEATURE_CLEAN_UP
334static void sockets_close(void)
335{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000336 struct aftype * const *aft;
Rob Landley93983042005-05-03 21:30:26 +0000337 for (aft = aftypes; *aft != NULL; aft++) {
338 struct aftype *af = *aft;
339 if( af->fd != -1 ) {
340 close(af->fd);
341 af->fd = -1;
342 }
343 }
344}
345#endif
Bernhard Reutner-Fischer57d83ff2006-12-07 12:25:17 +0000346#if 0
Eric Andersenf15d4da2001-03-06 00:48:59 +0000347/* like strcmp(), but knows about numbers */
Bernhard Reutner-Fischer57d83ff2006-12-07 12:25:17 +0000348except that the freshly added calls to xatoul() brf on ethernet aliases with
349uClibc with e.g.: ife->name='lo' name='eth0:1'
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000350static int nstrcmp(const char *a, const char *b)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000351{
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000352 const char *a_ptr = a;
353 const char *b_ptr = b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000354
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000355 while (*a == *b) {
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000356 if (*a == '\0') {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000357 return 0;
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000358 }
359 if (!isdigit(*a) && isdigit(*(a+1))) {
360 a_ptr = a+1;
361 b_ptr = b+1;
362 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000363 a++;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000364 b++;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000365 }
Glenn L McGrath2e99d432004-07-23 01:49:46 +0000366
367 if (isdigit(*a) && isdigit(*b)) {
Denis Vlasenko13858992006-10-08 12:49:22 +0000368 return xatoul(a_ptr) > xatoul(b_ptr) ? 1 : -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000369 }
370 return *a - *b;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000371}
Bernhard Reutner-Fischer57d83ff2006-12-07 12:25:17 +0000372#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000373
374static struct interface *add_interface(char *name)
375{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000376 struct interface *ife, **nextp, *new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000377
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000378 for (ife = int_last; ife; ife = ife->prev) {
Bernhard Reutner-Fischer57d83ff2006-12-07 12:25:17 +0000379 int n = /*n*/strcmp(ife->name, name);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000380
381 if (n == 0)
382 return ife;
383 if (n < 0)
384 break;
385 }
Rob Landleya6e131d2006-05-29 06:43:55 +0000386
387 new = xzalloc(sizeof(*new));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000388 safe_strncpy(new->name, name, IFNAMSIZ);
389 nextp = ife ? &ife->next : &int_list;
390 new->prev = ife;
391 new->next = *nextp;
392 if (new->next)
393 new->next->prev = new;
394 else
395 int_last = new;
396 *nextp = new;
397 return new;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000398}
399
400
401static int if_readconf(void)
402{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000403 int numreqs = 30;
404 struct ifconf ifc;
405 struct ifreq *ifr;
406 int n, err = -1;
407 int skfd2;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000408
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000409 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
410 (as of 2.1.128) */
411 skfd2 = get_socket_for_af(AF_INET);
412 if (skfd2 < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000413 bb_perror_msg(("warning: no inet socket available"));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000414 /* Try to soldier on with whatever socket we can get hold of. */
415 skfd2 = sockets_open(0);
416 if (skfd2 < 0)
417 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000418 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000419
420 ifc.ifc_buf = NULL;
421 for (;;) {
422 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
423 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
424
425 if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
426 perror("SIOCGIFCONF");
427 goto out;
428 }
429 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
430 /* assume it overflowed and try again */
431 numreqs += 10;
432 continue;
433 }
434 break;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000435 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000436
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000437 ifr = ifc.ifc_req;
438 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
439 add_interface(ifr->ifr_name);
440 ifr++;
441 }
442 err = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000443
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000444 out:
445 free(ifc.ifc_buf);
446 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000447}
448
Eric Andersen14f5c8d2005-04-16 19:39:00 +0000449static char *get_name(char *name, char *p)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000450{
Rob Landley9fe801e2006-06-20 21:13:29 +0000451 /* Extract <name> from nul-terminated p where p matches
452 <name>: after leading whitespace.
Eric Andersen9940e082004-08-12 16:52:00 +0000453 If match is not made, set name empty and return unchanged p */
Rob Landley9fe801e2006-06-20 21:13:29 +0000454 int namestart=0, nameend=0;
Eric Andersen9940e082004-08-12 16:52:00 +0000455 while (isspace(p[namestart]))
456 namestart++;
457 nameend=namestart;
458 while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
459 nameend++;
460 if (p[nameend]==':') {
Eric Andersen9940e082004-08-12 16:52:00 +0000461 if ((nameend-namestart)<IFNAMSIZ) {
462 memcpy(name,&p[namestart],nameend-namestart);
463 name[nameend-namestart]='\0';
464 p=&p[nameend];
465 } else {
466 /* Interface name too large */
467 name[0]='\0';
468 }
469 } else {
Rob Landley9fe801e2006-06-20 21:13:29 +0000470 /* trailing ':' not found - return empty */
Eric Andersen9940e082004-08-12 16:52:00 +0000471 name[0]='\0';
Eric Andersenf15d4da2001-03-06 00:48:59 +0000472 }
Eric Andersen6fea7322004-08-26 21:45:21 +0000473 return p + 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000474}
475
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000476/* If scanf supports size qualifiers for %n conversions, then we can
477 * use a modified fmt that simply stores the position in the fields
478 * having no associated fields in the proc string. Of course, we need
479 * to zero them again when we're done. But that is smaller than the
480 * old approach of multiple scanf occurrences with large numbers of
481 * args. */
482
Bernhard Reutner-Fischera901b402006-01-19 14:51:17 +0000483/* static const char * const ss_fmt[] = { */
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +0000484/* "%lln%llu%lu%lu%lu%lu%ln%ln%lln%llu%lu%lu%lu%lu%lu", */
485/* "%llu%llu%lu%lu%lu%lu%ln%ln%llu%llu%lu%lu%lu%lu%lu", */
486/* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000487/* }; */
488
489 /* Lie about the size of the int pointed to for %n. */
490#if INT_MAX == LONG_MAX
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000491static const char * const ss_fmt[] = {
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +0000492 "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u",
493 "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u",
494 "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u"
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000495};
496#else
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000497static const char * const ss_fmt[] = {
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +0000498 "%n%llu%lu%lu%lu%lu%n%n%n%llu%lu%lu%lu%lu%lu",
499 "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu",
500 "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu"
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000501};
502
503#endif
504
505static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000506{
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000507 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
508
509 sscanf(bp, ss_fmt[procnetdev_vsn],
510 &ife->stats.rx_bytes, /* missing for 0 */
511 &ife->stats.rx_packets,
512 &ife->stats.rx_errors,
513 &ife->stats.rx_dropped,
514 &ife->stats.rx_fifo_errors,
515 &ife->stats.rx_frame_errors,
516 &ife->stats.rx_compressed, /* missing for <= 1 */
517 &ife->stats.rx_multicast, /* missing for <= 1 */
518 &ife->stats.tx_bytes, /* missing for 0 */
519 &ife->stats.tx_packets,
520 &ife->stats.tx_errors,
521 &ife->stats.tx_dropped,
522 &ife->stats.tx_fifo_errors,
523 &ife->stats.collisions,
524 &ife->stats.tx_carrier_errors,
525 &ife->stats.tx_compressed /* missing for <= 1 */
526 );
527
528 if (procnetdev_vsn <= 1) {
529 if (procnetdev_vsn == 0) {
530 ife->stats.rx_bytes = 0;
531 ife->stats.tx_bytes = 0;
532 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000533 ife->stats.rx_multicast = 0;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000534 ife->stats.rx_compressed = 0;
535 ife->stats.tx_compressed = 0;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000536 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000537}
538
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000539static inline int procnetdev_version(char *buf)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000540{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000541 if (strstr(buf, "compressed"))
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000542 return 2;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000543 if (strstr(buf, "bytes"))
544 return 1;
545 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000546}
547
548static int if_readlist_proc(char *target)
549{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000550 static int proc_read;
551 FILE *fh;
552 char buf[512];
553 struct interface *ife;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000554 int err, procnetdev_vsn;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000555
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000556 if (proc_read)
557 return 0;
558 if (!target)
559 proc_read = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000560
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000561 fh = fopen(_PATH_PROCNET_DEV, "r");
562 if (!fh) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +0000563 bb_perror_msg("warning: cannot open %s, limiting output", _PATH_PROCNET_DEV);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000564 return if_readconf();
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000565 }
566 fgets(buf, sizeof buf, fh); /* eat line */
567 fgets(buf, sizeof buf, fh);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000568
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000569 procnetdev_vsn = procnetdev_version(buf);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000570
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000571 err = 0;
572 while (fgets(buf, sizeof buf, fh)) {
Eric Andersenf96675b2003-07-28 06:37:04 +0000573 char *s, name[128];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000574
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000575 s = get_name(name, buf);
576 ife = add_interface(name);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000577 get_dev_fields(s, ife, procnetdev_vsn);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000578 ife->statistics_valid = 1;
579 if (target && !strcmp(target, name))
580 break;
581 }
582 if (ferror(fh)) {
583 perror(_PATH_PROCNET_DEV);
584 err = -1;
585 proc_read = 0;
586 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000587 fclose(fh);
588 return err;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000589}
590
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000591static int if_readlist(void)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000592{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000593 int err = if_readlist_proc(NULL);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000594
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000595 if (!err)
596 err = if_readconf();
597 return err;
598}
599
600static int for_all_interfaces(int (*doit) (struct interface *, void *),
601 void *cookie)
602{
603 struct interface *ife;
604
605 if (!int_list && (if_readlist() < 0))
606 return -1;
607 for (ife = int_list; ife; ife = ife->next) {
608 int err = doit(ife, cookie);
609
610 if (err)
611 return err;
612 }
613 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000614}
615
Eric Andersenf15d4da2001-03-06 00:48:59 +0000616/* Fetch the interface configuration from the kernel. */
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000617static int if_fetch(struct interface *ife)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000618{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000619 struct ifreq ifr;
620 int fd;
621 char *ifname = ife->name;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000622
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000623 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000624 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000625 return -1;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000626 ife->flags = ifr.ifr_flags;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000627
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000628 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000629 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
630 memset(ife->hwaddr, 0, 32);
631 else
632 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000633
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000634 ife->type = ifr.ifr_hwaddr.sa_family;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000635
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000636 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000637 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
638 ife->metric = 0;
639 else
640 ife->metric = ifr.ifr_metric;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000641
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000642 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000643 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
644 ife->mtu = 0;
645 else
646 ife->mtu = ifr.ifr_mtu;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000647
Rob Landley93983042005-05-03 21:30:26 +0000648#ifdef SIOCGIFMAP
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000649 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Rob Landley93983042005-05-03 21:30:26 +0000650 if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000651 ife->map = ifr.ifr_map;
Rob Landley93983042005-05-03 21:30:26 +0000652 else
653#endif
654 memset(&ife->map, 0, sizeof(struct ifmap));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000655
656#ifdef HAVE_TXQUEUELEN
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000657 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000658 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
659 ife->tx_queue_len = -1; /* unknown value */
660 else
661 ife->tx_queue_len = ifr.ifr_qlen;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000662#else
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000663 ife->tx_queue_len = -1; /* unknown value */
Eric Andersenf15d4da2001-03-06 00:48:59 +0000664#endif
665
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000666 /* IPv4 address? */
667 fd = get_socket_for_af(AF_INET);
668 if (fd >= 0) {
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000669 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000670 ifr.ifr_addr.sa_family = AF_INET;
671 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
672 ife->has_ip = 1;
673 ife->addr = ifr.ifr_addr;
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000674 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000675 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
676 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
677 else
678 ife->dstaddr = ifr.ifr_dstaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000679
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000680 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000681 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
682 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
683 else
684 ife->broadaddr = ifr.ifr_broadaddr;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000685
Denis Vlasenko229b3d22006-11-27 23:44:57 +0000686 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000687 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
688 memset(&ife->netmask, 0, sizeof(struct sockaddr));
689 else
690 ife->netmask = ifr.ifr_netmask;
691 } else
692 memset(&ife->addr, 0, sizeof(struct sockaddr));
693 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000694
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000695 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000696}
697
698
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000699static int do_if_fetch(struct interface *ife)
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000700{
701 if (if_fetch(ife) < 0) {
702 char *errmsg;
703
704 if (errno == ENODEV) {
705 /* Give better error message for this case. */
Rob Landley4e3aff32006-05-29 04:37:28 +0000706 errmsg = "Device not found";
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000707 } else {
708 errmsg = strerror(errno);
709 }
Rob Landley4e3aff32006-05-29 04:37:28 +0000710 bb_error_msg("%s: error fetching interface information: %s",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000711 ife->name, errmsg);
712 return -1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000713 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000714 return 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000715}
716
717/* This structure defines hardware protocols and their handlers. */
718struct hwtype {
Bernhard Reutner-Fischera901b402006-01-19 14:51:17 +0000719 const char * const name;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000720 const char *title;
721 int type;
722 int alen;
723 char *(*print) (unsigned char *);
724 int (*input) (char *, struct sockaddr *);
725 int (*activate) (int fd);
726 int suppress_null_addr;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000727};
728
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000729static const struct hwtype unspec_hwtype = {
"Robert P. J. Day"4137dd72006-06-26 21:54:57 +0000730 .name = "unspec",
731 .title = "UNSPEC",
732 .type = -1,
733 .print = UNSPEC_print
Eric Andersenf15d4da2001-03-06 00:48:59 +0000734};
735
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000736static const struct hwtype loop_hwtype = {
"Robert P. J. Day"4137dd72006-06-26 21:54:57 +0000737 .name = "loop",
738 .title = "Local Loopback",
739 .type = ARPHRD_LOOPBACK
Eric Andersenf15d4da2001-03-06 00:48:59 +0000740};
741
Eric Andersenf15d4da2001-03-06 00:48:59 +0000742#include <net/if_arp.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +0000743
Denis Vlasenko83e5d6f2006-12-18 21:49:06 +0000744#if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION)
Eric Andersenab4e19a2003-01-14 08:54:08 +0000745#include <net/ethernet.h>
746#else
Eric Andersenf15d4da2001-03-06 00:48:59 +0000747#include <linux/if_ether.h>
Eric Andersenab4e19a2003-01-14 08:54:08 +0000748#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000749
Eric Andersenf15d4da2001-03-06 00:48:59 +0000750/* Display an Ethernet address in readable format. */
751static char *pr_ether(unsigned char *ptr)
752{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000753 static char buff[64];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000754
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000755 snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
756 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
757 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
758 );
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000759 return buff;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000760}
761
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000762static const struct hwtype ether_hwtype = {
"Robert P. J. Day"4137dd72006-06-26 21:54:57 +0000763 .name = "ether",
764 .title = "Ethernet",
765 .type = ARPHRD_ETHER,
766 .alen = ETH_ALEN,
767 .print = pr_ether
Eric Andersenf15d4da2001-03-06 00:48:59 +0000768};
769
Eric Andersenf15d4da2001-03-06 00:48:59 +0000770#include <net/if_arp.h>
771
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000772static const struct hwtype ppp_hwtype = {
"Robert P. J. Day"4137dd72006-06-26 21:54:57 +0000773 .name = "ppp",
774 .title = "Point-to-Point Protocol",
775 .type = ARPHRD_PPP
Eric Andersenf15d4da2001-03-06 00:48:59 +0000776};
777
"Robert P. J. Day"21302c22006-06-26 22:03:43 +0000778#ifdef CONFIG_FEATURE_IPV6
779static const struct hwtype sit_hwtype = {
780 .name = "sit",
781 .title = "IPv6-in-IPv4",
782 .type = ARPHRD_SIT,
783 .print = UNSPEC_print,
784 .suppress_null_addr = 1
785} ;
786#endif
787
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000788static const struct hwtype * const hwtypes[] = {
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000789 &loop_hwtype,
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000790 &ether_hwtype,
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000791 &ppp_hwtype,
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000792 &unspec_hwtype,
"Robert P. J. Day"21302c22006-06-26 22:03:43 +0000793#ifdef CONFIG_FEATURE_IPV6
794 &sit_hwtype,
795#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000796 NULL
Eric Andersenf15d4da2001-03-06 00:48:59 +0000797};
798
Eric Andersenf15d4da2001-03-06 00:48:59 +0000799#ifdef IFF_PORTSEL
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000800static const char * const if_port_text[] = {
801 /* Keep in step with <linux/netdevice.h> */
802 "unknown",
803 "10base2",
804 "10baseT",
805 "AUI",
806 "100baseT",
807 "100baseTX",
808 "100baseFX",
809 NULL
810};
811#endif
Eric Andersenf15d4da2001-03-06 00:48:59 +0000812
813/* Check our hardware type table for this type. */
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000814static const struct hwtype *get_hwntype(int type)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000815{
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000816 const struct hwtype * const *hwp;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000817
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000818 hwp = hwtypes;
819 while (*hwp != NULL) {
820 if ((*hwp)->type == type)
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000821 return *hwp;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000822 hwp++;
823 }
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000824 return NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000825}
826
827/* return 1 if address is all zeros */
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000828static int hw_null_address(const struct hwtype *hw, void *ap)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000829{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000830 unsigned int i;
831 unsigned char *address = (unsigned char *) ap;
832
833 for (i = 0; i < hw->alen; i++)
834 if (address[i])
835 return 0;
836 return 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000837}
838
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000839static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000840
841static void print_bytes_scaled(unsigned long long ull, const char *end)
842{
843 unsigned long long int_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000844 const char *ext;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000845 unsigned int frac_part;
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000846 int i;
847
848 frac_part = 0;
849 ext = TRext;
850 int_part = ull;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000851 i = 4;
852 do {
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000853 if (int_part >= 1024) {
854 frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
855 int_part /= 1024;
856 ext += 3; /* KiB, MiB, GiB, TiB */
857 }
858 --i;
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000859 } while (i);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000860
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +0000861 printf("X bytes:%llu (%llu.%u %sB)%s", ull, int_part, frac_part, ext, end);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000862}
863
Manuel Novoa III b1d5b742003-08-02 00:04:18 +0000864static const char * const ife_print_flags_strs[] = {
865 "UP ",
866 "BROADCAST ",
867 "DEBUG ",
868 "LOOPBACK ",
869 "POINTOPOINT ",
870 "NOTRAILERS ",
871 "RUNNING ",
872 "NOARP ",
873 "PROMISC ",
874 "ALLMULTI ",
875 "SLAVE ",
876 "MASTER ",
877 "MULTICAST ",
878#ifdef HAVE_DYNAMIC
879 "DYNAMIC "
880#endif
881};
882
883static const unsigned short ife_print_flags_mask[] = {
884 IFF_UP,
885 IFF_BROADCAST,
886 IFF_DEBUG,
887 IFF_LOOPBACK,
888 IFF_POINTOPOINT,
889 IFF_NOTRAILERS,
890 IFF_RUNNING,
891 IFF_NOARP,
892 IFF_PROMISC,
893 IFF_ALLMULTI,
894 IFF_SLAVE,
895 IFF_MASTER,
896 IFF_MULTICAST,
897#ifdef HAVE_DYNAMIC
898 IFF_DYNAMIC
899#endif
900 0
901};
902
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +0000903static void ife_print(struct interface *ptr)
Eric Andersenf15d4da2001-03-06 00:48:59 +0000904{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000905 struct aftype *ap;
"Vladimir N. Oleynik"0fa9ded2005-10-20 09:48:28 +0000906 const struct hwtype *hw;
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000907 int hf;
908 int can_compress = 0;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000909
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000910#ifdef HAVE_AFINET6
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000911 FILE *f;
912 char addr6[40], devname[20];
913 struct sockaddr_in6 sap;
914 int plen, scope, dad_status, if_idx;
915 char addr6p[8][5];
Eric Andersenf15d4da2001-03-06 00:48:59 +0000916#endif
917
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000918 ap = get_afntype(ptr->addr.sa_family);
919 if (ap == NULL)
920 ap = get_afntype(0);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000921
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000922 hf = ptr->type;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000923
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000924 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
925 can_compress = 1;
Eric Andersenf15d4da2001-03-06 00:48:59 +0000926
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000927 hw = get_hwntype(hf);
928 if (hw == NULL)
929 hw = get_hwntype(-1);
Eric Andersenf15d4da2001-03-06 00:48:59 +0000930
Rob Landley4e3aff32006-05-29 04:37:28 +0000931 printf("%-9.9s Link encap:%s ", ptr->name, hw->title);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000932 /* For some hardware types (eg Ash, ATM) we don't print the
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000933 hardware address if it's null. */
934 if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
935 hw->suppress_null_addr)))
Rob Landley4e3aff32006-05-29 04:37:28 +0000936 printf("HWaddr %s ", hw->print((unsigned char *)ptr->hwaddr));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000937#ifdef IFF_PORTSEL
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000938 if (ptr->flags & IFF_PORTSEL) {
Rob Landley4e3aff32006-05-29 04:37:28 +0000939 printf("Media:%s", if_port_text[ptr->map.port] /* [0] */);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000940 if (ptr->flags & IFF_AUTOMEDIA)
Rob Landley4e3aff32006-05-29 04:37:28 +0000941 printf("(auto)");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000942 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000943#endif
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +0000944 puts("");
Eric Andersenf15d4da2001-03-06 00:48:59 +0000945
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000946 if (ptr->has_ip) {
Rob Landley4e3aff32006-05-29 04:37:28 +0000947 printf(" %s addr:%s ", ap->name,
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000948 ap->sprint(&ptr->addr, 1));
949 if (ptr->flags & IFF_POINTOPOINT) {
Rob Landley4e3aff32006-05-29 04:37:28 +0000950 printf(" P-t-P:%s ", ap->sprint(&ptr->dstaddr, 1));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000951 }
952 if (ptr->flags & IFF_BROADCAST) {
Rob Landley4e3aff32006-05-29 04:37:28 +0000953 printf(" Bcast:%s ", ap->sprint(&ptr->broadaddr, 1));
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000954 }
Rob Landley4e3aff32006-05-29 04:37:28 +0000955 printf(" Mask:%s\n", ap->sprint(&ptr->netmask, 1));
Eric Andersenf15d4da2001-03-06 00:48:59 +0000956 }
Eric Andersenf15d4da2001-03-06 00:48:59 +0000957
Denis Vlasenkoaad49992006-11-22 02:12:07 +0000958#ifdef HAVE_AFINET6
Eric Andersenf15d4da2001-03-06 00:48:59 +0000959
Eric Andersen51b8bd62002-07-03 11:46:38 +0000960#define IPV6_ADDR_ANY 0x0000U
961
962#define IPV6_ADDR_UNICAST 0x0001U
963#define IPV6_ADDR_MULTICAST 0x0002U
964#define IPV6_ADDR_ANYCAST 0x0004U
965
966#define IPV6_ADDR_LOOPBACK 0x0010U
967#define IPV6_ADDR_LINKLOCAL 0x0020U
968#define IPV6_ADDR_SITELOCAL 0x0040U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000969
Eric Andersen51b8bd62002-07-03 11:46:38 +0000970#define IPV6_ADDR_COMPATv4 0x0080U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000971
Eric Andersen51b8bd62002-07-03 11:46:38 +0000972#define IPV6_ADDR_SCOPE_MASK 0x00f0U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000973
Eric Andersen51b8bd62002-07-03 11:46:38 +0000974#define IPV6_ADDR_MAPPED 0x1000U
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000975#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
976
977 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
978 while (fscanf
979 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
980 addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
981 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
982 &dad_status, devname) != EOF) {
983 if (!strcmp(devname, ptr->name)) {
984 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
985 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
986 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
987 inet_pton(AF_INET6, addr6,
988 (struct sockaddr *) &sap.sin6_addr);
989 sap.sin6_family = AF_INET6;
Rob Landley4e3aff32006-05-29 04:37:28 +0000990 printf(" inet6 addr: %s/%d",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000991 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
992 plen);
Rob Landley4e3aff32006-05-29 04:37:28 +0000993 printf(" Scope:");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000994 switch (scope & IPV6_ADDR_SCOPE_MASK) {
995 case 0:
Rob Landley4e3aff32006-05-29 04:37:28 +0000996 printf("Global");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +0000997 break;
998 case IPV6_ADDR_LINKLOCAL:
Rob Landley4e3aff32006-05-29 04:37:28 +0000999 printf("Link");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001000 break;
1001 case IPV6_ADDR_SITELOCAL:
Rob Landley4e3aff32006-05-29 04:37:28 +00001002 printf("Site");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001003 break;
1004 case IPV6_ADDR_COMPATv4:
Rob Landley4e3aff32006-05-29 04:37:28 +00001005 printf("Compat");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001006 break;
1007 case IPV6_ADDR_LOOPBACK:
Rob Landley4e3aff32006-05-29 04:37:28 +00001008 printf("Host");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001009 break;
1010 default:
Rob Landley4e3aff32006-05-29 04:37:28 +00001011 printf("Unknown");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001012 }
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00001013 puts("");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001014 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001015 }
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001016 fclose(f);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001017 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001018#endif
1019
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001020 printf(" ");
1021 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001022
1023 if (ptr->flags == 0) {
Rob Landley4e3aff32006-05-29 04:37:28 +00001024 printf("[NO FLAGS] ");
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001025 } else {
1026 int i = 0;
1027 do {
1028 if (ptr->flags & ife_print_flags_mask[i]) {
Rob Landley4e3aff32006-05-29 04:37:28 +00001029 printf(ife_print_flags_strs[i]);
Manuel Novoa III b1d5b742003-08-02 00:04:18 +00001030 }
1031 } while (ife_print_flags_mask[++i]);
1032 }
1033
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001034 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
Rob Landley4e3aff32006-05-29 04:37:28 +00001035 printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001036#ifdef SIOCSKEEPALIVE
1037 if (ptr->outfill || ptr->keepalive)
Rob Landley4e3aff32006-05-29 04:37:28 +00001038 printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001039#endif
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00001040 puts("");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001041
1042 /* If needed, display the interface statistics. */
1043
1044 if (ptr->statistics_valid) {
1045 /* XXX: statistics are currently only printed for the primary address,
1046 * not for the aliases, although strictly speaking they're shared
1047 * by all addresses.
1048 */
1049 printf(" ");
1050
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001051 printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001052 ptr->stats.rx_packets, ptr->stats.rx_errors,
1053 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1054 ptr->stats.rx_frame_errors);
1055 if (can_compress)
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001056 printf(" compressed:%lu\n",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001057 ptr->stats.rx_compressed);
1058 printf(" ");
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001059 printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001060 ptr->stats.tx_packets, ptr->stats.tx_errors,
1061 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
1062 ptr->stats.tx_carrier_errors);
Bernhard Reutner-Fischer214744d2006-03-30 13:38:19 +00001063 printf(" collisions:%lu ", ptr->stats.collisions);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001064 if (can_compress)
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001065 printf("compressed:%lu ", ptr->stats.tx_compressed);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001066 if (ptr->tx_queue_len != -1)
Bernhard Reutner-Fischerd409c3a2006-03-29 22:34:47 +00001067 printf("txqueuelen:%d ", ptr->tx_queue_len);
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001068 printf("\n R");
1069 print_bytes_scaled(ptr->stats.rx_bytes, " T");
1070 print_bytes_scaled(ptr->stats.tx_bytes, "\n");
1071
1072 }
1073
1074 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
1075 ptr->map.base_addr)) {
1076 printf(" ");
1077 if (ptr->map.irq)
Rob Landley4e3aff32006-05-29 04:37:28 +00001078 printf("Interrupt:%d ", ptr->map.irq);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001079 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001080 I/O maps */
Rob Landley4e3aff32006-05-29 04:37:28 +00001081 printf("Base address:0x%lx ",
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001082 (unsigned long) ptr->map.base_addr);
1083 if (ptr->map.mem_start) {
Rob Landley4e3aff32006-05-29 04:37:28 +00001084 printf("Memory:%lx-%lx ", ptr->map.mem_start,
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001085 ptr->map.mem_end);
1086 }
1087 if (ptr->map.dma)
Rob Landley4e3aff32006-05-29 04:37:28 +00001088 printf("DMA chan:%x ", ptr->map.dma);
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00001089 puts("");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001090 }
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00001091 puts("");
Eric Andersenf15d4da2001-03-06 00:48:59 +00001092}
1093
1094
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001095static int do_if_print(struct interface *ife, void *cookie)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001096{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001097 int *opt_a = (int *) cookie;
1098 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001099
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001100 res = do_if_fetch(ife);
1101 if (res >= 0) {
1102 if ((ife->flags & IFF_UP) || *opt_a)
1103 ife_print(ife);
1104 }
1105 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001106}
1107
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001108static struct interface *lookup_interface(char *name)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001109{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001110 struct interface *ife = NULL;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001111
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001112 if (if_readlist_proc(name) < 0)
1113 return NULL;
1114 ife = add_interface(name);
1115 return ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001116}
1117
1118/* for ipv4 add/del modes */
1119static int if_print(char *ifname)
1120{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001121 int res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001122
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001123 if (!ifname) {
1124 res = for_all_interfaces(do_if_print, &interface_opt_a);
1125 } else {
1126 struct interface *ife;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001127
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001128 ife = lookup_interface(ifname);
1129 res = do_if_fetch(ife);
1130 if (res >= 0)
1131 ife_print(ife);
1132 }
1133 return res;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001134}
1135
Mike Frysingerb5547fb2006-05-11 02:35:55 +00001136int display_interfaces(char *ifname);
Manuel Novoa III 68ea1d02001-03-12 09:57:59 +00001137int display_interfaces(char *ifname)
Eric Andersenf15d4da2001-03-06 00:48:59 +00001138{
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001139 int status;
Eric Andersenf15d4da2001-03-06 00:48:59 +00001140
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001141 /* Create a channel to the NET kernel. */
1142 if ((skfd = sockets_open(0)) < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00001143 bb_perror_msg_and_die("socket");
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001144 }
Eric Andersenf15d4da2001-03-06 00:48:59 +00001145
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001146 /* Do we have to show the current setup? */
1147 status = if_print(ifname);
Rob Landley93983042005-05-03 21:30:26 +00001148#ifdef CONFIG_FEATURE_CLEAN_UP
1149 sockets_close();
1150#endif
Glenn L McGrath1ed9dd92002-08-22 19:35:36 +00001151 exit(status < 0);
Eric Andersenf15d4da2001-03-06 00:48:59 +00001152}