--- arp.c.orig 2010-01-29 23:27:01.000000000 +0300 +++ arp.c 2010-01-29 23:35:28.000000000 +0300 @@ -485,6 +485,21 @@ return (1); } +struct arpent { + in_addr_t addr; + char *ent; +}; + +static int arpent_compare(const void *a, const void *b) { + struct arpent *aa = (struct arpent*)a; + struct arpent *bb = (struct arpent*)b; + if (aa->addr < bb->addr) + return -1; + if (aa->addr > bb->addr) + return 1; + return 0; +} + /* * Search the arp table and do some action on matching entries */ @@ -531,8 +546,28 @@ if (st == -1) err(1, "actual retrieval of routing table"); lim = buf + needed; + + int entcount = 0, i; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; + entcount++; + } + + struct arpent *arpents = malloc(sizeof(struct arpent)*entcount); + if (arpents == NULL) + errx(1, "could not reallocate memory"); + for (next = buf, i = 0; next < lim; next += rtm->rtm_msglen, i++) { + rtm = (struct rt_msghdr *)next; + sin2 = (struct sockaddr_inarp *)(rtm + 1); + arpents[i].addr = htonl(sin2->sin_addr.s_addr); + arpents[i].ent = next; + } + + qsort(arpents, entcount, sizeof(struct arpent), arpent_compare); + + for (i = 0; i < entcount; i++) { + next = arpents[i].ent; + rtm = (struct rt_msghdr *)next; sin2 = (struct sockaddr_inarp *)(rtm + 1); sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2)); if (rifname && if_indextoname(sdl->sdl_index, ifname) && @@ -546,6 +581,7 @@ (*action)(sdl, sin2, rtm); } free(buf); + free(arpents); return (found_entry); }