arp: Use SIOCGNBRINFO to display neighbor state information

This commit is contained in:
roy 2020-09-11 15:28:29 +00:00
parent 3a97901738
commit 222abc89f8
5 changed files with 148 additions and 9 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: arp.8,v 1.24 2018/07/06 00:50:05 christos Exp $
.\" $NetBSD: arp.8,v 1.25 2020/09/11 15:28:29 roy Exp $
.\"
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)arp.8 8.2 (Berkeley) 4/27/95
.\"
.Dd July 5, 2018
.Dd September 11, 2020
.Dt ARP 8
.Os
.Sh NAME
@ -69,6 +69,27 @@ entry for
The host may be specified by name or by number,
using Internet dot notation.
.Pp
The state of the arp entry is shown as a single letter preceeded by the
time the state is applicable for:
.Bl -tag -width indent -compact
.It D
Delay
.It I
Incomplete
.It N
Nostate
.It P
Probe
.It R
Reachable
.It S
Stale
.It W
Waitdelete
.It ?
Unknown state (should never happen).
.El
.Pp
Available options:
.Bl -tag -width Ds
.It Fl a

View File

@ -1,4 +1,4 @@
/* $NetBSD: arp.c,v 1.65 2019/02/28 01:20:25 nonaka Exp $ */
/* $NetBSD: arp.c,v 1.66 2020/09/11 15:28:29 roy Exp $ */
/*
* Copyright (c) 1984, 1993
@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1984, 1993\
#if 0
static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: arp.c,v 1.65 2019/02/28 01:20:25 nonaka Exp $");
__RCSID("$NetBSD: arp.c,v 1.66 2020/09/11 15:28:29 roy Exp $");
#endif
#endif /* not lint */
@ -60,8 +60,10 @@ __RCSID("$NetBSD: arp.c,v 1.65 2019/02/28 01:20:25 nonaka Exp $");
#include <net/if_dl.h>
#include <net/if_ether.h>
#include <net/if_types.h>
#include <net/nd.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_inarp.h>
#include <arpa/inet.h>
@ -92,6 +94,8 @@ static int getsocket(void);
static int getetheraddr(struct in_addr, struct sockaddr_dl *);
static struct rt_msghdr * rtmsg(const int, const int, struct rt_msghdr *,
const struct sockaddr_inarp *, const struct sockaddr_dl *);
static struct in_nbrinfo * getnbrinfo(const char *, struct in_addr *);
static const char * sec2str(time_t);
static int set(int, char **);
static void usage(void) __dead;
@ -439,6 +443,8 @@ dump(uint32_t addr)
struct sockaddr_inarp *sina;
struct sockaddr_dl *sdl;
struct hostent *hp;
struct timeval tim;
struct in_nbrinfo *nbi;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
@ -497,6 +503,49 @@ dump(uint32_t addr)
if (sina->sin_len != 8)
(void)printf("(weird)");
}
if (sdl->sdl_index == 0)
goto done;
(void)gettimeofday(&tim, 0);
nbi = getnbrinfo(ifname, &sina->sin_addr);
if (nbi != NULL) {
if (nbi->expire > tim.tv_sec) {
(void)printf(" %s",
sec2str(nbi->expire - tim.tv_sec));
} else if (nbi->expire == 0)
(void)printf(" %s", "permanent");
else
(void)printf(" %s", "expired");
switch (nbi->state) {
case ND_LLINFO_NOSTATE:
(void)printf(" N");
break;
case ND_LLINFO_WAITDELETE:
(void)printf(" W");
break;
case ND_LLINFO_INCOMPLETE:
(void)printf(" I");
break;
case ND_LLINFO_REACHABLE:
(void)printf(" R");
break;
case ND_LLINFO_STALE:
(void)printf(" S");
break;
case ND_LLINFO_DELAY:
(void)printf(" D");
break;
case ND_LLINFO_PROBE:
(void)printf(" P");
break;
default:
(void)printf(" ?");
break;
}
}
done:
(void)printf("\n");
}
free(buf);
@ -800,3 +849,66 @@ getetheraddr(struct in_addr ipaddr, struct sockaddr_dl *sdl)
freeifaddrs(ifaddrs);
return -1;
}
static struct in_nbrinfo *
getnbrinfo(const char *ifname, struct in_addr *addr)
{
static struct in_nbrinfo nbi, *nbip;
int s;
if ((s = prog_socket(AF_INET, SOCK_DGRAM, 0)) == -1)
err(1, "socket");
(void)memset(&nbi, 0, sizeof(nbi));
(void)strlcpy(nbi.ifname, ifname, sizeof(nbi.ifname));
nbi.addr = *addr;
if (prog_ioctl(s, SIOCGNBRINFO, &nbi) == -1) {
warn("ioctl(SIOCGNBRINFO)");
nbip = NULL;
} else
nbip = &nbi;
(void)prog_close(s);
return nbip;
}
static const char *
sec2str(time_t total)
{
static char result[256];
int days, hours, mins, secs;
int first = 1;
char *p = result;
char *ep = &result[sizeof(result)];
int n;
days = total / 3600 / 24;
hours = (total / 3600) % 24;
mins = (total / 60) % 60;
secs = total % 60;
if (days) {
first = 0;
n = snprintf(p, (size_t)(ep - p), "%dd", days);
if (n < 0 || n >= ep - p)
return "?";
p += n;
}
if (!first || hours) {
first = 0;
n = snprintf(p, (size_t)(ep - p), "%dh", hours);
if (n < 0 || n >= ep - p)
return "?";
p += n;
}
if (!first || mins) {
first = 0;
n = snprintf(p, (size_t)(ep - p), "%dm", mins);
if (n < 0 || n >= ep - p)
return "?";
p += n;
}
(void)snprintf(p, (size_t)(ep - p), "%ds", secs);
return(result);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: arp_hostops.c,v 1.2 2019/02/27 23:29:50 dholland Exp $ */
/* $NetBSD: arp_hostops.c,v 1.3 2020/09/11 15:28:29 roy Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -28,9 +28,10 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: arp_hostops.c,v 1.2 2019/02/27 23:29:50 dholland Exp $");
__RCSID("$NetBSD: arp_hostops.c,v 1.3 2020/09/11 15:28:29 roy Exp $");
#endif /* !lint */
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
@ -45,6 +46,7 @@ const struct prog_ops prog_ops = {
.op_open = open,
.op_getpid = getpid,
.op_ioctl = ioctl,
.op_read = read,
.op_write = write,
.op_close = close,

View File

@ -1,4 +1,4 @@
/* $NetBSD: arp_rumpops.c,v 1.2 2019/02/27 23:29:50 dholland Exp $ */
/* $NetBSD: arp_rumpops.c,v 1.3 2020/09/11 15:28:29 roy Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: arp_rumpops.c,v 1.2 2019/02/27 23:29:50 dholland Exp $");
__RCSID("$NetBSD: arp_rumpops.c,v 1.3 2020/09/11 15:28:29 roy Exp $");
#endif /* !lint */
#include <sys/types.h>
@ -49,6 +49,7 @@ const struct prog_ops prog_ops = {
.op_open = rump_sys_open,
.op_getpid = rump_sys_getpid,
.op_ioctl = rump_sys_ioctl,
.op_read = rump_sys_read,
.op_write = rump_sys_write,
.op_close = rump_sys_close,

View File

@ -1,4 +1,4 @@
/* $NetBSD: prog_ops.h,v 1.2 2019/02/27 23:29:50 dholland Exp $ */
/* $NetBSD: prog_ops.h,v 1.3 2020/09/11 15:28:29 roy Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -43,6 +43,7 @@ struct prog_ops {
int (*op_open)(const char *, int, ...);
pid_t (*op_getpid)(void);
int (*op_ioctl)(int, unsigned long, ...);
ssize_t (*op_read)(int, void *, size_t);
ssize_t (*op_write)(int, const void *, size_t);
@ -54,6 +55,7 @@ extern const struct prog_ops prog_ops;
#define prog_socket prog_ops.op_socket
#define prog_open prog_ops.op_open
#define prog_getpid prog_ops.op_getpid
#define prog_ioctl prog_ops.op_ioctl
#define prog_read prog_ops.op_read
#define prog_write prog_ops.op_write
#define prog_close prog_ops.op_close
@ -63,6 +65,7 @@ extern const struct prog_ops prog_ops;
#define prog_socket socket
#define prog_open open
#define prog_getpid getpid
#define prog_ioctl ioctl
#define prog_read read
#define prog_write write
#define prog_close close