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