bin/76075: arp program failures due to ARP table growth
Maxim Konovalov
maxim at macomnet.ru
Sat Jan 22 18:20:25 PST 2005
The following reply was made to PR bin/76075; it has been noted by GNATS.
From: Maxim Konovalov <maxim at macomnet.ru>
To: Dmitrij Tejblum <tejblum at yandex-team.ru>
Cc: bug-followup at freebsd.org
Subject: Re: bin/76075: arp program failures due to ARP table growth
Date: Sun, 23 Jan 2005 05:16:35 +0300 (MSK)
[...]
> >Description:
>
> The arp -an command sometimes fail with
>
> arp: actual retrieval of routing table: Cannot allocate memory
>
> if ARP tables has been grown after its size was estimated.
>
> >How-To-Repeat:
> >Fix:
>
> Allocate a bit more memory for ARP table, so the event will be less likely.
>
>
> --- arp.c Tue Jan 11 02:00:45 2005
> +++ arp.c Tue Jan 11 02:05:15 2005
> @@ -471,10 +471,11 @@
> mib[5] = RTF_LLINFO;
> if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
> err(1, "route-sysctl-estimate");
> if (needed == 0) /* empty table */
> return 0;
> + needed += needed / 2;
> if ((buf = malloc(needed)) == NULL)
> err(1, "malloc");
> if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
> err(1, "actual retrieval of routing table");
> lim = buf + needed;
What is your opinion about an enclosed diff (a bit more adaptable
algorithm stolen from killall(1))?
Index: arp.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/arp/arp.c,v
retrieving revision 1.54
diff -u -r1.54 arp.c
--- arp.c 24 Dec 2004 22:16:38 -0000 1.54
+++ arp.c 23 Jan 2005 02:14:10 -0000
@@ -456,12 +456,12 @@
{
int mib[6];
size_t needed;
- char *lim, *buf, *next;
+ char *lim, *buf, *newbuf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin2;
struct sockaddr_dl *sdl;
char ifname[IF_NAMESIZE];
- int found_entry = 0;
+ int st, found_entry = 0;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
@@ -475,7 +475,19 @@
return 0;
if ((buf = malloc(needed)) == NULL)
err(1, "malloc");
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+ st = sysctl(mib, 6, NULL, &needed, NULL, 0);
+ do {
+ needed += needed / 2;
+ newbuf = realloc(buf, needed);
+ if (newbuf == NULL) {
+ if (buf != NULL)
+ free(buf);
+ errx(1, "could not reallocate memory");
+ }
+ buf = newbuf;
+ st = sysctl(mib, 6, buf, &needed, NULL, 0);
+ } while (st == -1 && errno == ENOMEM);
+ if (st == -1)
err(1, "actual retrieval of routing table");
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
%%%
--
Maxim Konovalov
More information about the freebsd-bugs
mailing list