mirror of https://github.com/F-Stack/f-stack.git
Add tool: arp.
The arp utility displays and modifies the Internet-to-Ethernet address translation tables used by the address resolution protocol.
This commit is contained in:
parent
4ca4a48737
commit
df9cc249f2
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS=compat libutil libmemstat libxo libnetgraph sysctl ifconfig route top netstat ngctl ipfw
|
||||
SUBDIRS=compat libutil libmemstat libxo libnetgraph sysctl ifconfig route top netstat ngctl ipfw arp
|
||||
|
||||
all:
|
||||
for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done
|
||||
|
|
|
@ -198,6 +198,20 @@ Note [dummynet](https://www.freebsd.org/cgi/man.cgi?query=dummynet) is not suppo
|
|||
|
||||
For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?ipfw) or [handbook](https://www.freebsd.org/doc/handbook/firewalls-ipfw.html).
|
||||
|
||||
# arp
|
||||
Usage
|
||||
```
|
||||
usage: arp -p <f-stack proc_id> [-n] [-i interface] hostname
|
||||
arp -p <f-stack proc_id> [-n] [-i interface] -a
|
||||
arp -p <f-stack proc_id> -d hostname [pub]
|
||||
arp -p <f-stack proc_id> -d [-i interface] -a
|
||||
arp -p <f-stack proc_id> -s hostname ether_addr [temp] [reject | blackhole] [pub [only]]
|
||||
arp -p <f-stack proc_id> -S hostname ether_addr [temp] [reject | blackhole] [pub [only]]
|
||||
arp -p <f-stack proc_id> -f filename
|
||||
```
|
||||
|
||||
For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?arp).
|
||||
|
||||
# how to implement a custom tool for communicating with F-Stack process
|
||||
|
||||
Add a new FF_MSG_TYPE in ff_msg.h:
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# @(#)Makefile 8.2 (Berkeley) 4/18/94
|
||||
# $FreeBSD$
|
||||
|
||||
TOPDIR?=${CURDIR}/../..
|
||||
|
||||
PROG=arp
|
||||
|
||||
include ${TOPDIR}/tools/prog.mk
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
.\" 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.
|
||||
.\" 4. 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.
|
||||
.\"
|
||||
.\" @(#)arp4.4 6.5 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 5, 2013
|
||||
.Dt ARP 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm arp
|
||||
.Nd Address Resolution Protocol
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device ether"
|
||||
.Sh DESCRIPTION
|
||||
The Address Resolution Protocol (ARP) is used to dynamically
|
||||
map between Protocol Addresses (such as IP addresses) and
|
||||
Local Network Addresses (such as Ethernet addresses).
|
||||
This implementation maps IP addresses to Ethernet,
|
||||
ARCnet,
|
||||
or Token Ring addresses.
|
||||
It is used by all the Ethernet interface drivers.
|
||||
.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 allowing an error to be returned to
|
||||
transmission attempts.
|
||||
Further demand for this mapping causes ARP request retransmissions, that
|
||||
are ratelimited to one packet per second.
|
||||
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
|
||||
.Li 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).
|
||||
.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).
|
||||
.Pp
|
||||
Proxy ARP is a feature whereby the local host will respond to requests
|
||||
for addresses other than itself, with its own address.
|
||||
Normally, proxy ARP in
|
||||
.Fx
|
||||
is set up on a host-by-host basis using the
|
||||
.Xr arp 8
|
||||
utility, by adding an entry for each host inside a given subnet for
|
||||
which proxying of ARP requests is desired.
|
||||
However, the
|
||||
.Dq "proxy all"
|
||||
feature causes the local host to act as a proxy for
|
||||
.Em all
|
||||
hosts reachable through some other network interface,
|
||||
different from the one the request came in from.
|
||||
It may be enabled by setting the
|
||||
.Xr sysctl 8
|
||||
MIB variable
|
||||
.Va net.link.ether.inet.proxyall
|
||||
to 1.
|
||||
.Sh MIB Variables
|
||||
The ARP protocol implements a number of configurable variables in
|
||||
.Va net.link.ether.inet
|
||||
branch
|
||||
of the
|
||||
.Xr sysctl 3
|
||||
MIB.
|
||||
.Bl -tag -width "log_arp_permanent_modify"
|
||||
.It Va allow_multicast
|
||||
Should the kernel install ARP entries with multicast bit set in
|
||||
the hardware address.
|
||||
Installing such entries is RFC 1812 violation, but some prorietary
|
||||
load balancing techniques require routers on network to do so.
|
||||
Turned off by default.
|
||||
.It Va log_arp_movements
|
||||
Should the kernel log movements of IP addresses from one hardware
|
||||
address to an other.
|
||||
See
|
||||
.Sx DIAGNOSTICS
|
||||
below.
|
||||
Turned on by default.
|
||||
.It Va log_arp_permanent_modify
|
||||
Should the kernel log attempts of remote host on network to modify a
|
||||
permanent ARP entry.
|
||||
See
|
||||
.Sx DIAGNOSTICS
|
||||
below.
|
||||
Turned on by default.
|
||||
.It Va log_arp_wrong_iface
|
||||
Should the kernel log attempts to insert an ARP entry on an interface
|
||||
when the IP network the address belongs to is connected to an other
|
||||
interface.
|
||||
See
|
||||
.Sx DIAGNOSTICS
|
||||
below.
|
||||
Turned on by default.
|
||||
.It Va max_log_per_second
|
||||
Limit number of remotely triggered logging events to a configured value
|
||||
per second.
|
||||
Default is 1 log message per second.
|
||||
.It Va max_age
|
||||
How long an ARP entry is held in the cache until it needs to be refreshed.
|
||||
Default is 1200 seconds.
|
||||
.It Va maxhold
|
||||
How many packets hold in the per-entry output queue while the entry
|
||||
is being resolved.
|
||||
Default is one packet.
|
||||
.It Va maxtries
|
||||
Number of retransmits before host is considered down and error is returned.
|
||||
Default is 5 tries.
|
||||
.It Va proxyall
|
||||
Enables ARP proxying for all hosts on net.
|
||||
Turned off by default.
|
||||
.It Va wait
|
||||
Lifetime of an incomplete ARP entry.
|
||||
Default is 20 seconds.
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
.Bl -diag
|
||||
.It "arp: %x:%x:%x:%x:%x:%x is using my IP address %d.%d.%d.%d on %s!"
|
||||
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.
|
||||
.It "arp: link address is broadcast for IP address %d.%d.%d.%d!"
|
||||
ARP requested information for a host, and received an answer indicating
|
||||
that the host's ethernet address is the ethernet broadcast address.
|
||||
This indicates a misconfigured or broken device.
|
||||
.It "arp: %d.%d.%d.%d moved from %x:%x:%x:%x:%x:%x to %x:%x:%x:%x:%x:%x on %s"
|
||||
ARP had a cached value for the ethernet address of the referenced host,
|
||||
but received a reply indicating that the host is at a new address.
|
||||
This can happen normally when host hardware addresses change,
|
||||
or when a mobile node arrives or leaves the local subnet.
|
||||
It can also indicate a problem with proxy ARP.
|
||||
This message can only be issued if the sysctl
|
||||
.Va net.link.ether.inet.log_arp_movements
|
||||
is set to 1, which is the system's default behaviour.
|
||||
.It "arpresolve: can't allocate llinfo for %d.%d.%d.%d"
|
||||
The route for the referenced host points to a device upon which ARP is
|
||||
required, but ARP was unable to allocate a routing table entry in which
|
||||
to store the host's MAC address.
|
||||
This usually points to a misconfigured routing table.
|
||||
It can also occur if the kernel cannot allocate memory.
|
||||
.It "arp: %d.%d.%d.%d is on if0 but got reply from %x:%x:%x:%x:%x:%x on if1"
|
||||
Physical connections exist to the same logical IP network on both if0 and if1.
|
||||
It can also occur if an entry already exists in the ARP cache for the IP
|
||||
address above, and the cable has been disconnected from if0, then reconnected
|
||||
to if1.
|
||||
This message can only be issued if the sysctl
|
||||
.Va net.link.ether.inet.log_arp_wrong_iface
|
||||
is set to 1, which is the system's default behaviour.
|
||||
.It "arp: %x:%x:%x:%x:%x:%x attempts to modify permanent entry for %d.%d.%d.%d on %s"
|
||||
ARP has received an ARP reply that attempts to overwrite a permanent
|
||||
entry in the local ARP table.
|
||||
This error will only be logged if the sysctl
|
||||
.Va net.link.ether.inet.log_arp_permanent_modify
|
||||
is set to 1, which is the system's default behaviour.
|
||||
.It "arp: %x:%x:%x:%x:%x:%x is multicast"
|
||||
Kernel refused to install an entry with multicast hardware address.
|
||||
If you really want such addresses being installed, set the sysctl
|
||||
.Va net.link.ether.inet.allow_multicast
|
||||
to a positive value.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr inet 4 ,
|
||||
.Xr route 4 ,
|
||||
.Xr arp 8 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr route 8 ,
|
||||
.Xr sysctl 8
|
||||
.Rs
|
||||
.%A Plummer, D.
|
||||
.%B "An Ethernet Address Resolution Protocol"
|
||||
.%T RFC826
|
||||
.Re
|
||||
.Rs
|
||||
.%A Leffler, S.J.
|
||||
.%A Karels, M.J.
|
||||
.%B "Trailer Encapsulations"
|
||||
.%T RFC893
|
||||
.Re
|
|
@ -0,0 +1,192 @@
|
|||
.\" 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.
|
||||
.\" 4. 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.
|
||||
.\"
|
||||
.\" @(#)arp.8 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 31, 2013
|
||||
.Dt ARP 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm arp
|
||||
.Nd address resolution display and control
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl n
|
||||
.Op Fl i Ar interface
|
||||
.Ar hostname
|
||||
.Nm
|
||||
.Op Fl n
|
||||
.Op Fl i Ar interface
|
||||
.Fl a
|
||||
.Nm
|
||||
.Fl d Ar hostname
|
||||
.Op Cm pub
|
||||
.Nm
|
||||
.Fl d
|
||||
.Op Fl i Ar interface
|
||||
.Fl a
|
||||
.Nm
|
||||
.Fl s Ar hostname ether_addr
|
||||
.Op Cm temp
|
||||
.Op Cm blackhole No \&| Cm reject
|
||||
.Op Cm pub
|
||||
.Nm
|
||||
.Fl S Ar hostname ether_addr
|
||||
.Op Cm temp
|
||||
.Op Cm blackhole No \&| Cm reject
|
||||
.Op Cm pub
|
||||
.Nm
|
||||
.Fl f Ar filename
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility 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 indent
|
||||
.It Fl a
|
||||
The program displays or deletes 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 pub
|
||||
keyword is specified, only the
|
||||
.Dq published
|
||||
.Tn ARP
|
||||
entry
|
||||
for this host will be deleted.
|
||||
.Pp
|
||||
Alternatively, the
|
||||
.Fl d
|
||||
flag may be combined with the
|
||||
.Fl a
|
||||
flag to delete all entries.
|
||||
.It Fl i Ar interface
|
||||
Limit the operation scope to the
|
||||
.Tn ARP
|
||||
entries on
|
||||
.Ar interface .
|
||||
Applicable only to the following operations:
|
||||
display one, display all, delete all.
|
||||
.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
|
||||
.Dq 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.
|
||||
In this case the
|
||||
.Ar ether_addr
|
||||
can be given as
|
||||
.Cm auto
|
||||
in which case the interfaces on this host will be examined,
|
||||
and if one of them is found to occupy the same subnet, its
|
||||
Ethernet address will be used.
|
||||
.Pp
|
||||
If the
|
||||
.Cm reject
|
||||
keyword is specified the entry will be marked so that traffic to
|
||||
the host will be discarded and the sender will be notified the
|
||||
host is unreachable.
|
||||
The
|
||||
.Cm blackhole
|
||||
keyword is similar in that traffic is discarded but the sender is
|
||||
not notified.
|
||||
These can be used to block external traffic to a host without
|
||||
using a firewall.
|
||||
.It Fl S Ar hostname ether_addr
|
||||
Is just like
|
||||
.Fl s
|
||||
except any existing
|
||||
.Tn ARP
|
||||
entry for this host will be deleted first.
|
||||
.It Fl f Ar filename
|
||||
Cause 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 -ragged -offset indent -compact
|
||||
.Ar hostname ether_addr
|
||||
.Op Cm temp
|
||||
.Op Cm blackhole No \&| Cm reject
|
||||
.Op Cm pub
|
||||
.Ed
|
||||
.Pp
|
||||
with argument meanings as given above.
|
||||
Leading whitespace and empty lines are ignored.
|
||||
A
|
||||
.Ql #
|
||||
character will mark the rest of the line as a comment.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr inet 3 ,
|
||||
.Xr arp 4 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr ndp 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Bx 4.3 .
|
|
@ -0,0 +1,927 @@
|
|||
/*
|
||||
* 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.
|
||||
* 4. 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1984, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char const sccsid[] = "@(#)from: arp.c 8.2 (Berkeley) 1/2/94";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* arp - display, set, and delete arp table entries
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <net/iso88025.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.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 <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef FSTACK
|
||||
#include <time.h>
|
||||
#include "rtioctl.h"
|
||||
#include "ff_ipc.h"
|
||||
|
||||
#ifndef __unused
|
||||
#define __unused __attribute__((__unused__))
|
||||
|
||||
#define socket(a, b, c) rt_socket((a), (b), (c))
|
||||
#define close(a) rt_close(a)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef void (action_fn)(struct sockaddr_dl *sdl,
|
||||
struct sockaddr_in *s_in, struct rt_msghdr *rtm);
|
||||
|
||||
static int search(u_long addr, action_fn *action);
|
||||
static action_fn print_entry;
|
||||
static action_fn nuke_entry;
|
||||
|
||||
static int delete(char *host);
|
||||
static void usage(void);
|
||||
static int set(int argc, char **argv);
|
||||
static int get(char *host);
|
||||
static int file(char *name);
|
||||
static struct rt_msghdr *rtmsg(int cmd,
|
||||
struct sockaddr_in *dst, struct sockaddr_dl *sdl);
|
||||
static int get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr);
|
||||
static struct sockaddr_in *getaddr(char *host);
|
||||
static int valid_type(int type);
|
||||
|
||||
static int nflag; /* no reverse dns lookups */
|
||||
static char *rifname;
|
||||
|
||||
static time_t expire_time;
|
||||
static int flags, doing_proxy;
|
||||
|
||||
struct if_nameindex *ifnameindex;
|
||||
|
||||
/* which function we're supposed to do */
|
||||
#define F_GET 1
|
||||
#define F_SET 2
|
||||
#define F_FILESET 3
|
||||
#define F_REPLACE 4
|
||||
#define F_DELETE 5
|
||||
|
||||
#define SETFUNC(f) { if (func) usage(); func = (f); }
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, func = 0;
|
||||
int rtn = 0;
|
||||
int aflag = 0; /* do it for all entries */
|
||||
|
||||
#ifndef FSTACK
|
||||
while ((ch = getopt(argc, argv, "andfsSi:")) != -1)
|
||||
#else
|
||||
ff_ipc_init();
|
||||
while ((ch = getopt(argc, argv, "andfsSi:p:")) != -1)
|
||||
#endif
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
SETFUNC(F_DELETE);
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'S':
|
||||
SETFUNC(F_REPLACE);
|
||||
break;
|
||||
case 's':
|
||||
SETFUNC(F_SET);
|
||||
break;
|
||||
case 'f' :
|
||||
SETFUNC(F_FILESET);
|
||||
break;
|
||||
case 'i':
|
||||
rifname = optarg;
|
||||
break;
|
||||
#ifdef FSTACK
|
||||
case 'p':
|
||||
ff_set_proc_id(atoi(optarg));
|
||||
break;
|
||||
#endif
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!func)
|
||||
func = F_GET;
|
||||
if (rifname) {
|
||||
if (func != F_GET && !(func == F_DELETE && aflag))
|
||||
errx(1, "-i not applicable to this operation");
|
||||
if (if_nametoindex(rifname) == 0) {
|
||||
if (errno == ENXIO)
|
||||
errx(1, "interface %s does not exist", rifname);
|
||||
else
|
||||
err(1, "if_nametoindex(%s)", rifname);
|
||||
}
|
||||
}
|
||||
switch (func) {
|
||||
case F_GET:
|
||||
if (aflag) {
|
||||
if (argc != 0)
|
||||
usage();
|
||||
search(0, print_entry);
|
||||
} else {
|
||||
if (argc != 1)
|
||||
usage();
|
||||
rtn = get(argv[0]);
|
||||
}
|
||||
break;
|
||||
case F_SET:
|
||||
case F_REPLACE:
|
||||
if (argc < 2 || argc > 6)
|
||||
usage();
|
||||
if (func == F_REPLACE)
|
||||
(void)delete(argv[0]);
|
||||
rtn = set(argc, argv) ? 1 : 0;
|
||||
break;
|
||||
case F_DELETE:
|
||||
if (aflag) {
|
||||
if (argc != 0)
|
||||
usage();
|
||||
search(0, nuke_entry);
|
||||
} else {
|
||||
if (argc != 1)
|
||||
usage();
|
||||
rtn = delete(argv[0]);
|
||||
}
|
||||
break;
|
||||
case F_FILESET:
|
||||
if (argc != 1)
|
||||
usage();
|
||||
rtn = file(argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ifnameindex != NULL)
|
||||
if_freenameindex(ifnameindex);
|
||||
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a file to set standard arp entries
|
||||
*/
|
||||
static int
|
||||
file(char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
int i, retval;
|
||||
char line[100], arg[5][50], *args[5], *p;
|
||||
|
||||
if ((fp = fopen(name, "r")) == NULL)
|
||||
err(1, "cannot open %s", name);
|
||||
args[0] = &arg[0][0];
|
||||
args[1] = &arg[1][0];
|
||||
args[2] = &arg[2][0];
|
||||
args[3] = &arg[3][0];
|
||||
args[4] = &arg[4][0];
|
||||
retval = 0;
|
||||
while(fgets(line, sizeof(line), fp) != NULL) {
|
||||
if ((p = strchr(line, '#')) != NULL)
|
||||
*p = '\0';
|
||||
for (p = line; isblank(*p); p++);
|
||||
if (*p == '\n' || *p == '\0')
|
||||
continue;
|
||||
i = sscanf(p, "%49s %49s %49s %49s %49s", arg[0], arg[1],
|
||||
arg[2], arg[3], arg[4]);
|
||||
if (i < 2) {
|
||||
warnx("bad line: %s", line);
|
||||
retval = 1;
|
||||
continue;
|
||||
}
|
||||
if (set(i, args))
|
||||
retval = 1;
|
||||
}
|
||||
fclose(fp);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a hostname, fills up a (static) struct sockaddr_in with
|
||||
* the address of the host and returns a pointer to the
|
||||
* structure.
|
||||
*/
|
||||
static struct sockaddr_in *
|
||||
getaddr(char *host)
|
||||
{
|
||||
#ifndef FSTACK
|
||||
struct hostent *hp;
|
||||
#endif
|
||||
static struct sockaddr_in reply;
|
||||
|
||||
bzero(&reply, sizeof(reply));
|
||||
reply.sin_len = sizeof(reply);
|
||||
reply.sin_family = AF_INET;
|
||||
reply.sin_addr.s_addr = inet_addr(host);
|
||||
if (reply.sin_addr.s_addr == INADDR_NONE) {
|
||||
#ifndef FSTACK
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
warnx("%s: %s", host, hstrerror(h_errno));
|
||||
return (NULL);
|
||||
}
|
||||
bcopy((char *)hp->h_addr, (char *)&reply.sin_addr,
|
||||
sizeof reply.sin_addr);
|
||||
#else
|
||||
warnx("reply.sin_addr.s_addr == INADDR_NONE");
|
||||
#endif
|
||||
}
|
||||
return (&reply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the type is a valid one for ARP.
|
||||
*/
|
||||
static int
|
||||
valid_type(int type)
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case IFT_ETHER:
|
||||
case IFT_FDDI:
|
||||
case IFT_INFINIBAND:
|
||||
case IFT_ISO88023:
|
||||
case IFT_ISO88024:
|
||||
case IFT_ISO88025:
|
||||
case IFT_L2VLAN:
|
||||
case IFT_BRIDGE:
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an individual arp entry
|
||||
*/
|
||||
static int
|
||||
set(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_in *addr;
|
||||
struct sockaddr_in *dst; /* what are we looking for */
|
||||
struct sockaddr_dl *sdl;
|
||||
struct rt_msghdr *rtm;
|
||||
struct ether_addr *ea;
|
||||
char *host = argv[0], *eaddr = argv[1];
|
||||
struct sockaddr_dl sdl_m;
|
||||
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
bzero(&sdl_m, sizeof(sdl_m));
|
||||
sdl_m.sdl_len = sizeof(sdl_m);
|
||||
sdl_m.sdl_family = AF_LINK;
|
||||
|
||||
dst = getaddr(host);
|
||||
if (dst == NULL)
|
||||
return (1);
|
||||
doing_proxy = flags = expire_time = 0;
|
||||
while (argc-- > 0) {
|
||||
if (strncmp(argv[0], "temp", 4) == 0) {
|
||||
struct timespec tp;
|
||||
int max_age;
|
||||
size_t len = sizeof(max_age);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
if (sysctlbyname("net.link.ether.inet.max_age",
|
||||
&max_age, &len, NULL, 0) != 0)
|
||||
err(1, "sysctlbyname");
|
||||
expire_time = tp.tv_sec + max_age;
|
||||
} else if (strncmp(argv[0], "pub", 3) == 0) {
|
||||
flags |= RTF_ANNOUNCE;
|
||||
doing_proxy = 1;
|
||||
if (argc && strncmp(argv[1], "only", 3) == 0) {
|
||||
/*
|
||||
* Compatibility: in pre FreeBSD 8 times
|
||||
* the "only" keyword used to mean that
|
||||
* an ARP entry should be announced, but
|
||||
* not installed into routing table.
|
||||
*/
|
||||
argc--; argv++;
|
||||
}
|
||||
} else if (strncmp(argv[0], "blackhole", 9) == 0) {
|
||||
if (flags & RTF_REJECT) {
|
||||
printf("Choose one of blackhole or reject, not both.\n");
|
||||
}
|
||||
flags |= RTF_BLACKHOLE;
|
||||
} else if (strncmp(argv[0], "reject", 6) == 0) {
|
||||
if (flags & RTF_BLACKHOLE) {
|
||||
printf("Choose one of blackhole or reject, not both.\n");
|
||||
}
|
||||
flags |= RTF_REJECT;
|
||||
} else if (strncmp(argv[0], "trail", 5) == 0) {
|
||||
/* XXX deprecated and undocumented feature */
|
||||
printf("%s: Sending trailers is no longer supported\n",
|
||||
host);
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
ea = (struct ether_addr *)LLADDR(&sdl_m);
|
||||
if (doing_proxy && !strcmp(eaddr, "auto")) {
|
||||
if (!get_ether_addr(dst->sin_addr.s_addr, ea)) {
|
||||
printf("no interface found for %s\n",
|
||||
inet_ntoa(dst->sin_addr));
|
||||
return (1);
|
||||
}
|
||||
sdl_m.sdl_alen = ETHER_ADDR_LEN;
|
||||
} else {
|
||||
struct ether_addr *ea1 = ether_aton(eaddr);
|
||||
|
||||
if (ea1 == NULL) {
|
||||
warnx("invalid Ethernet address '%s'", eaddr);
|
||||
return (1);
|
||||
} else {
|
||||
*ea = *ea1;
|
||||
sdl_m.sdl_alen = ETHER_ADDR_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In the case a proxy-arp entry is being added for
|
||||
* a remote end point, the RTF_ANNOUNCE flag in the
|
||||
* RTM_GET command is an indication to the kernel
|
||||
* routing code that the interface associated with
|
||||
* the prefix route covering the local end of the
|
||||
* PPP link should be returned, on which ARP applies.
|
||||
*/
|
||||
rtm = rtmsg(RTM_GET, dst, &sdl_m);
|
||||
if (rtm == NULL) {
|
||||
warn("%s", host);
|
||||
return (1);
|
||||
}
|
||||
addr = (struct sockaddr_in *)(rtm + 1);
|
||||
sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
|
||||
|
||||
if ((sdl->sdl_family != AF_LINK) ||
|
||||
(rtm->rtm_flags & RTF_GATEWAY) ||
|
||||
!valid_type(sdl->sdl_type)) {
|
||||
printf("cannot intuit interface index and type for %s\n", host);
|
||||
return (1);
|
||||
}
|
||||
sdl_m.sdl_type = sdl->sdl_type;
|
||||
sdl_m.sdl_index = sdl->sdl_index;
|
||||
return (rtmsg(RTM_ADD, dst, &sdl_m) == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display an individual arp entry
|
||||
*/
|
||||
static int
|
||||
get(char *host)
|
||||
{
|
||||
struct sockaddr_in *addr;
|
||||
|
||||
addr = getaddr(host);
|
||||
if (addr == NULL)
|
||||
return (1);
|
||||
if (0 == search(addr->sin_addr.s_addr, print_entry)) {
|
||||
printf("%s (%s) -- no entry",
|
||||
host, inet_ntoa(addr->sin_addr));
|
||||
if (rifname)
|
||||
printf(" on %s", rifname);
|
||||
printf("\n");
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an arp entry
|
||||
*/
|
||||
static int
|
||||
delete(char *host)
|
||||
{
|
||||
struct sockaddr_in *addr, *dst;
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr_dl *sdl;
|
||||
struct sockaddr_dl sdl_m;
|
||||
|
||||
dst = getaddr(host);
|
||||
if (dst == NULL)
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Perform a regular entry delete first.
|
||||
*/
|
||||
flags &= ~RTF_ANNOUNCE;
|
||||
|
||||
/*
|
||||
* setup the data structure to notify the kernel
|
||||
* it is the ARP entry the RTM_GET is interested
|
||||
* in
|
||||
*/
|
||||
bzero(&sdl_m, sizeof(sdl_m));
|
||||
sdl_m.sdl_len = sizeof(sdl_m);
|
||||
sdl_m.sdl_family = AF_LINK;
|
||||
|
||||
for (;;) { /* try twice */
|
||||
rtm = rtmsg(RTM_GET, dst, &sdl_m);
|
||||
if (rtm == NULL) {
|
||||
warn("%s", host);
|
||||
return (1);
|
||||
}
|
||||
addr = (struct sockaddr_in *)(rtm + 1);
|
||||
sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
|
||||
|
||||
/*
|
||||
* With the new L2/L3 restructure, the route
|
||||
* returned is a prefix route. The important
|
||||
* piece of information from the previous
|
||||
* RTM_GET is the interface index. In the
|
||||
* case of ECMP, the kernel will traverse
|
||||
* the route group for the given entry.
|
||||
*/
|
||||
if (sdl->sdl_family == AF_LINK &&
|
||||
!(rtm->rtm_flags & RTF_GATEWAY) &&
|
||||
valid_type(sdl->sdl_type) ) {
|
||||
addr->sin_addr.s_addr = dst->sin_addr.s_addr;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regualar entry delete failed, now check if there
|
||||
* is a proxy-arp entry to remove.
|
||||
*/
|
||||
if (flags & RTF_ANNOUNCE) {
|
||||
fprintf(stderr, "delete: cannot locate %s\n",host);
|
||||
return (1);
|
||||
}
|
||||
|
||||
flags |= RTF_ANNOUNCE;
|
||||
}
|
||||
rtm->rtm_flags |= RTF_LLDATA;
|
||||
if (rtmsg(RTM_DELETE, dst, NULL) != NULL) {
|
||||
printf("%s (%s) deleted\n", host, inet_ntoa(addr->sin_addr));
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search the arp table and do some action on matching entries
|
||||
*/
|
||||
static int
|
||||
search(u_long addr, action_fn *action)
|
||||
{
|
||||
int mib[6];
|
||||
size_t needed;
|
||||
char *lim, *buf, *next;
|
||||
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;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = AF_INET;
|
||||
mib[4] = NET_RT_FLAGS;
|
||||
#ifdef RTF_LLINFO
|
||||
mib[5] = RTF_LLINFO;
|
||||
#else
|
||||
mib[5] = 0;
|
||||
#endif
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
err(1, "route-sysctl-estimate");
|
||||
if (needed == 0) /* empty table */
|
||||
return 0;
|
||||
buf = NULL;
|
||||
for (;;) {
|
||||
buf = reallocf(buf, needed);
|
||||
if (buf == NULL)
|
||||
errx(1, "could not reallocate memory");
|
||||
st = sysctl(mib, 6, buf, &needed, NULL, 0);
|
||||
if (st == 0 || errno != ENOMEM)
|
||||
break;
|
||||
needed += needed / 8;
|
||||
}
|
||||
if (st == -1)
|
||||
err(1, "actual retrieval of routing table");
|
||||
lim = buf + needed;
|
||||
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
||||
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))
|
||||
continue;
|
||||
if (addr) {
|
||||
if (addr != sin2->sin_addr.s_addr)
|
||||
continue;
|
||||
found_entry = 1;
|
||||
}
|
||||
(*action)(sdl, sin2, rtm);
|
||||
}
|
||||
free(buf);
|
||||
return (found_entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display an arp entry
|
||||
*/
|
||||
|
||||
static void
|
||||
print_entry(struct sockaddr_dl *sdl,
|
||||
struct sockaddr_in *addr, struct rt_msghdr *rtm)
|
||||
{
|
||||
const char *host;
|
||||
struct hostent *hp;
|
||||
struct iso88025_sockaddr_dl_data *trld;
|
||||
struct if_nameindex *p;
|
||||
int seg;
|
||||
|
||||
if (ifnameindex == NULL)
|
||||
if ((ifnameindex = if_nameindex()) == NULL)
|
||||
err(1, "cannot retrieve interface names");
|
||||
|
||||
if (nflag == 0)
|
||||
hp = gethostbyaddr((caddr_t)&(addr->sin_addr),
|
||||
sizeof addr->sin_addr, AF_INET);
|
||||
else
|
||||
hp = 0;
|
||||
if (hp)
|
||||
host = hp->h_name;
|
||||
else {
|
||||
host = "?";
|
||||
if (h_errno == TRY_AGAIN)
|
||||
nflag = 1;
|
||||
}
|
||||
printf("%s (%s) at ", host, inet_ntoa(addr->sin_addr));
|
||||
if (sdl->sdl_alen) {
|
||||
if ((sdl->sdl_type == IFT_ETHER ||
|
||||
sdl->sdl_type == IFT_L2VLAN ||
|
||||
sdl->sdl_type == IFT_BRIDGE) &&
|
||||
sdl->sdl_alen == ETHER_ADDR_LEN)
|
||||
printf("%s", ether_ntoa((struct ether_addr *)LLADDR(sdl)));
|
||||
else {
|
||||
int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
|
||||
|
||||
printf("%s", link_ntoa(sdl) + n);
|
||||
}
|
||||
} else
|
||||
printf("(incomplete)");
|
||||
|
||||
for (p = ifnameindex; p && ifnameindex->if_index &&
|
||||
ifnameindex->if_name; p++) {
|
||||
if (p->if_index == sdl->sdl_index) {
|
||||
printf(" on %s", p->if_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtm->rtm_rmx.rmx_expire == 0)
|
||||
printf(" permanent");
|
||||
else {
|
||||
static struct timespec tp;
|
||||
if (tp.tv_sec == 0)
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
if ((expire_time = rtm->rtm_rmx.rmx_expire - tp.tv_sec) > 0)
|
||||
printf(" expires in %d seconds", (int)expire_time);
|
||||
else
|
||||
printf(" expired");
|
||||
}
|
||||
if (rtm->rtm_flags & RTF_ANNOUNCE)
|
||||
printf(" published");
|
||||
switch(sdl->sdl_type) {
|
||||
case IFT_ETHER:
|
||||
printf(" [ethernet]");
|
||||
break;
|
||||
case IFT_ISO88025:
|
||||
printf(" [token-ring]");
|
||||
trld = SDL_ISO88025(sdl);
|
||||
if (trld->trld_rcf != 0) {
|
||||
printf(" rt=%x", ntohs(trld->trld_rcf));
|
||||
for (seg = 0;
|
||||
seg < ((TR_RCF_RIFLEN(trld->trld_rcf) - 2 ) / 2);
|
||||
seg++)
|
||||
printf(":%x", ntohs(*(trld->trld_route[seg])));
|
||||
}
|
||||
break;
|
||||
case IFT_FDDI:
|
||||
printf(" [fddi]");
|
||||
break;
|
||||
case IFT_ATM:
|
||||
printf(" [atm]");
|
||||
break;
|
||||
case IFT_L2VLAN:
|
||||
printf(" [vlan]");
|
||||
break;
|
||||
case IFT_IEEE1394:
|
||||
printf(" [firewire]");
|
||||
break;
|
||||
case IFT_BRIDGE:
|
||||
printf(" [bridge]");
|
||||
break;
|
||||
case IFT_INFINIBAND:
|
||||
printf(" [infiniband]");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Nuke an arp entry
|
||||
*/
|
||||
static void
|
||||
nuke_entry(struct sockaddr_dl *sdl __unused,
|
||||
struct sockaddr_in *addr, struct rt_msghdr *rtm)
|
||||
{
|
||||
char ip[20];
|
||||
|
||||
if (rtm->rtm_flags & RTF_PINNED)
|
||||
return;
|
||||
|
||||
snprintf(ip, sizeof(ip), "%s", inet_ntoa(addr->sin_addr));
|
||||
delete(ip);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
|
||||
#ifndef FSTACK
|
||||
"usage: arp [-n] [-i interface] hostname",
|
||||
" arp [-n] [-i interface] -a",
|
||||
" arp -d hostname [pub]",
|
||||
" arp -d [-i interface] -a",
|
||||
" arp -s hostname ether_addr [temp] [reject | blackhole] [pub [only]]",
|
||||
" arp -S hostname ether_addr [temp] [reject | blackhole] [pub [only]]",
|
||||
" arp -f filename");
|
||||
#else
|
||||
"usage: arp -p <f-stack proc_id> [-n] [-i interface] hostname",
|
||||
" arp -p <f-stack proc_id> [-n] [-i interface] -a",
|
||||
" arp -p <f-stack proc_id> -d hostname [pub]",
|
||||
" arp -p <f-stack proc_id> -d [-i interface] -a",
|
||||
" arp -p <f-stack proc_id> -s hostname ether_addr [temp] [reject | blackhole] [pub [only]]",
|
||||
" arp -p <f-stack proc_id> -S hostname ether_addr [temp] [reject | blackhole] [pub [only]]",
|
||||
" arp -p <f-stack proc_id> -f filename");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static struct rt_msghdr *
|
||||
rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl)
|
||||
{
|
||||
static int seq;
|
||||
int rlen;
|
||||
int l;
|
||||
struct sockaddr_in so_mask, *som = &so_mask;
|
||||
static int s = -1;
|
||||
static pid_t pid;
|
||||
|
||||
static struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
} m_rtmsg;
|
||||
|
||||
struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
|
||||
char *cp = m_rtmsg.m_space;
|
||||
|
||||
if (s < 0) { /* first time: open socket, get pid */
|
||||
s = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (s < 0)
|
||||
err(1, "socket");
|
||||
pid = getpid();
|
||||
}
|
||||
bzero(&so_mask, sizeof(so_mask));
|
||||
so_mask.sin_len = 8;
|
||||
so_mask.sin_addr.s_addr = 0xffffffff;
|
||||
|
||||
errno = 0;
|
||||
/*
|
||||
* XXX RTM_DELETE relies on a previous RTM_GET to fill the buffer
|
||||
* appropriately.
|
||||
*/
|
||||
if (cmd == RTM_DELETE)
|
||||
goto doit;
|
||||
bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
rtm->rtm_flags = flags;
|
||||
rtm->rtm_version = RTM_VERSION;
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
errx(1, "internal wrong cmd");
|
||||
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 | RTF_LLDATA);
|
||||
if (doing_proxy) {
|
||||
rtm->rtm_addrs |= RTA_NETMASK;
|
||||
rtm->rtm_flags &= ~RTF_HOST;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case RTM_GET:
|
||||
rtm->rtm_addrs |= RTA_DST;
|
||||
}
|
||||
#define NEXTADDR(w, s) \
|
||||
do { \
|
||||
if ((s) != NULL && rtm->rtm_addrs & (w)) { \
|
||||
bcopy((s), cp, sizeof(*(s))); \
|
||||
cp += SA_SIZE(s); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
NEXTADDR(RTA_DST, dst);
|
||||
NEXTADDR(RTA_GATEWAY, sdl);
|
||||
NEXTADDR(RTA_NETMASK, som);
|
||||
|
||||
rtm->rtm_msglen = cp - (char *)&m_rtmsg;
|
||||
doit:
|
||||
l = rtm->rtm_msglen;
|
||||
rtm->rtm_seq = ++seq;
|
||||
rtm->rtm_type = cmd;
|
||||
#ifndef FSTACK
|
||||
if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
|
||||
if (errno != ESRCH || cmd != RTM_DELETE) {
|
||||
warn("writing to routing socket");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
do {
|
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
|
||||
#else
|
||||
l = rtioctl((char *)&m_rtmsg, l, sizeof(m_rtmsg));
|
||||
#endif
|
||||
if (l < 0)
|
||||
warn("read from routing socket");
|
||||
return (rtm);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_ether_addr - get the hardware address of an interface on the
|
||||
* the same subnet as ipaddr.
|
||||
*/
|
||||
#define MAX_IFS 32
|
||||
|
||||
static int
|
||||
get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr)
|
||||
{
|
||||
struct ifreq *ifr, *ifend, *ifp;
|
||||
in_addr_t ina, mask;
|
||||
struct sockaddr_dl *dla;
|
||||
struct ifreq ifreq;
|
||||
struct ifconf ifc;
|
||||
struct ifreq ifs[MAX_IFS];
|
||||
int sock;
|
||||
int retval = 0;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
err(1, "socket");
|
||||
|
||||
ifc.ifc_len = sizeof(ifs);
|
||||
ifc.ifc_req = ifs;
|
||||
if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
|
||||
warnx("ioctl(SIOCGIFCONF)");
|
||||
goto done;
|
||||
}
|
||||
|
||||
#define NEXTIFR(i) \
|
||||
((struct ifreq *)((char *)&(i)->ifr_addr \
|
||||
+ MAX((i)->ifr_addr.sa_len, sizeof((i)->ifr_addr))) )
|
||||
|
||||
/*
|
||||
* Scan through looking for an interface with an Internet
|
||||
* address on the same subnet as `ipaddr'.
|
||||
*/
|
||||
ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
|
||||
for (ifr = ifc.ifc_req; ifr < ifend; ifr = NEXTIFR(ifr) ) {
|
||||
if (ifr->ifr_addr.sa_family != AF_INET)
|
||||
continue;
|
||||
strncpy(ifreq.ifr_name, ifr->ifr_name,
|
||||
sizeof(ifreq.ifr_name));
|
||||
ifreq.ifr_addr = ifr->ifr_addr;
|
||||
/*
|
||||
* Check that the interface is up,
|
||||
* and not point-to-point or loopback.
|
||||
*/
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0)
|
||||
continue;
|
||||
if ((ifreq.ifr_flags &
|
||||
(IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|
|
||||
IFF_LOOPBACK|IFF_NOARP))
|
||||
!= (IFF_UP|IFF_BROADCAST))
|
||||
continue;
|
||||
/*
|
||||
* Get its netmask and check that it's on
|
||||
* the right subnet.
|
||||
*/
|
||||
if (ioctl(sock, SIOCGIFNETMASK, &ifreq) < 0)
|
||||
continue;
|
||||
mask = ((struct sockaddr_in *)
|
||||
&ifreq.ifr_addr)->sin_addr.s_addr;
|
||||
ina = ((struct sockaddr_in *)
|
||||
&ifr->ifr_addr)->sin_addr.s_addr;
|
||||
if ((ipaddr & mask) == (ina & mask))
|
||||
break; /* ok, we got it! */
|
||||
}
|
||||
|
||||
if (ifr >= ifend)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Now scan through again looking for a link-level address
|
||||
* for this interface.
|
||||
*/
|
||||
ifp = ifr;
|
||||
for (ifr = ifc.ifc_req; ifr < ifend; ifr = NEXTIFR(ifr))
|
||||
if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 &&
|
||||
ifr->ifr_addr.sa_family == AF_LINK)
|
||||
break;
|
||||
if (ifr >= ifend)
|
||||
goto done;
|
||||
/*
|
||||
* Found the link-level address - copy it out
|
||||
*/
|
||||
dla = (struct sockaddr_dl *) &ifr->ifr_addr;
|
||||
memcpy(hwaddr, LLADDR(dla), dla->sdl_alen);
|
||||
printf("using interface %s for proxy with address ",
|
||||
ifp->ifr_name);
|
||||
printf("%s\n", ether_ntoa(hwaddr));
|
||||
retval = dla->sdl_alen;
|
||||
done:
|
||||
close(sock);
|
||||
return (retval);
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 2000
|
||||
* Berkeley Software Design, 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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.
|
||||
*
|
||||
* BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef FSTACK
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* From RFC 2553:
|
||||
*
|
||||
* 4.3 Return All Interface Names and Indexes
|
||||
*
|
||||
* The if_nameindex structure holds the information about a single
|
||||
* interface and is defined as a result of including the <net/if.h>
|
||||
* header.
|
||||
*
|
||||
* struct if_nameindex {
|
||||
* unsigned int if_index;
|
||||
* char *if_name;
|
||||
* };
|
||||
*
|
||||
* The final function returns an array of if_nameindex structures, one
|
||||
* structure per interface.
|
||||
*
|
||||
* struct if_nameindex *if_nameindex(void);
|
||||
*
|
||||
* The end of the array of structures is indicated by a structure with
|
||||
* an if_index of 0 and an if_name of NULL. The function returns a NULL
|
||||
* pointer upon an error, and would set errno to the appropriate value.
|
||||
*
|
||||
* The memory used for this array of structures along with the interface
|
||||
* names pointed to by the if_name members is obtained dynamically.
|
||||
* This memory is freed by the next function.
|
||||
*
|
||||
* 4.4. Free Memory
|
||||
*
|
||||
* The following function frees the dynamic memory that was allocated by
|
||||
* if_nameindex().
|
||||
*
|
||||
* #include <net/if.h>
|
||||
*
|
||||
* void if_freenameindex(struct if_nameindex *ptr);
|
||||
*
|
||||
* The argument to this function must be a pointer that was returned by
|
||||
* if_nameindex().
|
||||
*/
|
||||
|
||||
struct if_nameindex *
|
||||
if_nameindex(void)
|
||||
{
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
unsigned int ni;
|
||||
int nbytes;
|
||||
struct if_nameindex *ifni, *ifni2;
|
||||
char *cp;
|
||||
|
||||
if (getifaddrs(&ifaddrs) < 0)
|
||||
return(NULL);
|
||||
|
||||
/*
|
||||
* First, find out how many interfaces there are, and how
|
||||
* much space we need for the string names.
|
||||
*/
|
||||
ni = 0;
|
||||
nbytes = 0;
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr &&
|
||||
ifa->ifa_addr->sa_family == AF_LINK) {
|
||||
nbytes += strlen(ifa->ifa_name) + 1;
|
||||
ni++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, allocate a chunk of memory, use the first part
|
||||
* for the array of structures, and the last part for
|
||||
* the strings.
|
||||
*/
|
||||
cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
|
||||
ifni = (struct if_nameindex *)cp;
|
||||
if (ifni == NULL)
|
||||
goto out;
|
||||
cp += (ni + 1) * sizeof(struct if_nameindex);
|
||||
|
||||
/*
|
||||
* Now just loop through the list of interfaces again,
|
||||
* filling in the if_nameindex array and making copies
|
||||
* of all the strings.
|
||||
*/
|
||||
ifni2 = ifni;
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr &&
|
||||
ifa->ifa_addr->sa_family == AF_LINK) {
|
||||
ifni2->if_index =
|
||||
LLINDEX((struct sockaddr_dl*)ifa->ifa_addr);
|
||||
ifni2->if_name = cp;
|
||||
strcpy(cp, ifa->ifa_name);
|
||||
ifni2++;
|
||||
cp += strlen(cp) + 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Finally, don't forget to terminate the array.
|
||||
*/
|
||||
ifni2->if_index = 0;
|
||||
ifni2->if_name = NULL;
|
||||
out:
|
||||
freeifaddrs(ifaddrs);
|
||||
return(ifni);
|
||||
}
|
||||
|
||||
void
|
||||
if_freenameindex(struct if_nameindex *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/*-
|
||||
* Copyright (c) 1998, Larry Lile
|
||||
* All rights reserved.
|
||||
*
|
||||
* For latest sources and information on this driver, please
|
||||
* go to http://anarchy.stdio.com.
|
||||
*
|
||||
* Questions, comments or suggestions should be directed to
|
||||
* Larry Lile <lile@stdio.com>.
|
||||
*
|
||||
* 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 unmodified, 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 AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* Information gathered from tokenring@freebsd, /sys/net/ethernet.h and
|
||||
* the Mach token ring driver.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fundamental constants relating to iso 802.5
|
||||
*/
|
||||
|
||||
#ifndef _NET_ISO88025_H_
|
||||
#define _NET_ISO88025_H_
|
||||
|
||||
#ifdef FSTACK
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((__packed__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* General ISO 802.5 definitions
|
||||
*/
|
||||
#define ISO88025_ADDR_LEN 6
|
||||
#define ISO88025_CF_LEN 2
|
||||
#define ISO88025_HDR_LEN (ISO88025_CF_LEN + (ISO88025_ADDR_LEN * 2))
|
||||
#define RCF_LEN 2
|
||||
#define RIF_MAX_RD 14
|
||||
#define RIF_MAX_LEN 16
|
||||
|
||||
#define TR_AC 0x10
|
||||
#define TR_LLC_FRAME 0x40
|
||||
|
||||
#define TR_4MBPS 4000000
|
||||
#define TR_16MBPS 16000000
|
||||
#define TR_100MBPS 100000000
|
||||
|
||||
/*
|
||||
* Source routing
|
||||
*/
|
||||
#define TR_RII 0x80
|
||||
#define TR_RCF_BCST_MASK 0xe000
|
||||
#define TR_RCF_LEN_MASK 0x1f00
|
||||
#define TR_RCF_DIR 0x0080
|
||||
#define TR_RCF_LF_MASK 0x0070
|
||||
|
||||
#define TR_RCF_RIFLEN(x) ((ntohs(x) & TR_RCF_LEN_MASK) >> 8)
|
||||
|
||||
/*
|
||||
* Minimum and maximum packet payload lengths.
|
||||
*/
|
||||
#define ISO88025_MIN_LEN 0
|
||||
#define ISO88025_MAX_LEN_4 4464
|
||||
#define ISO88025_MAX_LEN_16 17960
|
||||
#define ISO88025_MAX_LEN ISO88025_MAX_LEN_16
|
||||
|
||||
/*
|
||||
* A macro to validate a length with
|
||||
*/
|
||||
#define ISO88025_IS_VALID_LEN(foo) \
|
||||
((foo) >= ISO88025_MIN_LEN && (foo) <= ISO88025_MAX_LEN)
|
||||
|
||||
/* Access Control field */
|
||||
#define AC_PRI_MASK 0xe0 /* Priority bits */
|
||||
#define AC_TOKEN 0x10 /* Token bit: 0=Token, 1=Frame */
|
||||
#define AC_MONITOR 0x08 /* Monitor */
|
||||
#define AC_RESV_MASK 0x07 /* Reservation bits */
|
||||
|
||||
/* Frame Control field */
|
||||
#define FC_FT_MASK 0xc0 /* Frame Type */
|
||||
#define FC_FT_MAC 0x00 /* MAC frame */
|
||||
#define FC_FT_LLC 0x40 /* LLC frame */
|
||||
#define FC_ATTN_MASK 0x0f /* Attention bits */
|
||||
#define FC_ATTN_EB 0x01 /* Express buffer */
|
||||
#define FC_ATTN_BE 0x02 /* Beacon */
|
||||
#define FC_ATTN_CT 0x03 /* Claim token */
|
||||
#define FC_ATTN_RP 0x04 /* Ring purge */
|
||||
#define FC_ATTN_AMP 0x05 /* Active monitor present */
|
||||
#define FC_ATTN_SMP 0x06 /* Standby monitor present */
|
||||
|
||||
/* Token Ring destination address */
|
||||
#define DA_IG 0x80 /* Individual/group address. */
|
||||
/* 0=Individual, 1=Group */
|
||||
#define DA_UL 0x40 /* Universal/local address. */
|
||||
/* 0=Universal, 1=Local */
|
||||
/* Token Ring source address */
|
||||
#define SA_RII 0x80 /* Routing information indicator */
|
||||
#define SA_IG 0x40 /* Individual/group address */
|
||||
/* 0=Group, 1=Individual */
|
||||
|
||||
/*
|
||||
* ISO 802.5 physical header
|
||||
*/
|
||||
struct iso88025_header {
|
||||
u_int8_t ac; /* access control field */
|
||||
u_int8_t fc; /* frame control field */
|
||||
u_int8_t iso88025_dhost[ISO88025_ADDR_LEN]; /* destination address */
|
||||
u_int8_t iso88025_shost[ISO88025_ADDR_LEN]; /* source address */
|
||||
u_int16_t rcf; /* route control field */
|
||||
u_int16_t rd[RIF_MAX_RD]; /* routing designators */
|
||||
} __packed;
|
||||
|
||||
struct iso88025_rif {
|
||||
u_int16_t rcf; /* route control field */
|
||||
u_int16_t rd[RIF_MAX_RD]; /* routing designators */
|
||||
} __packed;
|
||||
|
||||
struct iso88025_sockaddr_data {
|
||||
u_char ether_dhost[ISO88025_ADDR_LEN];
|
||||
u_char ether_shost[ISO88025_ADDR_LEN];
|
||||
u_char ac;
|
||||
u_char fc;
|
||||
};
|
||||
|
||||
struct iso88025_sockaddr_dl_data {
|
||||
u_short trld_rcf;
|
||||
u_short *trld_route[RIF_MAX_LEN];
|
||||
};
|
||||
|
||||
#define ISO88025_MAX(a, b) (((a)>(b))?(a):(b))
|
||||
#define SDL_ISO88025(s) ((struct iso88025_sockaddr_dl_data *) \
|
||||
((s)->sdl_data + \
|
||||
ISO88025_MAX((s)->sdl_nlen + (s)->sdl_alen + \
|
||||
(s)->sdl_slen, 12)))
|
||||
|
||||
/*
|
||||
* Structure of a 48-bit iso 802.5 address.
|
||||
* ( We could also add the 16 bit addresses as a union)
|
||||
*/
|
||||
struct iso88025_addr {
|
||||
u_char octet[ISO88025_ADDR_LEN];
|
||||
};
|
||||
|
||||
#define ISO88025_MAX_MTU 18000
|
||||
#define ISO88025_DEFAULT_MTU 1500
|
||||
|
||||
#define ISO88025_BPF_UNSUPPORTED 0
|
||||
#define ISO88025_BPF_SUPPORTED 1
|
||||
|
||||
#ifdef _KERNEL
|
||||
void iso88025_ifattach (struct ifnet *, const u_int8_t *, int);
|
||||
void iso88025_ifdetach (struct ifnet *, int);
|
||||
int iso88025_ioctl (struct ifnet *, u_long, caddr_t );
|
||||
int iso88025_output (struct ifnet *, struct mbuf *,
|
||||
const struct sockaddr *, struct route *);
|
||||
void iso88025_input (struct ifnet *, struct mbuf *);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_NET_ISO88025_H_ */
|
|
@ -93,7 +93,16 @@ typedef __uint32_t uint32_t;
|
|||
#define _PATH_SERVICES "/etc/services"
|
||||
#define _PATH_SERVICES_DB "/var/db/services.db"
|
||||
|
||||
#ifndef FSTACK
|
||||
#define h_errno (*__h_errno())
|
||||
#else
|
||||
/* Error status for non-reentrant lookup functions.
|
||||
We use a macro to access always the thread-specific `h_errno' variable. */
|
||||
# define h_errno (*__h_errno_location ())
|
||||
|
||||
/* Function to get address of global `h_errno' variable. */
|
||||
extern int *__h_errno_location (void) __THROW __attribute__ ((__const__));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structures returned by network data base library. All addresses are
|
||||
|
@ -250,5 +259,8 @@ struct hostent *gethostbyaddr(const void *addr,
|
|||
socklen_t len, int type);
|
||||
|
||||
struct hostent *gethostbyname2(const char *name, int af);
|
||||
struct hostent *gethostbyname(const char *name);
|
||||
|
||||
const char *hstrerror(int err);
|
||||
|
||||
#endif /* !_NETDB_H_ */
|
||||
|
|
|
@ -149,3 +149,4 @@ ioctl_va(int fd, unsigned long com, void *data, int argc, ...)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
|
||||
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "rtioctl.h"
|
||||
#include "ff_ipc.h"
|
||||
|
||||
int rt_shutdown_rd = 0;
|
||||
int rt_sofib = 0;
|
||||
|
||||
int
|
||||
rt_socket(int domain, int type, int protocol)
|
||||
{
|
||||
if (domain != PF_ROUTE || type != SOCK_RAW) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rt_shutdown(int fd, int how)
|
||||
{
|
||||
if (how == SHUT_RD) {
|
||||
rt_shutdown_rd = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rt_setsockopt(int sockfd, int level, int optname,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
if (level == SOL_SOCKET && optname == SO_SETFIB) {
|
||||
rt_sofib = *(int *)optval;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rt_close(int fd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
rtioctl(char *data, unsigned len, unsigned read_len)
|
||||
{
|
||||
struct ff_msg *msg, *retmsg = NULL;
|
||||
unsigned maxlen;
|
||||
|
||||
msg = ff_ipc_msg_alloc();
|
||||
if (msg == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > msg->buf_len) {
|
||||
errno = EINVAL;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_len > msg->buf_len) {
|
||||
read_len = msg->buf_len;
|
||||
}
|
||||
|
||||
maxlen = read_len ? read_len : len;
|
||||
|
||||
msg->msg_type = FF_ROUTE;
|
||||
msg->route.fib = rt_sofib;
|
||||
msg->route.len = len;
|
||||
msg->route.maxlen = maxlen;
|
||||
msg->route.data = msg->buf_addr;
|
||||
memcpy(msg->route.data, data, len);
|
||||
msg->buf_addr += len;
|
||||
|
||||
int ret = ff_ipc_send(msg);
|
||||
if (ret < 0) {
|
||||
errno = EPIPE;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (retmsg != NULL) {
|
||||
ff_ipc_msg_free(retmsg);
|
||||
}
|
||||
ret = ff_ipc_recv(&retmsg);
|
||||
if (ret < 0) {
|
||||
errno = EPIPE;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
} while (msg != retmsg);
|
||||
|
||||
if (retmsg->result == 0) {
|
||||
ret = retmsg->route.len;
|
||||
|
||||
if (!rt_shutdown_rd && read_len > 0) {
|
||||
memcpy(data, retmsg->route.data, retmsg->route.len);
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
errno = retmsg->result;
|
||||
}
|
||||
|
||||
ff_ipc_msg_free(msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
|
||||
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 RTIOCTL_H
|
||||
#define RTIOCTL_H
|
||||
|
||||
extern int rt_shutdown_rd;
|
||||
extern int rt_sofib;
|
||||
|
||||
int rtioctl(char *data, unsigned len, unsigned read_len);
|
||||
|
||||
int rt_socket(int domain, int type, int protocol);
|
||||
int rt_shutdown(int fd, int how);
|
||||
int rt_setsockopt(int sockfd, int level, int optname,
|
||||
const void *optval, socklen_t optlen);
|
||||
void rt_close(int fd);
|
||||
|
||||
#endif
|
|
@ -426,7 +426,9 @@ main(int argc, char *argv[])
|
|||
struct option *p;
|
||||
size_t iflen;
|
||||
|
||||
#ifdef FSTACK
|
||||
ff_ipc_init();
|
||||
#endif
|
||||
|
||||
all = downonly = uponly = namesonly = noload = verbose = 0;
|
||||
f_inet = f_inet6 = f_ether = f_addr = NULL;
|
||||
|
|
|
@ -646,7 +646,9 @@ main(int ac, char *av[])
|
|||
* If the last argument is an absolute pathname, interpret it
|
||||
* as a file to be preprocessed.
|
||||
*/
|
||||
#ifdef FSTACK
|
||||
ff_ipc_init();
|
||||
#endif
|
||||
if (ac > 1 && av[ac - 1][0] == '/') {
|
||||
if (access(av[ac - 1], R_OK) == 0)
|
||||
ipfw_readfile(ac, av);
|
||||
|
|
|
@ -247,7 +247,9 @@ main(int argc, char *argv[])
|
|||
char *endptr;
|
||||
bool first = true;
|
||||
|
||||
#ifdef FSTACK
|
||||
ff_ipc_init();
|
||||
#endif
|
||||
|
||||
af = AF_UNSPEC;
|
||||
|
||||
|
|
|
@ -74,104 +74,13 @@ __FBSDID("$FreeBSD$");
|
|||
#include <ifaddrs.h>
|
||||
|
||||
#ifdef FSTACK
|
||||
#include "rtioctl.h"
|
||||
#include "compat.h"
|
||||
#include "ff_ipc.h"
|
||||
|
||||
static int shutdown_rd;
|
||||
static int sofib;
|
||||
|
||||
static int
|
||||
fake_socket(int domain, int type, int protocol)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fake_shutdown(int fd, int how)
|
||||
{
|
||||
if (how == SHUT_RD) {
|
||||
shutdown_rd = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fake_setsockopt(int sockfd, int level, int optname,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rtioctl(char *data, unsigned len, unsigned read_len)
|
||||
{
|
||||
struct ff_msg *msg, *retmsg = NULL;
|
||||
unsigned maxlen;
|
||||
|
||||
msg = ff_ipc_msg_alloc();
|
||||
if (msg == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > msg->buf_len) {
|
||||
errno = EINVAL;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_len > msg->buf_len) {
|
||||
read_len = msg->buf_len;
|
||||
}
|
||||
|
||||
maxlen = read_len ? read_len : len;
|
||||
|
||||
msg->msg_type = FF_ROUTE;
|
||||
msg->route.fib = sofib;
|
||||
msg->route.len = len;
|
||||
msg->route.maxlen = maxlen;
|
||||
msg->route.data = msg->buf_addr;
|
||||
memcpy(msg->route.data, data, len);
|
||||
msg->buf_addr += len;
|
||||
|
||||
int ret = ff_ipc_send(msg);
|
||||
if (ret < 0) {
|
||||
errno = EPIPE;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (retmsg != NULL) {
|
||||
ff_ipc_msg_free(retmsg);
|
||||
}
|
||||
ret = ff_ipc_recv(&retmsg);
|
||||
if (ret < 0) {
|
||||
errno = EPIPE;
|
||||
ff_ipc_msg_free(msg);
|
||||
return -1;
|
||||
}
|
||||
} while (msg != retmsg);
|
||||
|
||||
if (retmsg->result == 0) {
|
||||
ret = retmsg->route.len;
|
||||
|
||||
if (!shutdown_rd && read_len > 0) {
|
||||
memcpy(data, retmsg->route.data, retmsg->route.len);
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
errno = retmsg->result;
|
||||
}
|
||||
|
||||
ff_ipc_msg_free(msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define socket(a, b, c) fake_socket((a), (b), (c))
|
||||
#define shutdown(a, b) fake_shutdown((a), (b))
|
||||
#define setsockopt(a, b, c, d, e) fake_setsockopt((a), (b), (c), (d), (e))
|
||||
#define socket(a, b, c) rt_socket((a), (b), (c))
|
||||
#define shutdown(a, b) rt_shutdown((a), (b))
|
||||
#define setsockopt(a, b, c, d, e) rt_setsockopt((a), (b), (c), (d), (e))
|
||||
|
||||
#define write(a, b, c) rtioctl((b), (c), (0))
|
||||
|
||||
|
@ -281,11 +190,10 @@ main(int argc, char **argv)
|
|||
if (argc < 2)
|
||||
usage(NULL);
|
||||
|
||||
ff_ipc_init();
|
||||
|
||||
#ifndef FSTACK
|
||||
while ((ch = getopt(argc, argv, "46nqdtv")) != -1)
|
||||
#else
|
||||
ff_ipc_init();
|
||||
while ((ch = getopt(argc, argv, "46nqdtvp:")) != -1)
|
||||
#endif
|
||||
switch(ch) {
|
||||
|
@ -389,7 +297,8 @@ set_sofib(int fib)
|
|||
if (fib < 0)
|
||||
return (0);
|
||||
#ifdef FSTACK
|
||||
sofib = fib;
|
||||
return (rt_setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
|
||||
sizeof(fib)));
|
||||
#endif
|
||||
return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
|
||||
sizeof(fib)));
|
||||
|
|
|
@ -241,7 +241,9 @@ main(int argc, char **argv)
|
|||
int ch;
|
||||
int warncount = 0;
|
||||
|
||||
#ifdef FSTACK
|
||||
ff_ipc_init();
|
||||
#endif
|
||||
|
||||
setlocale(LC_NUMERIC, "");
|
||||
setbuf(stdout,0);
|
||||
|
|
Loading…
Reference in New Issue