Import NetBSD arp(8)

Behaviorally this port should already be largely on par with the
NetBSD 8 version, in that it sets the RTF_LLDATA flag on routing
socket requests to indicate that they target link-local data.

Many parts of the arp(8) functionality are currently not yet supported
by the operating system, largely due to lwIP not exposing appropriate
means of implementing them.

Change-Id: Icfac054b4deddda03eee4acf0e261aa48cd031ba
This commit is contained in:
David van Moolenbroek 2017-02-15 13:02:59 +00:00
parent 66dfcc8533
commit 04e82b7dc9
11 changed files with 1219 additions and 1 deletions

View File

@ -1010,6 +1010,7 @@
./usr/preserve minix-base
./usr/run minix-base
./usr/sbin minix-base
./usr/sbin/arp minix-base
./usr/sbin/audit-packages minix-base crypto
./usr/sbin/bpm minix-base crypto
./usr/sbin/btrace minix-base

View File

@ -591,6 +591,7 @@
./usr/libdata/debug/usr/libexec/rshd.debug minix-debug debug
./usr/libdata/debug/usr/mdec minix-debug
./usr/libdata/debug/usr/sbin minix-debug
./usr/libdata/debug/usr/sbin/arp.debug minix-debug debug
./usr/libdata/debug/usr/sbin/btrace.debug minix-debug debug
./usr/libdata/debug/usr/sbin/chroot.debug minix-debug debug
./usr/libdata/debug/usr/sbin/dev_mkdb.debug minix-debug debug

View File

@ -3249,6 +3249,7 @@
./usr/man/man3/zlib.3 minix-man
./usr/man/man4 minix-man
./usr/man/man4/aha1540.4 minix-man
./usr/man/man4/arp.4 minix-man
./usr/man/man4/at.4 minix-man
./usr/man/man4/atf-test-case.4 minix-man atf
./usr/man/man4/bios.4 minix-man
@ -3377,6 +3378,7 @@
./usr/man/man8/MAKEDEV.8 minix-man
./usr/man/man8/add_route.8 minix-man obsolete
./usr/man/man8/adduser.8 minix-man
./usr/man/man8/arp.8 minix-man
./usr/man/man8/atnormalize.8 minix-man
./usr/man/man8/autopart.8 minix-man
./usr/man/man8/backup.8 minix-man

View File

@ -3,7 +3,7 @@
.include <bsd.own.mk>
SUBDIR= \
SUBDIR= arp \
\
chroot \
dev_mkdb \

15
usr.sbin/arp/Makefile Normal file
View File

@ -0,0 +1,15 @@
# $NetBSD: Makefile,v 1.12 2015/07/29 06:07:35 ozaki-r Exp $
# from: @(#)Makefile 8.2 (Berkeley) 4/18/94
.include <bsd.own.mk>
RUMPPRG= arp
MAN= arp.4 arp.8
.PATH: ${.CURDIR}/../../lib/libc/net
RUMPSRCS= getifaddrs.c getnameinfo.c
.if (${MKRUMP} != "no")
CPPFLAGS+= -DRUMP_ACTION
.endif
.include <bsd.prog.mk>

123
usr.sbin/arp/arp.4 Normal file
View File

@ -0,0 +1,123 @@
.\" $NetBSD: arp.4,v 1.10 2003/09/07 16:22:24 wiz Exp $
.\"
.\" Copyright (c) 1985, 1986, 1988, 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)arp4.4 6.5 (Berkeley) 4/18/94
.\"
.Dd April 18, 1994
.Dt ARP 4
.Os
.Sh NAME
.Nm arp
.Nd Address Resolution Protocol
.Sh SYNOPSIS
.In netinet/if_ether.h
.Sh DESCRIPTION
The Address Resolution Protocol (ARP) is a protocol used to dynamically
map between Internet host addresses and Ethernet addresses.
It is used by all the Ethernet interface drivers.
It is not specific to Internet protocols or to Ethernet,
but this implementation currently supports only that combination.
.Pp
ARP caches Internet-Ethernet address mappings.
When an interface requests a mapping for an address not in the cache,
ARP queues the message which requires the mapping and broadcasts
a message on the associated network requesting the address mapping.
If a response is provided, the new mapping is cached and any pending
message is transmitted.
ARP will queue at most one packet while waiting for a response to a
mapping request;
only the most recently ``transmitted'' packet is kept.
If the target host does not respond after several requests,
the host is considered to be down for a short period (normally 20 seconds),
allowing an error to be returned to transmission attempts during this
interval.
The error is
.Er EHOSTDOWN
for a non-responding destination host, and
.Er EHOSTUNREACH
for a non-responding router.
.Pp
The ARP cache is stored in the system routing table as
dynamically-created host routes.
The route to a directly-attached Ethernet network is installed as a
.Dq cloning
route (one with the
.Dv RTF_CLONING
flag set),
causing routes to individual hosts on that network to be created on
demand.
These routes time out periodically (normally 20 minutes after validated;
entries are not validated when not in use).
An entry for a host which is not responding is a
.Dq reject
route (one with the
.Dv RTF_REJECT
flag set).
.Pp
ARP entries may be added, deleted or changed with the
.Xr arp 8
utility.
Manually-added entries may be temporary or permanent,
and may be
.Dq published ,
in which case the system will respond to ARP requests for that host
as if it were the target of the request.
.Pp
In the past,
ARP was used to negotiate the use of a trailer encapsulation.
This is no longer supported.
.Pp
ARP watches passively for hosts impersonating the local host (i.e. a host
which responds to an ARP mapping request for the local host's address).
.Sh DIAGNOSTICS
.Bl -diag
.It "duplicate IP address %x sent from ethernet address %x:%x:%x:%x:%x:%x."
ARP has discovered another host on the local network which responds to
mapping requests for its own Internet address with a different Ethernet
address, generally indicating that two hosts are attempting to use the
same Internet address.
.El
.Sh SEE ALSO
.Xr inet 4 ,
.Xr route 4 ,
.Xr arp 8 ,
.Xr ifconfig 8 ,
.Xr route 8
.sp
.Rs
.%A Plummer, D.
.%B "An Ethernet Address Resolution Protocol"
.%T RFC 826
.Re
.Rs
.%A Leffler, S.J.
.%A Karels, M.J.
.%B "Trailer Encapsulations"
.%T RFC 893
.Re

153
usr.sbin/arp/arp.8 Normal file
View File

@ -0,0 +1,153 @@
.\" $NetBSD: arp.8,v 1.23 2013/07/08 04:31:12 apb Exp $
.\"
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)arp.8 8.2 (Berkeley) 4/27/95
.\"
.Dd July 8, 2013
.Dt ARP 8
.Os
.Sh NAME
.Nm arp
.Nd address resolution display and control
.Sh SYNOPSIS
.Nm
.Op Fl n
.Ar hostname
.Nm
.Op Fl nv
.Fl a
.Nm
.Op Fl v
.Fl d
.Fl a
.Nm
.Op Fl v
.Fl d Ar hostname
.Op Cm proxy
.Nm
.Fl s Ar hostname ether_addr
.Op Cm temp
.Op Cm pub Op Cm proxy
.Nm
.Fl f Ar filename
.Sh DESCRIPTION
The
.Nm
program displays and modifies the Internet-to-Ethernet address translation
tables used by the address resolution protocol
.Pq Xr arp 4 .
With no flags, the program displays the current
.Tn ARP
entry for
.Ar hostname .
The host may be specified by name or by number,
using Internet dot notation.
.Pp
Available options:
.Bl -tag -width Ds
.It Fl a
The program displays all of the current
.Tn ARP
entries.
.It Fl d
A super-user may delete an entry for the host called
.Ar hostname
with the
.Fl d
flag.
If the
.Cm proxy
keyword is specified, only the published
.Dq proxy only
.Tn ARP
entry
for this host will be deleted.
If used with
.Fl a
instead of a
.Ar hostname ,
it will delete all arp entries.
.It Fl f
Causes the file
.Ar filename
to be read and multiple entries to be set in the
.Tn ARP
tables.
Entries in the file should be of the form
.Pp
.Bd -filled -offset indent -compact
.Ar hostname ether_addr
.Op Cm temp
.Op Cm pub
.Ed
.Pp
with argument meanings as described below.
.It Fl n
Show network addresses as numbers (normally
.Nm
attempts to display addresses symbolically).
.It Fl s Ar hostname ether_addr
Create an
.Tn ARP
entry for the host called
.Ar hostname
with the Ethernet address
.Ar ether_addr .
The Ethernet address is given as six hex bytes separated by colons.
The entry will be permanent unless the word
.Cm temp
is given in the command.
If the word
.Cm pub
is given, the entry will be "published"; i.e., this system will
act as an
.Tn ARP
server,
responding to requests for
.Ar hostname
even though the host address is not its own.
If the word
.Cm proxy
is also given, the published entry will be a
.Dq proxy only
entry.
.It Fl v
Display verbose information when adding or deleting
.Tn ARP
entries.
.El
.Sh SEE ALSO
.Xr inet 3 ,
.Xr arp 4 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.3 .

747
usr.sbin/arp/arp.c Normal file
View File

@ -0,0 +1,747 @@
/* $NetBSD: arp.c,v 1.53 2015/07/31 04:02:40 ozaki-r Exp $ */
/*
* Copyright (c) 1984, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Sun Microsystems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1984, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: arp.c,v 1.53 2015/07/31 04:02:40 ozaki-r Exp $");
#endif
#endif /* not lint */
/*
* arp - display, set, and delete arp table entries
*/
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_ether.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_inarp.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <nlist.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ifaddrs.h>
#include "prog_ops.h"
static int is_llinfo(const struct sockaddr_dl *, int);
static int delete(const char *, const char *);
static void dump(uint32_t);
static void delete_all(void);
static void sdl_print(const struct sockaddr_dl *);
static int getifname(u_int16_t, char *, size_t);
static int atosdl(const char *s, struct sockaddr_dl *sdl);
static int file(const char *);
static void get(const char *);
static int getinetaddr(const char *, struct in_addr *);
static int getsocket(void);
static struct rt_msghdr *
rtmsg(const int, const int, const struct sockaddr_inarp *,
const struct sockaddr_dl *);
static int set(int, char **);
static void usage(void) __dead;
static int aflag, nflag, vflag;
static struct sockaddr_in so_mask = {
.sin_len = 8,
.sin_addr = {
.s_addr = 0xffffffff
}
};
static struct sockaddr_inarp blank_sin = {
.sin_len = sizeof(blank_sin),
.sin_family = AF_INET
};
static struct sockaddr_dl blank_sdl = {
.sdl_len = sizeof(blank_sdl),
.sdl_family = AF_LINK
};
static int expire_time, flags, export_only, doing_proxy, found_entry;
int
main(int argc, char **argv)
{
int ch;
int op = 0;
setprogname(argv[0]);
while ((ch = getopt(argc, argv, "andsfv")) != -1)
switch((char)ch) {
case 'a':
aflag = 1;
break;
case 'd':
case 's':
case 'f':
if (op)
usage();
op = ch;
break;
case 'n':
nflag = 1;
break;
case 'v':
vflag = 1;
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (!op && aflag)
op = 'a';
if (prog_init && prog_init() == -1)
err(1, "init failed");
switch((char)op) {
case 'a':
dump(0);
break;
case 'd':
if (aflag && argc == 0)
delete_all();
else {
if (aflag || argc < 1 || argc > 2)
usage();
(void)delete(argv[0], argv[1]);
}
break;
case 's':
if (argc < 2 || argc > 7)
usage();
return (set(argc, argv) ? 1 : 0);
case 'f':
if (argc != 1)
usage();
return (file(argv[0]));
default:
if (argc != 1)
usage();
get(argv[0]);
break;
}
return (0);
}
/*
* Process a file to set standard arp entries
*/
static int
file(const char *name)
{
char *line, *argv[5];
int i, retval;
FILE *fp;
if (!strcmp(name, "-")) {
fp = stdin;
} else {
fp = fopen(name, "r");
if (fp == NULL) {
err(1, "Cannot open %s", name);
}
}
retval = 0;
for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL; free(line)) {
char **ap, *inputstring;
inputstring = line;
for (ap = argv; ap < &argv[sizeof(argv) / sizeof(argv[0])] &&
(*ap = stresep(&inputstring, " \t", '\\')) != NULL;) {
if (**ap != '\0')
ap++;
}
i = ap - argv;
if (i < 2) {
warnx("bad line: %s", line);
retval = 1;
continue;
}
if (set(i, argv))
retval = 1;
}
if (fp != stdin)
(void)fclose(fp);
return retval;
}
static int
getsocket(void)
{
int s;
s = prog_socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0)
err(1, "socket");
return s;
}
static int
getlink(const char *name, struct sockaddr_dl *sdl)
{
struct ifaddrs *ifap, *ifa;
if (getifaddrs(&ifap) != 0) {
warn("getifaddrs");
return 0;
}
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
if (strcmp(ifa->ifa_name, name) != 0)
continue;
memcpy(sdl, ifa->ifa_addr, sizeof(*sdl));
freeifaddrs(ifap);
return 1;
}
freeifaddrs(ifap);
return 0;
}
/*
* Set an individual arp entry
*/
static int
set(int argc, char **argv)
{
struct sockaddr_inarp *sina;
struct sockaddr_dl *sdl;
struct rt_msghdr *rtm;
char *host = argv[0], *eaddr;
struct sockaddr_inarp sin_m = blank_sin; /* struct copy */
struct sockaddr_dl sdl_m = blank_sdl; /* struct copy */
int s;
eaddr = argv[1];
s = getsocket();
argc -= 2;
argv += 2;
if (getinetaddr(host, &sin_m.sin_addr) == -1)
return (1);
if (atosdl(eaddr, &sdl_m))
warnx("invalid link-level address '%s'", eaddr);
doing_proxy = flags = export_only = expire_time = 0;
for (; argc-- > 0; argv++) {
if (strncmp(argv[0], "temp", 4) == 0) {
struct timeval timev;
(void)gettimeofday(&timev, 0);
expire_time = timev.tv_sec + 20 * 60;
}
else if (strncmp(argv[0], "pub", 3) == 0) {
flags |= RTF_ANNOUNCE;
doing_proxy = SIN_PROXY;
if (argc && strncmp(argv[1], "pro", 3) == 0) {
export_only = 1;
argc--; argv++;
}
} else if (strncmp(argv[0], "trail", 5) == 0) {
warnx("%s: Sending trailers is no longer supported",
host);
} else if (strcmp(argv[0], "ifscope") == 0) {
if (argc == 0) {
warnx("missing interface for ifscope");
continue;
}
argc--;
argv++;
if (!getlink(argv[0], &sdl_m))
warnx("cannot get link address for %s", argv[0]);
}
}
if (memcmp(&sdl_m, &blank_sdl, sizeof(blank_sdl)))
goto out;
tryagain:
rtm = rtmsg(s, RTM_GET, &sin_m, &sdl_m);
if (rtm == NULL) {
warn("%s", host);
return (1);
}
sina = (struct sockaddr_inarp *)(void *)(rtm + 1);
sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(sina->sin_len) +
(char *)(void *)sina);
if (sina->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
if (is_llinfo(sdl, rtm->rtm_flags))
goto overwrite;
if (doing_proxy == 0) {
warnx("set: can only proxy for %s", host);
return (1);
}
if (sin_m.sin_other & SIN_PROXY) {
warnx("set: proxy entry exists for non 802 device");
return (1);
}
sin_m.sin_other = SIN_PROXY;
export_only = 1;
goto tryagain;
}
overwrite:
if (sdl->sdl_family != AF_LINK) {
warnx("cannot intuit interface index and type for %s",
host);
return (1);
}
sdl_m.sdl_type = sdl->sdl_type;
sdl_m.sdl_index = sdl->sdl_index;
out:
sin_m.sin_other = 0;
if (doing_proxy && export_only)
sin_m.sin_other = SIN_PROXY;
rtm = rtmsg(s, RTM_ADD, &sin_m, &sdl_m);
if (vflag)
(void)printf("%s (%s) added\n", host, eaddr);
return (rtm == NULL) ? 1 : 0;
}
/*
* Display an individual arp entry
*/
static void
get(const char *host)
{
struct sockaddr_inarp sin = blank_sin; /* struct copy */
if (getinetaddr(host, &sin.sin_addr) == -1)
exit(1);
dump(sin.sin_addr.s_addr);
if (found_entry == 0)
errx(1, "%s (%s) -- no entry", host, inet_ntoa(sin.sin_addr));
}
static int
is_llinfo(const struct sockaddr_dl *sdl, int rtflags)
{
if (sdl->sdl_family != AF_LINK ||
(rtflags & (RTF_LLINFO|RTF_GATEWAY)) != RTF_LLINFO)
return 0;
switch (sdl->sdl_type) {
case IFT_ETHER:
case IFT_FDDI:
case IFT_ISO88023:
case IFT_ISO88024:
case IFT_ISO88025:
case IFT_ARCNET:
return 1;
default:
return 0;
}
}
/*
* Delete an arp entry
*/
int
delete(const char *host, const char *info)
{
struct sockaddr_inarp *sina;
struct sockaddr_dl *sdl;
struct rt_msghdr *rtm;
struct sockaddr_inarp sin_m = blank_sin; /* struct copy */
struct sockaddr_dl sdl_m = blank_sdl; /* struct copy */
int s;
s = getsocket();
if (info && strncmp(info, "pro", 3) == 0)
sin_m.sin_other = SIN_PROXY;
if (getinetaddr(host, &sin_m.sin_addr) == -1)
return (1);
tryagain:
rtm = rtmsg(s, RTM_GET, &sin_m, &sdl_m);
if (rtm == NULL) {
warn("%s", host);
return (1);
}
sina = (struct sockaddr_inarp *)(void *)(rtm + 1);
sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(sina->sin_len) +
(char *)(void *)sina);
if (sina->sin_addr.s_addr == sin_m.sin_addr.s_addr &&
is_llinfo(sdl, rtm->rtm_flags))
goto delete;
if (sin_m.sin_other & SIN_PROXY) {
warnx("delete: can't locate %s", host);
return (1);
} else {
sin_m.sin_other = SIN_PROXY;
goto tryagain;
}
delete:
if (sdl->sdl_family != AF_LINK) {
(void)warnx("cannot locate %s", host);
return (1);
}
rtm = rtmsg(s, RTM_DELETE, &sin_m, sdl);
if (rtm == NULL)
return (1);
if (vflag)
(void)printf("%s (%s) deleted\n", host,
inet_ntoa(sin_m.sin_addr));
return (0);
}
/*
* Dump the entire arp table
*/
void
dump(uint32_t addr)
{
int mib[6];
size_t needed;
char ifname[IFNAMSIZ];
char *lim, *buf, *next;
const char *host;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sina;
struct sockaddr_dl *sdl;
struct hostent *hp;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if (needed == 0)
return;
if ((buf = malloc(needed)) == NULL)
err(1, "malloc");
if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
err(1, "actual retrieval of routing table");
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)(void *)next;
sina = (struct sockaddr_inarp *)(void *)(rtm + 1);
sdl = (struct sockaddr_dl *)(void *)
(RT_ROUNDUP(sina->sin_len) + (char *)(void *)sina);
if (addr) {
if (addr != sina->sin_addr.s_addr)
continue;
found_entry = 1;
}
if (nflag == 0)
hp = gethostbyaddr((const char *)(void *)
&(sina->sin_addr),
sizeof sina->sin_addr, AF_INET);
else
hp = NULL;
host = hp ? hp->h_name : "?";
(void)printf("%s (%s) at ", host, inet_ntoa(sina->sin_addr));
if (sdl->sdl_alen)
sdl_print(sdl);
else
(void)printf("(incomplete)");
if (sdl->sdl_index) {
if (getifname(sdl->sdl_index, ifname, sizeof(ifname)) == 0)
(void)printf(" on %s", ifname);
}
if (rtm->rtm_rmx.rmx_expire == 0)
(void)printf(" permanent");
if (sina->sin_other & SIN_PROXY)
(void)printf(" published (proxy only)");
if (rtm->rtm_addrs & RTA_NETMASK) {
sina = (struct sockaddr_inarp *)(void *)
(RT_ROUNDUP(sdl->sdl_len) + (char *)(void *)sdl);
if (sina->sin_addr.s_addr == 0xffffffff)
(void)printf(" published");
if (sina->sin_len != 8)
(void)printf("(weird)");
}
(void)printf("\n");
}
free(buf);
}
/*
* Delete the entire arp table
*/
void
delete_all(void)
{
int mib[6];
size_t needed;
char addr[sizeof("000.000.000.000\0")];
char *lim, *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sina;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if (needed == 0)
return;
if ((buf = malloc(needed)) == NULL)
err(1, "malloc");
if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
err(1, "actual retrieval of routing table");
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)(void *)next;
sina = (struct sockaddr_inarp *)(void *)(rtm + 1);
(void)snprintf(addr, sizeof(addr), "%s",
inet_ntoa(sina->sin_addr));
(void)delete(addr, NULL);
}
free(buf);
}
void
sdl_print(const struct sockaddr_dl *sdl)
{
char hbuf[NI_MAXHOST];
if (getnameinfo((const struct sockaddr *)(const void *)sdl,
(socklen_t)sdl->sdl_len,
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
(void)printf("<invalid>");
else
(void)printf("%s", hbuf);
}
static int
atosdl(const char *ss, struct sockaddr_dl *sdl)
{
int i;
unsigned long b;
char *endp;
char *p;
char *t, *r;
p = LLADDR(sdl);
endp = ((char *)(void *)sdl) + sdl->sdl_len;
i = 0;
b = strtoul(ss, &t, 16);
if (b > 255 || t == ss)
return 1;
*p++ = (char)b;
++i;
while ((p < endp) && (*t++ == ':')) {
b = strtoul(t, &r, 16);
if (b > 255 || r == t)
break;
*p++ = (char)b;
++i;
t = r;
}
sdl->sdl_alen = i;
return 0;
}
static void
usage(void)
{
const char *progname;
progname = getprogname();
(void)fprintf(stderr, "Usage: %s [-n] hostname\n", progname);
(void)fprintf(stderr, " %s [-nv] -a\n", progname);
(void)fprintf(stderr, " %s [-v] -d [-a|hostname [pub [proxy]]]\n",
progname);
(void)fprintf(stderr, " %s -s hostname ether_addr [temp] [pub [proxy]]\n",
progname);
(void)fprintf(stderr, " %s -f filename\n", progname);
exit(1);
}
static struct rt_msghdr *
rtmsg(const int s, const int cmd, const struct sockaddr_inarp *sin,
const struct sockaddr_dl *sdl)
{
static int seq;
struct rt_msghdr *rtm;
char *cp;
int l;
static struct {
struct rt_msghdr m_rtm;
char m_space[512];
} m_rtmsg;
pid_t pid;
rtm = &m_rtmsg.m_rtm;
cp = m_rtmsg.m_space;
errno = 0;
if (cmd == RTM_DELETE)
goto doit;
(void)memset(&m_rtmsg, 0, sizeof(m_rtmsg));
rtm->rtm_flags = flags;
rtm->rtm_version = RTM_VERSION;
switch (cmd) {
default:
errx(1, "internal wrong cmd");
/*NOTREACHED*/
case RTM_ADD:
rtm->rtm_addrs |= RTA_GATEWAY;
rtm->rtm_rmx.rmx_expire = expire_time;
rtm->rtm_inits = RTV_EXPIRE;
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
if (doing_proxy) {
if (!export_only) {
rtm->rtm_addrs |= RTA_NETMASK;
rtm->rtm_flags &= ~RTF_HOST;
}
}
/* FALLTHROUGH */
case RTM_GET:
rtm->rtm_addrs |= RTA_DST;
}
#define NEXTADDR(w, s) \
if (rtm->rtm_addrs & (w)) { \
(void)memcpy(cp, &s, \
(size_t)((const struct sockaddr *)&s)->sa_len); \
RT_ADVANCE(cp, ((const struct sockaddr *)&s)); \
}
NEXTADDR(RTA_DST, *sin);
NEXTADDR(RTA_GATEWAY, *sdl);
NEXTADDR(RTA_NETMASK, so_mask);
rtm->rtm_msglen = cp - (char *)(void *)&m_rtmsg;
doit:
l = rtm->rtm_msglen;
rtm->rtm_seq = ++seq;
rtm->rtm_type = cmd;
#ifdef __minix
/*
* Borrow from the future by setting the "this is a link-local request"
* flag on all routing socket requests. IMPORTANT: this change may be
* dropped with the resync to NetBSD 8 as it will do the same thing,
* although slightly differently (and hence may not create a conflict).
*/
rtm->rtm_flags |= RTF_LLDATA;
#endif /* __minix */
if (prog_write(s, &m_rtmsg, (size_t)l) < 0) {
if (errno != ESRCH || cmd != RTM_DELETE) {
warn("writing to routing socket");
return NULL;
}
}
pid = prog_getpid();
do {
l = prog_read(s, &m_rtmsg, sizeof(m_rtmsg));
} while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
if (l < 0)
warn("read from routing socket");
return rtm;
}
static int
getinetaddr(const char *host, struct in_addr *inap)
{
struct hostent *hp;
if (inet_aton(host, inap) == 1)
return (0);
if ((hp = gethostbyname(host)) == NULL) {
warnx("%s: %s", host, hstrerror(h_errno));
return (-1);
}
(void)memcpy(inap, hp->h_addr, sizeof(*inap));
return (0);
}
static int
getifname(u_int16_t ifindex, char *ifname, size_t l)
{
int i;
struct ifaddrs *addr;
const struct sockaddr_dl *sdl = NULL;
static struct ifaddrs* ifaddrs = NULL;
if (ifaddrs == NULL) {
i = getifaddrs(&ifaddrs);
if (i != 0)
err(1, "getifaddrs");
}
for (addr = ifaddrs; addr; addr = addr->ifa_next) {
if (addr->ifa_addr == NULL ||
addr->ifa_addr->sa_family != AF_LINK)
continue;
sdl = (const struct sockaddr_dl *)(void *)addr->ifa_addr;
if (sdl && sdl->sdl_index == ifindex) {
(void) strlcpy(ifname, addr->ifa_name, l);
return 0;
}
}
return -1;
}

View File

@ -0,0 +1,52 @@
/* $NetBSD: arp_hostops.c,v 1.1 2015/07/29 06:07:35 ozaki-r Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: arp_hostops.c,v 1.1 2015/07/29 06:07:35 ozaki-r Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <fcntl.h>
#include <unistd.h>
#include "prog_ops.h"
const struct prog_ops prog_ops = {
.op_socket = socket,
.op_open = open,
.op_getpid = getpid,
.op_read = read,
.op_write = write,
.op_sysctl = sysctl,
};

View File

@ -0,0 +1,56 @@
/* $NetBSD: arp_rumpops.c,v 1.1 2015/07/29 06:07:35 ozaki-r Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: arp_rumpops.c,v 1.1 2015/07/29 06:07:35 ozaki-r Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#include <rump/rumpclient.h>
#include "prog_ops.h"
const struct prog_ops prog_ops = {
.op_init = rumpclient_init,
.op_socket = rump_sys_socket,
.op_open = rump_sys_open,
.op_getpid = rump_sys_getpid,
.op_read = rump_sys_read,
.op_write = rump_sys_write,
.op_sysctl = rump_sys___sysctl,
};

68
usr.sbin/arp/prog_ops.h Normal file
View File

@ -0,0 +1,68 @@
/* $NetBSD: prog_ops.h,v 1.1 2015/07/29 06:07:35 ozaki-r Exp $ */
/*
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PROG_OPS_H_
#define _PROG_OPS_H_
#include <sys/types.h>
#ifndef CRUNCHOPS
/* XXX: Keep same order with netstat! */
struct prog_ops {
int (*op_init)(void);
int (*op_sysctl)(const int *, u_int, void *, size_t *,
const void *, size_t);
int (*op_socket)(int, int, int);
int (*op_open)(const char *, int, ...);
pid_t (*op_getpid)(void);
ssize_t (*op_read)(int, void *, size_t);
ssize_t (*op_write)(int, const void *, size_t);
};
extern const struct prog_ops prog_ops;
#define prog_init prog_ops.op_init
#define prog_socket prog_ops.op_socket
#define prog_open prog_ops.op_open
#define prog_getpid prog_ops.op_getpid
#define prog_read prog_ops.op_read
#define prog_write prog_ops.op_write
#define prog_sysctl prog_ops.op_sysctl
#else
#define prog_init ((int (*)(void))NULL)
#define prog_socket socket
#define prog_open open
#define prog_getpid getpid
#define prog_read read
#define prog_write write
#define prog_sysctl sysctl
#endif
#endif /* _PROG_OPS_H_ */