/*
- * stolen from net-tools-1.59 and stripped down for busybox by
+ * stolen from net-tools-1.59 and stripped down for busybox by
* Erik Andersen <andersen@codepoet.org>
*
* Heavily modified by Manuel Novoa III Mar 12, 2001
* that either displays or sets the characteristics of
* one or more of the system's networking interfaces.
*
- * Version: $Id: interface.c,v 1.19 2003/08/02 00:04:18 mjn3 Exp $
+ * Version: $Id: interface.c,v 1.25 2004/08/26 21:45:21 andersen Exp $
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
* and others. Copyright 1993 MicroWalt Corporation
*
* {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - gettext instead of catgets for i18n
- * 10/1998 - Andi Kleen. Use interface list primitives.
- * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
+ * 10/1998 - Andi Kleen. Use interface list primitives.
+ * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu
* (default AF was wrong)
*/
/* #define KEEP_UNUSED */
-/*
- *
+/*
+ *
* Protocol Families.
- *
+ *
*/
#define HAVE_AFINET 1
#undef HAVE_AFIPX
#undef HAVE_AFECONET
#undef HAVE_AFASH
-#ifdef CONFIG_FEATURE_IPV6
-# define HAVE_AFINET6 1
-#else
-# undef HAVE_AFINET6
-#endif
-
-/*
- *
+/*
+ *
* Device Hardware types.
- *
+ *
*/
#define HAVE_HWETHER 1
#define HAVE_HWPPP 1
#include <net/if_arp.h>
#include "libbb.h"
+#ifdef CONFIG_FEATURE_IPV6
+# define HAVE_AFINET6 1
+#else
+# undef HAVE_AFINET6
+#endif
+
#define _(x) x
#define _PATH_PROCNET_DEV "/proc/net/dev"
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
struct in6_ifreq {
struct in6_addr ifr6_addr;
- __u32 ifr6_prefixlen;
+ uint32_t ifr6_prefixlen;
unsigned int ifr6_ifindex;
};
return sfd;
}
+#ifdef CONFIG_FEATURE_CLEAN_UP
+static void sockets_close(void)
+{
+ struct aftype **aft;
+ for (aft = aftypes; *aft != NULL; aft++) {
+ struct aftype *af = *aft;
+ if( af->fd != -1 ) {
+ close(af->fd);
+ af->fd = -1;
+ }
+ }
+}
+#endif
+
/* like strcmp(), but knows about numbers */
-static int nstrcmp(const char *astr, const char *b)
+static int nstrcmp(const char *a, const char *b)
{
- const char *a = astr;
+ const char *a_ptr = a;
+ const char *b_ptr = b;
while (*a == *b) {
- if (*a == '\0')
+ if (*a == '\0') {
return 0;
+ }
+ if (!isdigit(*a) && isdigit(*(a+1))) {
+ a_ptr = a+1;
+ b_ptr = b+1;
+ }
a++;
b++;
}
- if (isdigit(*a)) {
- if (!isdigit(*b))
- return -1;
- while (a > astr) {
- a--;
- if (!isdigit(*a)) {
- a++;
- break;
- }
- if (!isdigit(*b))
- return -1;
- b--;
- }
- return atoi(a) > atoi(b) ? 1 : -1;
+
+ if (isdigit(*a) && isdigit(*b)) {
+ return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
}
return *a - *b;
}
static char *get_name(char *name, char *p)
{
- while (isspace(*p))
- p++;
- while (*p) {
- if (isspace(*p))
- break;
- if (*p == ':') { /* could be an alias */
- char *dot = p, *dotname = name;
-
- *name++ = *p++;
- while (isdigit(*p))
- *name++ = *p++;
- if (*p != ':') { /* it wasn't, backup */
- p = dot;
- name = dotname;
- }
- if (*p == '\0')
- return NULL;
- p++;
- break;
+ /* Extract <name>[:<alias>] from nul-terminated p where p matches
+ <name>[:<alias>]: after leading whitespace.
+ If match is not made, set name empty and return unchanged p */
+ int namestart=0, nameend=0, aliasend;
+ while (isspace(p[namestart]))
+ namestart++;
+ nameend=namestart;
+ while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
+ nameend++;
+ if (p[nameend]==':') {
+ aliasend=nameend+1;
+ while (p[aliasend] && isdigit(p[aliasend]))
+ aliasend++;
+ if (p[aliasend]==':') {
+ nameend=aliasend;
}
- *name++ = *p++;
+ if ((nameend-namestart)<IFNAMSIZ) {
+ memcpy(name,&p[namestart],nameend-namestart);
+ name[nameend-namestart]='\0';
+ p=&p[nameend];
+ } else {
+ /* Interface name too large */
+ name[0]='\0';
+ }
+ } else {
+ /* first ':' not found - return empty */
+ name[0]='\0';
}
- *name++ = '\0';
- return p;
+ return p + 1;
}
/* If scanf supports size qualifiers for %n conversions, then we can
}
#endif
+#ifdef SIOCGIFMAP
strcpy(ifr.ifr_name, ifname);
- if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
- memset(&ife->map, 0, sizeof(struct ifmap));
+ if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
+ ife->map = ifr.ifr_map;
else
- memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
-
- strcpy(ifr.ifr_name, ifname);
- if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
+#endif
memset(&ife->map, 0, sizeof(struct ifmap));
- else
- ife->map = ifr.ifr_map;
#ifdef HAVE_TXQUEUELEN
strcpy(ifr.ifr_name, ifname);
#if HAVE_HWETHER
#include <net/if_arp.h>
-#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
+#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION)
#include <net/ethernet.h>
#else
#include <linux/if_ether.h>
return 1;
}
-#warning devel code
static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
static void print_bytes_scaled(unsigned long long ull, const char *end)
hw = get_hwntype(-1);
printf(_("%-9.9s Link encap:%s "), ptr->name, _(hw->title));
- /* For some hardware types (eg Ash, ATM) we don't print the
+ /* For some hardware types (eg Ash, ATM) we don't print the
hardware address if it's null. */
if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
hw->suppress_null_addr)))
printf(" ");
if (ptr->map.irq)
printf(_("Interrupt:%d "), ptr->map.irq);
- if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
+ if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
I/O maps */
printf(_("Base address:0x%lx "),
(unsigned long) ptr->map.base_addr);
/* Do we have to show the current setup? */
status = if_print(ifname);
- close(skfd);
+#ifdef CONFIG_FEATURE_CLEAN_UP
+ sockets_close();
+#endif
exit(status < 0);
}