bin/54151: [PATCH] -i (restrict to one interface) patch from arp(8)

Dmitry Morozovsky marck at rinet.ru
Sun Jul 6 09:20:19 PDT 2003


>Number:         54151
>Category:       bin
>Synopsis:       [PATCH] -i (restrict to one interface) patch from arp(8)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 06 09:20:16 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Dmitry Morozovsky
>Release:        FreeBSD 4-STABLE i386
>Organization:
Cronyx Plus LLC (RiNet ISP)
>Environment:
System: FreeBSD 4-STABLE 


>Description:

Router with many ARP-enabled interfaces, such as inter-vlan router may have
very long ARP table. It is very usefult to have ability to view ARP table for
one onterface. Provided patches implements -i option and may be applied both to
-STABLE and -CURRENT.

The second patch adds checking for interface existance (I'm not sure whether
it's worth to blow /usr/sbin/arp with this check, so make it as independent
patch).

>How-To-Repeat:

>Fix:

*** PATCH 1

Index: usr.sbin/arp/arp.8
===================================================================
RCS file: /home/ncvs/src/usr.sbin/arp/arp.8,v
retrieving revision 1.8.2.11
diff -u -r1.8.2.11 arp.8
--- usr.sbin/arp/arp.8	11 Mar 2003 21:13:48 -0000	1.8.2.11
+++ usr.sbin/arp/arp.8	6 Jul 2003 14:23:14 -0000
@@ -41,9 +41,11 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl n
+.Op Fl i Ar ifname
 .Ar hostname
 .Nm
 .Op Fl n
+.Op Fl i Ar ifname
 .Fl a
 .Nm
 .Fl d Ar hostname
@@ -99,6 +101,11 @@
 flag may be combined with the
 .Fl a
 flag to delete all entries.
+.It Fl i Ar ifname
+Restrict searching for
+.Tn ARP
+entries to single interface
+.Ar ifname .
 .It Fl n
 Show network addresses as numbers (normally
 .Nm
Index: usr.sbin/arp/arp.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/arp/arp.c,v
retrieving revision 1.22.2.12
diff -u -r1.22.2.12 arp.c
--- usr.sbin/arp/arp.c	16 Apr 2003 10:02:37 -0000	1.22.2.12
+++ usr.sbin/arp/arp.c	6 Jul 2003 14:23:14 -0000
@@ -103,6 +103,7 @@
 static int nflag;	/* no reverse dns lookups */
 static int aflag;	/* do it for all entries */
 static int s = -1;
+static char *rifname = NULL;
 
 struct	sockaddr_in so_mask;
 struct	sockaddr_inarp blank_sin, sin_m;
@@ -131,7 +132,7 @@
 	int rtn = 0;
 
 	pid = getpid();
-	while ((ch = getopt(argc, argv, "andfsS")) != -1)
+	while ((ch = getopt(argc, argv, "andfsSi:")) != -1)
 		switch((char)ch) {
 		case 'a':
 			aflag = 1;
@@ -151,6 +152,10 @@
 		case 'f' :
 			SETFUNC(F_FILESET);
 			break;
+		case 'i':
+			if ((rifname = optarg) == NULL)
+				errx(1, "out of memory");
+			break;
 		case '?':
 		default:
 			usage();
@@ -170,6 +175,8 @@
 
 	if (!func)
 		func = F_GET;
+	if (rifname && func != F_GET)
+		errx(1, "-i not applicable to non-read functions");
 	switch (func) {
 	case F_GET:
 		if (aflag) {
@@ -375,8 +382,11 @@
 	}
 	search(addr->sin_addr.s_addr, print_entry);
 	if (found_entry == 0) {
-		printf("%s (%s) -- no entry\n",
+		printf("%s (%s) -- no entry",
 		    host, inet_ntoa(addr->sin_addr));
+		if (rifname)
+			printf(" at %s", rifname);
+		printf("\n");
 		return(1);
 	}
 	return(0);
@@ -458,6 +468,7 @@
 	struct rt_msghdr *rtm;
 	struct sockaddr_inarp *sin2;
 	struct sockaddr_dl *sdl;
+	char ifname[IF_NAMESIZE];
 
 	mib[0] = CTL_NET;
 	mib[1] = PF_ROUTE;
@@ -476,6 +487,9 @@
 		rtm = (struct rt_msghdr *)next;
 		sin2 = (struct sockaddr_inarp *)(rtm + 1);
 		(char *)sdl = (char *)sin2 + ROUNDUP(sin2->sin_len);
+		if (rifname && if_indextoname(sdl->sdl_index, ifname) != NULL &&
+		    strcmp(ifname, rifname))
+			continue;
 		if (addr) {
 			if (addr != sin2->sin_addr.s_addr)
 				continue;
@@ -585,8 +599,8 @@
 usage(void)
 {
 	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-		"usage: arp [-n] hostname",
-		"       arp [-n] -a",
+		"usage: arp [-n] [-i ifname] hostname",
+		"       arp [-n] [-i ifname] -a",
 		"       arp -d hostname [pub]",
 		"       arp -d -a",
 		"       arp -s hostname ether_addr [temp] [pub]",



*** PATCH 2


--- arp.c.iflag	Sun Jul  6 18:23:31 2003
+++ arp.c	Sun Jul  6 20:01:18 2003
@@ -98,6 +98,8 @@
 int my_ether_aton(char *a, struct ether_addr *n);
 int rtmsg(int cmd);
 int get_ether_addr(u_int32_t ipaddr, struct ether_addr *hwaddr);
+char **getifnlist(void);
+int checkifname(char *ifname);
 
 static int pid;
 static int nflag;	/* no reverse dns lookups */
@@ -155,6 +157,8 @@
 		case 'i':
 			if ((rifname = optarg) == NULL)
 				errx(1, "out of memory");
+			if (checkifname(rifname) == 0)
+				errx(1, "no such interface: %s", rifname);
 			break;
 		case '?':
 		default:
@@ -216,6 +220,81 @@
 	}
 
 	return(rtn);
+}
+
+/*
+ * Get interface list
+ */
+#define	MIBSZ	6
+
+char **getifnlist(void)
+{
+	size_t	needed;
+	int	ifcount;
+	int	mib[MIBSZ];
+	char	*buf, *lim, *next;
+	struct	if_msghdr *ifm, *nextifm;
+	struct	sockaddr_dl *sdl;
+	char	*name, **ifnlist;
+
+	mib[0] = CTL_NET;
+	mib[1] = PF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_INET;	/* address family */
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = 0;
+
+	if (sysctl(mib, MIBSZ, NULL, &needed, NULL, 0) < 0)
+		errx(1, "iflist-sysctl-estimate");
+	if ((buf = malloc(needed)) == NULL)
+		errx(1, "malloc");
+	if (sysctl(mib, MIBSZ, buf, &needed, NULL, 0) < 0)
+		errx(1, "actual retrieval of interface table");
+	lim = buf + needed;
+
+	ifcount = 1;	/* reserve space for trailing NULL */
+	ifnlist = NULL;
+	next = buf;
+	while (next < lim) {
+		ifm = (struct if_msghdr *)next;
+		
+		if (ifm->ifm_type == RTM_IFINFO)
+			sdl = (struct sockaddr_dl *)(ifm + 1);
+		else
+			errx(1, "out of sync parsing NET_RT_IFLIST");
+
+		next += ifm->ifm_msglen;
+		while (next < lim) {
+			nextifm = (struct if_msghdr *)next;
+
+			if (nextifm->ifm_type != RTM_NEWADDR)
+				break;
+
+			next += nextifm->ifm_msglen;
+		}
+		name = malloc(sdl->sdl_nlen + 1);
+		if (name == NULL)
+			errx(1, "malloc");
+		strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
+		name[sdl->sdl_nlen] = '\0';
+		ifnlist = realloc(ifnlist, ifcount*sizeof(char *));
+		if (ifnlist == NULL)
+			errx(1, "malloc");
+		ifnlist[ifcount-1] = name;
+		ifnlist[ifcount] = NULL;
+		ifcount++;
+	}
+	return ifnlist;
+}
+
+int checkifname(char *ifname)
+{
+	char **ifl, *p;
+	ifl = getifnlist();
+	while ((p = *ifl++) != NULL)
+		if (strcmp(p, ifname) == 0)
+			return 1;
+	return 0;
 }
 
 /*
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list