Subject: bin/8566: [rkb] Make 'arp(8)' output interface associated with each ARP entry
To: None <gnats-bugs@gnats.netbsd.org>
From: None <rafal@mediaone.net>
List: netbsd-bugs
Date: 10/06/1999 04:36:45
>Number:         8566
>Category:       bin
>Synopsis:       an option to print the interface name for ARP entries is added
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed Oct  6 04:35:00 1999
>Last-Modified:
>Originator:     Rafal Boni
>Organization:
	...me organized? Ha!
>Release:        -current as of 10/4
>Environment:
System: NetBSD groo-the-wanderer.waterside.net 1.4K NetBSD 1.4K (GROO) #2: Mon Aug 30 07:10:25 EDT 1999 root@groo-the-wanderer.waterside.net:/usr/src/sys/arch/i386/compile/GROO i386


>Description:
	arp(8) does not print which interface an ARP entry is associated with.
	On machines multihomed machines, it's often useful to know which 
	interface the ARP entry is associated with (for debugging network
	topologies, etc.)

>How-To-Repeat:
	Run arp.  See that no interface is printed.
>Fix:

Index: arp.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/arp/arp.c,v
retrieving revision 1.23
diff -b -u -r1.23 arp.c
--- arp.c	1998/02/10 03:45:06	1.23
+++ arp.c	1999/10/06 11:17:56
@@ -58,6 +58,7 @@
 #include <sys/file.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
+#include <sys/ioctl.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -81,6 +82,7 @@
 int	delete __P((const char *, const char *));
 void	dump __P((u_long));
 void	sdl_print __P((const struct sockaddr_dl *));
+int	getifname __P((u_int16_t, char *));
 int	atosdl __P((const char *s, struct sockaddr_dl *sdl));
 int	file __P((char *));
 void	get __P((const char *));
@@ -94,7 +96,11 @@
 static int pid;
 static int nflag, vflag;
 static int s = -1;
+static int is = -1;
 
+static struct ifconf ifc;
+static char ifconfbuf[8192];
+
 int	delete __P((const char *, const char *));
 void	dump __P((u_long));
 void	ether_print __P((const u_char *));
@@ -390,6 +396,7 @@
 {
 	int mib[6];
 	size_t needed;
+	char ifname[IF_NAMESIZE];
 	char *host, *lim, *buf, *next;
 	struct rt_msghdr *rtm;
 	struct sockaddr_inarp *sin;
@@ -438,6 +445,12 @@
 			sdl_print(sdl);
 		else
 			(void)printf("(incomplete)");
+
+		if (sdl->sdl_index) {
+			if (getifname(sdl->sdl_index, ifname) == 0)
+				printf(" on %s", ifname);
+		}
+
 		if (rtm->rtm_rmx.rmx_expire == 0)
 			(void)printf(" permanent");
 		if (sin->sin_other & SIN_PROXY)
@@ -607,4 +620,58 @@
 	}
 	(void)memcpy(inap, hp->h_addr, sizeof(*inap));
 	return (0);
+}
+
+int
+getifname(ifindex, ifname)
+	u_int16_t ifindex;
+	char* ifname;
+{
+	int i, idx, siz;
+	char ifrbuf[8192];
+	struct ifreq ifreq, *ifr;
+	const struct sockaddr_dl *sdl = NULL;
+
+	if (is < 0) {
+		is = socket(PF_INET, SOCK_DGRAM, 0);
+		if (is < 0)
+			err(1, "socket");
+
+		ifc.ifc_len = sizeof(ifconfbuf);
+		ifc.ifc_buf = ifconfbuf;
+
+		if (ioctl(is, SIOCGIFCONF, &ifc) < 0) {
+			close(is);
+			err(1, "SIOCGIFCONF");
+			is = -1;
+		}
+	}
+
+	ifr = ifc.ifc_req;
+	ifreq.ifr_name[0] = '\0';
+	for (i = 0, idx = 0; i < ifc.ifc_len; ) {
+		ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
+		siz = sizeof(ifr->ifr_name) +
+			(ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
+				? ifr->ifr_addr.sa_len
+				: sizeof(struct sockaddr));
+		i += siz;
+		/* avoid alignment issue */
+		if (sizeof(ifrbuf) < siz)
+			errx(1, "ifr too big");
+
+		memcpy(ifrbuf, ifr, siz);
+		ifr = (struct ifreq *)ifrbuf;
+
+		if (ifr->ifr_addr.sa_family != AF_LINK)
+			continue;
+
+		sdl = (const struct sockaddr_dl *) &ifr->ifr_addr;
+		if (sdl && sdl->sdl_index == ifindex) {
+			(void) strncpy(ifname, ifr->ifr_name, IF_NAMESIZE);
+			return 0;
+		}
+	}
+
+	return -1;
 }
>Audit-Trail:
>Unformatted: