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:
|
all:
|
||||||
for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done
|
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).
|
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
|
# how to implement a custom tool for communicating with F-Stack process
|
||||||
|
|
||||||
Add a new FF_MSG_TYPE in ff_msg.h:
|
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 "/etc/services"
|
||||||
#define _PATH_SERVICES_DB "/var/db/services.db"
|
#define _PATH_SERVICES_DB "/var/db/services.db"
|
||||||
|
|
||||||
|
#ifndef FSTACK
|
||||||
#define h_errno (*__h_errno())
|
#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
|
* 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);
|
socklen_t len, int type);
|
||||||
|
|
||||||
struct hostent *gethostbyname2(const char *name, int af);
|
struct hostent *gethostbyname2(const char *name, int af);
|
||||||
|
struct hostent *gethostbyname(const char *name);
|
||||||
|
|
||||||
|
const char *hstrerror(int err);
|
||||||
|
|
||||||
#endif /* !_NETDB_H_ */
|
#endif /* !_NETDB_H_ */
|
||||||
|
|
|
@ -149,3 +149,4 @@ ioctl_va(int fd, unsigned long com, void *data, int argc, ...)
|
||||||
|
|
||||||
return ret;
|
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;
|
struct option *p;
|
||||||
size_t iflen;
|
size_t iflen;
|
||||||
|
|
||||||
|
#ifdef FSTACK
|
||||||
ff_ipc_init();
|
ff_ipc_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
all = downonly = uponly = namesonly = noload = verbose = 0;
|
all = downonly = uponly = namesonly = noload = verbose = 0;
|
||||||
f_inet = f_inet6 = f_ether = f_addr = NULL;
|
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
|
* If the last argument is an absolute pathname, interpret it
|
||||||
* as a file to be preprocessed.
|
* as a file to be preprocessed.
|
||||||
*/
|
*/
|
||||||
|
#ifdef FSTACK
|
||||||
ff_ipc_init();
|
ff_ipc_init();
|
||||||
|
#endif
|
||||||
if (ac > 1 && av[ac - 1][0] == '/') {
|
if (ac > 1 && av[ac - 1][0] == '/') {
|
||||||
if (access(av[ac - 1], R_OK) == 0)
|
if (access(av[ac - 1], R_OK) == 0)
|
||||||
ipfw_readfile(ac, av);
|
ipfw_readfile(ac, av);
|
||||||
|
|
|
@ -247,7 +247,9 @@ main(int argc, char *argv[])
|
||||||
char *endptr;
|
char *endptr;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
|
#ifdef FSTACK
|
||||||
ff_ipc_init();
|
ff_ipc_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
af = AF_UNSPEC;
|
af = AF_UNSPEC;
|
||||||
|
|
||||||
|
|
|
@ -74,104 +74,13 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
#ifdef FSTACK
|
#ifdef FSTACK
|
||||||
|
#include "rtioctl.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ff_ipc.h"
|
#include "ff_ipc.h"
|
||||||
|
|
||||||
static int shutdown_rd;
|
#define socket(a, b, c) rt_socket((a), (b), (c))
|
||||||
static int sofib;
|
#define shutdown(a, b) rt_shutdown((a), (b))
|
||||||
|
#define setsockopt(a, b, c, d, e) rt_setsockopt((a), (b), (c), (d), (e))
|
||||||
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 write(a, b, c) rtioctl((b), (c), (0))
|
#define write(a, b, c) rtioctl((b), (c), (0))
|
||||||
|
|
||||||
|
@ -281,11 +190,10 @@ main(int argc, char **argv)
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage(NULL);
|
usage(NULL);
|
||||||
|
|
||||||
ff_ipc_init();
|
|
||||||
|
|
||||||
#ifndef FSTACK
|
#ifndef FSTACK
|
||||||
while ((ch = getopt(argc, argv, "46nqdtv")) != -1)
|
while ((ch = getopt(argc, argv, "46nqdtv")) != -1)
|
||||||
#else
|
#else
|
||||||
|
ff_ipc_init();
|
||||||
while ((ch = getopt(argc, argv, "46nqdtvp:")) != -1)
|
while ((ch = getopt(argc, argv, "46nqdtvp:")) != -1)
|
||||||
#endif
|
#endif
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
|
@ -389,7 +297,8 @@ set_sofib(int fib)
|
||||||
if (fib < 0)
|
if (fib < 0)
|
||||||
return (0);
|
return (0);
|
||||||
#ifdef FSTACK
|
#ifdef FSTACK
|
||||||
sofib = fib;
|
return (rt_setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
|
||||||
|
sizeof(fib)));
|
||||||
#endif
|
#endif
|
||||||
return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
|
return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
|
||||||
sizeof(fib)));
|
sizeof(fib)));
|
||||||
|
|
|
@ -241,7 +241,9 @@ main(int argc, char **argv)
|
||||||
int ch;
|
int ch;
|
||||||
int warncount = 0;
|
int warncount = 0;
|
||||||
|
|
||||||
|
#ifdef FSTACK
|
||||||
ff_ipc_init();
|
ff_ipc_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
setlocale(LC_NUMERIC, "");
|
setlocale(LC_NUMERIC, "");
|
||||||
setbuf(stdout,0);
|
setbuf(stdout,0);
|
||||||
|
|
Loading…
Reference in New Issue