aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/ifconfig.c186
1 files changed, 75 insertions, 111 deletions
diff --git a/toys/pending/ifconfig.c b/toys/pending/ifconfig.c
index 92002921..cffeaf58 100644
--- a/toys/pending/ifconfig.c
+++ b/toys/pending/ifconfig.c
@@ -52,7 +52,7 @@ typedef struct sockaddr_with_len {
struct if_list {
struct if_list *next;
int hw_type, mtu, metric, txqueuelen, non_virtual_iface;
- short flags, hasaddr;
+ short flags;
struct sockaddr addr, dstaddr, broadaddr, netmask, hwaddr;
struct ifmap map;
@@ -195,15 +195,6 @@ char *address_to_name(struct sockaddr *sock)
} else return NULL;
}
-static void set_flags(int sockfd, struct ifreq *ifre, int set_flag,
- int reset_flag)
-{
- xioctl(sockfd, SIOCGIFFLAGS, ifre);
- ifre->ifr_flags &= ~reset_flag;
- ifre->ifr_flags |= set_flag;
- xioctl(sockfd, SIOCSIFFLAGS, ifre);
-}
-
static void set_ipv6_addr(int sockfd, struct ifreq *ifre, char *ipv6_addr, int request)
{
char *prefix;
@@ -279,43 +270,29 @@ static void get_device_info(struct if_list *il)
char *name = il->name;
int sokfd;
+ il->txqueuelen = -1;
+
sokfd = xsocket(AF_INET, SOCK_DGRAM, 0);
xstrncpy(ifre.ifr_name, name, IFNAMSIZ);
- if(ioctl(sokfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name);
+ if (ioctl(sokfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name);
il->flags = ifre.ifr_flags;
- if(ioctl(sokfd, SIOCGIFHWADDR, &ifre) >= 0)
+ if (ioctl(sokfd, SIOCGIFHWADDR, &ifre) >= 0)
memcpy(il->hwaddr.sa_data, ifre.ifr_hwaddr.sa_data, sizeof(il->hwaddr.sa_data));
-
il->hw_type = ifre.ifr_hwaddr.sa_family;
- if(ioctl(sokfd, SIOCGIFMETRIC, &ifre) >= 0)
- il->metric = ifre.ifr_metric;
-
- if(ioctl(sokfd, SIOCGIFMTU, &ifre) >= 0)
- il->mtu = ifre.ifr_mtu;
+ if (ioctl(sokfd, SIOCGIFMETRIC, &ifre) >= 0) il->metric = ifre.ifr_metric;
+ if (ioctl(sokfd, SIOCGIFMTU, &ifre) >= 0) il->mtu = ifre.ifr_mtu;
+ if (ioctl(sokfd, SIOCGIFMAP, &ifre) == 0) il->map = ifre.ifr_map;
+ if (ioctl(sokfd, SIOCGIFTXQLEN, &ifre) >= 0) il->txqueuelen = ifre.ifr_qlen;
- if(ioctl(sokfd, SIOCGIFMAP, &ifre) == 0)
- il->map = ifre.ifr_map;
-
- il->txqueuelen = -1;
- if(ioctl(sokfd, SIOCGIFTXQLEN, &ifre) >= 0)
- il->txqueuelen = ifre.ifr_qlen;
+ // If an address is assigned record that.
ifre.ifr_addr.sa_family = AF_INET;
-
- if(!ioctl(sokfd, SIOCGIFADDR, &ifre)) {
- il->hasaddr = 1;
- il->addr = ifre.ifr_addr;
- if(ioctl(sokfd, SIOCGIFDSTADDR, &ifre) >= 0)
- il->dstaddr = ifre.ifr_dstaddr;
-
- if(ioctl(sokfd, SIOCGIFBRDADDR, &ifre) >= 0)
- il->broadaddr = ifre.ifr_broadaddr;
-
- if(ioctl(sokfd, SIOCGIFNETMASK, &ifre) >= 0)
- il->netmask = ifre.ifr_netmask;
- }
+ if (!ioctl(sokfd, SIOCGIFADDR, &ifre)) il->addr = ifre.ifr_addr;
+ if (ioctl(sokfd, SIOCGIFDSTADDR, &ifre) >= 0) il->dstaddr = ifre.ifr_dstaddr;
+ if (ioctl(sokfd, SIOCGIFBRDADDR, &ifre) >= 0) il->broadaddr = ifre.ifr_broadaddr;
+ if (ioctl(sokfd, SIOCGIFNETMASK, &ifre) >= 0) il->netmask = ifre.ifr_netmask;
close(sokfd);
}
@@ -376,6 +353,7 @@ static void display_ifconfig(struct if_list *il)
{ARPHRD_SIT, "IPv6-in-IPv4"}, {-1, "UNSPEC"}
};
int i;
+ char *p;
for (i=0; i < (sizeof(types)/sizeof(*types))-1; i++)
if (il->hw_type == types[i].type) break;
@@ -387,7 +365,9 @@ static void display_ifconfig(struct if_list *il)
}
xputc('\n');
- if(il->hasaddr) {
+ p = (char *)&il->addr;
+ for (i = 0; i<sizeof(il->addr); i++) if (p[i]) break;
+ if (i != sizeof(il->addr)) {
int af = il->addr.sa_family;
struct {
char *name;
@@ -467,39 +447,33 @@ static void display_ifconfig(struct if_list *il)
static void readconf(void)
{
- int num_of_req = 30;
struct ifconf ifcon;
struct ifreq *ifre;
int num, sokfd;
+ sokfd = xsocket(AF_INET, SOCK_DGRAM, 0);
+
+ // Loop until buffer's big enough
ifcon.ifc_buf = NULL;
- sokfd = socket(AF_INET, SOCK_DGRAM, 0);
- if(sokfd < 0) perror_exit("socket");
- for (;;) {
- ifcon.ifc_len = sizeof(struct ifreq) * num_of_req; //Size of buffer.
+ for (num = 30;;num += 10) {
+ ifcon.ifc_len = sizeof(struct ifreq)*num;
ifcon.ifc_buf = xrealloc(ifcon.ifc_buf, ifcon.ifc_len);
-
xioctl(sokfd, SIOCGIFCONF, &ifcon);
- //in case of overflow, increase number of requests and retry.
- if (ifcon.ifc_len == (int)(sizeof(struct ifreq) * num_of_req)) {
- num_of_req += 10;
- continue;
- }
- break;
+ if (ifcon.ifc_len != sizeof(struct ifreq)*num) break;
}
ifre = ifcon.ifc_req;
- for(num = 0; num < ifcon.ifc_len && ifre; num += sizeof(struct ifreq), ifre++) {
- //Escape duplicate values from the list.
+ for(num = 0; num < ifcon.ifc_len && ifre; num += sizeof(struct ifreq), ifre++)
+ {
struct if_list *il;
+ // Skip duplicates
for(il = TT.if_list; il; il = il->next)
if(!strcmp(ifre->ifr_name, il->name)) break;
if(!il) {
il = xzalloc(sizeof(struct if_list));
xstrncpy(il->name, ifre->ifr_name, IFNAMSIZ);
add_iface_to_list(il);
- errno = 0;
get_device_info(il);
}
}
@@ -538,7 +512,7 @@ static void show_iface(char *iface_name)
}
fclose(fp);
- if(iface_name) {
+ if (iface_name) {
for(il = TT.if_list; il; il = il->next) {
if(!strcmp(il->name, iface_name)) {
display_ifconfig(il);
@@ -564,6 +538,9 @@ static void show_iface(char *iface_name)
if (CFG_TOYBOX_FREE) llist_traverse(TT.if_list, free);
}
+// Encode offset and size of field into an int, and make result negative
+#define IFREQ_OFFSZ(x) -(int)((offsetof(struct ifreq, x)<<16) + sizeof(ifre.x))
+
void ifconfig_main(void)
{
char **argv = toys.optargs;
@@ -577,11 +554,12 @@ void ifconfig_main(void)
return;
}
- //get interface name
+ // Open interface
memset(&ifre, 0, sizeof(struct ifreq));
xstrncpy(ifre.ifr_name, *argv, IFNAMSIZ);
sockfd = xsocket(AF_INET, SOCK_DGRAM, 0);
+ // Perform operations on interface
while(*++argv) {
struct argh {
char *name;
@@ -598,7 +576,17 @@ void ifconfig_main(void)
{"pointopoint", IFF_POINTOPOINT, SIOCSIFDSTADDR},
{"broadcast", IFF_BROADCAST, SIOCSIFBRDADDR},
{"netmask", 0, SIOCSIFNETMASK},
- {"dstaddr", 0, SIOCSIFDSTADDR}
+ {"dstaddr", 0, SIOCSIFDSTADDR},
+ {"mtu", IFREQ_OFFSZ(ifr_mtu), SIOCSIFMTU},
+ {"keepalive", IFREQ_OFFSZ(ifr_data), SIOCSKEEPALIVE},
+ {"outfill", IFREQ_OFFSZ(ifr_data), SIOCSOUTFILL},
+ {"metric", IFREQ_OFFSZ(ifr_metric), SIOCSIFMETRIC},
+ {"txqueuelen", IFREQ_OFFSZ(ifr_qlen), SIOCSIFTXQLEN},
+ {"mem_start", IFREQ_OFFSZ(ifr_map.mem_start), SIOCSIFMAP},
+ {"io_addr", IFREQ_OFFSZ(ifr_map.base_addr), SIOCSIFMAP},
+ {"irq", IFREQ_OFFSZ(ifr_map.irq), SIOCSIFMAP},
+ {"inet", 0, 0},
+ {"inet6", 0, 0}
};
char *s = *argv;
int rev = (*s == '-');
@@ -612,13 +600,25 @@ void ifconfig_main(void)
if (strcmp(t->name, s)) continue;
// Is this an SIOCSI entry?
- if ((t->off | 0xff) == 0x89ff) {
+ if ((off|0xff) == 0x89ff) {
if (!rev) {
if (!*++argv) show_help();
- set_address(sockfd, *argv, &ifre, off);
+
+ // Assign value to ifre field and call ioctl? (via IFREQ_OFFSZ.)
+ if (on < 0) {
+ long l = strtoul(*argv, 0, 0);
+
+ if (off == SIOCSIFMAP) xioctl(sockfd, SIOCGIFMAP, &ifre);
+ on = -on;
+ poke((on>>16) + (char *)&ifre, l, on&15);
+ xioctl(sockfd, off, &ifre);
+ break;
+ } else set_address(sockfd, *argv, &ifre, off);
}
off = 0;
}
+
+ // Set flags
if (on || off) {
xioctl(sockfd, SIOCGIFFLAGS, &ifre);
ifre.ifr_flags &= ~(rev ? on : off);
@@ -663,62 +663,26 @@ void ifconfig_main(void)
if ((p-ptr) != count || *hw_addr)
error_exit("bad hw-addr '%s'", hw_addr ? hw_addr : "");
xioctl(sockfd, SIOCSIFHWADDR, &ifre);
- } else if (!strcmp(*argv, "mtu")) {
- if (!*++argv) show_help();
- ifre.ifr_mtu = strtoul(*argv, NULL, 0);
- xioctl(sockfd, SIOCSIFMTU, &ifre);
- } else if (!strcmp(*argv, "keepalive")) {
- if (!*++argv) show_help();
- ifre.ifr_data = (void *)strtoul(*argv, 0, 0);
- xioctl(sockfd, SIOCSKEEPALIVE, &ifre);
- } else if (!strcmp(*argv, "outfill")) {
- if (!*++argv) show_help();
- ifre.ifr_data = (void *)strtoul(*argv, 0, 0);
- xioctl(sockfd, SIOCSOUTFILL, &ifre);
- } else if (!strcmp(*argv, "metric")) {
- if (!*++argv) show_help();
- ifre.ifr_metric = strtoul(*argv, NULL, 0);
- xioctl(sockfd, SIOCSIFMETRIC, &ifre);
- } else if (!strcmp(*argv, "txqueuelen")) {
- if (!*++argv) show_help();
- ifre.ifr_qlen = strtoul(*argv, NULL, 0);
- xioctl(sockfd, SIOCSIFTXQLEN, &ifre);
- } else if (!strcmp(*argv, "add")) {
- if (!*++argv) show_help();
- set_ipv6_addr(sockfd, &ifre, *argv, SIOCSIFADDR);
- } else if (!strcmp(*argv, "del")) {
- if (!*++argv) show_help();
- set_ipv6_addr(sockfd, &ifre, *argv, SIOCDIFADDR);
- } else if (!strcmp(*argv, "mem_start")) {
- if (!*++argv) show_help();
- xioctl(sockfd, SIOCGIFMAP, &ifre);
- ifre.ifr_map.mem_start = strtoul(*argv, NULL, 0);
- xioctl(sockfd, SIOCSIFMAP, &ifre);
- } else if (!strcmp(*argv, "io_addr")) {
- if (!*++argv) show_help();
- xioctl(sockfd, SIOCGIFMAP, &ifre);
- ifre.ifr_map.base_addr = strtoul(*argv, NULL, 0);
- xioctl(sockfd, SIOCSIFMAP, &ifre);
- } else if (!strcmp(*argv, "irq")) {
- if (!*++argv) show_help();
- xioctl(sockfd, SIOCGIFMAP, &ifre);
- ifre.ifr_map.irq = strtoul(*argv, NULL, 0);
- xioctl(sockfd, SIOCSIFMAP, &ifre);
- } else {
- if (isdigit(**argv) || !strcmp(*argv, "default")) {
+ } else if (!strcmp(*argv, "add") || !strcmp(*argv, "del")) {
+ if (!argv[1]) show_help();
+ set_ipv6_addr(sockfd, &ifre, argv[1],
+ **argv=='a' ? SIOCSIFADDR : SIOCDIFADDR);
+ argv++;
+ } else if (isdigit(**argv) || !strcmp(*argv, "default")) {
set_address(sockfd, *argv, &ifre, SIOCSIFADDR);
//if the interface name is not an alias; set the flag and continue.
- if(!strchr(ifre.ifr_name, ':'))
- set_flags(sockfd, &ifre, IFF_UP | IFF_RUNNING, 0);
- } else if (!strcmp(*argv, "inet") || !strcmp(*argv, "inet6")) continue;
- else {
- errno = EINVAL;
- toys.exithelp++;
- error_exit("bad argument '%s'", *argv);
- }
- }
+ if(!strchr(ifre.ifr_name, ':')) {
+ xioctl(sockfd, SIOCGIFFLAGS, &ifre);
+ ifre.ifr_flags |= IFF_UP|IFF_RUNNING;
+ xioctl(sockfd, SIOCSIFFLAGS, &ifre);
+ }
+ } else {
+ errno = EINVAL;
+ toys.exithelp++;
+ error_exit("bad argument '%s'", *argv);
}
- if(sockfd > 0) close(sockfd);
+ }
+ if (CFG_TOYBOX_FREE && sockfd > 0) close(sockfd);
}