tftpd: show requested file name in open error message
[oweals/busybox.git] / networking / arp.c
index e2c5bbb7f6189767a6613cb9510731b400c99c51..6519f8156c3f4bab13e71550716e8f89b3fad7f5 100644 (file)
  *
  * modified for getopt32 by Arne Bernin <arne [at] alamut.de>
  */
+//config:config ARP
+//config:      bool "arp (10 kb)"
+//config:      default y
+//config:      select PLATFORM_LINUX
+//config:      help
+//config:      Manipulate the system ARP cache.
+
+//applet:IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_ARP) += arp.o interface.o
+
+//usage:#define arp_trivial_usage
+//usage:     "\n[-vn]  [-H HWTYPE] [-i IF] -a [HOSTNAME]"
+//usage:     "\n[-v]               [-i IF] -d HOSTNAME [pub]"
+//usage:     "\n[-v]   [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [temp]"
+//usage:     "\n[-v]   [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [netmask MASK] pub"
+//usage:     "\n[-v]   [-H HWTYPE] [-i IF] -Ds HOSTNAME IFACE [netmask MASK] pub"
+//usage:#define arp_full_usage "\n\n"
+//usage:       "Manipulate ARP cache\n"
+//usage:       "\n     -a              Display (all) hosts"
+//usage:       "\n     -d              Delete ARP entry"
+//usage:       "\n     -s              Set new entry"
+//usage:       "\n     -v              Verbose"
+//usage:       "\n     -n              Don't resolve names"
+//usage:       "\n     -i IF           Network interface"
+//usage:       "\n     -D              Read HWADDR from IFACE"
+//usage:       "\n     -A,-p AF        Protocol family"
+//usage:       "\n     -H HWTYPE       Hardware address type"
 
 #include "libbb.h"
+#include "common_bufsiz.h"
 #include "inet_common.h"
 
 #include <arpa/inet.h>
 #define DFLT_AF "inet"
 #define DFLT_HW "ether"
 
-#define        ARP_OPT_A (0x1)
-#define        ARP_OPT_p (0x2)
-#define        ARP_OPT_H (0x4)
-#define        ARP_OPT_t (0x8)
-#define        ARP_OPT_i (0x10)
-#define        ARP_OPT_a (0x20)
-#define        ARP_OPT_d (0x40)
-#define        ARP_OPT_n (0x80)        /* do not resolve addresses     */
-#define        ARP_OPT_D (0x100)       /* HW-address is devicename     */
-#define        ARP_OPT_s (0x200)
-#define        ARP_OPT_v (0x400 * DEBUG)       /* debugging output flag        */
-
-
-static const struct aftype *ap; /* current address family       */
-static const struct hwtype *hw; /* current hardware type        */
-static int sockfd;              /* active socket descriptor     */
-static smallint hw_set;         /* flag if hw-type was set (-H) */
-static const char *device = ""; /* current device               */
+enum {
+       ARP_OPT_A = (1 << 0),
+       ARP_OPT_p = (1 << 1),
+       ARP_OPT_H = (1 << 2),
+       ARP_OPT_t = (1 << 3),
+       ARP_OPT_i = (1 << 4),
+       ARP_OPT_a = (1 << 5),
+       ARP_OPT_d = (1 << 6),
+       ARP_OPT_n = (1 << 7), /* do not resolve addresses */
+       ARP_OPT_D = (1 << 8), /* HW-address is devicename */
+       ARP_OPT_s = (1 << 9),
+       ARP_OPT_v = (1 << 10) * DEBUG, /* debugging output flag */
+};
+
+enum {
+       sockfd = 3, /* active socket descriptor */
+};
+
+struct globals {
+       const struct aftype *ap; /* current address family */
+       const struct hwtype *hw; /* current hardware type */
+       const char *device;      /* current device */
+       smallint hw_set;         /* flag if hw-type was set (-H) */
+} FIX_ALIASING;
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define ap         (G.ap        )
+#define hw         (G.hw        )
+#define device     (G.device    )
+#define hw_set     (G.hw_set    )
+#define INIT_G() do { \
+       setup_common_bufsiz(); \
+       device = ""; \
+} while (0)
+
 
 static const char options[] ALIGN1 =
        "pub\0"
@@ -71,7 +116,7 @@ static int arp_del(char **args)
        /* Resolve the host name. */
        host = *args;
        if (ap->input(host, &sa) < 0) {
-               bb_herror_msg_and_die("%s", host);
+               bb_simple_herror_msg_and_die(host);
        }
 
        /* If a host has more than one address, use the correct one! */
@@ -104,7 +149,7 @@ static int arp_del(char **args)
 #ifdef HAVE_ATF_DONTPUB
                        req.arp_flags |= ATF_DONTPUB;
 #else
-                       bb_error_msg("feature ATF_DONTPUB is not supported");
+                       bb_simple_error_msg("feature ATF_DONTPUB is not supported");
 #endif
                        args++;
                        break;
@@ -112,7 +157,7 @@ static int arp_del(char **args)
 #ifdef HAVE_ATF_MAGIC
                        req.arp_flags |= ATF_MAGIC;
 #else
-                       bb_error_msg("feature ATF_MAGIC is not supported");
+                       bb_simple_error_msg("feature ATF_MAGIC is not supported");
 #endif
                        args++;
                        break;
@@ -128,7 +173,7 @@ static int arp_del(char **args)
                        if (strcmp(*args, "255.255.255.255") != 0) {
                                host = *args;
                                if (ap->input(host, &sa) < 0) {
-                                       bb_herror_msg_and_die("%s", host);
+                                       bb_simple_herror_msg_and_die(host);
                                }
                                memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
                                req.arp_flags |= ATF_NETMASK;
@@ -143,14 +188,14 @@ static int arp_del(char **args)
        if (flags == 0)
                flags = 3;
 
-       strncpy(req.arp_dev, device, sizeof(req.arp_dev));
+       strncpy_IFNAMSIZ(req.arp_dev, device);
 
        err = -1;
 
        /* Call the kernel. */
        if (flags & 2) {
                if (option_mask32 & ARP_OPT_v)
-                       bb_error_msg("SIOCDARP(nopub)");
+                       bb_simple_error_msg("SIOCDARP(nopub)");
                err = ioctl(sockfd, SIOCDARP, &req);
                if (err < 0) {
                        if (errno == ENXIO) {
@@ -159,37 +204,36 @@ static int arp_del(char **args)
                                printf("No ARP entry for %s\n", host);
                                return -1;
                        }
-                       bb_perror_msg_and_die("SIOCDARP(priv)");
+                       bb_simple_perror_msg_and_die("SIOCDARP(priv)");
                }
        }
        if ((flags & 1) && err) {
  nopub:
                req.arp_flags |= ATF_PUBL;
                if (option_mask32 & ARP_OPT_v)
-                       bb_error_msg("SIOCDARP(pub)");
+                       bb_simple_error_msg("SIOCDARP(pub)");
                if (ioctl(sockfd, SIOCDARP, &req) < 0) {
                        if (errno == ENXIO) {
                                printf("No ARP entry for %s\n", host);
                                return -1;
                        }
-                       bb_perror_msg_and_die("SIOCDARP(pub)");
+                       bb_simple_perror_msg_and_die("SIOCDARP(pub)");
                }
        }
        return 0;
 }
 
 /* Get the hardware address to a specified interface name */
-static void arp_getdevhw(char *ifname, struct sockaddr *sa,
-                                                const struct hwtype *hwt)
+static void arp_getdevhw(char *ifname, struct sockaddr *sa)
 {
        struct ifreq ifr;
        const struct hwtype *xhw;
 
-       strcpy(ifr.ifr_name, ifname);
+       strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
        ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr,
-                                       "cant get HW-Address for '%s'", ifname);
-       if (hwt && (ifr.ifr_hwaddr.sa_family != hw->type)) {
-               bb_error_msg_and_die("protocol type mismatch");
+                                       "can't get HW-Address for '%s'", ifname);
+       if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) {
+               bb_simple_error_msg_and_die("protocol type mismatch");
        }
        memcpy(sa, &(ifr.ifr_hwaddr), sizeof(struct sockaddr));
 
@@ -199,8 +243,8 @@ static void arp_getdevhw(char *ifname, struct sockaddr *sa,
                        xhw = get_hwntype(-1);
                }
                bb_error_msg("device '%s' has HW address %s '%s'",
-                                        ifname, xhw->name,
-                                        xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
+                               ifname, xhw->name,
+                               xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
        }
 }
 
@@ -217,20 +261,20 @@ static int arp_set(char **args)
 
        host = *args++;
        if (ap->input(host, &sa) < 0) {
-               bb_herror_msg_and_die("%s", host);
+               bb_simple_herror_msg_and_die(host);
        }
        /* If a host has more than one address, use the correct one! */
        memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr));
 
        /* Fetch the hardware address. */
        if (*args == NULL) {
-               bb_error_msg_and_die("need hardware address");
+               bb_simple_error_msg_and_die("need hardware address");
        }
        if (option_mask32 & ARP_OPT_D) {
-               arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL);
+               arp_getdevhw(*args++, &req.arp_ha);
        } else {
                if (hw->input(*args++, &req.arp_ha) < 0) {
-                       bb_error_msg_and_die("invalid hardware address");
+                       bb_simple_error_msg_and_die("invalid hardware address");
                }
        }
 
@@ -258,7 +302,7 @@ static int arp_set(char **args)
 #ifdef HAVE_ATF_DONTPUB
                        flags |= ATF_DONTPUB;
 #else
-                       bb_error_msg("feature ATF_DONTPUB is not supported");
+                       bb_simple_error_msg("feature ATF_DONTPUB is not supported");
 #endif
                        args++;
                        break;
@@ -266,7 +310,7 @@ static int arp_set(char **args)
 #ifdef HAVE_ATF_MAGIC
                        flags |= ATF_MAGIC;
 #else
-                       bb_error_msg("feature ATF_MAGIC is not supported");
+                       bb_simple_error_msg("feature ATF_MAGIC is not supported");
 #endif
                        args++;
                        break;
@@ -282,7 +326,7 @@ static int arp_set(char **args)
                        if (strcmp(*args, "255.255.255.255") != 0) {
                                host = *args;
                                if (ap->input(host, &sa) < 0) {
-                                       bb_herror_msg_and_die("%s", host);
+                                       bb_simple_herror_msg_and_die(host);
                                }
                                memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
                                flags |= ATF_NETMASK;
@@ -298,11 +342,11 @@ static int arp_set(char **args)
        /* Fill in the remainder of the request. */
        req.arp_flags = flags;
 
-       strncpy(req.arp_dev, device, sizeof(req.arp_dev));
+       strncpy_IFNAMSIZ(req.arp_dev, device);
 
        /* Call the kernel. */
        if (option_mask32 & ARP_OPT_v)
-               bb_error_msg("SIOCSARP()");
+               bb_simple_error_msg("SIOCSARP()");
        xioctl(sockfd, SIOCSARP, &req);
        return 0;
 }
@@ -311,7 +355,7 @@ static int arp_set(char **args)
 /* Print the contents of an ARP request block. */
 static void
 arp_disp(const char *name, char *ip, int type, int arp_flags,
-                char *hwa, char *mask, char *dev)
+               char *hwa, char *mask, char *dev)
 {
        static const int arp_masks[] = {
                ATF_PERM, ATF_PUBL,
@@ -378,7 +422,7 @@ static int arp_show(char *name)
        if (name != NULL) {
                /* Resolve the host name. */
                if (ap->input(name, &sa) < 0) {
-                       bb_herror_msg_and_die("%s", name);
+                       bb_simple_herror_msg_and_die(name);
                }
                host = xstrdup(ap->sprint(&sa, 1));
        }
@@ -394,7 +438,7 @@ static int arp_show(char *name)
                /* All these strings can't overflow
                 * because fgets above reads limited amount of data */
                num = sscanf(line, "%s 0x%x 0x%x %s %s %s\n",
-                                        ip, &type, &flags, hwa, mask, dev);
+                                       ip, &type, &flags, hwa, mask, dev);
                if (num < 4)
                        break;
 
@@ -426,12 +470,12 @@ static int arp_show(char *name)
                arp_disp(hostname, ip, type, flags, hwa, mask, dev);
        }
        if (option_mask32 & ARP_OPT_v)
-               printf("Entries: %d\tSkipped: %d\tFound: %d\n",
-                          entries, entries - shown, shown);
+               printf("Entries: %u\tSkipped: %u\tFound: %u\n",
+                               entries, entries - shown, shown);
 
        if (!shown) {
                if (hw_set || host || device[0])
-                       printf("No match found in %d entries\n", entries);
+                       printf("No match found in %u entries\n", entries);
        }
        if (ENABLE_FEATURE_CLEAN_UP) {
                free((char*)host);
@@ -443,55 +487,55 @@ static int arp_show(char *name)
 int arp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int arp_main(int argc UNUSED_PARAM, char **argv)
 {
-       const char *hw_type = "ether";
+       const char *hw_type;
        const char *protocol;
+       unsigned opts;
 
-       /* Initialize variables... */
-       ap = get_aftype(DFLT_AF);
-       if (!ap)
-               bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
+       INIT_G();
+
+       xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sockfd);
 
-       getopt32(argv, "A:p:H:t:i:adnDsv", &protocol, &protocol,
+       ap = get_aftype(DFLT_AF);
+       /* Defaults are always supported */
+       //if (!ap)
+       //      bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
+       hw = get_hwtype(DFLT_HW);
+       //if (!hw)
+       //      bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
+
+       opts = getopt32(argv, "A:p:H:t:i:adnDsv", &protocol, &protocol,
                                 &hw_type, &hw_type, &device);
        argv += optind;
-       if (option_mask32 & ARP_OPT_A || option_mask32 & ARP_OPT_p) {
+       if (opts & (ARP_OPT_A | ARP_OPT_p)) {
                ap = get_aftype(protocol);
-               if (ap == NULL)
+               if (!ap)
                        bb_error_msg_and_die("%s: unknown %s", protocol, "address family");
        }
-       if (option_mask32 & ARP_OPT_A || option_mask32 & ARP_OPT_p) {
+       if (opts & (ARP_OPT_H | ARP_OPT_t)) {
                hw = get_hwtype(hw_type);
-               if (hw == NULL)
+               if (!hw)
                        bb_error_msg_and_die("%s: unknown %s", hw_type, "hardware type");
                hw_set = 1;
        }
-       //if (option_mask32 & ARP_OPT_i)... -i
+       //if (opts & ARP_OPT_i)... -i
 
        if (ap->af != AF_INET) {
                bb_error_msg_and_die("%s: kernel only supports 'inet'", ap->name);
        }
-
-       /* If no hw type specified get default */
-       if (!hw) {
-               hw = get_hwtype(DFLT_HW);
-               if (!hw)
-                       bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
-       }
-
        if (hw->alen <= 0) {
                bb_error_msg_and_die("%s: %s without ARP support",
-                                                        hw->name, "hardware type");
+                               hw->name, "hardware type");
        }
-       sockfd = xsocket(AF_INET, SOCK_DGRAM, 0);
 
        /* Now see what we have to do here... */
-       if (option_mask32 & (ARP_OPT_d|ARP_OPT_s)) {
+       if (opts & (ARP_OPT_d | ARP_OPT_s)) {
                if (argv[0] == NULL)
-                       bb_error_msg_and_die("need host name");
-               if (option_mask32 & ARP_OPT_s)
+                       bb_simple_error_msg_and_die("need host name");
+               if (opts & ARP_OPT_s)
                        return arp_set(argv);
                return arp_del(argv);
        }
-       //if (option_mask32 & ARP_OPT_a) - default
+
+       //if (opts & ARP_OPT_a) - default
        return arp_show(argv[0]);
 }