httpd: trivial simplification
[oweals/busybox.git] / networking / arp.c
index 10934c254c67b90a78cbdaa864afa68e742b889f..8cdee18325c7bec125d4510c8d80d0353b8b5b20 100644 (file)
@@ -13,7 +13,7 @@
  * modified for getopt32 by Arne Bernin <arne [at] alamut.de>
  */
 
-#include "busybox.h"
+#include "libbb.h"
 #include "inet_common.h"
 
 #include <arpa/inet.h>
@@ -27,8 +27,6 @@
 #define DFLT_AF "inet"
 #define DFLT_HW "ether"
 
-#define _PATH_PROCNET_ARP "/proc/net/arp"
-
 #define        ARP_OPT_A (0x1)
 #define        ARP_OPT_p (0x2)
 #define        ARP_OPT_H (0x4)
@@ -46,25 +44,23 @@ 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 char *device = "";       /* current device               */
-
-static const char *const options[] = {
-       "pub",
-       "priv",
-       "temp",
-       "trail",
-       "dontpub",
-       "auto",
-       "dev",
-       "netmask",
-       NULL
-};
+static const char *device = ""; /* current device               */
+
+static const char options[] ALIGN1 =
+       "pub\0"
+       "priv\0"
+       "temp\0"
+       "trail\0"
+       "dontpub\0"
+       "auto\0"
+       "dev\0"
+       "netmask\0";
 
 /* Delete an entry from the ARP cache. */
 /* Called only from main, once */
 static int arp_del(char **args)
 {
-       char host[128];
+       char *host;
        struct arpreq req;
        struct sockaddr sa;
        int flags = 0;
@@ -73,8 +69,8 @@ static int arp_del(char **args)
        memset(&req, 0, sizeof(req));
 
        /* Resolve the host name. */
-       safe_strncpy(host, *args, 128);
-       if (ap->input(0, host, &sa) < 0) {
+       host = *args;
+       if (ap->input(host, &sa) < 0) {
                bb_herror_msg_and_die("%s", host);
        }
 
@@ -87,27 +83,24 @@ static int arp_del(char **args)
        req.arp_flags = ATF_PERM;
        args++;
        while (*args != NULL) {
-               if (option_mask32 & ARP_OPT_v)
-                       bb_error_msg("args=%s", *args);
-
-               switch (index_in_str_array(options, *args)) {
-               case 0: // "pub"
+               switch (index_in_strings(options, *args)) {
+               case 0: /* "pub" */
                        flags |= 1;
                        args++;
                        break;
-               case 1: // "priv"
+               case 1: /* "priv" */
                        flags |= 2;
                        args++;
                        break;
-               case 2: // "temp"
+               case 2: /* "temp" */
                        req.arp_flags &= ~ATF_PERM;
                        args++;
                        break;
-               case 3: // "trail"
+               case 3: /* "trail" */
                        req.arp_flags |= ATF_USETRAILERS;
                        args++;
                        break;
-               case 4: // "dontpub"
+               case 4: /* "dontpub" */
 #ifdef HAVE_ATF_DONTPUB
                        req.arp_flags |= ATF_DONTPUB;
 #else
@@ -115,7 +108,7 @@ static int arp_del(char **args)
 #endif
                        args++;
                        break;
-               case 5: // "auto"
+               case 5: /* "auto" */
 #ifdef HAVE_ATF_MAGIC
                        req.arp_flags |= ATF_MAGIC;
 #else
@@ -123,20 +116,19 @@ static int arp_del(char **args)
 #endif
                        args++;
                        break;
-               case 6: // "dev"
+               case 6: /* "dev" */
                        if (*++args == NULL)
                                bb_show_usage();
                        device = *args;
                        args++;
                        break;
-               case 7: // "netmask"
+               case 7: /* "netmask" */
                        if (*++args == NULL)
                                bb_show_usage();
                        if (strcmp(*args, "255.255.255.255") != 0) {
-                               safe_strncpy(host, *args, 128);
-                               if (ap->input(0, host, &sa) < 0) {
-                                       bb_herror_msg("%s", host);
-                                       return -1;
+                               host = *args;
+                               if (ap->input(host, &sa) < 0) {
+                                       bb_herror_msg_and_die("%s", host);
                                }
                                memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
                                req.arp_flags |= ATF_NETMASK;
@@ -187,16 +179,15 @@ static int arp_del(char **args)
 }
 
 /* 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,
+                                                const struct hwtype *hwt)
 {
        struct ifreq ifr;
        const struct hwtype *xhw;
 
        strcpy(ifr.ifr_name, ifname);
-       if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
-               bb_perror_msg_and_die("cant get HW-Address for '%s'", 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");
        }
@@ -217,15 +208,15 @@ arp_getdevhw(char *ifname, struct sockaddr *sa, const struct hwtype *hwt)
 /* Called only from main, once */
 static int arp_set(char **args)
 {
-       char host[128];
+       char *host;
        struct arpreq req;
        struct sockaddr sa;
        int flags;
-       
+
        memset(&req, 0, sizeof(req));
 
-       safe_strncpy(host, *args++, 128);
-       if (ap->input(0, host, &sa) < 0) {
+       host = *args++;
+       if (ap->input(host, &sa) < 0) {
                bb_herror_msg_and_die("%s", host);
        }
        /* If a host has more than one address, use the correct one! */
@@ -246,24 +237,24 @@ static int arp_set(char **args)
        /* Check out any modifiers. */
        flags = ATF_PERM | ATF_COM;
        while (*args != NULL) {
-               switch (index_in_str_array(options, *args)) {
-               case 0: // "pub"
+               switch (index_in_strings(options, *args)) {
+               case 0: /* "pub" */
                        flags |= ATF_PUBL;
                        args++;
                        break;
-               case 1: // "priv"
+               case 1: /* "priv" */
                        flags &= ~ATF_PUBL;
                        args++;
                        break;
-               case 2: // "temp"
+               case 2: /* "temp" */
                        flags &= ~ATF_PERM;
                        args++;
                        break;
-               case 3: // "trail"
+               case 3: /* "trail" */
                        flags |= ATF_USETRAILERS;
                        args++;
                        break;
-               case 4: // "dontpub"
+               case 4: /* "dontpub" */
 #ifdef HAVE_ATF_DONTPUB
                        flags |= ATF_DONTPUB;
 #else
@@ -271,7 +262,7 @@ static int arp_set(char **args)
 #endif
                        args++;
                        break;
-               case 5: // "auto"
+               case 5: /* "auto" */
 #ifdef HAVE_ATF_MAGIC
                        flags |= ATF_MAGIC;
 #else
@@ -279,18 +270,18 @@ static int arp_set(char **args)
 #endif
                        args++;
                        break;
-               case 6: // "dev"
+               case 6: /* "dev" */
                        if (*++args == NULL)
                                bb_show_usage();
                        device = *args;
                        args++;
                        break;
-               case 7: // "netmask"
+               case 7: /* "netmask" */
                        if (*++args == NULL)
                                bb_show_usage();
                        if (strcmp(*args, "255.255.255.255") != 0) {
-                               safe_strncpy(host, *args++, 128);
-                               if (ap->input(0, host, &sa) < 0) {
+                               host = *args;
+                               if (ap->input(host, &sa) < 0) {
                                        bb_herror_msg_and_die("%s", host);
                                }
                                memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
@@ -312,16 +303,14 @@ static int arp_set(char **args)
        /* Call the kernel. */
        if (option_mask32 & ARP_OPT_v)
                bb_error_msg("SIOCSARP()");
-       if (ioctl(sockfd, SIOCSARP, &req) < 0) {
-               bb_perror_msg_and_die("SIOCSARP");
-       }
+       xioctl(sockfd, SIOCSARP, &req);
        return 0;
 }
 
 
 /* Print the contents of an ARP request block. */
 static void
-arp_disp(char *name, char *ip, int type, int arp_flags,
+arp_disp(const char *name, char *ip, int type, int arp_flags,
                 char *hwa, char *mask, char *dev)
 {
        const struct hwtype *xhw;
@@ -366,84 +355,86 @@ arp_disp(char *name, char *ip, int type, int arp_flags,
 /* Called only from main, once */
 static int arp_show(char *name)
 {
-       char host[100];
+       const char *host;
+       const char *hostname;
+       FILE *fp;
        struct sockaddr sa;
-       char ip[100];
-       char hwa[100];
-       char mask[100];
-       char line[200];
-       char dev[100];
        int type, flags;
-       FILE *fp;
-       char *hostname;
-       int num, entries = 0, shown = 0;
-
-       host[0] = '\0';
-
+       int num;
+       unsigned entries = 0, shown = 0;
+       char ip[128];
+       char hwa[128];
+       char mask[128];
+       char line[128];
+       char dev[128];
+
+       host = NULL;
        if (name != NULL) {
                /* Resolve the host name. */
-               safe_strncpy(host, name, (sizeof host));
-               if (ap->input(0, host, &sa) < 0) {
-                       bb_herror_msg_and_die("%s", host);
+               if (ap->input(name, &sa) < 0) {
+                       bb_herror_msg_and_die("%s", name);
                }
-               safe_strncpy(host, ap->sprint(&sa, 1), sizeof(host));
+               host = xstrdup(ap->sprint(&sa, 1));
        }
-       /* Open the PROCps kernel table. */
-       fp = xfopen(_PATH_PROCNET_ARP, "r");
-       /* Bypass header -- read until newline */
-       if (fgets(line, sizeof(line), fp) != (char *) NULL) {
+       fp = xfopen("/proc/net/arp", "r");
+       /* Bypass header -- read one line */
+       fgets(line, sizeof(line), fp);
+
+       /* Read the ARP cache entries. */
+       while (fgets(line, sizeof(line), fp)) {
+
                mask[0] = '-'; mask[1] = '\0';
                dev[0] = '-'; dev[1] = '\0';
-               /* Read the ARP cache entries. */
-               for (; fgets(line, sizeof(line), fp);) {
-                       num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
-                                                ip, &type, &flags, hwa, mask, dev);
-                       if (num < 4)
-                               break;
-
-                       entries++;
-                       /* if the user specified hw-type differs, skip it */
-                       if (hw_set && (type != hw->type))
-                               continue;
-
-                       /* if the user specified address differs, skip it */
-                       if (host[0] && strcmp(ip, host) != 0)
-                               continue;
-
-                       /* if the user specified device differs, skip it */
-                       if (device && strcmp(dev, device) != 0)
-                               continue;
-
-                       shown++;
-                       /* This IS ugly but it works -be */
-                       if (option_mask32 & ARP_OPT_n)
-                               hostname = "?";
-                       else {
-                               if (ap->input(0, ip, &sa) < 0)
-                                       hostname = ip;
-                               else
-                                       hostname = ap->sprint(&sa, (option_mask32 & ARP_OPT_n) | 0x8000);
-                               if (strcmp(hostname, ip) == 0)
-                                       hostname = "?";
-                       }
+               /* 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);
+               if (num < 4)
+                       break;
 
-                       arp_disp(hostname, ip, type, flags, hwa, mask, dev);
+               entries++;
+               /* if the user specified hw-type differs, skip it */
+               if (hw_set && (type != hw->type))
+                       continue;
+
+               /* if the user specified address differs, skip it */
+               if (host && strcmp(ip, host) != 0)
+                       continue;
+
+               /* if the user specified device differs, skip it */
+               if (device[0] && strcmp(dev, device) != 0)
+                       continue;
+
+               shown++;
+               /* This IS ugly but it works -be */
+               hostname = "?";
+               if (!(option_mask32 & ARP_OPT_n)) {
+                       if (ap->input(ip, &sa) < 0)
+                               hostname = ip;
+                       else
+                               hostname = ap->sprint(&sa, (option_mask32 & ARP_OPT_n) | 0x8000);
+                       if (strcmp(hostname, ip) == 0)
+                               hostname = "?";
                }
+
+               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);
 
        if (!shown) {
-               if (hw_set || host[0] || device)
+               if (hw_set || host || device[0])
                        printf("No match found in %d entries\n", entries);
        }
-
-       fclose(fp);
-
+       if (ENABLE_FEATURE_CLEAN_UP) {
+               free((char*)host);
+               fclose(fp);
+       }
        return 0;
 }
 
+int arp_main(int argc, char **argv);
 int arp_main(int argc, char **argv)
 {
        char *hw_type;
@@ -454,7 +445,7 @@ int arp_main(int argc, char **argv)
        if (!ap)
                bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
 
-       getopt32(argc, argv, "A:p:H:t:i:adnDsv", &protocol, &protocol,
+       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) {