Date: Sun, 6 Jul 2003 20:15:54 +0400 (MSD) From: Dmitry Morozovsky <marck@rinet.ru> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/54151: [PATCH] -i (restrict to one interface) patch from arp(8) Message-ID: <200307061615.h66GFsBe020532@woozle.rinet.ru> Resent-Message-ID: <200307061620.h66GKHQf026619@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200307061615.h66GFsBe020532>