summaryrefslogtreecommitdiff
path: root/arp.c
diff options
context:
space:
mode:
authorPhil Blundell <philb@gnu.org>1998-02-08 19:38:50 +0000
committerPhil Blundell <philb@gnu.org>1998-02-08 19:38:50 +0000
commit1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d (patch)
tree2628d723cf995ff551213fe4e679f2634632893a /arp.c
parentb1279cc68c387980090293ccba91afc5afaeabef (diff)
downloadnet-tools-1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d.tar.gz
net-tools-1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d.tar.bz2
net-tools-1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d.zip
Various ifconfig cleanups and new arp.
Diffstat (limited to 'arp.c')
-rw-r--r--arp.c421
1 files changed, 318 insertions, 103 deletions
diff --git a/arp.c b/arp.c
index c2377e1..d6080ba 100644
--- a/arp.c
+++ b/arp.c
@@ -8,13 +8,14 @@
* NET-3 Networking Distribution for the LINUX operating
* system.
*
- * Version: arp 1.69 (1996-05-17)
+ * Version: arp 1.82 (1997-09-25)
*
* Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Changes:
+ * (based on work from Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>)
* Alan Cox : modified for NET3
* Andrew Tridgell : proxy arp netmasks
* Bernd Eckenfels : -n option
@@ -24,14 +25,21 @@
* {1.61} Bernd Eckenfels : more verbose messages
* {1.62} Bernd Eckenfels : check -t for hw adresses and try to
* explain EINVAL (jeff)
- *960125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle
- *960201 {1.64} Bernd Eckenfels : net-features.h support
- *960203 {1.65} Bernd Eckenfels : "#define" in "#if",
+ *970125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle
+ *970201 {1.64} Bernd Eckenfels : net-features.h support
+ *970203 {1.65} Bernd Eckenfels : "#define" in "#if",
* -H|-A additional to -t|-p
- *960214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A
- *960412 {1.67} Bernd Eckenfels : device=""; is default
- *960514 {1.68} Bernd Eckenfels : -N and -D
- *960517 {1.69} Bernd Eckenfels : usage() fixed
+ *970214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A
+ *970412 {1.67} Bernd Eckenfels : device=""; is default
+ *970514 {1.68} Bernd Eckenfels : -N and -D
+ *970517 {1.69} Bernd Eckenfels : usage() fixed
+ *970622 {1.70} Bernd Eckenfels : arp -d priv
+ *970106 {1.80} Bernd Eckenfels : new syntax without -D and with "dev <If>",
+ * ATF_MAGIC, ATF_DONTPUB support.
+ * Typo fix (Debian Bug#5728 Giuliano Procida)
+ *970803 {1.81} Bernd Eckenfels : removed junk comment line 1
+ *970925 {1.82} Bernd Eckenfels : include fix for libc6
+ *
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
@@ -43,6 +51,8 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+/* #include <linux/netdevice.h> */
+/* #include <linux/if_arp.h> */
#include <net/if_arp.h>
#include <stdlib.h>
#include <stdio.h>
@@ -66,12 +76,14 @@
char *Release = RELEASE,
- *Version = "arp 1.69 (1996-05-17)";
+ *Version = "arp 1.82 (1997-09-25)";
int opt_n = 0; /* do not resolve addresses */
int opt_N = 0; /* use symbolic names */
int opt_v = 0; /* debugging output flag */
int opt_D = 0; /* HW-address is devicename */
+int opt_e = 0; /* 0=BSD output, 1=new linux */
+int opt_a = 0; /* all entries, substring match */
struct aftype *ap; /* current address family */
struct hwtype *hw; /* current hardware type */
int sockfd=0; /* active socket descriptor */
@@ -86,6 +98,7 @@ arp_del(char **args)
char host[128];
struct arpreq req;
struct sockaddr sa;
+ int flags=0;
#if HAVE_NEW_SIOCSARP
struct arpreq_old old_req;
#endif
@@ -106,40 +119,133 @@ arp_del(char **args)
/* If a host has more than one address, use the correct one! */
memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
- req.arp_flags=0;
+ if (hw_set)
+ req.arp_ha.sa_family=hw->type;
- if (args[1]) {
- if (strcmp(args[1],"pub")==0)
- req.arp_flags|=ATF_PUBL;
- else
- usage();
+ req.arp_flags=ATF_PERM;
+ args++;
+ while (*args != NULL) {
+ if (opt_v) fprintf(stderr,"args=%s\n",*args);
+ if (! strcmp(*args, "pub")) {
+ flags |= 1;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "priv")) {
+ flags |= 2;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "temp")) {
+ req.arp_flags &= ~ATF_PERM;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "trail")) {
+ req.arp_flags |= ATF_USETRAILERS;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dontpub")) {
+#ifdef HAVE_ATF_DONTPUB
+ req.arp_flags |= ATF_DONTPUB;
+#else
+ ENOSUPP("arp", "ATF_DONTPUB");
+#endif
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "auto")) {
+#ifdef HAVE_ATF_MAGIC
+ req.arp_flags |= ATF_MAGIC;
+#else
+ ENOSUPP("arp", "ATF_MAGIC");
+#endif
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dev")) {
+ if (*++args == NULL) usage();
+ strncpy(device,*args,sizeof(device)-1);
+ device[sizeof(device)-1]='\0';
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "netmask")) {
+ if (*++args == NULL) usage();
+ if (strcmp(*args,"255.255.255.255") != 0) {
+ strcpy(host, *args);
+ if (ap->input(0, host, &sa) < 0) {
+ ap->herror(host);
+ return(-1);
+ }
+ memcpy((char *) &req.arp_netmask, (char *) &sa,
+ sizeof(struct sockaddr));
+ req.arp_flags |= ATF_NETMASK;
+ }
+ args++;
+ continue;
+ }
+ usage();
}
-
+ if (flags == 0)
+ flags = 3;
+
#if HAVE_NEW_SIOCSARP
strcpy(req.arp_dev,device);
- memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
/* Call the kernel. */
- if (opt_v) fprintf(stderr,"arp: SIOCDARP()\n");
- if (ioctl(sockfd, SIOCDARP, &req) < 0) {
- if (errno == EINVAL) {
- if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP()\n");
- if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
- if (errno != ENXIO) {
- perror("OLD_SIOCSARP");
- return(-1);
+ if (flags & 2) {
+ if (opt_v) fprintf(stderr,"arp: SIOCDARP(nopub)\n");
+ if (ioctl(sockfd, SIOCDARP, &req) < 0) {
+ if (errno == EINVAL) {
+ if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP(priv)\n");
+ memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
+ if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
+ if (errno != ENXIO) {
+ perror("OLD_SIOCSARP(priv)");
+ return(-1);
+ }
+ } else {
+ return(0);
}
- } else {
- return(0);
}
- }
- if (errno == ENXIO) {
- printf(NLS_CATGETS(catfd, arpSet, arp_no_arp,
- "No ARP entry for %s\n"), host);
+ if (errno == ENXIO) {
+ if (flags & 1)
+ goto nopub;
+ printf(NLS_CATGETS(catfd, arpSet, arp_no_arp,
+ "No ARP entry for %s\n"), host);
+ return(-1);
+ }
+ perror("SIOCDARP(priv)");
return(-1);
- }
- perror("SIOCDARP");
- return(-1);
+ }
+ }
+ if (flags & 1) {
+nopub:
+ req.arp_flags |= ATF_PUBL;
+ if (opt_v) fprintf(stderr,"arp: SIOCDARP(pub)\n");
+ if (ioctl(sockfd, SIOCDARP, &req) < 0) {
+ if (errno == EINVAL) {
+ if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP(pub)\n");
+ memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
+ if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
+ if (errno != ENXIO) {
+ perror("OLD_SIOCSARP(pub)");
+ return(-1);
+ }
+ } else {
+ return(0);
+ }
+ }
+ if (errno == ENXIO) {
+ printf(NLS_CATGETS(catfd, arpSet, arp_no_arp,
+ "No ARP entry for %s\n"), host);
+ return(-1);
+ }
+ perror("SIOCDARP(pub)");
+ return(-1);
+ }
}
#else
/* Call the kernel. */
@@ -227,30 +333,70 @@ arp_set(char **args)
/* Check out any modifiers. */
flags = ATF_PERM;
while (*args != NULL) {
- if (! strcmp(*args, "temp")) flags &= ~ATF_PERM;
- if (! strcmp(*args, "pub")) flags |= ATF_PUBL;
-/* if (! strcmp(*args, "rarp")) flags |= ATF_RARP;*/
- if (! strcmp(*args, "trail")) flags |= ATF_USETRAILERS;
- if (! strcmp(*args, "netmask"))
- {
- if (*++args == NULL) usage();
- if (strcmp(*args,"255.255.255.255") != 0)
- {
- strcpy(host, *args);
- if (ap->input(0, host, &sa) < 0) {
- ap->herror(host);
- return(-1);
- }
- memcpy((char *) &req.arp_netmask, (char *) &sa,
- sizeof(struct sockaddr));
- flags |= ATF_NETMASK;
- }
- }
- args++;
- }
+ if (! strcmp(*args, "temp")) {
+ flags &= ~ATF_PERM;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "pub")) {
+ flags |= ATF_PUBL;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "priv")) {
+ flags &= ~ATF_PUBL;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "trail")) {
+ flags |= ATF_USETRAILERS;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dontpub")) {
+#ifdef HAVE_ATF_DONTPUB
+ flags |= ATF_DONTPUB;
+#else
+ ENOSUPP("arp", "ATF_DONTPUB");
+#endif
+ args++;
+ continue;
+ }
+
+ if (! strcmp(*args, "auto")) {
+#ifdef HAVE_ATF_MAGIC
+ flags |= ATF_MAGIC;
+#else
+ ENOSUPP("arp", "ATF_MAGIC");
+#endif
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dev")) {
+ if (*++args == NULL) usage();
+ strncpy(device,*args,sizeof(device)-1);
+ device[sizeof(device)-1]='\0';
+ args++;
+ continue;
+ }
- if ((flags & ATF_NETMASK) && !(flags & ATF_PUBL))
- usage();
+ if (! strcmp(*args, "netmask")) {
+ if (*++args == NULL) usage();
+ if (strcmp(*args,"255.255.255.255") != 0) {
+ strcpy(host, *args);
+ if (ap->input(0, host, &sa) < 0) {
+ ap->herror(host);
+ return(-1);
+ }
+ memcpy((char *) &req.arp_netmask, (char *) &sa,
+ sizeof(struct sockaddr));
+ flags |= ATF_NETMASK;
+ }
+ args++;
+ continue;
+ }
+ usage();
+ }
/* Fill in the remainder of the request. */
req.arp_flags = flags;
@@ -275,10 +421,10 @@ arp_set(char **args)
perror("SIOCSARP and OLD_SIOCSARP");
if (flags & ATF_PUBL)
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_pub,
- "Probably destination is reached via ARP Interface. See arp(8)\n"));
+ "Probably route to destination points to interface. See arp(8)\n"));
else
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_nopub,
- "Probably destination is on different Interface. See arp(8)\n"));
+ "No ARP Support or route to destination points to other interface. See arp(8)\n"));
return(-1);
}
}
@@ -339,23 +485,15 @@ arp_file(char *name)
/* Print the contents of an ARP request block. */
static void
-arp_disp_2(char *ip,int type,int arp_flags,char *hwa,char *mask,char *dev)
+arp_disp_2(char *name,int type,int arp_flags,char *hwa,char *mask,char *dev)
{
static int title = 0;
struct hwtype *xhw;
- struct aftype *xap;
- char *sp;
- struct sockaddr sap;
- char flags[6];
+ char flags[10];
xhw = get_hwntype(type);
if (xhw == NULL)
- xhw = get_hwtype("ether");
-/*
- * xap = get_afntype(req->arp_pa.sa_family);
- * if (xap == NULL)
- */
- xap = get_aftype("inet");
+ xhw = get_hwtype(DFLT_HW);
if (title++ == 0) {
printf(NLS_CATGETS(catfd, arpSet, arp_address,
@@ -366,17 +504,67 @@ arp_disp_2(char *ip,int type,int arp_flags,char *hwa,char *mask,char *dev)
if (arp_flags & ATF_COM) strcat(flags, "C");
if (arp_flags & ATF_PERM) strcat(flags, "M");
if (arp_flags & ATF_PUBL) strcat(flags, "P");
-/* if (arp_flags & ATF_RARP) strcat(flags, "R");*/
+#ifdef HAVE_ATF_MAGIC
+ if (arp_flags & ATF_MAGIC) strcat(flags, "A");
+#endif
+#ifdef HAVE_ATF_DONTPUB
+ if (arp_flags & ATF_DONTPUB) strcat(flags, "!");
+#endif
if (arp_flags & ATF_USETRAILERS) strcat(flags, "T");
- /* This IS ugly but it works -be */
- if (xap->input(0, ip,&sap) < 0)
- sp=ip;
- else
- sp = xap->sprint(&sap, opt_n);
+ if (!(arp_flags & ATF_NETMASK)) mask="";
+
+ printf("%-23.23s\t", name);
+
+ if (!(arp_flags & ATF_COM)) {
+ if (arp_flags & ATF_PUBL)
+ printf("%-8.8s%-20.20s","*","*");
+ else
+ printf("%-8.8s%-20.20s","","(incomplete)");
+ } else {
+ printf("%-8.8s%-20.20s", xhw->name, hwa);
+ }
+
+ printf("%-6.6s%-15.15s %s\n", flags,mask,dev);
+}
+
+/* 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)
+{
+ struct hwtype *xhw;
+
+ xhw = get_hwntype(type);
+ if (xhw == NULL)
+ xhw = get_hwtype(DFLT_HW);
+
+
+
+ printf("%s (%s) at ", name, ip);
+
+ if (!(arp_flags & ATF_COM)) {
+ if (arp_flags & ATF_PUBL)
+ printf("* ");
+ else
+ printf("<incomplete> ");
+ } else {
+ printf("%s [%s] ", hwa, xhw->name);
+ }
- printf("%-23.23s\t%-8.8s", sp, xhw->name);
- printf("%-20.20s%-6.6s%-15.15s %s\n", hwa, flags,mask,dev);
+ if (arp_flags & ATF_NETMASK)
+ printf("netmask %s ", mask);
+
+ if (arp_flags & ATF_PERM) printf("PERM ");
+ if (arp_flags & ATF_PUBL) printf("PUP ");
+#ifdef HAVE_ATF_MAGIC
+ if (arp_flags & ATF_MAGIC) printf("AUTO ");
+#endif
+#ifdef HAVE_ATF_DONTPUB
+ if (arp_flags & ATF_DONTPUB) printf("DONTPUB ");
+#endif
+ if (arp_flags & ATF_USETRAILERS) printf("TRAIL ");
+
+ printf("on %s\n", dev);
}
@@ -393,6 +581,7 @@ arp_show(char *name)
char dev[100];
int type,flags;
FILE *fp;
+ char *hostname;
int num,entries=0,showed=0;
host[0]='\0';
@@ -437,17 +626,38 @@ arp_show(char *name)
/* if the user specified device differs, skip it */
if (device[0] && strcmp(dev,device))
continue;
- showed++;
- arp_disp_2(ip,type,flags,hwa,mask,dev);
+
+ showed++;
+ /* This IS ugly but it works -be */
+ if (opt_n)
+ hostname="?";
+ else {
+ if (ap->input(0, ip,&sa) < 0)
+ hostname=ip;
+ else
+ hostname = ap->sprint(&sa, opt_n | 0x8000);
+ if (strcmp(hostname, ip)==0)
+ hostname="?";
+ }
+
+ if (opt_e)
+ arp_disp_2(hostname[0]=='?'?ip:hostname,type,flags,hwa,mask,dev);
+ else
+ arp_disp(hostname,ip,type,flags,hwa,mask,dev);
}
}
if (opt_v)
printf(NLS_CATGETS(catfd, arpSet, arp_sum,
- "Entries: %d\tSkiped: %d\tFound: %d\n"),entries,entries-showed,showed);
+ "Entries: %d\tSkipped: %d\tFound: %d\n"),entries,entries-showed,showed);
- if (!showed && (hw_set || host[0] || device[0]))
- printf(NLS_CATGETS(catfd, arpSet, arp_none,
- "arp: in %d entries no match found.\n"),entries);
+ if (!showed) {
+ if (host[0] && !opt_a)
+ printf("%s (%s) -- no entry\n", name, host);
+ else if (hw_set || host[0] || device[0]) {
+ printf(NLS_CATGETS(catfd, arpSet, arp_none,
+ "arp: in %d entries no match found.\n"),entries);
+ }
+ }
(void) fclose(fp);
return(0);
}
@@ -466,9 +676,9 @@ usage(void)
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage1,
"Usage: arp [-vn] [-H type] [-i if] -a [hostname]\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage2,
- " arp [-v] [-i if] -d hostname [pub]\n"));
+ " arp [-v] [-i if] -d hostname [pub][nopub]\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage3,
- " arp [-v] [-H type] [-i if] -s hostname hw_addr [temp]\n"));
+ " arp [-v] [-H type] [-i if] -s hostname hw_addr [temp][nopub]\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage4,
" arp [-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage5,
@@ -487,7 +697,7 @@ main(int argc, char **argv)
{
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
- {"display", 0, 0, 'a'},
+ {"all", 0, 0, 'a'},
{"delete", 0, 0, 'd'},
{"file", 0, 0, 'f'},
{"numeric", 0, 0, 'n'},
@@ -519,23 +729,29 @@ main(int argc, char **argv)
NLS_CATCLOSE(catfd)
return(-1);
}
- what = -1;
+ what = 0;
/* Fetch the command-line arguments. */
/* opterr = 0; */
- while ((i = getopt_long(argc, argv, "A:H:adfp:nsi:t:vh?DNV",longopts, &lop)) != EOF) switch(i) {
+ while ((i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV",longopts, &lop)) != EOF) switch(i) {
case 'a':
what = 1;
+ opt_a = 1;
+ break;
+ case 'f':
+ what = 2;
break;
-
case 'd':
what = 3;
break;
-
- case 'f':
- what = 2;
+ case 's':
+ what = 4;
break;
+
+ case 'e':
+ opt_e = 1;
+ break;
case 'n':
opt_n = FLAG_NUM;
break;
@@ -546,6 +762,10 @@ main(int argc, char **argv)
opt_N = FLAG_SYM;
fprintf(stderr,"arp: -N not yet supported.\n");
break;
+ case 'v':
+ opt_v = 1;
+ break;
+
case 'A':
case 'p':
ap = get_aftype(optarg);
@@ -557,11 +777,6 @@ main(int argc, char **argv)
exit(-1);
}
break;
-
- case 's':
- what = 4;
- break;
-
case 'H':
case 't':
hw = get_hwtype(optarg);
@@ -579,13 +794,8 @@ main(int argc, char **argv)
device[sizeof(device)-1]='\0';
break;
- case 'v':
- opt_v = 1;
- break;
-
case 'V':
version();
-
case '?':
case 'h':
default:
@@ -615,6 +825,11 @@ main(int argc, char **argv)
/* Now see what we have to do here... */
switch(what) {
+ case 0:
+ opt_e = 1;
+ what = arp_show(argv[optind]);
+ break;
+
case 1: /* show an ARP entry in the cache */
what = arp_show(argv[optind]);
break;