mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-18 02:19:39 +00:00
arp(8): fix by-interface and by-host filtering when using netlink
arp(8) has traditionally supported filtering by interface via -i and by hostname. However, this functionality was omitted from the initial netlink-ification of arp. This patch re-introduces this filtering functionality. This patch also improves by-interface filtering by storing and using the ifindex of the requested interface for filtering instead of comparing interface name strings Reviewed by: melifaro Sponsored by: Rubicon Communications, LLC ("Netgate")
This commit is contained in:
parent
dd0d16cc4d
commit
79278872ad
@ -98,8 +98,6 @@ static int get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr);
|
||||
static int set_rtsock(struct sockaddr_in *dst, struct sockaddr_dl *sdl_m,
|
||||
char *host);
|
||||
|
||||
static char *rifname;
|
||||
|
||||
struct if_nameindex *ifnameindex;
|
||||
|
||||
struct arp_opts opts = {};
|
||||
@ -146,7 +144,7 @@ main(int argc, char *argv[])
|
||||
SETFUNC(F_FILESET);
|
||||
break;
|
||||
case 'i':
|
||||
rifname = optarg;
|
||||
opts.rifname = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
@ -157,15 +155,15 @@ main(int argc, char *argv[])
|
||||
|
||||
if (!func)
|
||||
func = F_GET;
|
||||
if (rifname) {
|
||||
if (opts.rifname) {
|
||||
if (func != F_GET && !(func == F_DELETE && opts.aflag))
|
||||
xo_errx(1, "-i not applicable to this operation");
|
||||
if (if_nametoindex(rifname) == 0) {
|
||||
if ((opts.rifindex = if_nametoindex(opts.rifname)) == 0) {
|
||||
if (errno == ENXIO)
|
||||
xo_errx(1, "interface %s does not exist",
|
||||
rifname);
|
||||
opts.rifname);
|
||||
else
|
||||
xo_err(1, "if_nametoindex(%s)", rifname);
|
||||
xo_err(1, "if_nametoindex(%s)", opts.rifname);
|
||||
}
|
||||
}
|
||||
switch (func) {
|
||||
@ -179,7 +177,7 @@ main(int argc, char *argv[])
|
||||
xo_open_list("arp-cache");
|
||||
|
||||
struct in_addr all_addrs = {};
|
||||
print_entries(0, all_addrs);
|
||||
print_entries(opts.rifindex, all_addrs);
|
||||
|
||||
xo_close_list("arp-cache");
|
||||
xo_close_container("arp");
|
||||
@ -448,13 +446,13 @@ get(char *host)
|
||||
xo_open_container("arp");
|
||||
xo_open_list("arp-cache");
|
||||
|
||||
found = print_entries(0, addr->sin_addr);
|
||||
found = print_entries(opts.rifindex, addr->sin_addr);
|
||||
|
||||
if (found == 0) {
|
||||
xo_emit("{d:hostname/%s} ({d:ip-address/%s}) -- no entry",
|
||||
host, inet_ntoa(addr->sin_addr));
|
||||
if (rifname)
|
||||
xo_emit(" on {d:interface/%s}", rifname);
|
||||
if (opts.rifname)
|
||||
xo_emit(" on {d:interface/%s}", opts.rifname);
|
||||
xo_emit("\n");
|
||||
}
|
||||
|
||||
@ -552,7 +550,6 @@ search(u_long addr, action_fn *action)
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr_in *sin2;
|
||||
struct sockaddr_dl *sdl;
|
||||
char ifname[IF_NAMESIZE];
|
||||
int st, found_entry = 0;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
@ -586,14 +583,13 @@ search(u_long addr, action_fn *action)
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
sin2 = (struct sockaddr_in *)(rtm + 1);
|
||||
sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
|
||||
if (rifname && if_indextoname(sdl->sdl_index, ifname) &&
|
||||
strcmp(ifname, rifname))
|
||||
if (opts.rifindex &&
|
||||
(opts.rifindex != sdl->sdl_index))
|
||||
continue;
|
||||
if (addr) {
|
||||
if (addr != sin2->sin_addr.s_addr)
|
||||
continue;
|
||||
found_entry = 1;
|
||||
}
|
||||
if (addr &&
|
||||
(addr != sin2->sin_addr.s_addr))
|
||||
continue;
|
||||
found_entry = 1;
|
||||
(*action)(sdl, sin2, rtm);
|
||||
}
|
||||
free(buf);
|
||||
|
@ -10,6 +10,8 @@ struct arp_opts {
|
||||
bool nflag;
|
||||
time_t expire_time;
|
||||
int flags;
|
||||
char *rifname;
|
||||
unsigned int rifindex;
|
||||
};
|
||||
extern struct arp_opts opts;
|
||||
|
||||
|
@ -281,6 +281,7 @@ print_entries_nl(uint32_t ifindex, struct in_addr addr)
|
||||
struct ndmsg *ndmsg = snl_reserve_msg_object(&nw, struct ndmsg);
|
||||
if (ndmsg != NULL) {
|
||||
ndmsg->ndm_family = AF_INET;
|
||||
/* let kernel filter results by interface if provided */
|
||||
ndmsg->ndm_ifindex = ifindex;
|
||||
}
|
||||
|
||||
@ -296,6 +297,7 @@ print_entries_nl(uint32_t ifindex, struct in_addr addr)
|
||||
|
||||
while ((hdr = snl_read_reply_multi(&ss_req, nlmsg_seq, &e)) != NULL) {
|
||||
struct snl_parsed_neigh neigh = {};
|
||||
struct sockaddr_in *neighaddr;
|
||||
|
||||
if (!snl_parse_nlmsg(&ss_req, hdr, &snl_rtm_neigh_parser, &neigh))
|
||||
continue;
|
||||
@ -307,6 +309,12 @@ print_entries_nl(uint32_t ifindex, struct in_addr addr)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter results based on host if provided */
|
||||
neighaddr = (struct sockaddr_in *)neigh.nda_dst;
|
||||
if (addr.s_addr &&
|
||||
(addr.s_addr != neighaddr->sin_addr.s_addr))
|
||||
continue;
|
||||
|
||||
print_entry(&neigh, &link);
|
||||
count++;
|
||||
snl_clear_lb(&ss_req);
|
||||
|
Loading…
Reference in New Issue
Block a user