X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fifconfig.c;h=5742399c5b460b6125513b4b860b33946305c94d;hb=b51fd3525e48c79ef9e854dd357a9cdfdfeef72b;hp=4e3df2982cfa7e57a8a943de4b5b1d16cb68c913;hpb=c11a6a887b82e4c1f51e18499b06c0d745771ab0;p=oweals%2Fbusybox.git diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 4e3df2982..5742399c5 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c @@ -1,3 +1,4 @@ +/* vi: set sw=4 ts=4: */ /* ifconfig * * Similar to the standard Unix ifconfig, but with only the necessary @@ -9,14 +10,7 @@ * Authors of the original ifconfig was: * Fred N. van Kempen, * - * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU General - * Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * $Id: ifconfig.c,v 1.30 2004/03/31 11:30:08 andersen Exp $ - * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ /* @@ -32,27 +26,20 @@ * IPV6 support added by Bart Visscher */ -#include -#include -#include /* strcmp and friends */ -#include /* isdigit and friends */ -#include /* offsetof */ -#include -#include #include #include #include -#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 +#if defined(__GLIBC__) && __GLIBC__ >=2 && __GLIBC_MINOR__ >= 1 #include #include #else -#include -#include +#include +#include #endif #include "inet_common.h" -#include "busybox.h" +#include "libbb.h" -#ifdef CONFIG_FEATURE_IFCONFIG_SLIP +#if ENABLE_FEATURE_IFCONFIG_SLIP # include #endif @@ -75,7 +62,7 @@ # define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ #endif -#ifdef CONFIG_FEATURE_IPV6 +#if ENABLE_FEATURE_IPV6 struct in6_ifreq { struct in6_addr ifr6_addr; uint32_t ifr6_prefixlen; @@ -126,7 +113,7 @@ struct in6_ifreq { #define A_NETMASK 0x20 /* Set if netmask (check for multiple sets). */ #define A_SET_AFTER 0x40 /* Set a flag at the end. */ #define A_COLON_CHK 0x80 /* Is this needed? See below. */ -#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS +#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS #define A_HOSTNAME 0x100 /* Set if it is ip addr. */ #define A_BROADCAST 0x200 /* Set if it is broadcast addr. */ #else @@ -177,13 +164,13 @@ struct in6_ifreq { struct arg1opt { const char *name; - unsigned short selector; + int selector; unsigned short ifr_offset; }; struct options { const char *name; -#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS +#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS const unsigned int flags:6; const unsigned int arg_flags:10; #else @@ -202,7 +189,7 @@ static const struct arg1opt Arg1Opt[] = { {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)}, {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)}, -#ifdef CONFIG_FEATURE_IFCONFIG_HW +#if ENABLE_FEATURE_IFCONFIG_HW {"SIOCSIFHWADDR", SIOCSIFHWADDR, ifreq_offsetof(ifr_hwaddr)}, #endif {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, @@ -212,13 +199,13 @@ static const struct arg1opt Arg1Opt[] = { #ifdef SIOCSOUTFILL {"SIOCSOUTFILL", SIOCSOUTFILL, ifreq_offsetof(ifr_data)}, #endif -#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#if ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.mem_start)}, {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr)}, {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq)}, #endif /* Last entry if for unmatched (possibly hostname) arg. */ -#ifdef CONFIG_FEATURE_IPV6 +#if ENABLE_FEATURE_IPV6 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */ {"SIOCDIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */ #endif @@ -232,7 +219,7 @@ static const struct options OptArray[] = { {"dstaddr", N_ARG, ARG_DSTADDR, 0}, {"netmask", N_ARG, ARG_NETMASK, 0}, {"broadcast", N_ARG | M_CLR, ARG_BROADCAST, IFF_BROADCAST}, -#ifdef CONFIG_FEATURE_IFCONFIG_HW +#if ENABLE_FEATURE_IFCONFIG_HW {"hw", N_ARG, ARG_HW, 0}, #endif {"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT}, @@ -242,12 +229,12 @@ static const struct options OptArray[] = { #ifdef SIOCSOUTFILL {"outfill", N_ARG, ARG_OUTFILL, 0}, #endif -#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#if ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ {"mem_start", N_ARG, ARG_MEM_START, 0}, {"io_addr", N_ARG, ARG_IO_ADDR, 0}, {"irq", N_ARG, ARG_IRQ, 0}, #endif -#ifdef CONFIG_FEATURE_IPV6 +#if ENABLE_FEATURE_IPV6 {"add", N_ARG, ARG_ADD_DEL, 0}, {"del", N_ARG, ARG_ADD_DEL, 0}, #endif @@ -266,35 +253,27 @@ static const struct options OptArray[] = { * A couple of prototypes. */ -#ifdef CONFIG_FEATURE_IFCONFIG_HW -static int in_ether(char *bufp, struct sockaddr *sap); -#endif - -#ifdef CONFIG_FEATURE_IFCONFIG_STATUS -extern int interface_opt_a; -extern int display_interfaces(char *ifname); +#if ENABLE_FEATURE_IFCONFIG_HW +static int in_ether(const char *bufp, struct sockaddr *sap); #endif /* * Our main function. */ +int ifconfig_main(int argc, char **argv); int ifconfig_main(int argc, char **argv) { struct ifreq ifr; struct sockaddr_in sai; -#ifdef CONFIG_FEATURE_IPV6 - struct sockaddr_in6 sai6; -#endif -#ifdef CONFIG_FEATURE_IFCONFIG_HW +#if ENABLE_FEATURE_IFCONFIG_HW struct sockaddr sa; #endif const struct arg1opt *a1op; const struct options *op; int sockfd; /* socket fd we use to manipulate stuff with */ - int goterr; int selector; -#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS +#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS unsigned int mask; unsigned int did_flags; unsigned int sai_hostname, sai_netmask; @@ -303,11 +282,11 @@ int ifconfig_main(int argc, char **argv) unsigned char did_flags; #endif char *p; - char host[128]; + /*char host[128];*/ + const char *host = NULL; /* make gcc happy */ - goterr = 0; did_flags = 0; -#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS +#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS sai_hostname = 0; sai_netmask = 0; #endif @@ -316,8 +295,8 @@ int ifconfig_main(int argc, char **argv) ++argv; --argc; -#ifdef CONFIG_FEATURE_IFCONFIG_STATUS - if ((argc > 0) && (((*argv)[0] == '-') && ((*argv)[1] == 'a') && !(*argv)[2])) { +#if ENABLE_FEATURE_IFCONFIG_STATUS + if (argc > 0 && (argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2])) { interface_opt_a = 1; --argc; ++argv; @@ -325,18 +304,15 @@ int ifconfig_main(int argc, char **argv) #endif if (argc <= 1) { -#ifdef CONFIG_FEATURE_IFCONFIG_STATUS +#if ENABLE_FEATURE_IFCONFIG_STATUS return display_interfaces(argc ? *argv : NULL); #else - bb_error_msg_and_die - ("ifconfig was not compiled with interface status display support."); + bb_error_msg_and_die("no support for status display"); #endif } /* Create a channel to the NET kernel. */ - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - bb_perror_msg_and_die("socket"); - } + sockfd = xsocket(AF_INET, SOCK_DGRAM, 0); /* get interface name */ safe_strncpy(ifr.ifr_name, *argv, IFNAMSIZ); @@ -351,13 +327,12 @@ int ifconfig_main(int argc, char **argv) } for (op = OptArray; op->name; op++) { /* Find table entry. */ if (strcmp(p, op->name) == 0) { /* If name matches... */ - if ((mask &= op->flags)) { /* set the mask and go. */ - goto FOUND_ARG;; - } + mask &= op->flags; + if (mask) /* set the mask and go. */ + goto FOUND_ARG; /* If we get here, there was a valid arg with an */ /* invalid '-' prefix. */ - ++goterr; - goto LOOP; + bb_error_msg_and_die("bad: '%s'", p-1); } } @@ -366,206 +341,172 @@ int ifconfig_main(int argc, char **argv) mask = op->arg_flags; goto HOSTNAME; - FOUND_ARG: + FOUND_ARG: if (mask & ARG_MASK) { mask = op->arg_flags; a1op = Arg1Opt + (op - OptArray); - if (mask & A_NETMASK & did_flags) { + if (mask & A_NETMASK & did_flags) bb_show_usage(); - } if (*++argv == NULL) { - if (mask & A_ARG_REQ) { + if (mask & A_ARG_REQ) bb_show_usage(); - } else { - --argv; - mask &= A_SET_AFTER; /* just for broadcast */ - } + --argv; + mask &= A_SET_AFTER; /* just for broadcast */ } else { /* got an arg so process it */ - HOSTNAME: + HOSTNAME: did_flags |= (mask & (A_NETMASK|A_HOSTNAME)); if (mask & A_CAST_HOST_COPY) { -#ifdef CONFIG_FEATURE_IFCONFIG_HW +#if ENABLE_FEATURE_IFCONFIG_HW if (mask & A_CAST_RESOLVE) { #endif -#ifdef CONFIG_FEATURE_IPV6 +#if ENABLE_FEATURE_IPV6 char *prefix; int prefix_len = 0; #endif - - safe_strncpy(host, *argv, (sizeof host)); -#ifdef CONFIG_FEATURE_IPV6 - if ((prefix = strchr(host, '/'))) { - if (safe_strtoi(prefix + 1, &prefix_len) || - (prefix_len < 0) || (prefix_len > 128)) - { - ++goterr; - goto LOOP; - } - *prefix = 0; + /*safe_strncpy(host, *argv, (sizeof host));*/ + host = *argv; +#if ENABLE_FEATURE_IPV6 + prefix = strchr(host, '/'); + if (prefix) { + prefix_len = xatou_range(prefix + 1, 0, 128); + *prefix = '\0'; } #endif - sai.sin_family = AF_INET; sai.sin_port = 0; - if (!strcmp(host, bb_INET_default)) { + if (!strcmp(host, bb_str_default)) { /* Default is special, meaning 0.0.0.0. */ sai.sin_addr.s_addr = INADDR_ANY; -#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS - } else if (((host[0] == '+') && !host[1]) && (mask & A_BROADCAST) && - (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)) { + } +#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS + else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST) + && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME) + ) { /* + is special, meaning broadcast is derived. */ sai.sin_addr.s_addr = (~sai_netmask) | (sai_hostname & sai_netmask); + } #endif -#ifdef CONFIG_FEATURE_IPV6 - } else if (inet_pton(AF_INET6, host, &sai6.sin6_addr) > 0) { - int sockfd6; - struct in6_ifreq ifr6; - - memcpy((char *) &ifr6.ifr6_addr, - (char *) &sai6.sin6_addr, - sizeof(struct in6_addr)); - - /* Create a channel to the NET kernel. */ - if ((sockfd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - bb_perror_msg_and_die("socket6"); - } - if (ioctl(sockfd6, SIOGIFINDEX, &ifr) < 0) { - perror("SIOGIFINDEX"); - ++goterr; + else { + len_and_sockaddr *lsa; + if (strcmp(host, "inet") == 0) + continue; /* compat stuff */ + lsa = xhost2sockaddr(host, 0); +#if ENABLE_FEATURE_IPV6 + if (lsa->sa.sa_family == AF_INET6) { + int sockfd6; + struct in6_ifreq ifr6; + + memcpy((char *) &ifr6.ifr6_addr, + (char *) &(lsa->sin6.sin6_addr), + sizeof(struct in6_addr)); + + /* Create a channel to the NET kernel. */ + sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0); + if (ioctl(sockfd6, SIOGIFINDEX, &ifr) < 0) + bb_perror_msg_and_die("SIOGIFINDEX"); + ifr6.ifr6_ifindex = ifr.ifr_ifindex; + ifr6.ifr6_prefixlen = prefix_len; + if (ioctl(sockfd6, a1op->selector, &ifr6) < 0) + bb_perror_msg_and_die(a1op->name); + if (ENABLE_FEATURE_CLEAN_UP) + free(lsa); continue; } - ifr6.ifr6_ifindex = ifr.ifr_ifindex; - ifr6.ifr6_prefixlen = prefix_len; - if (ioctl(sockfd6, a1op->selector, &ifr6) < 0) { - perror(a1op->name); - ++goterr; - } - continue; #endif - } else if (inet_aton(host, &sai.sin_addr) == 0) { - /* It's not a dotted quad. */ - struct hostent *hp; - if ((hp = gethostbyname(host)) == (struct hostent *)NULL) { - ++goterr; - continue; - } - memcpy((char *) &sai.sin_addr, (char *) hp->h_addr_list[0], - sizeof(struct in_addr)); + sai.sin_addr = lsa->sin.sin_addr; + if (ENABLE_FEATURE_CLEAN_UP) + free(lsa); } -#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS - if (mask & A_HOSTNAME) { +#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS + if (mask & A_HOSTNAME) sai_hostname = sai.sin_addr.s_addr; - } - if (mask & A_NETMASK) { + if (mask & A_NETMASK) sai_netmask = sai.sin_addr.s_addr; - } #endif p = (char *) &sai; -#ifdef CONFIG_FEATURE_IFCONFIG_HW +#if ENABLE_FEATURE_IFCONFIG_HW } else { /* A_CAST_HOST_COPY_IN_ETHER */ /* This is the "hw" arg case. */ - if (strcmp("ether", *argv) || (*++argv == NULL)) { + if (strcmp("ether", *argv) || !*++argv) bb_show_usage(); - } - safe_strncpy(host, *argv, (sizeof host)); - if (in_ether(host, &sa)) { - bb_error_msg("invalid hw-addr %s", host); - ++goterr; - continue; - } + /*safe_strncpy(host, *argv, sizeof(host));*/ + host = *argv; + if (in_ether(host, &sa)) + bb_error_msg_and_die("invalid hw-addr %s", host); p = (char *) &sa; } #endif - memcpy((((char *) (&ifr)) + a1op->ifr_offset), + memcpy( (((char *)&ifr) + a1op->ifr_offset), p, sizeof(struct sockaddr)); } else { - unsigned int i = strtoul(*argv, NULL, 0); - - p = ((char *) (&ifr)) + a1op->ifr_offset; -#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ + /* FIXME: error check?? */ + unsigned long i = strtoul(*argv, NULL, 0); + p = ((char *)&ifr) + a1op->ifr_offset; +#if ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ if (mask & A_MAP_TYPE) { - if (ioctl(sockfd, SIOCGIFMAP, &ifr) < 0) { - ++goterr; - continue; - } - if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR) { + if (ioctl(sockfd, SIOCGIFMAP, &ifr) < 0) + bb_perror_msg_and_die("SIOCGIFMAP"); + if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR) *((unsigned char *) p) = i; - } else if (mask & A_MAP_USHORT) { + else if (mask & A_MAP_USHORT) *((unsigned short *) p) = i; - } else { + else *((unsigned long *) p) = i; - } } else #endif - if (mask & A_CAST_CHAR_PTR) { + if (mask & A_CAST_CHAR_PTR) *((caddr_t *) p) = (caddr_t) i; - } else { /* A_CAST_INT */ + else /* A_CAST_INT */ *((int *) p) = i; - } } - if (ioctl(sockfd, a1op->selector, &ifr) < 0) { - perror(a1op->name); - ++goterr; - continue; - } + if (ioctl(sockfd, a1op->selector, &ifr) < 0) + bb_perror_msg_and_die(a1op->name); #ifdef QUESTIONABLE_ALIAS_CASE if (mask & A_COLON_CHK) { /* * Don't do the set_flag() if the address is an alias with - * a - at the end, since it's deleted already! - Roman + * a '-' at the end, since it's deleted already! - Roman * * Should really use regex.h here, not sure though how well * it'll go with the cross-platform support etc. */ char *ptr; short int found_colon = 0; - - for (ptr = ifr.ifr_name; *ptr; ptr++) { - if (*ptr == ':') { + for (ptr = ifr.ifr_name; *ptr; ptr++) + if (*ptr == ':') found_colon++; - } - } - - if (found_colon && *(ptr - 1) == '-') { + if (found_colon && ptr[-1] == '-') continue; - } } #endif } - if (!(mask & A_SET_AFTER)) { + if (!(mask & A_SET_AFTER)) continue; - } mask = N_SET; } - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { - perror("SIOCGIFFLAGS"); - ++goterr; - } else { - selector = op->selector; - if (mask & SET_MASK) { - ifr.ifr_flags |= selector; - } else { - ifr.ifr_flags &= ~selector; - } - if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { - perror("SIOCSIFFLAGS"); - ++goterr; - } - } - LOOP: - continue; - } /* end of while-loop */ - - return goterr; + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) + bb_perror_msg_and_die("SIOCGIFFLAGS"); + selector = op->selector; + if (mask & SET_MASK) + ifr.ifr_flags |= selector; + else + ifr.ifr_flags &= ~selector; + if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) + bb_perror_msg_and_die("SIOCSIFFLAGS"); + } /* while () */ + + if (ENABLE_FEATURE_CLEAN_UP) + close(sockfd); + return 0; } -#ifdef CONFIG_FEATURE_IFCONFIG_HW +#if ENABLE_FEATURE_IFCONFIG_HW /* Input an Ethernet address and convert to binary. */ -static int in_ether(char *bufp, struct sockaddr *sap) +static int in_ether(const char *bufp, struct sockaddr *sap) { - unsigned char *ptr; + char *ptr; int i, j; unsigned char val; unsigned char c; @@ -600,6 +541,6 @@ static int in_ether(char *bufp, struct sockaddr *sap) *ptr++ = val; } while (++i < ETH_ALEN); - return (int) (*bufp); /* Error if we don't end at end of string. */ + return *bufp; /* Error if we don't end at end of string. */ } #endif