Add in a first pass at ifconfig status reporting. It took a long while
hacking on the mess in net-tools-1.59, but it currently adds 12k and
supports ethernet, loop, ppp, and treats everything else as a generic
interface. Works ok for me.
-Erik
diff --git a/ifconfig.c b/ifconfig.c
index a3e2c0f..2a50a96 100644
--- a/ifconfig.c
+++ b/ifconfig.c
@@ -15,16 +15,19 @@
* Foundation; either version 2 of the License, or (at
* your option) any later version.
*
- * $Id: ifconfig.c,v 1.3 2001/02/20 06:14:07 andersen Exp $
+ * $Id: ifconfig.c,v 1.4 2001/03/06 00:48:59 andersen Exp $
+ *
+ * Majorly hacked up by Larry Doolittle <ldoolitt@recycle.lbl.gov>
*
*/
+#include "busybox.h"
+#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h> // strcmp and friends
#include <ctype.h> // isdigit and friends
-#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
@@ -32,10 +35,50 @@
#include <net/if.h>
#include <net/if_arp.h>
#include <linux/if_ether.h>
-#include "busybox.h"
static int sockfd; /* socket fd we use to manipulate stuff with */
+#define TESTME 0
+#if TESTME
+#define ioctl test_ioctl
+char *saddr_to_a(struct sockaddr *s)
+{
+ if (s->sa_family == ARPHRD_ETHER) {
+ static char hw[18];
+ sprintf(hw, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ s->sa_data[0], s->sa_data[1], s->sa_data[2],
+ s->sa_data[3], s->sa_data[4], s->sa_data[5]);
+ return hw;
+ } else if (s->sa_family == AF_INET) {
+ struct sockaddr_in *ss = (struct sockaddr_in *) s;
+ return inet_ntoa(ss->sin_addr);
+ } else {
+ return NULL;
+ }
+}
+
+int test_ioctl(int __fd, unsigned long int __request, void *param)
+{
+ struct ifreq *i=(struct ifreq *)param;
+ printf("ioctl fd=%d, request=%ld\n", __fd, __request);
+
+ switch(__request) {
+ case SIOCGIFFLAGS: printf(" SIOCGIFFLAGS\n"); i->ifr_flags = 0; break;
+ case SIOCSIFFLAGS: printf(" SIOCSIFFLAGS, %x\n", i->ifr_flags); break;
+ case SIOCSIFMETRIC: printf(" SIOCSIFMETRIC, %d\n", i->ifr_metric); break;
+ case SIOCSIFMTU: printf(" SIOCSIFMTU, %d\n", i->ifr_mtu); break;
+ case SIOCSIFBRDADDR: printf(" SIOCSIFBRDADDR, %s\n", saddr_to_a(&(i->ifr_broadaddr))); break;
+ case SIOCSIFDSTADDR: printf(" SIOCSIFDSTADDR, %s\n", saddr_to_a(&(i->ifr_dstaddr ))); break;
+ case SIOCSIFNETMASK: printf(" SIOCSIFNETMASK, %s\n", saddr_to_a(&(i->ifr_netmask ))); break;
+ case SIOCSIFADDR: printf(" SIOCSIFADDR, %s\n", saddr_to_a(&(i->ifr_addr ))); break;
+ case SIOCSIFHWADDR: printf(" SIOCSIFHWADDR, %s\n", saddr_to_a(&(i->ifr_hwaddr ))); break; /* broken */
+ default:
+ }
+ return 0;
+}
+#endif
+
+
/* print usage and exit */
#define _(x) x
@@ -49,7 +92,7 @@
strcpy(ifr.ifr_name, ifname);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
perror("SIOCGIFFLAGS");
- return (-1);
+ return -1;
}
strcpy(ifr.ifr_name, ifname);
ifr.ifr_flags |= flag;
@@ -57,7 +100,7 @@
perror("SIOCSIFFLAGS");
return -1;
}
- return (0);
+ return 0;
}
@@ -78,9 +121,62 @@
perror("SIOCSIFFLAGS");
return -1;
}
- return (0);
+ return 0;
}
+/* which element in struct ifreq to frob */
+enum frob {
+ L_METRIC,
+ L_MTU,
+ L_DATA,
+ L_BROAD,
+ L_DEST,
+ L_MASK,
+ L_HWAD,
+};
+
+
+struct flag_map {
+ char *name;
+ enum frob frob;
+ int flag;
+ int sflag;
+ int action;
+};
+
+/* action:
+ * 2 set
+ * 4 clear
+ * 6 set/clear
+ * 8 clear/set
+ * 10 numeric
+ * 12 address
+ * 14 address/clear
+ */
+const static struct flag_map flag_table[] = {
+ {"arp", 0, IFF_NOARP, 0, 6},
+ {"trailers", 0, IFF_NOTRAILERS, 0, 6},
+ {"promisc", 0, IFF_PROMISC, 0, 8},
+ {"multicast", 0, IFF_MULTICAST, 0, 8},
+ {"allmulti", 0, IFF_ALLMULTI, 0, 8},
+ {"up", 0, (IFF_UP | IFF_RUNNING), 0, 2},
+ {"down", 0, IFF_UP, 0, 4},
+ {"metric", L_METRIC, 0, SIOCSIFMETRIC, 10},
+ {"mtu", L_MTU, 0, SIOCSIFMTU, 10},
+#ifdef SIOCSKEEPALIVE
+ {"keepalive", L_DATA, 0, SIOCSKEEPALIVE, 10},
+#endif
+#ifdef SIOCSOUTFILL
+ {"outfill", L_DATA, 0, SIOCSOUTFILL, 10},
+#endif
+ {"broadcast", L_BROAD, IFF_BROADCAST, SIOCSIFBRDADDR, 14},
+ {"dstaddr", L_DEST, 0, SIOCSIFDSTADDR, 12},
+ {"netmask", L_MASK, 0, SIOCSIFNETMASK, 12},
+ {"pointopoint", L_DEST, IFF_POINTOPOINT, SIOCSIFDSTADDR, 14},
+ {"hw", L_HWAD, 0, SIOCSIFHWADDR, 14},
+};
+
+
/* resolve XXX.YYY.ZZZ.QQQ -> binary */
static int
@@ -90,15 +186,16 @@
sin->sin_port = 0;
/* Default is special, meaning 0.0.0.0. */
- if (!strcmp(name, "default")) {
+ if (strcmp(name, "default")==0) {
sin->sin_addr.s_addr = INADDR_ANY;
- return (1);
+ return 1;
}
/* Look to see if it's a dotted quad. */
if (inet_aton(name, &sin->sin_addr)) {
return 0;
}
/* guess not.. */
+ errno = EINVAL;
return -1;
}
@@ -127,12 +224,12 @@
val = c - 'A' + 10;
else {
#ifdef DEBUG
- fprintf(stderr,
- _("in_ether(%s): invalid ether address!\n"),
+ error_msg(
+ _("in_ether(%s): invalid ether address!"),
orig);
#endif
errno = EINVAL;
- return (-1);
+ return -1;
}
val <<= 4;
c = *bufp;
@@ -146,22 +243,19 @@
val >>= 4;
else {
#ifdef DEBUG
- fprintf(stderr,
- _("in_ether(%s): invalid ether address!\n"),
+ error_msg(
+ _("in_ether(%s): invalid ether address!"),
orig);
#endif
errno = EINVAL;
- return (-1);
+ return -1;
}
if (c != 0)
bufp++;
*ptr++ = (unsigned char) (val & 0377);
i++;
- /* We might get a semicolon here - not required. */
- if (*bufp == ':')
- bufp++;
-
+ /* optional colon already handled, don't swallow a second */
}
if(i != ETH_ALEN) {
@@ -171,25 +265,37 @@
return 0;
}
+
+#ifdef BB_FEATURE_IFCONFIG_STATUS
+extern int display_interfaces(void);
+#else
+int display_interfaces(void)
+{
+ show_usage();
+}
+#endif
int ifconfig_main(int argc, char **argv)
{
struct ifreq ifr;
struct sockaddr_in sa;
- struct sockaddr sa2;
- char **spp;
+ char **spp, *cmd;
int goterr = 0;
- int r, didnetmask = 0;
+ int r;
+ /* int didnetmask = 0; special case input error detection no longer implemented */
char host[128];
+ const struct flag_map *ft;
+ int i, sense;
+ int a, ecode;
+ struct sockaddr *d;
if(argc < 2) {
- show_usage();
+ return(display_interfaces());
}
/* Create a channel to the NET kernel. */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- perror("socket");
- exit(1);
+ perror_msg_and_die("socket");
}
/* skip argv[0] */
@@ -205,235 +311,84 @@
/* Process the remaining arguments. */
while (*spp != (char *) NULL) {
- if (!strcmp(*spp, "arp")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_NOARP);
- spp++;
- continue;
+ cmd = *spp;
+ sense=0;
+ if (*cmd=='-') {
+ sense=1;
+ cmd++;
}
- if (!strcmp(*spp, "-arp")) {
- goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
- spp++;
+ ft = NULL;
+ for (i=0; i<(sizeof(flag_table)/sizeof(struct flag_map)); i++) {
+ if (strcmp(cmd, flag_table[i].name)==0) {
+ ft=flag_table+i;
+ spp++;
+ break;
+ }
+ }
+ if (ft) {
+ switch (ft->action+sense) {
+ case 4:
+ case 7:
+ case 8:
+ case 15:
+ goterr |= clr_flag(ifr.ifr_name, ft->flag);
+ break;
+ case 2:
+ case 6:
+ case 9:
+ goterr |= set_flag(ifr.ifr_name, ft->flag);
+ break;
+ case 10:
+ if (*spp == NULL)
+ show_usage();
+ a = atoi(*spp++);
+ switch (ft->frob) {
+ case L_METRIC: ifr.ifr_metric = a; break;
+ case L_MTU: ifr.ifr_mtu = a; break;
+ case L_DATA: ifr.ifr_data = (caddr_t) a; break;
+ default: error_msg_and_die("bugaboo");
+ }
+
+ if (ioctl(sockfd, ft->sflag, &ifr) < 0) {
+ perror(ft->name); /* imperfect */
+ goterr++;
+ }
+ break;
+ case 12:
+ case 14:
+ if (ft->action+sense==10 && *spp == NULL) {
+ show_usage();
+ break;
+ }
+ if (*spp != NULL) {
+ safe_strncpy(host, *spp, (sizeof host));
+ spp++;
+ if (ft->frob == L_HWAD) {
+ ecode = in_ether(host, &ifr.ifr_hwaddr);
+ } else {
+ switch (ft->frob) {
+ case L_BROAD: d = &ifr.ifr_broadaddr; break;
+ case L_DEST: d = &ifr.ifr_dstaddr; break;
+ case L_MASK: d = &ifr.ifr_netmask; break;
+ default: error_msg_and_die("bugaboo");
+ }
+ ecode = INET_resolve(host, (struct sockaddr_in *) d);
+ }
+ if (ecode < 0 || ioctl(sockfd, ft->sflag, &ifr) < 0) {
+ perror(ft->name); /* imperfect */
+ goterr++;
+ }
+ }
+ if (ft->flag != 0) {
+ goterr |= set_flag(ifr.ifr_name, ft->flag);
+ }
+ break;
+ default:
+ show_usage();
+ } /* end of switch */
continue;
}
- if (!strcmp(*spp, "trailers")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "-trailers")) {
- goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "promisc")) {
- goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "-promisc")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "multicast")) {
- goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "-multicast")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "allmulti")) {
- goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "-allmulti")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "up")) {
- goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
- spp++;
- continue;
- }
- if (!strcmp(*spp, "down")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_UP);
- spp++;
- continue;
- }
-
- if (!strcmp(*spp, "metric")) {
- if (*++spp == NULL)
- show_usage();
- ifr.ifr_metric = atoi(*spp);
- if (ioctl(sockfd, SIOCSIFMETRIC, &ifr) < 0) {
- fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
- goterr++;
- }
- spp++;
- continue;
- }
- if (!strcmp(*spp, "mtu")) {
- if (*++spp == NULL)
- show_usage();
- ifr.ifr_mtu = atoi(*spp);
- if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
- fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
- goterr++;
- }
- spp++;
- continue;
- }
-#ifdef SIOCSKEEPALIVE
- if (!strcmp(*spp, "keepalive")) {
- if (*++spp == NULL)
- show_usage();
- ifr.ifr_data = (caddr_t) atoi(*spp);
- if (ioctl(sockfd, SIOCSKEEPALIVE, &ifr) < 0) {
- fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno));
- goterr++;
- }
- spp++;
- continue;
- }
-#endif
-
-#ifdef SIOCSOUTFILL
- if (!strcmp(*spp, "outfill")) {
- if (*++spp == NULL)
- show_usage();
- ifr.ifr_data = (caddr_t) atoi(*spp);
- if (ioctl(sockfd, SIOCSOUTFILL, &ifr) < 0) {
- fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno));
- goterr++;
- }
- spp++;
- continue;
- }
-#endif
-
- if (!strcmp(*spp, "-broadcast")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "broadcast")) {
- if (*++spp != NULL) {
- safe_strncpy(host, *spp, (sizeof host));
- if (INET_resolve(host, &sa) < 0) {
- goterr++;
- spp++;
- continue;
- }
- memcpy((char *) &ifr.ifr_broadaddr,
- (char *) &sa,
- sizeof(struct sockaddr));
- if (ioctl(sockfd, SIOCSIFBRDADDR, &ifr) < 0) {
- perror("SIOCSIFBRDADDR");
- goterr++;
- }
- spp++;
- }
- goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
- continue;
- }
- if (!strcmp(*spp, "dstaddr")) {
- if (*++spp == NULL)
- show_usage();
- safe_strncpy(host, *spp, (sizeof host));
- if (INET_resolve(host, &sa) < 0) {
- goterr++;
- spp++;
- continue;
- }
- memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
- sizeof(struct sockaddr));
- if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
- fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
- strerror(errno));
- goterr++;
- }
- spp++;
- continue;
- }
- if (!strcmp(*spp, "netmask")) {
- if (*++spp == NULL || didnetmask)
- show_usage();
- safe_strncpy(host, *spp, (sizeof host));
- if (INET_resolve(host, &sa) < 0) {
- goterr++;
- spp++;
- continue;
- }
- didnetmask++;
- memcpy((char *) &ifr.ifr_netmask, (char *) &sa,
- sizeof(struct sockaddr));
- if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
- perror("SIOCSIFNETMASK");
- goterr++;
- }
- spp++;
- continue;
- }
-
- if (!strcmp(*spp, "-pointopoint")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
- spp++;
- continue;
- }
- if (!strcmp(*spp, "pointopoint")) {
- if (*(spp + 1) != NULL) {
- spp++;
- safe_strncpy(host, *spp, (sizeof host));
- if (INET_resolve(host, &sa)) {
- goterr++;
- spp++;
- continue;
- }
- memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
- sizeof(struct sockaddr));
- if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
- perror("SIOCSIFDSTADDR");
- goterr++;
- }
- }
- goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT);
- spp++;
- continue;
- };
-
- if (!strcmp(*spp, "hw")) {
- if (*++spp == NULL || strcmp("ether", *spp)) {
- show_usage();
- }
-
- if (*++spp == NULL) {
- /* silently ignore it if no address */
- continue;
- }
-
- safe_strncpy(host, *spp, (sizeof host));
- if (in_ether(host, &sa2) < 0) {
- fprintf(stderr, "invalid hw-addr %s\n", host);
- goterr++;
- spp++;
- continue;
- }
- memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa2,
- sizeof(struct sockaddr));
- if (ioctl(sockfd, SIOCSIFHWADDR, &ifr) < 0) {
- perror("SIOCSIFHWADDR");
- goterr++;
- }
- spp++;
- continue;
- }
-
/* If the next argument is a valid hostname, assume OK. */
safe_strncpy(host, *spp, (sizeof host));
@@ -471,6 +426,6 @@
} /* end of while-loop */
- exit(0);
+ return goterr;
}