netstat memory leak fixed.
[platform/upstream/net-tools.git] / arp.c
diff --git a/arp.c b/arp.c
index 7001814..72e87d6 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -8,7 +8,7 @@
  *              NET-3 Networking Distribution for the LINUX operating
  *              system.
  *
- * Version:     $Id: arp.c,v 1.21 2001/05/06 02:14:07 ecki Exp $
+ * Version:     $Id: arp.c,v 1.27 2009/09/06 22:50:11 vapier Exp $
  *
  * Maintainer:  Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
  *
@@ -100,9 +100,10 @@ static int arp_del(char **args)
 {
     char host[128];
     struct arpreq req;
-    struct sockaddr sa;
+    struct sockaddr_storage ss;
+    struct sockaddr *sa;
     int flags = 0;
-    int err;
+    int deleted = 0;
 
     memset((char *) &req, 0, sizeof(req));
 
@@ -112,12 +113,13 @@ static int arp_del(char **args)
        return (-1);
     }
     safe_strncpy(host, *args, (sizeof host));
-    if (ap->input(0, host, &sa) < 0) {
+    sa = (struct sockaddr *)&ss;
+    if (ap->input(0, host, sa) < 0) {
        ap->herror(host);
        return (-1);
     }
     /* If a host has more than one address, use the correct one! */
-    memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
+    memcpy((char *) &req.arp_pa, (char *) sa, sizeof(struct sockaddr));
 
     if (hw_set)
        req.arp_ha.sa_family = hw->type;
@@ -148,7 +150,7 @@ static int arp_del(char **args)
            continue;
        }
        if (!strcmp(*args, "dontpub")) {
-#ifdef HAVE_ATF_DONTPUB
+#ifdef ATF_DONTPUB
            req.arp_flags |= ATF_DONTPUB;
 #else
            ENOSUPP("arp", "ATF_DONTPUB");
@@ -157,7 +159,7 @@ static int arp_del(char **args)
            continue;
        }
        if (!strcmp(*args, "auto")) {
-#ifdef HAVE_ATF_MAGIC
+#ifdef ATF_MAGIC
            req.arp_flags |= ATF_MAGIC;
 #else
            ENOSUPP("arp", "ATF_MAGIC");
@@ -177,11 +179,11 @@ static int arp_del(char **args)
                usage();
            if (strcmp(*args, "255.255.255.255") != 0) {
                strcpy(host, *args);
-               if (ap->input(0, host, &sa) < 0) {
+               if (ap->input(0, host, sa) < 0) {
                    ap->herror(host);
                    return (-1);
                }
-               memcpy((char *) &req.arp_netmask, (char *) &sa,
+               memcpy((char *) &req.arp_netmask, (char *) sa,
                       sizeof(struct sockaddr));
                req.arp_flags |= ATF_NETMASK;
            }
@@ -190,35 +192,41 @@ static int arp_del(char **args)
        }
        usage();
     }
+
+    // if neighter priv nor pub is given, work on both
     if (flags == 0)
        flags = 3;
 
     strcpy(req.arp_dev, device);
 
-    err = -1;
+    /* unfortuatelly the kernel interface does not allow us to
+       delete private entries anlone, so we need this hack
+       to avoid "not found" errors if we try both. */
+    deleted = 0;
 
     /* Call the kernel. */
     if (flags & 2) {
        if (opt_v)
-           fprintf(stderr, "arp: SIOCDARP(nopub)\n");
-       if ((err = ioctl(sockfd, SIOCDARP, &req) < 0)) {
-           if (errno == ENXIO) {
+           fprintf(stderr, "arp: SIOCDARP(dontpub)\n");
+       if (ioctl(sockfd, SIOCDARP, &req) < 0) {
+           if ((errno == ENXIO) || (errno == ENOENT)) {
                if (flags & 1)
-                   goto nopub;
+                   goto dontpub;
                printf(_("No ARP entry for %s\n"), host);
                return (-1);
            }
-           perror("SIOCDARP(priv)");
+           perror("SIOCDARP(dontpub)");
            return (-1);
-       }
+       } else
+         deleted = 1;
     }
-    if ((flags & 1) && (err)) {
-      nopub:
+    if (!deleted && (flags & 1)) {
+      dontpub:
        req.arp_flags |= ATF_PUBL;
        if (opt_v)
            fprintf(stderr, "arp: SIOCDARP(pub)\n");
        if (ioctl(sockfd, SIOCDARP, &req) < 0) {
-           if (errno == ENXIO) {
+           if ((errno == ENXIO) || (errno == ENOENT)) {
                printf(_("No ARP entry for %s\n"), host);
                return (-1);
            }
@@ -235,7 +243,7 @@ static int arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw)
     struct ifreq ifr;
     struct hwtype *xhw;
 
-    strcpy(ifr.ifr_name, ifname);
+    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
     if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
        fprintf(stderr, _("arp: cant get HW-Address for `%s': %s.\n"), ifname, strerror(errno));
        return (-1);
@@ -260,7 +268,8 @@ static int arp_set(char **args)
 {
     char host[128];
     struct arpreq req;
-    struct sockaddr sa;
+    struct sockaddr_storage ss;
+    struct sockaddr *sa;
     int flags;
 
     memset((char *) &req, 0, sizeof(req));
@@ -271,12 +280,13 @@ static int arp_set(char **args)
        return (-1);
     }
     safe_strncpy(host, *args++, (sizeof host));
-    if (ap->input(0, host, &sa) < 0) {
+    sa = (struct sockaddr *)&ss;
+    if (ap->input(0, host, sa) < 0) {
        ap->herror(host);
        return (-1);
     }
     /* If a host has more than one address, use the correct one! */
-    memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
+    memcpy((char *) &req.arp_pa, (char *) sa, sizeof(struct sockaddr));
 
     /* Fetch the hardware address. */
     if (*args == NULL) {
@@ -317,7 +327,7 @@ static int arp_set(char **args)
            continue;
        }
        if (!strcmp(*args, "dontpub")) {
-#ifdef HAVE_ATF_DONTPUB
+#ifdef ATF_DONTPUB
            flags |= ATF_DONTPUB;
 #else
            ENOSUPP("arp", "ATF_DONTPUB");
@@ -326,7 +336,7 @@ static int arp_set(char **args)
            continue;
        }
        if (!strcmp(*args, "auto")) {
-#ifdef HAVE_ATF_MAGIC
+#ifdef ATF_MAGIC
            flags |= ATF_MAGIC;
 #else
            ENOSUPP("arp", "ATF_MAGIC");
@@ -346,11 +356,11 @@ static int arp_set(char **args)
                usage();
            if (strcmp(*args, "255.255.255.255") != 0) {
                strcpy(host, *args);
-               if (ap->input(0, host, &sa) < 0) {
+               if (ap->input(0, host, sa) < 0) {
                    ap->herror(host);
                    return (-1);
                }
-               memcpy((char *) &req.arp_netmask, (char *) &sa,
+               memcpy((char *) &req.arp_netmask, (char *) sa,
                       sizeof(struct sockaddr));
                flags |= ATF_NETMASK;
            }
@@ -424,7 +434,7 @@ static int arp_file(char *name)
 
 
 /* Print the contents of an ARP request block. */
-static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mask, char *dev)
+static void arp_disp_2(const char *name, int type, int arp_flags, const char *hwa, const char *mask, const char *dev)
 {
     static int title = 0;
     struct hwtype *xhw;
@@ -445,11 +455,11 @@ static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mas
        strcat(flags, "M");
     if (arp_flags & ATF_PUBL)
        strcat(flags, "P");
-#ifdef HAVE_ATF_MAGIC
+#ifdef ATF_MAGIC
     if (arp_flags & ATF_MAGIC)
        strcat(flags, "A");
 #endif
-#ifdef HAVE_ATF_DONTPUB
+#ifdef ATF_DONTPUB
     if (arp_flags & ATF_DONTPUB)
        strcat(flags, "!");
 #endif
@@ -463,7 +473,7 @@ static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mas
 
     if (!(arp_flags & ATF_COM)) {
        if (arp_flags & ATF_PUBL)
-           printf("%-8.8s%-20.20s", "*", "*");
+           printf("%-8.8s%-20.20s", "*", _("<from_interface>"));
        else
            printf("%-8.8s%-20.20s", "", _("(incomplete)"));
     } else {
@@ -474,7 +484,7 @@ static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mas
 }
 
 /* Print the contents of an ARP request block. */
-static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, char *mask, char *dev)
+static void arp_disp(const char *name, const char *ip, int type, int arp_flags, const char *hwa, const char *mask, const char *dev)
 {
     struct hwtype *xhw;
 
@@ -486,7 +496,7 @@ static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, c
 
     if (!(arp_flags & ATF_COM)) {
        if (arp_flags & ATF_PUBL)
-           printf("* ");
+           printf("<from_interface> ");
        else
            printf(_("<incomplete> "));
     } else {
@@ -500,11 +510,11 @@ static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, c
        printf("PERM ");
     if (arp_flags & ATF_PUBL)
        printf("PUB ");
-#ifdef HAVE_ATF_MAGIC
+#ifdef ATF_MAGIC
     if (arp_flags & ATF_MAGIC)
        printf("AUTO ");
 #endif
-#ifdef HAVE_ATF_DONTPUB
+#ifdef ATF_DONTPUB
     if (arp_flags & ATF_DONTPUB)
        printf("DONTPUB ");
 #endif
@@ -519,7 +529,8 @@ static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, c
 static int arp_show(char *name)
 {
     char host[100];
-    struct sockaddr sa;
+    struct sockaddr_storage ss;
+    struct sockaddr *sa;
     char ip[100];
     char hwa[100];
     char mask[100];
@@ -527,19 +538,20 @@ static int arp_show(char *name)
     char dev[100];
     int type, flags;
     FILE *fp;
-    char *hostname;
+    const char *hostname;
     int num, entries = 0, showed = 0;
 
     host[0] = '\0';
 
+    sa = (struct sockaddr *)&ss;
     if (name != NULL) {
        /* Resolve the host name. */
        safe_strncpy(host, name, (sizeof host));
-       if (ap->input(0, host, &sa) < 0) {
+       if (ap->input(0, host, sa) < 0) {
            ap->herror(host);
            return (-1);
        }
-       safe_strncpy(host, ap->sprint(&sa, 1), sizeof(host));
+       safe_strncpy(host, ap->sprint(sa, 1), sizeof(host));
     }
     /* Open the PROCps kernel table. */
     if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
@@ -552,7 +564,7 @@ static int arp_show(char *name)
        strcpy(dev, "-");
        /* Read the ARP cache entries. */
        for (; fgets(line, sizeof(line), fp);) {
-           num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
+           num = sscanf(line, "%s 0x%x 0x%x %99s %99s %99s\n",
                         ip, &type, &flags, hwa, mask, dev);
            if (num < 4)
                break;
@@ -575,10 +587,10 @@ static int arp_show(char *name)
            if (opt_n)
                hostname = "?";
            else {
-               if (ap->input(0, ip, &sa) < 0)
+               if (ap->input(0, ip, sa) < 0)
                    hostname = ip;
                else
-                   hostname = ap->sprint(&sa, opt_n | 0x8000);
+                   hostname = ap->sprint(sa, opt_n | 0x8000);
                if (strcmp(hostname, ip) == 0)
                    hostname = "?";
            }
@@ -612,13 +624,13 @@ static void version(void)
 static void usage(void)
 {
     fprintf(stderr, _("Usage:\n  arp [-vn]  [<HW>] [-i <if>] [-a] [<hostname>]             <-Display ARP cache\n"));
-    fprintf(stderr, _("  arp [-v]          [-i <if>] -d  <hostname> [pub][nopub]    <-Delete ARP entry\n"));
-    fprintf(stderr, _("  arp [-vnD] [<HW>] [-i <if>] -f  [<filename>]              <-Add entry from file\n"));
-    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -s  <hostname> <hwaddr> [temp][nopub] <-Add entry\n"));
-    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -s  <hostname> <hwaddr> [netmask <nm>] pub  <-''-\n"));
-    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -Ds <hostname> <if> [netmask <nm>] pub      <-''-\n\n"));
+    fprintf(stderr, _("  arp [-v]          [-i <if>] -d  <host> [pub]               <-Delete ARP entry\n"));
+    fprintf(stderr, _("  arp [-vnD] [<HW>] [-i <if>] -f  [<filename>]            <-Add entry from file\n"));
+    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -s  <host> <hwaddr> [temp]            <-Add entry\n"));
+    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -Ds <host> <if> [netmask <nm>] pub          <-''-\n\n"));
     
     fprintf(stderr, _("        -a                       display (all) hosts in alternative (BSD) style\n"));
+    fprintf(stderr, _("        -e                       display (all) hosts in default (Linux) style\n"));
     fprintf(stderr, _("        -s, --set                set a new ARP entry\n"));
     fprintf(stderr, _("        -d, --delete             delete a specified entry\n"));
     fprintf(stderr, _("        -v, --verbose            be verbose\n"));