Remove mrouted from -CURRENT.
Discussed with: fenner, net@
This commit is contained in:
parent
13b3ebf134
commit
aa805a5eb7
@ -1,48 +0,0 @@
|
||||
|
||||
The mrouted program is covered by the following license. Use of the
|
||||
mrouted program represents acceptance of these terms and conditions.
|
||||
|
||||
1. STANFORD grants to LICENSEE a nonexclusive and nontransferable license
|
||||
to use, copy and modify the computer software ``mrouted'' (hereinafter
|
||||
called the ``Program''), upon the terms and conditions hereinafter set
|
||||
out and until Licensee discontinues use of the Licensed Program.
|
||||
|
||||
2. LICENSEE acknowledges that the Program is a research tool still in
|
||||
the development state, that it is being supplied ``as is,'' without any
|
||||
accompanying services from STANFORD, and that this license is entered
|
||||
into in order to encourage scientific collaboration aimed at further
|
||||
development and application of the Program.
|
||||
|
||||
3. LICENSEE may copy the Program and may sublicense others to use object
|
||||
code copies of the Program or any derivative version of the Program.
|
||||
All copies must contain all copyright and other proprietary notices found
|
||||
in the Program as provided by STANFORD. Title to copyright to the
|
||||
Program remains with STANFORD.
|
||||
|
||||
4. LICENSEE may create derivative versions of the Program. LICENSEE
|
||||
hereby grants STANFORD a royalty-free license to use, copy, modify,
|
||||
distribute and sublicense any such derivative works. At the time
|
||||
LICENSEE provides a copy of a derivative version of the Program to a
|
||||
third party, LICENSEE shall provide STANFORD with one copy of the source
|
||||
code of the derivative version at no charge to STANFORD.
|
||||
|
||||
5. STANFORD MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
By way of example, but not limitation, STANFORD MAKES NO REPRESENTATION
|
||||
OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR
|
||||
THAT THE USE OF THE LICENSED PROGRAM WILL NOT INFRINGE ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. STANFORD shall not be held liable
|
||||
for any liability nor for any direct, indirect or consequential damages
|
||||
with respect to any claim by LICENSEE or any third party on account of or
|
||||
arising from this Agreement or use of the Program.
|
||||
|
||||
6. This agreement shall be construed, interpreted and applied in
|
||||
accordance with the State of California and any legal action arising
|
||||
out of this Agreement or use of the Program shall be filed in a court
|
||||
in the State of California.
|
||||
|
||||
7. Nothing in this Agreement shall be construed as conferring rights to
|
||||
use in advertising, publicity or otherwise any trademark or the name
|
||||
of ``Stanford''.
|
||||
|
||||
The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
Leland Stanford Junior University.
|
@ -1,5 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= common mrouted mrinfo map-mbone mtrace testrsrr
|
||||
|
||||
.include <bsd.subdir.mk>
|
@ -1,7 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
CFLAGS+= -DRSRR -Dlog=logit
|
||||
|
||||
LIBMROUTED= ${.OBJDIR}/../common/libmrouted.a
|
||||
|
||||
.include "../Makefile.inc"
|
@ -1,493 +0,0 @@
|
||||
README-3.9-beta3.mrouted,v 1.1.2.1 1998/03/01 03:00:20 fenner Exp
|
||||
|
||||
IP Multicast Extensions for BSD-Derived Unix Systems
|
||||
Multicast Routing Daemon
|
||||
|
||||
Release 3.9-beta3
|
||||
February 28, 1998
|
||||
|
||||
available from parcftp.xerox.com,
|
||||
file pub/net-research/ipmulti/beta-test/mrouted3.9-beta3.tar.Z
|
||||
binaries:
|
||||
pub/net-research/ipmulti/beta-test/mrouted3.9-beta3-sparc-sunos41x.tar.Z
|
||||
pub/net-research/ipmulti/beta-test/mrouted3.9-beta3-sparc-solaris2.tar.Z
|
||||
pub/net-research/ipmulti/beta-test/mrouted3.9-beta3-i386-freebsd22.tar.Z
|
||||
pub/net-research/ipmulti/beta-test/mrouted3.9-beta3-alpha-osf1.tar.Z
|
||||
pub/net-research/ipmulti/beta-test/mrouted3.9-beta3-sgi-irix6.tar.Z
|
||||
|
||||
Note: The 3.9 release is mrouted-only, and will run on top of a 3.5 kernel.
|
||||
It is a drop-in replacement for mrouted 3.5, 3.6, 3.7 or 3.8.
|
||||
|
||||
NOTE WELL: This is a beta-test release of mrouted. The basic
|
||||
functionality has been extensively tested in CAIRN and other
|
||||
testbeds, but it is expected to have bugs. Please report bugs to Bill
|
||||
Fenner <fenner@parc.xerox.com>.
|
||||
|
||||
|
||||
The 3.9-beta3 release fixes the following bugs:
|
||||
o There was a bug handling routing updates which caused random black
|
||||
holes.
|
||||
|
||||
o There was a race condition in the timer handlers causing free'd memory
|
||||
to sometimes get touched.
|
||||
|
||||
o "allow_nonpruners" wasn't allowed in the configuration file (and almost
|
||||
nobody noticed! - probably a good sign)
|
||||
|
||||
o When a prune times out and the source has been active "recently",
|
||||
mrouted now waits for further traffic instead of triggering a new
|
||||
prune.
|
||||
|
||||
o mrouted now ignores unreachable routes when making a routing decision
|
||||
(previously it would blackhole, now it can find a less-specific)
|
||||
|
||||
The 3.9-beta3 release has the following new features:
|
||||
o A "blaster" keyword for mrouted.conf, to turn on handling of routers
|
||||
(mostly ciscos) which overwhelm the socket buffers by blasting the
|
||||
whole routing table at once.
|
||||
|
||||
o A "notransit" keyword; routes learned on a "notransit" vif will not be
|
||||
readvertised onto another "notransit" vif.
|
||||
|
||||
o The 500kbps default rate limit on tunnels has been removed.
|
||||
|
||||
o An ICMP listener which logs ICMP errors which appear to be in response to
|
||||
tunnel packets that we sent.
|
||||
|
||||
o A tunnel traffic encapsulator, which encapsulates control traffic
|
||||
inside the tunnel instead of unicasting it "beside" the tunnel.
|
||||
This is turned off by default; use "beside off" to turn it on.
|
||||
|
||||
o A "force_leaf" flag to ignore any potential neighbors on a given interface.
|
||||
|
||||
|
||||
=========
|
||||
3.9-beta2
|
||||
June 11, 1997
|
||||
|
||||
The 3.9-beta2 release fixes the following bugs:
|
||||
o There was a bug in 3.9-beta1's raw socket buffer processing that
|
||||
would cause an immediate lockup on startup on some systems.
|
||||
|
||||
o RSRR would not clear out the group membership information if
|
||||
further notification of changes to this route entry was not possible.
|
||||
|
||||
There is no need to upgrade to 3.9-beta2 if you are not experiencing
|
||||
one of the aforementioned bugs.
|
||||
|
||||
=========
|
||||
3.9-beta1
|
||||
June 6, 1997
|
||||
|
||||
The 3.9-beta1 release has the following known bugs:
|
||||
|
||||
o The startup message doesn't print properly if you have too many
|
||||
interfaces.
|
||||
|
||||
The 3.9-beta1 release fixes the following bugs:
|
||||
|
||||
o mrouted did not properly keep track of subordinates, and would not
|
||||
time out subordinateness. This caused 2 major problems:
|
||||
1. pruning did not happen when there were equal-cost paths to
|
||||
the same multi-access link
|
||||
2. subordinateness which did not get cancelled by a non-poisoned
|
||||
route (e.g. in the face of route filtering) did not time out,
|
||||
causing traffic to continue to flow.
|
||||
|
||||
o mrouted's IGMPv2 processing when it is not the querier now
|
||||
conforms to draft-ietf-idmr-igmp-v2-06.txt Thanks to Lorenzo
|
||||
VICISANO <L.Vicisano@cs.ucl.ac.uk> for finding a problem.
|
||||
|
||||
o mrouted is much more careful about forgetting prunes; 3.8
|
||||
would forget prunes whenever any route change ocurred.
|
||||
|
||||
The 3.9-beta1 release has the following new features:
|
||||
|
||||
o Longer prune lifetimes (2 hours) by default. Prune lifetimes may
|
||||
be configured per-vif, with the "prune_lifetime N" mrouted.conf
|
||||
configuration file entry (where N is in seconds). This helps to
|
||||
work around the black holes caused on restart when you have a Cisco
|
||||
upstream which does not handle genid's; if this is your situation
|
||||
the recommended value is 300.
|
||||
|
||||
o mrouted's behavior of flooding new routes by default at startup
|
||||
in order to speed healing of paths during startup can be turned off
|
||||
per-vif or globally with the "noflood" configuration option.
|
||||
Turning this option off means you are likely to experience
|
||||
black holes for a minute or two when you restart a router. The
|
||||
default is to flood for a minute or two until mrouted is able to
|
||||
learn subordinate relationships.
|
||||
|
||||
o mrouted now retransmits prunes by default on point-to-point links.
|
||||
prune retransmission can be turned on or off per vif via the
|
||||
"rexmit_prunes [on|off]" mrouted.conf command. Prune retransmission
|
||||
helps on lossy links, and also helps when a router has forgotten
|
||||
about a prune (e.g. if it is out of memory and needs to shed state,
|
||||
or due to a bug).
|
||||
|
||||
o The new "passive" mode causes mrouted to not actively send probes
|
||||
looking for neighbors. This allows a dialup link to become quiescent
|
||||
if there is no DVMRP neighbor on the other end. Configuring
|
||||
"passive" on both ends of a link will cause it to never come up.
|
||||
|
||||
o mrouted defaults to not peering with DVMRP routers that do not
|
||||
prune. Use the "allow_nonpruners" mrouted.conf option on a vif
|
||||
on which you want to allow such peerings.
|
||||
|
||||
o mrouted now allows route filtering. mrouted.conf syntax:
|
||||
accept 13/8
|
||||
|
||||
accepts all routes matching 13/8 (e.g. accepts
|
||||
13.2.116/22). If you want to accept only exactly
|
||||
13/8, use
|
||||
|
||||
accept 13/8 exact
|
||||
|
||||
deny 10/8 64/2 130/8 exact 172/8 exact
|
||||
|
||||
denies some common MBone martians
|
||||
|
||||
Only "accept" or "deny" is allowed, no combinations.
|
||||
|
||||
Add "bidir" to apply the filter to output too, otherwise
|
||||
it's input only.
|
||||
|
||||
Expected usage:
|
||||
- Providers filter routes that customers send them
|
||||
- Martian removal
|
||||
- Topology modification (e.g. don't let the existence of
|
||||
private tunnel foo out into the world).
|
||||
|
||||
|
||||
o mrouted now malloc's the buffer it uses for SIOCGIFCONF, to allow
|
||||
for more interfaces. Thanks to Danny Mitzel
|
||||
|
||||
o mrouted now ignores multiple entries for a single interface
|
||||
name (temporary hack until mrouted understands interface aliases)
|
||||
|
||||
o mrouted's "-d" flag has been modified to accept the names of the
|
||||
systems which you would like to debug.
|
||||
packet, prunes, routes, peers, cache, timeout, interface,
|
||||
membership, traceroute, igmp
|
||||
|
||||
o mrouted now times neighbors out fater, and fully detects and
|
||||
ignores routes from one-way peerings.
|
||||
|
||||
o mrouted's route processing has been sped up, especially at startup.
|
||||
|
||||
o mrouted uses the biggest SO_RCVBUF the operating system allows
|
||||
(up to 256Kbytes)
|
||||
|
||||
o mrouted uses TOS 0xc0 ("Internet Control") for DVMRP messages.
|
||||
|
||||
===========
|
||||
Release 3.8
|
||||
November 29, 1995
|
||||
|
||||
The 3.8 release fixes the following bugs:
|
||||
|
||||
o mrouted would fail to forget prunes when a neighbor went away,
|
||||
thus potentially sending traffic down a tunnel after the tunnel
|
||||
endpoint has gone down. This was due to some research code making
|
||||
it into the "emergency" 3.7 release, sigh.
|
||||
|
||||
o mrouted could send prunes with negative lifetimes. This causes
|
||||
slightly higher prune traffic but shouldn't be any major problem.
|
||||
|
||||
===========
|
||||
Release 3.7
|
||||
November 28, 1995
|
||||
|
||||
The 3.7 release fixes the following bugs:
|
||||
|
||||
o mrouted now ignores route reports that include bogus netmasks.
|
||||
There was a bug in 3.5 that would mangle default routes into
|
||||
tens of bogus routes; this should prevent that bug from killing
|
||||
the MBONE.
|
||||
|
||||
This solution can cause route flaps and black holes until the
|
||||
3.5's are gone or all of the 3.5's neighbors are 3.7 .
|
||||
|
||||
o mrouted now ignores duplicate routes. Ciscos and the above 3.5
|
||||
bug could cause two copies of the same route to appear in a single
|
||||
routing update; mrouted would insert two copies of the same route
|
||||
into its routing table and wreak all sorts of havoc.
|
||||
|
||||
o mrouted now sends a group-specific query for both retransmissions
|
||||
of a g-s query; previous versions sent a general query the second
|
||||
time.
|
||||
|
||||
o mrouted now loops back multicasted mtrace responses and
|
||||
group-specific membership queries
|
||||
|
||||
o mrouted now performs deterministic tiebreaking between two
|
||||
neighbors on the same vif.
|
||||
|
||||
o mrouted now only does duplicate suppression on traceroute requests,
|
||||
not all traceroute packets, so that a loop can be nicely detected
|
||||
via a duplicate router instead of just a timeout.
|
||||
|
||||
o the buffer size that mrouted uses has been increased to allow
|
||||
more than 16 hops in mtrace messages.
|
||||
|
||||
o mtrace's hop-by-hop termination is now more likely to be correct.
|
||||
|
||||
o mrinfo now waits for the responses to its retransmitted queries.
|
||||
|
||||
The 3.7 release has the following new features:
|
||||
|
||||
o The configuration file can accept a hostname as the other end
|
||||
of a tunnel. There must be a single name->ip mapping for the
|
||||
given name, however, or mrouted will fail to start up.
|
||||
|
||||
o mrinfo now sends requests to all interfaces of a multihomed host.
|
||||
|
||||
o mtrace's passive mode has been implemented.
|
||||
|
||||
o The first screen of mtrace statistics is shorter and more likely
|
||||
to fit on one screen.
|
||||
|
||||
===========
|
||||
Release 3.6
|
||||
June 26, 1995
|
||||
|
||||
The 3.6 release fixes the following bugs:
|
||||
|
||||
o mrouted would dump core when attempting to report no routes (i.e. upon
|
||||
startup, if you have no enabled phyint's)
|
||||
|
||||
o mrouted would dump core if requested to traceroute a source for which it
|
||||
had no route
|
||||
|
||||
o neighbor flags were not always properly updated on probe or report
|
||||
|
||||
o mrouted would sometimes reply to a multicast traceroute on a disabled
|
||||
phyint; now it uses the first configured phyint to reply to traceroutes.
|
||||
|
||||
o host routes (i.e. netmask 0xffffffff) works now; it was discarding
|
||||
IGMP from the host because it was coming from the "broadcast address"
|
||||
of the subnet.
|
||||
|
||||
o send_igmp() now treats the failure to send an mtrace or a neighbor
|
||||
reply as informational, as opposed to warning.
|
||||
|
||||
o mrouted would go into an infinite loop trying to respond to a traceroute
|
||||
for a source with a netmask of 0xffffffff.
|
||||
|
||||
o vifs_with_neighbors was not being reset if the mrouted was restarted
|
||||
with SIGHUP
|
||||
|
||||
o the default route was not being properly advertised to neighbors (although
|
||||
it was accepted if it was advertised to it)
|
||||
|
||||
o ANSI-fication for those who it helps, still-K&R-ish for those it doesn't.
|
||||
|
||||
o mtrace now attempts to trace three hops past a non-responding router,
|
||||
in the hopes that it does support traceroute but just couldn't respond
|
||||
(i.e. unicast didn't work and it can't source multicast because all its
|
||||
phyints are disabled).
|
||||
|
||||
o mrinfo now times out even on a multicast router.
|
||||
|
||||
|
||||
===========
|
||||
Release 3.5
|
||||
May 8, 1995
|
||||
|
||||
The 3.5 release has the following new features:
|
||||
|
||||
o The kernel and mrouted make sure that each is the correct version, to
|
||||
prevent problems with mismatched kernel/mrouted versions. A too-old
|
||||
mrouted will die with the error:
|
||||
|
||||
can't enable DVMRP routing in kernel: Option not supported by protocol
|
||||
|
||||
o mrouted can accept and propogate a default route (essential for
|
||||
heirarchical multicast routing)
|
||||
|
||||
o Kernel route cache keeps source-specific routes instead of subnet routes,
|
||||
eliminating hashing and longest-match problems.
|
||||
(allows classless routing, longest-match and default routing)
|
||||
|
||||
o Cached kernel routes only get deleted if no traffic is flowing, to
|
||||
facilitate multicast traceroute
|
||||
|
||||
o mrouted has a new configuration file parser, which provides better error
|
||||
messages than before, and allows named boundaries (see man page)
|
||||
|
||||
o added "netmask" to phyint configuration, at the suggestion of
|
||||
Anders Klemets
|
||||
|
||||
o System V and FreeBSD compatibility from John Brezak <brezak@ch.hp.com>
|
||||
|
||||
o phyint's can have additional subnets configured, for people with
|
||||
multiple subnets on one physical network. mrouted.conf syntax is
|
||||
altnet 1.2.3.0, or altnet 1.2.3.0/24 if you need to specify
|
||||
a different netmask. There can be as many altnet statements
|
||||
as you need.
|
||||
|
||||
o both mrouted and the kernel now support classless addresses.
|
||||
|
||||
o the kernel supports PIM assert processing by notifying the router
|
||||
when a packet arrives on the wrong interface
|
||||
|
||||
o the kernel keeps additional counters, and mrouted can be compiled to
|
||||
support SNMP and the Multicast MIB
|
||||
|
||||
o the packet classifier in the kernel now uses the following udp port
|
||||
ranges:
|
||||
[0, 16384) - lowest priority, unclassified
|
||||
[16384, 32768) - highest priority, i.e. audio
|
||||
[32768, 49152) - medium priority, i.e. whiteboard
|
||||
[49152, 65536) - low priority, i.e. video
|
||||
A future release of a session directory will allocate ports in these
|
||||
ranges.
|
||||
|
||||
o the configuration code has been modified to default tunnels' rate_limit
|
||||
parameters to 500kbps. This is easily modified with a rate_limit keyword
|
||||
in mrouted.conf, but should be a good default for the MBONE in general.
|
||||
|
||||
o The tunnel sending code now caches a route for ip_output(), this should
|
||||
help performance on machines with lots of tunnels.
|
||||
|
||||
o Dispatching for de-capsulating packets is now via protosw[], making
|
||||
reception of other raw protocols more efficient
|
||||
|
||||
o Neighbor capabilities are discovered via a bitmask as opposed to
|
||||
version number.
|
||||
|
||||
o Multicast traceroute code improved
|
||||
|
||||
o mrouted can be compiled with Routing Support for Resource Reservation
|
||||
(RSRR), required for RSVP.
|
||||
|
||||
|
||||
The 3.5 release fixes the following bugs:
|
||||
|
||||
o The IGMPv2 query timeout field was interpreted as being in units of
|
||||
200ms as opposed to 100ms, thus the maximum timeout was set to twice
|
||||
the expected value. This is not fatal, as mrouted always queries
|
||||
twice in the expectation that a packet could get loss, but it does
|
||||
make it less robust in the face of packet loss.
|
||||
|
||||
o IGMP could report membership in local-only groups (i.e. 224.0.0.X)
|
||||
|
||||
o IGMP could get confused by hearing its own new membership reports, thus
|
||||
a router would never perform fast leave.
|
||||
|
||||
o IGMP could reset timers for the wrong interface.
|
||||
|
||||
o mrouted put a bogus value in the maximum timeout field of IGMPv2 query
|
||||
packets.
|
||||
|
||||
o Non-querier mrouters would respond to IGMP leave messages
|
||||
|
||||
o mrouted was not performing fast leave properly
|
||||
|
||||
o If the last member goes away on a transit network, the upstream router
|
||||
would stop forwarding even if there are downstream members.
|
||||
|
||||
o Kernel hash function improved
|
||||
|
||||
o Eliminated possibility of panic(): timeout in cache maintenance
|
||||
|
||||
o Reordered resource allocation when sending upcall to handle failure properly
|
||||
|
||||
o some endian-ness bugs squashed in mrouted, probably more to go.
|
||||
|
||||
o Multicast traceroute could send a reply on a disabled interface.
|
||||
|
||||
|
||||
This release consists of the following files:
|
||||
|
||||
|
||||
README-3.8.mrouted - this file
|
||||
|
||||
mrouted/* - version 3.8 of mrouted,
|
||||
mrinfo, map-mbone and
|
||||
mtrace.
|
||||
|
||||
ifconfig/* - Changes to ifconfig to
|
||||
show multicast interfaces
|
||||
|
||||
netstat/* - Diffs to netstat
|
||||
|
||||
ping/* - sources for ping
|
||||
which support
|
||||
multicasting
|
||||
|
||||
mtest/* - utility for testing
|
||||
multicast group
|
||||
membership
|
||||
|
||||
|
||||
MROUTED 3.8
|
||||
|
||||
Mrouted 3.8 has two optional features: SNMP and RSRR. RSRR support
|
||||
is required for running RSVP; the SNMP code, with the help of the
|
||||
ISODE snmpd, implements both the Multicast MIB and the DVMRP MIB.
|
||||
|
||||
RSRR
|
||||
----
|
||||
Routing Support for Resource Reservations (RSRR) was contributed by
|
||||
Daniel Zappala <daniel@isi.edu>.
|
||||
|
||||
To enable RSRR support, uncomment the three lines starting with
|
||||
RSRR near the top of the Makefile and "make clean; make". Or use
|
||||
the prebuilt binary, mrouted.rsrr .
|
||||
|
||||
RSRR allows RSVP to query mrouted for its routing entry for a particular
|
||||
source-group pair. Using the routing entry and the IP_MULTICAST_VIF
|
||||
socket call, RSVP can forward distinct control messages out each
|
||||
outgoing interface. This version of mrouted supports RSRR messages
|
||||
using a Unix datagram socket.
|
||||
|
||||
RSRR currently includes two pairs of query-reply messages. RSVP sends
|
||||
an Initial Query when it starts. Mrouted responds with an Initial Reply
|
||||
that includes the set of vifs it is using, flagging those that are
|
||||
administratively disabled. When RSVP needs the routing entry for a
|
||||
source-group pair, it sends a Route Query. Mrouted responds with a
|
||||
Route Reply that includes the incoming vif and outgoing vifs for the
|
||||
source-group pair.
|
||||
|
||||
RSVP may request route change notification by setting the notification
|
||||
bit in the Route Query. If mrouted can provide route change
|
||||
notification for the source-group pair, it sets the notification bit in
|
||||
its Route Reply. When the routing entry for the source-group pair
|
||||
changes, mrouted sends an unsolicited Route Reply containing the new
|
||||
routing information. The initial release of mrouted 3.5 did not support
|
||||
route change notification and always returned a Route Reply with the
|
||||
notification bit cleared. This release of mrouted provides route change
|
||||
notification when possible.
|
||||
|
||||
SNMP
|
||||
----
|
||||
SNMP support was contributed by David Thaler <thalerd@eecs.umich.edu>.
|
||||
|
||||
To enable SNMP support, uncomment the six lines near the top of
|
||||
the Makefile below the description of SNMP support, or use the
|
||||
prebuilt binary, mrouted.snmp or mrouted.rsrr.snmp .
|
||||
|
||||
To link the SNMP-capable mrouted, you need the CMU libraries.
|
||||
See http://nic.merit.edu/~mbone/ for a full mrouted-snmp distribution.
|
||||
|
||||
Make sure to add the "sysName", "sysContact", "sysVersion" and
|
||||
"sysLocation" variables to your /etc/mrouted.conf if you want them
|
||||
to provide anything other than default values.
|
||||
|
||||
Example:
|
||||
|
||||
sysName "tibia"
|
||||
sysContact "Bill Fenner <fenner@parc.xerox.com> +1 415 812-4816"
|
||||
sysVersion "SunOS 4.1.3 and mrouted 3.8"
|
||||
sysLocation "MAXC room, PARC building 35"
|
||||
|
||||
The SNMP version of mrouted has an additional command line flag:
|
||||
|
||||
-P snmp_port
|
||||
|
||||
Specifies a port for SNMP communication (default 161). This option
|
||||
should be used when another SNMP daemon already exists. The
|
||||
preferred alternate port in this case is port 9161.
|
||||
|
||||
The mstat(8) program allows querying of statistics using SNMP.
|
@ -1 +0,0 @@
|
||||
3.9-beta3+IOS12
|
@ -1,250 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* callout.c,v 3.8.4.8 1998/01/06 01:58:45 fenner Exp
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/* the code below implements a callout queue */
|
||||
static int id = 0;
|
||||
static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
|
||||
|
||||
struct timeout_q {
|
||||
struct timeout_q *next; /* next event */
|
||||
int id;
|
||||
cfunc_t func; /* function to call */
|
||||
void *data; /* func's data */
|
||||
int time; /* time offset to next event*/
|
||||
};
|
||||
|
||||
#ifdef IGMP_DEBUG
|
||||
static void print_Q __P((void));
|
||||
#else
|
||||
#define print_Q()
|
||||
#endif
|
||||
|
||||
void
|
||||
callout_init()
|
||||
{
|
||||
Q = (struct timeout_q *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
free_all_callouts()
|
||||
{
|
||||
struct timeout_q *p;
|
||||
|
||||
while (Q) {
|
||||
p = Q;
|
||||
Q = Q->next;
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* elapsed_time seconds have passed; perform all the events that should
|
||||
* happen.
|
||||
*/
|
||||
void
|
||||
age_callout_queue(elapsed_time)
|
||||
int elapsed_time;
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
int i = 0;
|
||||
|
||||
for (ptr = Q; ptr; ptr = Q, i++) {
|
||||
if (ptr->time > elapsed_time) {
|
||||
ptr->time -= elapsed_time;
|
||||
return;
|
||||
} else {
|
||||
elapsed_time -= ptr->time;
|
||||
Q = Q->next;
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
log(LOG_DEBUG, 0, "about to call timeout %d (#%d)", ptr->id, i);
|
||||
if (ptr->func)
|
||||
ptr->func(ptr->data);
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return in how many seconds age_callout_queue() would like to be called.
|
||||
* Return -1 if there are no events pending.
|
||||
*/
|
||||
int
|
||||
timer_nextTimer()
|
||||
{
|
||||
if (Q) {
|
||||
if (Q->time < 0) {
|
||||
log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
|
||||
Q->time);
|
||||
return 0;
|
||||
}
|
||||
return Q->time;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* sets the timer
|
||||
*/
|
||||
int
|
||||
timer_setTimer(delay, action, data)
|
||||
int delay; /* number of units for timeout */
|
||||
cfunc_t action; /* function to be called on timeout */
|
||||
void *data; /* what to call the timeout function with */
|
||||
{
|
||||
struct timeout_q *ptr, *node, *prev;
|
||||
int i = 0;
|
||||
|
||||
/* create a node */
|
||||
node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
|
||||
if (node == 0) {
|
||||
log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
|
||||
return -1;
|
||||
}
|
||||
node->func = action;
|
||||
node->data = data;
|
||||
node->time = delay;
|
||||
node->next = 0;
|
||||
node->id = ++id;
|
||||
|
||||
prev = ptr = Q;
|
||||
|
||||
/* insert node in the queue */
|
||||
|
||||
/* if the queue is empty, insert the node and return */
|
||||
if (!Q)
|
||||
Q = node;
|
||||
else {
|
||||
/* chase the pointer looking for the right place */
|
||||
while (ptr) {
|
||||
|
||||
if (delay < ptr->time) {
|
||||
/* right place */
|
||||
|
||||
node->next = ptr;
|
||||
if (ptr == Q)
|
||||
Q = node;
|
||||
else
|
||||
prev->next = node;
|
||||
ptr->time -= node->time;
|
||||
print_Q();
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
log(LOG_DEBUG, 0, "created timeout %d (#%d)", node->id, i);
|
||||
return node->id;
|
||||
} else {
|
||||
/* keep moving */
|
||||
|
||||
delay -= ptr->time; node->time = delay;
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
prev->next = node;
|
||||
}
|
||||
print_Q();
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
log(LOG_DEBUG, 0, "created timeout %d (#%d)", node->id, i);
|
||||
return node->id;
|
||||
}
|
||||
|
||||
/* returns the time until the timer is scheduled */
|
||||
int
|
||||
timer_leftTimer(timer_id)
|
||||
int timer_id;
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
int left = 0;
|
||||
|
||||
if (!timer_id)
|
||||
return -1;
|
||||
|
||||
for (ptr = Q; ptr; ptr = ptr->next) {
|
||||
left += ptr->time;
|
||||
if (ptr->id == timer_id)
|
||||
return left;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* clears the associated timer. Returns 1 if succeeded. */
|
||||
int
|
||||
timer_clearTimer(timer_id)
|
||||
int timer_id;
|
||||
{
|
||||
struct timeout_q *ptr, *prev;
|
||||
int i = 0;
|
||||
|
||||
if (!timer_id)
|
||||
return 0;
|
||||
|
||||
prev = ptr = Q;
|
||||
|
||||
/*
|
||||
* find the right node, delete it. the subsequent node's time
|
||||
* gets bumped up
|
||||
*/
|
||||
|
||||
print_Q();
|
||||
while (ptr) {
|
||||
if (ptr->id == timer_id) {
|
||||
/* got the right node */
|
||||
|
||||
/* unlink it from the queue */
|
||||
if (ptr == Q)
|
||||
Q = Q->next;
|
||||
else
|
||||
prev->next = ptr->next;
|
||||
|
||||
/* increment next node if any */
|
||||
if (ptr->next != 0)
|
||||
(ptr->next)->time += ptr->time;
|
||||
|
||||
if (ptr->data)
|
||||
free(ptr->data);
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
log(LOG_DEBUG, 0, "deleted timer %d (#%d)", ptr->id, i);
|
||||
free(ptr);
|
||||
print_Q();
|
||||
return 1;
|
||||
}
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
i++;
|
||||
}
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
log(LOG_DEBUG, 0, "failed to delete timer %d (#%d)", timer_id, i);
|
||||
print_Q();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef IGMP_DEBUG
|
||||
/*
|
||||
* debugging utility
|
||||
*/
|
||||
static void
|
||||
print_Q()
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
for (ptr = Q; ptr; ptr = ptr->next)
|
||||
log(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
|
||||
}
|
||||
#endif /* IGMP_DEBUG */
|
@ -1,927 +0,0 @@
|
||||
%{
|
||||
/*
|
||||
* Configuration file parser for mrouted.
|
||||
*
|
||||
* Written by Bill Fenner, NRL, 1994
|
||||
*
|
||||
* $FreeBSD$
|
||||
* cfparse.y,v 3.8.4.30 1998/03/01 01:48:58 fenner Exp
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include "defs.h"
|
||||
#include <netdb.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
/*
|
||||
* Local function declarations
|
||||
*/
|
||||
static void fatal __P((char *fmt, ...)) __printflike(1, 2);
|
||||
static void warn __P((char *fmt, ...)) __printflike(1, 2);
|
||||
static void yyerror __P((char *s));
|
||||
static char * next_word __P((void));
|
||||
static int yylex __P((void));
|
||||
static u_int32 valid_if __P((char *s));
|
||||
static const char * ifconfaddr(u_int32_t a);
|
||||
int yyparse __P((void));
|
||||
|
||||
static FILE *f;
|
||||
|
||||
char *configfilename = _PATH_MROUTED_CONF;
|
||||
|
||||
extern int cache_lifetime;
|
||||
extern int prune_lifetime;
|
||||
|
||||
/* imported from config.c, with slight memory leak */
|
||||
extern struct ifconf ifc;
|
||||
|
||||
int allow_black_holes = 0;
|
||||
|
||||
static int lineno;
|
||||
|
||||
static struct uvif *v;
|
||||
|
||||
static int order, state;
|
||||
static int noflood = 0;
|
||||
static int rexmit = VIFF_REXMIT_PRUNES;
|
||||
|
||||
struct addrmask {
|
||||
u_int32 addr;
|
||||
int mask;
|
||||
};
|
||||
|
||||
struct boundnam {
|
||||
char *name;
|
||||
struct addrmask bound;
|
||||
};
|
||||
|
||||
#define MAXBOUNDS 20
|
||||
|
||||
struct boundnam boundlist[MAXBOUNDS]; /* Max. of 20 named boundaries */
|
||||
int numbounds = 0; /* Number of named boundaries */
|
||||
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
int num;
|
||||
char *ptr;
|
||||
struct addrmask addrmask;
|
||||
u_int32 addr;
|
||||
struct vf_element *filterelem;
|
||||
};
|
||||
|
||||
%token CACHE_LIFETIME PRUNE_LIFETIME PRUNING BLACK_HOLE NOFLOOD
|
||||
%token PHYINT TUNNEL NAME
|
||||
%token DISABLE IGMPV1 SRCRT BESIDE
|
||||
%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET ADVERT_METRIC
|
||||
%token FILTER ACCEPT DENY EXACT BIDIR REXMIT_PRUNES REXMIT_PRUNES2
|
||||
%token PASSIVE ALLOW_NONPRUNERS
|
||||
%token NOTRANSIT BLASTER FORCE_LEAF
|
||||
%token PRUNE_LIFETIME2 NOFLOOD2
|
||||
%token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION
|
||||
%token <num> BOOLEAN
|
||||
%token <num> NUMBER
|
||||
%token <ptr> STRING
|
||||
%token <addrmask> ADDRMASK
|
||||
%token <addr> ADDR
|
||||
|
||||
%type <addr> interface addrname
|
||||
%type <addrmask> bound boundary addrmask
|
||||
%type <filterelem> filter filtlist filtelement filtelem
|
||||
|
||||
%start conf
|
||||
|
||||
%%
|
||||
|
||||
conf : stmts
|
||||
;
|
||||
|
||||
stmts : /* Empty */
|
||||
| stmts stmt
|
||||
;
|
||||
|
||||
stmt : error
|
||||
| PHYINT interface {
|
||||
|
||||
vifi_t vifi;
|
||||
|
||||
state++;
|
||||
|
||||
if (order)
|
||||
fatal("phyints must appear before tunnels");
|
||||
|
||||
for (vifi = 0, v = uvifs;
|
||||
vifi < numvifs;
|
||||
++vifi, ++v)
|
||||
if (!(v->uv_flags & VIFF_TUNNEL) &&
|
||||
$2 == v->uv_lcl_addr)
|
||||
break;
|
||||
|
||||
if (vifi == numvifs)
|
||||
fatal("%s is not a configured interface",
|
||||
inet_fmt($2,s1));
|
||||
|
||||
}
|
||||
ifmods
|
||||
| TUNNEL interface addrname {
|
||||
const char *ifname;
|
||||
struct ifreq ffr;
|
||||
vifi_t vifi;
|
||||
|
||||
order++;
|
||||
|
||||
ifname = ifconfaddr($2);
|
||||
if (ifname == 0)
|
||||
fatal("Tunnel local address %s is not mine",
|
||||
inet_fmt($2, s1));
|
||||
|
||||
if (((ntohl($2) & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) ==
|
||||
IN_LOOPBACKNET)
|
||||
fatal("Tunnel local address %s is a loopback address",
|
||||
inet_fmt($2, s1));
|
||||
|
||||
if (ifconfaddr($3) != 0)
|
||||
fatal("Tunnel remote address %s is one of mine",
|
||||
inet_fmt($3, s1));
|
||||
|
||||
for (vifi = 0, v = uvifs;
|
||||
vifi < numvifs;
|
||||
++vifi, ++v)
|
||||
if (v->uv_flags & VIFF_TUNNEL) {
|
||||
if ($3 == v->uv_rmt_addr)
|
||||
fatal("Duplicate tunnel to %s",
|
||||
inet_fmt($3, s1));
|
||||
} else if (!(v->uv_flags & VIFF_DISABLED)) {
|
||||
if (($3 & v->uv_subnetmask) == v->uv_subnet)
|
||||
fatal("Unnecessary tunnel to %s, same subnet as vif %d (%s)",
|
||||
inet_fmt($3,s1), vifi, v->uv_name);
|
||||
}
|
||||
|
||||
if (numvifs == MAXVIFS)
|
||||
fatal("too many vifs");
|
||||
|
||||
strlcpy(ffr.ifr_name, ifname, sizeof(ffr.ifr_name));
|
||||
if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
|
||||
fatal("ioctl SIOCGIFFLAGS on %s", ffr.ifr_name);
|
||||
|
||||
v = &uvifs[numvifs];
|
||||
zero_vif(v, 1);
|
||||
v->uv_flags = VIFF_TUNNEL | rexmit | noflood;
|
||||
v->uv_flags |= VIFF_OTUNNEL; /*XXX*/
|
||||
v->uv_lcl_addr = $2;
|
||||
v->uv_rmt_addr = $3;
|
||||
v->uv_dst_addr = $3;
|
||||
strlcpy(v->uv_name, ffr.ifr_name, sizeof(v->uv_name));
|
||||
|
||||
if (!(ffr.ifr_flags & IFF_UP)) {
|
||||
v->uv_flags |= VIFF_DOWN;
|
||||
vifs_down = TRUE;
|
||||
}
|
||||
}
|
||||
tunnelmods
|
||||
{
|
||||
|
||||
if (!(v->uv_flags & VIFF_OTUNNEL)) {
|
||||
init_ipip_on_vif(v);
|
||||
}
|
||||
|
||||
log(LOG_INFO, 0,
|
||||
"installing tunnel from %s to %s as vif #%u - rate=%d",
|
||||
inet_fmt($2, s1), inet_fmt($3, s2),
|
||||
numvifs, v->uv_rate_limit);
|
||||
|
||||
++numvifs;
|
||||
|
||||
}
|
||||
| CACHE_LIFETIME NUMBER {
|
||||
|
||||
if ($2 < MIN_CACHE_LIFETIME) {
|
||||
warn("cache_lifetime %d must be at least %d",
|
||||
$2, MIN_CACHE_LIFETIME);
|
||||
} else {
|
||||
cache_lifetime = $2;
|
||||
}
|
||||
|
||||
}
|
||||
| PRUNE_LIFETIME NUMBER {
|
||||
|
||||
if ($2 < MIN_PRUNE_LIFETIME) {
|
||||
warn("prune_lifetime %d must be at least %d",
|
||||
$2, MIN_PRUNE_LIFETIME);
|
||||
} else {
|
||||
prune_lifetime = $2;
|
||||
}
|
||||
|
||||
}
|
||||
| PRUNING BOOLEAN {
|
||||
|
||||
if ($2 != 1) {
|
||||
warn("Disabling pruning is no longer supported");
|
||||
}
|
||||
|
||||
}
|
||||
| BLACK_HOLE {
|
||||
#ifdef ALLOW_BLACK_HOLES
|
||||
allow_black_holes = 1;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Turn off initial flooding (until subordinateness is learned
|
||||
* via route exchange) on all phyints and set the default for
|
||||
* all further tunnels.
|
||||
*/
|
||||
| NOFLOOD {
|
||||
|
||||
vifi_t vifi;
|
||||
|
||||
noflood = VIFF_NOFLOOD;
|
||||
for (vifi = 0, v = uvifs;
|
||||
vifi < numvifs;
|
||||
++vifi, ++v)
|
||||
v->uv_flags |= VIFF_NOFLOOD;
|
||||
|
||||
}
|
||||
/*
|
||||
* Turn on prune retransmission on all interfaces.
|
||||
* Tunnels default to retransmitting, so this just
|
||||
* needs to turn on phyints.
|
||||
*/
|
||||
| REXMIT_PRUNES {
|
||||
|
||||
vifi_t vifi;
|
||||
|
||||
for (vifi = 0, v = uvifs;
|
||||
vifi < numvifs;
|
||||
++vifi, ++v)
|
||||
v->uv_flags |= VIFF_REXMIT_PRUNES;
|
||||
|
||||
}
|
||||
/*
|
||||
* If true, do as above. If false, no need to turn
|
||||
* it off for phyints since they default to not
|
||||
* rexmit; need to set flag to not rexmit on tunnels.
|
||||
*/
|
||||
| REXMIT_PRUNES BOOLEAN {
|
||||
|
||||
if ($2) {
|
||||
vifi_t vifi;
|
||||
|
||||
for (vifi = 0, v = uvifs;
|
||||
vifi < numvifs;
|
||||
++vifi, ++v)
|
||||
v->uv_flags |= VIFF_REXMIT_PRUNES;
|
||||
} else {
|
||||
rexmit = 0;
|
||||
}
|
||||
|
||||
}
|
||||
| NAME STRING boundary { if (numbounds >= MAXBOUNDS) {
|
||||
fatal("Too many named boundaries (max %d)", MAXBOUNDS);
|
||||
}
|
||||
|
||||
boundlist[numbounds].name = malloc(strlen($2) + 1);
|
||||
strcpy(boundlist[numbounds].name, $2);
|
||||
boundlist[numbounds++].bound = $3;
|
||||
}
|
||||
| SYSNAM STRING {
|
||||
#ifdef SNMP
|
||||
set_sysName($2);
|
||||
#endif /* SNMP */
|
||||
}
|
||||
| SYSCONTACT STRING {
|
||||
#ifdef SNMP
|
||||
set_sysContact($2);
|
||||
#endif /* SNMP */
|
||||
}
|
||||
| SYSVERSION STRING {
|
||||
#ifdef SNMP
|
||||
set_sysVersion($2);
|
||||
#endif /* SNMP */
|
||||
}
|
||||
| SYSLOCATION STRING {
|
||||
#ifdef SNMP
|
||||
set_sysLocation($2);
|
||||
#endif /* SNMP */
|
||||
}
|
||||
;
|
||||
|
||||
tunnelmods : /* empty */
|
||||
| tunnelmods tunnelmod
|
||||
;
|
||||
|
||||
tunnelmod : mod
|
||||
| BESIDE { v->uv_flags |= VIFF_OTUNNEL; }
|
||||
| BESIDE BOOLEAN {
|
||||
|
||||
if ($2) {
|
||||
v->uv_flags |= VIFF_OTUNNEL;
|
||||
} else {
|
||||
v->uv_flags &= ~VIFF_OTUNNEL;
|
||||
}
|
||||
|
||||
}
|
||||
| SRCRT { fatal("Source-route tunnels not supported"); }
|
||||
;
|
||||
|
||||
ifmods : /* empty */
|
||||
| ifmods ifmod
|
||||
;
|
||||
|
||||
ifmod : mod
|
||||
| DISABLE { v->uv_flags |= VIFF_DISABLED; }
|
||||
| IGMPV1 { v->uv_flags |= VIFF_IGMPV1; }
|
||||
| NETMASK addrname {
|
||||
u_int32 subnet, mask;
|
||||
|
||||
mask = $2;
|
||||
subnet = v->uv_lcl_addr & mask;
|
||||
if (!inet_valid_subnet(subnet, mask))
|
||||
fatal("Invalid netmask");
|
||||
v->uv_subnet = subnet;
|
||||
v->uv_subnetmask = mask;
|
||||
v->uv_subnetbcast = subnet | ~mask;
|
||||
}
|
||||
| NETMASK {
|
||||
|
||||
warn("Expected address after netmask keyword, ignored");
|
||||
|
||||
}
|
||||
| ALTNET addrmask {
|
||||
|
||||
struct phaddr *ph;
|
||||
|
||||
ph = (struct phaddr *)malloc(sizeof(struct phaddr));
|
||||
if (ph == NULL)
|
||||
fatal("out of memory");
|
||||
if ($2.mask) {
|
||||
VAL_TO_MASK(ph->pa_subnetmask, $2.mask);
|
||||
} else
|
||||
ph->pa_subnetmask = v->uv_subnetmask;
|
||||
ph->pa_subnet = $2.addr & ph->pa_subnetmask;
|
||||
ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask;
|
||||
if ($2.addr & ~ph->pa_subnetmask)
|
||||
warn("Extra subnet %s/%d has host bits set",
|
||||
inet_fmt($2.addr,s1), $2.mask);
|
||||
ph->pa_next = v->uv_addrs;
|
||||
v->uv_addrs = ph;
|
||||
|
||||
}
|
||||
| ALTNET {
|
||||
|
||||
warn("Expected address after altnet keyword, ignored");
|
||||
|
||||
}
|
||||
| FORCE_LEAF {
|
||||
|
||||
v->uv_flags |= VIFF_FORCE_LEAF;
|
||||
|
||||
}
|
||||
| FORCE_LEAF BOOLEAN {
|
||||
|
||||
if ($2) {
|
||||
v->uv_flags |= VIFF_FORCE_LEAF;
|
||||
} else {
|
||||
v->uv_flags &= ~VIFF_FORCE_LEAF;
|
||||
}
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
|
||||
fatal("Invalid threshold %d",$2);
|
||||
v->uv_threshold = $2;
|
||||
}
|
||||
| THRESHOLD {
|
||||
|
||||
warn("Expected number after threshold keyword, ignored");
|
||||
|
||||
}
|
||||
| METRIC NUMBER { if ($2 < 1 || $2 > UNREACHABLE)
|
||||
fatal("Invalid metric %d",$2);
|
||||
v->uv_metric = $2;
|
||||
}
|
||||
| METRIC {
|
||||
|
||||
warn("Expected number after metric keyword, ignored");
|
||||
|
||||
}
|
||||
| ADVERT_METRIC NUMBER { if ($2 < 0 || $2 > UNREACHABLE - 1)
|
||||
fatal("Invalid advert_metric %d", $2);
|
||||
v->uv_admetric = $2;
|
||||
}
|
||||
| ADVERT_METRIC {
|
||||
|
||||
warn("Expected number after advert_metric keyword, ignored");
|
||||
|
||||
}
|
||||
| RATE_LIMIT NUMBER { if ($2 > MAX_RATE_LIMIT)
|
||||
fatal("Invalid rate_limit %d",$2);
|
||||
v->uv_rate_limit = $2;
|
||||
}
|
||||
| RATE_LIMIT {
|
||||
|
||||
warn("Expected number after rate_limit keyword, ignored");
|
||||
|
||||
}
|
||||
| BOUNDARY bound {
|
||||
|
||||
struct vif_acl *v_acl;
|
||||
|
||||
v_acl = (struct vif_acl *)malloc(sizeof(struct vif_acl));
|
||||
if (v_acl == NULL)
|
||||
fatal("out of memory");
|
||||
VAL_TO_MASK(v_acl->acl_mask, $2.mask);
|
||||
v_acl->acl_addr = $2.addr & v_acl->acl_mask;
|
||||
if ($2.addr & ~v_acl->acl_mask)
|
||||
warn("Boundary spec %s/%d has host bits set",
|
||||
inet_fmt($2.addr,s1),$2.mask);
|
||||
v_acl->acl_next = v->uv_acl;
|
||||
v->uv_acl = v_acl;
|
||||
|
||||
}
|
||||
| BOUNDARY {
|
||||
|
||||
warn("Expected boundary spec after boundary keyword, ignored");
|
||||
|
||||
}
|
||||
| REXMIT_PRUNES2 {
|
||||
|
||||
v->uv_flags |= VIFF_REXMIT_PRUNES;
|
||||
|
||||
}
|
||||
| REXMIT_PRUNES2 BOOLEAN {
|
||||
|
||||
if ($2) {
|
||||
v->uv_flags |= VIFF_REXMIT_PRUNES;
|
||||
} else {
|
||||
v->uv_flags &= ~VIFF_REXMIT_PRUNES;
|
||||
}
|
||||
|
||||
}
|
||||
| PASSIVE {
|
||||
|
||||
v->uv_flags |= VIFF_PASSIVE;
|
||||
|
||||
}
|
||||
| NOFLOOD2 {
|
||||
|
||||
v->uv_flags |= VIFF_NOFLOOD;
|
||||
|
||||
}
|
||||
| NOTRANSIT {
|
||||
|
||||
v->uv_flags |= VIFF_NOTRANSIT;
|
||||
|
||||
}
|
||||
| BLASTER {
|
||||
|
||||
v->uv_flags |= VIFF_BLASTER;
|
||||
blaster_alloc(v - uvifs);
|
||||
|
||||
}
|
||||
| ALLOW_NONPRUNERS {
|
||||
|
||||
v->uv_flags |= VIFF_ALLOW_NONPRUNERS;
|
||||
|
||||
}
|
||||
| PRUNE_LIFETIME2 NUMBER {
|
||||
|
||||
if ($2 < MIN_PRUNE_LIFETIME) {
|
||||
warn("prune_lifetime %d must be at least %d",
|
||||
$2, MIN_PRUNE_LIFETIME);
|
||||
} else {
|
||||
v->uv_prune_lifetime = $2;
|
||||
}
|
||||
|
||||
}
|
||||
| ACCEPT filter {
|
||||
|
||||
if (v->uv_filter == NULL) {
|
||||
struct vif_filter *v_filter;
|
||||
|
||||
v_filter = (struct vif_filter *)malloc(sizeof(struct vif_filter));
|
||||
if (v_filter == NULL)
|
||||
fatal("out of memory");
|
||||
v_filter->vf_flags = 0;
|
||||
v_filter->vf_type = VFT_ACCEPT;
|
||||
v_filter->vf_filter = $2;
|
||||
v->uv_filter = v_filter;
|
||||
} else if (v->uv_filter->vf_type != VFT_ACCEPT) {
|
||||
fatal("can't accept and deny");
|
||||
} else {
|
||||
struct vf_element *p;
|
||||
|
||||
p = v->uv_filter->vf_filter;
|
||||
while (p->vfe_next)
|
||||
p = p->vfe_next;
|
||||
p->vfe_next = $2;
|
||||
}
|
||||
|
||||
}
|
||||
| ACCEPT {
|
||||
|
||||
warn("Expected filter spec after accept keyword, ignored");
|
||||
|
||||
}
|
||||
| DENY filter {
|
||||
|
||||
if (v->uv_filter == NULL) {
|
||||
struct vif_filter *v_filter;
|
||||
|
||||
v_filter = (struct vif_filter *)malloc(sizeof(struct vif_filter));
|
||||
if (v_filter == NULL)
|
||||
fatal("out of memory");
|
||||
v_filter->vf_flags = 0;
|
||||
v_filter->vf_type = VFT_DENY;
|
||||
v_filter->vf_filter = $2;
|
||||
v->uv_filter = v_filter;
|
||||
} else if (v->uv_filter->vf_type != VFT_DENY) {
|
||||
fatal("can't accept and deny");
|
||||
} else {
|
||||
struct vf_element *p;
|
||||
|
||||
p = v->uv_filter->vf_filter;
|
||||
while (p->vfe_next)
|
||||
p = p->vfe_next;
|
||||
p->vfe_next = $2;
|
||||
}
|
||||
|
||||
}
|
||||
| DENY {
|
||||
|
||||
warn("Expected filter spec after deny keyword, ignored");
|
||||
|
||||
}
|
||||
| BIDIR {
|
||||
|
||||
if (v->uv_filter == NULL) {
|
||||
fatal("bidir goes after filters");
|
||||
}
|
||||
v->uv_filter->vf_flags |= VFF_BIDIR;
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
interface : ADDR { $$ = $1; }
|
||||
| STRING {
|
||||
$$ = valid_if($1);
|
||||
if ($$ == 0)
|
||||
fatal("Invalid interface name %s",$1);
|
||||
}
|
||||
;
|
||||
|
||||
addrname : ADDR { $$ = $1; }
|
||||
| STRING { struct hostent *hp;
|
||||
|
||||
if ((hp = gethostbyname($1)) == NULL ||
|
||||
hp->h_length != sizeof($$))
|
||||
fatal("No such host %s", $1);
|
||||
|
||||
if (hp->h_addr_list[1])
|
||||
fatal("Hostname %s does not %s",
|
||||
$1, "map to a unique address");
|
||||
|
||||
bcopy(hp->h_addr_list[0], &$$,
|
||||
hp->h_length);
|
||||
}
|
||||
|
||||
bound : boundary { $$ = $1; }
|
||||
| STRING { int i;
|
||||
|
||||
for (i=0; i < numbounds; i++) {
|
||||
if (!strcmp(boundlist[i].name, $1)) {
|
||||
$$ = boundlist[i].bound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == numbounds) {
|
||||
fatal("Invalid boundary name %s",$1);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
boundary : ADDRMASK {
|
||||
|
||||
#ifdef ALLOW_BLACK_HOLES
|
||||
if (!allow_black_holes)
|
||||
#endif
|
||||
if ((ntohl($1.addr) & 0xff000000) != 0xef000000) {
|
||||
fatal("Boundaries must be 239.x.x.x, not %s/%d",
|
||||
inet_fmt($1.addr, s1), $1.mask);
|
||||
}
|
||||
$$ = $1;
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
addrmask : ADDRMASK { $$ = $1; }
|
||||
| ADDR { $$.addr = $1; $$.mask = 0; }
|
||||
;
|
||||
|
||||
filter : filtlist { $$ = $1; }
|
||||
| STRING { fatal("named filters no implemented yet"); }
|
||||
;
|
||||
|
||||
filtlist : filtelement { $$ = $1; }
|
||||
| filtelement filtlist { $1->vfe_next = $2; $$ = $1; }
|
||||
;
|
||||
|
||||
filtelement : filtelem { $$ = $1; }
|
||||
| filtelem EXACT { $1->vfe_flags |= VFEF_EXACT; $$ = $1; }
|
||||
;
|
||||
|
||||
filtelem : ADDRMASK {
|
||||
|
||||
struct vf_element *vfe;
|
||||
|
||||
vfe = (struct vf_element *)malloc(sizeof(struct vf_element));
|
||||
if (vfe == NULL)
|
||||
fatal("out of memory");
|
||||
|
||||
vfe->vfe_addr = $1.addr;
|
||||
VAL_TO_MASK(vfe->vfe_mask, $1.mask);
|
||||
vfe->vfe_flags = 0;
|
||||
vfe->vfe_next = NULL;
|
||||
|
||||
$$ = vfe;
|
||||
|
||||
}
|
||||
%%
|
||||
#ifdef __STDC__
|
||||
static void
|
||||
fatal(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[MAXHOSTNAMELEN + 100];
|
||||
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
/*VARARGS1*/
|
||||
static void
|
||||
fatal(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char buf[MAXHOSTNAMELEN + 100];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log(LOG_ERR,0,"%s: %s near line %d", configfilename, buf, lineno);
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
static void
|
||||
warn(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[200];
|
||||
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
/*VARARGS1*/
|
||||
static void
|
||||
warn(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char buf[200];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log(LOG_WARNING,0,"%s: %s near line %d", configfilename, buf, lineno);
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror(s)
|
||||
char *s;
|
||||
{
|
||||
log(LOG_ERR, 0, "%s: %s near line %d", configfilename, s, lineno);
|
||||
}
|
||||
|
||||
static char *
|
||||
next_word()
|
||||
{
|
||||
static char buf[1024];
|
||||
static char *p=NULL;
|
||||
char *q;
|
||||
|
||||
while (1) {
|
||||
if (!p || !*p) {
|
||||
lineno++;
|
||||
if (fgets(buf, sizeof(buf), f) == NULL)
|
||||
return NULL;
|
||||
p = buf;
|
||||
}
|
||||
while (*p && (*p == ' ' || *p == '\t')) /* skip whitespace */
|
||||
p++;
|
||||
if (*p == '#') {
|
||||
p = NULL; /* skip comments */
|
||||
continue;
|
||||
}
|
||||
q = p;
|
||||
#ifdef SNMP
|
||||
if (*p == '"') {
|
||||
p++;
|
||||
while (*p && *p != '"' && *p != '\n')
|
||||
p++; /* find next whitespace */
|
||||
if (*p == '"')
|
||||
p++;
|
||||
} else
|
||||
#endif
|
||||
while (*p && *p != ' ' && *p != '\t' && *p != '\n')
|
||||
p++; /* find next whitespace */
|
||||
*p++ = '\0'; /* null-terminate string */
|
||||
|
||||
if (!*q) {
|
||||
p = NULL;
|
||||
continue; /* if 0-length string, read another line */
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* List of keywords. Must have an empty record at the end to terminate
|
||||
* list. If a second value is specified, the first is used at the beginning
|
||||
* of the file and the second is used while parsing interfaces (e.g. after
|
||||
* the first "phyint" or "tunnel" keyword).
|
||||
*/
|
||||
static struct keyword {
|
||||
char *word;
|
||||
int val1;
|
||||
int val2;
|
||||
} words[] = {
|
||||
{ "cache_lifetime", CACHE_LIFETIME },
|
||||
{ "prune_lifetime", PRUNE_LIFETIME, PRUNE_LIFETIME2 },
|
||||
{ "pruning", PRUNING },
|
||||
{ "phyint", PHYINT },
|
||||
{ "tunnel", TUNNEL },
|
||||
{ "disable", DISABLE },
|
||||
{ "metric", METRIC },
|
||||
{ "advert_metric", ADVERT_METRIC },
|
||||
{ "threshold", THRESHOLD },
|
||||
{ "rate_limit", RATE_LIMIT },
|
||||
{ "force_leaf", FORCE_LEAF },
|
||||
{ "srcrt", SRCRT },
|
||||
{ "sourceroute", SRCRT },
|
||||
{ "boundary", BOUNDARY },
|
||||
{ "netmask", NETMASK },
|
||||
{ "igmpv1", IGMPV1 },
|
||||
{ "altnet", ALTNET },
|
||||
{ "name", NAME },
|
||||
{ "accept", ACCEPT },
|
||||
{ "deny", DENY },
|
||||
{ "exact", EXACT },
|
||||
{ "bidir", BIDIR },
|
||||
{ "allow_nonpruners", ALLOW_NONPRUNERS },
|
||||
#ifdef ALLOW_BLACK_HOLES
|
||||
{ "allow_black_holes", BLACK_HOLE },
|
||||
#endif
|
||||
{ "noflood", NOFLOOD, NOFLOOD2},
|
||||
{ "notransit", NOTRANSIT },
|
||||
{ "blaster", BLASTER },
|
||||
{ "rexmit_prunes", REXMIT_PRUNES, REXMIT_PRUNES2 },
|
||||
{ "passive", PASSIVE },
|
||||
{ "beside", BESIDE },
|
||||
#ifdef SNMP
|
||||
{ "sysName", SYSNAM },
|
||||
{ "sysContact", SYSCONTACT },
|
||||
{ "sysVersion", SYSVERSION },
|
||||
{ "sysLocation", SYSLOCATION },
|
||||
#endif
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
yylex()
|
||||
{
|
||||
int n;
|
||||
u_int32 addr;
|
||||
char *q;
|
||||
struct keyword *w;
|
||||
|
||||
if ((q = next_word()) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (w = words; w->word; w++)
|
||||
if (!strcmp(q, w->word))
|
||||
return (state && w->val2) ? w->val2 : w->val1;
|
||||
|
||||
if (!strcmp(q,"on") || !strcmp(q,"yes")) {
|
||||
yylval.num = 1;
|
||||
return BOOLEAN;
|
||||
}
|
||||
if (!strcmp(q,"off") || !strcmp(q,"no")) {
|
||||
yylval.num = 0;
|
||||
return BOOLEAN;
|
||||
}
|
||||
if (!strcmp(q,"default")) {
|
||||
yylval.addrmask.mask = 0;
|
||||
yylval.addrmask.addr = 0;
|
||||
return ADDRMASK;
|
||||
}
|
||||
if (sscanf(q,"%[.0-9]/%d%c",s1,&n,s2) == 2) {
|
||||
if ((addr = inet_parse(s1,1)) != 0xffffffff) {
|
||||
yylval.addrmask.mask = n;
|
||||
yylval.addrmask.addr = addr;
|
||||
return ADDRMASK;
|
||||
}
|
||||
/* fall through to returning STRING */
|
||||
}
|
||||
if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) {
|
||||
if ((addr = inet_parse(s1,4)) != 0xffffffff &&
|
||||
inet_valid_host(addr)) {
|
||||
yylval.addr = addr;
|
||||
return ADDR;
|
||||
}
|
||||
}
|
||||
if (sscanf(q,"0x%8x%c",&n,s1) == 1) {
|
||||
yylval.addr = n;
|
||||
return ADDR;
|
||||
}
|
||||
if (sscanf(q,"%d%c",&n,s1) == 1) {
|
||||
yylval.num = n;
|
||||
return NUMBER;
|
||||
}
|
||||
#ifdef SNMP
|
||||
if (*q=='"') {
|
||||
if (q[ strlen(q)-1 ]=='"')
|
||||
q[ strlen(q)-1 ]='\0'; /* trash trailing quote */
|
||||
yylval.ptr = q+1;
|
||||
return STRING;
|
||||
}
|
||||
#endif
|
||||
yylval.ptr = q;
|
||||
return STRING;
|
||||
}
|
||||
|
||||
void
|
||||
config_vifs_from_file()
|
||||
{
|
||||
order = 0;
|
||||
state = 0;
|
||||
numbounds = 0;
|
||||
lineno = 0;
|
||||
|
||||
if ((f = fopen(configfilename, "r")) == NULL) {
|
||||
if (errno != ENOENT)
|
||||
log(LOG_ERR, errno, "can't open %s", configfilename);
|
||||
return;
|
||||
}
|
||||
|
||||
yyparse();
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static u_int32
|
||||
valid_if(s)
|
||||
char *s;
|
||||
{
|
||||
register vifi_t vifi;
|
||||
register struct uvif *v;
|
||||
|
||||
for (vifi=0, v=uvifs; vifi<numvifs; vifi++, v++)
|
||||
if (!strcmp(v->uv_name, s))
|
||||
return v->uv_lcl_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
ifconfaddr(u_int32_t a)
|
||||
{
|
||||
static char ifname[IFNAMSIZ];
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
|
||||
if (getifaddrs(&ifap) != 0)
|
||||
return (NULL);
|
||||
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family == AF_INET &&
|
||||
((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == a) {
|
||||
strlcpy(ifname, ifa->ifa_name, sizeof(ifname));
|
||||
freeifaddrs(ifap);
|
||||
return (ifname);
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifap);
|
||||
return (NULL);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
S= ${.CURDIR}/..
|
||||
.PATH: $S
|
||||
|
||||
LIB= mrouted
|
||||
INTERNALLIB=
|
||||
SRCS= igmp.c inet.c kern.c
|
||||
|
||||
CFLAGS+= -I$S
|
||||
|
||||
.include <bsd.lib.mk>
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* config.c,v 3.8.4.10 1998/01/06 01:57:41 fenner Exp
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "defs.h"
|
||||
#include <ifaddrs.h>
|
||||
|
||||
/*
|
||||
* Query the kernel to find network interfaces that are multicast-capable
|
||||
* and install them in the uvifs array.
|
||||
*/
|
||||
void
|
||||
config_vifs_from_kernel()
|
||||
{
|
||||
struct ifaddrs *ifa, *ifap;
|
||||
register struct uvif *v;
|
||||
register vifi_t vifi;
|
||||
u_int32 addr, mask, subnet;
|
||||
int flags;
|
||||
|
||||
if (getifaddrs(&ifap) < 0)
|
||||
log(LOG_ERR, errno, "getifaddrs");
|
||||
/*
|
||||
* Loop through all of the interfaces.
|
||||
*/
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
||||
/*
|
||||
* Ignore any interface for an address family other than IP.
|
||||
*/
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
|
||||
addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
|
||||
|
||||
/*
|
||||
* Ignore loopback interfaces and interfaces that do not support
|
||||
* multicast.
|
||||
*/
|
||||
flags = ifa->ifa_flags;
|
||||
if ((flags & (IFF_LOOPBACK|IFF_MULTICAST)) != IFF_MULTICAST)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Ignore any interface whose address and mask do not define a
|
||||
* valid subnet number, or whose address is of the form {subnet,0}
|
||||
* or {subnet,-1}.
|
||||
*/
|
||||
mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
|
||||
subnet = addr & mask;
|
||||
if (!inet_valid_subnet(subnet, mask) ||
|
||||
addr == subnet ||
|
||||
addr == (subnet | ~mask)) {
|
||||
log(LOG_WARNING, 0,
|
||||
"ignoring %s, has invalid address (%s) and/or mask (%s)",
|
||||
ifa->ifa_name, inet_fmt(addr, s1), inet_fmt(mask, s2));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore any interface that is connected to the same subnet as
|
||||
* one already installed in the uvifs array.
|
||||
*/
|
||||
for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
|
||||
if (strcmp(v->uv_name, ifa->ifa_name) == 0) {
|
||||
log(LOG_DEBUG, 0, "skipping %s (%s on subnet %s) (alias for vif#%u?)",
|
||||
v->uv_name, inet_fmt(addr, s1),
|
||||
inet_fmts(subnet, mask, s2), vifi);
|
||||
break;
|
||||
}
|
||||
if ((addr & v->uv_subnetmask) == v->uv_subnet ||
|
||||
(v->uv_subnet & mask) == subnet) {
|
||||
log(LOG_WARNING, 0, "ignoring %s, same subnet as %s",
|
||||
ifa->ifa_name, v->uv_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vifi != numvifs) continue;
|
||||
|
||||
/*
|
||||
* If there is room in the uvifs array, install this interface.
|
||||
*/
|
||||
if (numvifs == MAXVIFS) {
|
||||
log(LOG_WARNING, 0, "too many vifs, ignoring %s", ifa->ifa_name);
|
||||
continue;
|
||||
}
|
||||
v = &uvifs[numvifs];
|
||||
zero_vif(v, 0);
|
||||
v->uv_lcl_addr = addr;
|
||||
v->uv_subnet = subnet;
|
||||
v->uv_subnetmask = mask;
|
||||
v->uv_subnetbcast = subnet | ~mask;
|
||||
strlcpy(v->uv_name, ifa->ifa_name, sizeof(v->uv_name));
|
||||
|
||||
if (flags & IFF_POINTOPOINT)
|
||||
v->uv_flags |= VIFF_REXMIT_PRUNES;
|
||||
|
||||
log(LOG_INFO,0,"installing %s (%s on subnet %s) as vif #%u - rate=%d",
|
||||
v->uv_name, inet_fmt(addr, s1), inet_fmts(subnet, mask, s2),
|
||||
numvifs, v->uv_rate_limit);
|
||||
|
||||
++numvifs;
|
||||
|
||||
/*
|
||||
* If the interface is not yet up, set the vifs_down flag to
|
||||
* remind us to check again later.
|
||||
*/
|
||||
if (!(flags & IFF_UP)) {
|
||||
v->uv_flags |= VIFF_DOWN;
|
||||
vifs_down = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifap);
|
||||
}
|
@ -1,365 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
* defs.h,v 3.8.4.15 1998/03/01 02:51:42 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <net/if.h>
|
||||
#define rtentry kern_rtentry /* XXX !!! UGH */
|
||||
#include <net/route.h>
|
||||
#undef rtentry
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/igmp.h>
|
||||
#define rtentry kernel_rtentry
|
||||
#include <net/route.h>
|
||||
#undef rtentry
|
||||
#include <netinet/ip_mroute.h>
|
||||
#ifdef RSRR
|
||||
#include <sys/un.h>
|
||||
#endif /* RSRR */
|
||||
|
||||
/*XXX*/
|
||||
typedef u_int u_int32;
|
||||
|
||||
typedef void (*cfunc_t)(void *);
|
||||
typedef void (*ihfunc_t)(int, fd_set *);
|
||||
|
||||
#include "dvmrp.h"
|
||||
#include "igmpv2.h"
|
||||
#include "vif.h"
|
||||
#include "route.h"
|
||||
#include "prune.h"
|
||||
#include "pathnames.h"
|
||||
#ifdef RSRR
|
||||
#include "rsrr.h"
|
||||
#include "rsrr_var.h"
|
||||
#endif /* RSRR */
|
||||
|
||||
/*
|
||||
* Miscellaneous constants and macros.
|
||||
*/
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
|
||||
|
||||
#define TIMER_INTERVAL ROUTE_MAX_REPORT_DELAY
|
||||
|
||||
#define PROTOCOL_VERSION 3 /* increment when packet format/content changes */
|
||||
#define MROUTED_VERSION 9 /* not in DVMRP packets at all */
|
||||
|
||||
#define DVMRP_CONSTANT 0x000eff00 /* constant portion of 'group' field */
|
||||
|
||||
#define MROUTED_LEVEL (DVMRP_CONSTANT | PROTOCOL_VERSION)
|
||||
/* for IGMP 'group' field of DVMRP messages */
|
||||
|
||||
#define LEAF_FLAGS (( vifs_with_neighbors == 1 ) ? 0x010000 : 0)
|
||||
/* more for IGMP 'group' field of DVMRP messages */
|
||||
|
||||
#define DEL_RTE_GROUP 0
|
||||
#define DEL_ALL_ROUTES 1
|
||||
/* for Deleting kernel table entries */
|
||||
|
||||
#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
|
||||
|
||||
#ifdef RSRR
|
||||
#define BIT_ZERO(X) ((X) = 0)
|
||||
#define BIT_SET(X,n) ((X) |= 1 << (n))
|
||||
#define BIT_CLR(X,n) ((X) &= ~(1 << (n)))
|
||||
#define BIT_TST(X,n) ((X) & 1 << (n))
|
||||
#endif /* RSRR */
|
||||
|
||||
#define HAVE_SA_LEN
|
||||
|
||||
/*
|
||||
* External declarations for global variables and functions.
|
||||
*/
|
||||
#define RECV_BUF_SIZE 8192
|
||||
extern char *recv_buf;
|
||||
extern char *send_buf;
|
||||
extern int igmp_socket;
|
||||
#ifdef RSRR
|
||||
extern int rsrr_socket;
|
||||
#endif /* RSRR */
|
||||
extern u_int32 allhosts_group;
|
||||
extern u_int32 allrtrs_group;
|
||||
extern u_int32 dvmrp_group;
|
||||
extern u_int32 dvmrp_genid;
|
||||
|
||||
#define IF_DEBUG(l) if (debug && debug & (l))
|
||||
|
||||
#define DEBUG_PKT 0x0001
|
||||
#define DEBUG_PRUNE 0x0002
|
||||
#define DEBUG_ROUTE 0x0004
|
||||
#define DEBUG_PEER 0x0008
|
||||
#define DEBUG_CACHE 0x0010
|
||||
#define DEBUG_TIMEOUT 0x0020
|
||||
#define DEBUG_IF 0x0040
|
||||
#define DEBUG_MEMBER 0x0080
|
||||
#define DEBUG_TRACE 0x0100
|
||||
#define DEBUG_IGMP 0x0200
|
||||
#define DEBUG_RTDETAIL 0x0400
|
||||
#define DEBUG_KERN 0x0800
|
||||
#define DEBUG_RSRR 0x1000
|
||||
#define DEBUG_ICMP 0x2000
|
||||
|
||||
#define DEFAULT_DEBUG 0x02de /* default if "-d" given without value */
|
||||
|
||||
extern int debug;
|
||||
extern int did_final_init;
|
||||
|
||||
extern int routes_changed;
|
||||
extern int delay_change_reports;
|
||||
extern unsigned nroutes;
|
||||
|
||||
extern struct uvif uvifs[MAXVIFS];
|
||||
extern vifi_t numvifs;
|
||||
extern int vifs_down;
|
||||
extern int udp_socket;
|
||||
extern int vifs_with_neighbors;
|
||||
|
||||
extern char s1[];
|
||||
extern char s2[];
|
||||
extern char s3[];
|
||||
extern char s4[];
|
||||
|
||||
#ifndef IGMP_PIM
|
||||
#define IGMP_PIM 0x14
|
||||
#endif
|
||||
#ifndef IPPROTO_IPIP
|
||||
#define IPPROTO_IPIP 4
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The original multicast releases defined
|
||||
* IGMP_HOST_{MEMBERSHIP_QUERY,MEMBERSHIP_REPORT,NEW_MEMBERSHIP_REPORT
|
||||
* ,LEAVE_MESSAGE}. Later releases removed the HOST and inserted
|
||||
* the IGMP version number. NetBSD inserted the version number in
|
||||
* a different way. mrouted uses the new names, so we #define them
|
||||
* to the old ones if needed.
|
||||
*/
|
||||
#if !defined(IGMP_MEMBERSHIP_QUERY) && defined(IGMP_HOST_MEMBERSHIP_QUERY)
|
||||
#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
|
||||
#define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE
|
||||
#endif
|
||||
#ifndef IGMP_V1_MEMBERSHIP_REPORT
|
||||
#ifdef IGMP_HOST_MEMBERSHIP_REPORT
|
||||
#define IGMP_V1_MEMBERSHIP_REPORT IGMP_HOST_MEMBERSHIP_REPORT
|
||||
#define IGMP_V2_MEMBERSHIP_REPORT IGMP_HOST_NEW_MEMBERSHIP_REPORT
|
||||
#endif
|
||||
#ifdef IGMP_v1_HOST_MEMBERSHIP_REPORT
|
||||
#define IGMP_V1_MEMBERSHIP_REPORT IGMP_v1_HOST_MEMBERSHIP_REPORT
|
||||
#define IGMP_V2_MEMBERSHIP_REPORT IGMP_v2_HOST_MEMBERSHIP_REPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NetBSD also renamed the mtrace types.
|
||||
*/
|
||||
#if !defined(IGMP_MTRACE_RESP) && defined(IGMP_MTRACE_REPLY)
|
||||
#define IGMP_MTRACE_RESP IGMP_MTRACE_REPLY
|
||||
#define IGMP_MTRACE IGMP_MTRACE_QUERY
|
||||
#endif
|
||||
|
||||
/* main.c */
|
||||
extern char * scaletime __P((u_long));
|
||||
extern void log __P((int, int, char *, ...)) __printflike(3, 4);
|
||||
extern int register_input_handler __P((int, ihfunc_t));
|
||||
|
||||
/* igmp.c */
|
||||
extern void init_igmp __P((void));
|
||||
extern void accept_igmp __P((int));
|
||||
extern void build_igmp __P((u_int32, u_int32, int, int, u_int32,
|
||||
int));
|
||||
extern void send_igmp __P((u_int32, u_int32, int, int, u_int32,
|
||||
int));
|
||||
extern char * igmp_packet_kind __P((u_int, u_int));
|
||||
extern int igmp_debug_kind __P((u_int, u_int));
|
||||
|
||||
/* icmp.c */
|
||||
extern void init_icmp __P((void));
|
||||
|
||||
/* ipip.c */
|
||||
extern void init_ipip __P((void));
|
||||
extern void init_ipip_on_vif __P((struct uvif *));
|
||||
extern void send_ipip __P((u_int32, u_int32, int, int, u_int32,
|
||||
int, struct uvif *));
|
||||
|
||||
/* callout.c */
|
||||
extern void callout_init __P((void));
|
||||
extern void free_all_callouts __P((void));
|
||||
extern void age_callout_queue __P((int));
|
||||
extern int timer_nextTimer __P((void));
|
||||
extern int timer_setTimer __P((int, cfunc_t, void *));
|
||||
extern int timer_clearTimer __P((int));
|
||||
extern int timer_leftTimer __P((int));
|
||||
|
||||
/* route.c */
|
||||
extern void init_routes __P((void));
|
||||
extern void start_route_updates __P((void));
|
||||
extern void update_route __P((u_int32, u_int32, u_int, u_int32,
|
||||
vifi_t, struct listaddr *));
|
||||
extern void age_routes __P((void));
|
||||
extern void expire_all_routes __P((void));
|
||||
extern void free_all_routes __P((void));
|
||||
extern void accept_probe __P((u_int32, u_int32, char *, int,
|
||||
u_int32));
|
||||
extern void accept_report __P((u_int32, u_int32, char *, int,
|
||||
u_int32));
|
||||
extern struct rtentry * determine_route __P((u_int32 src));
|
||||
extern void report __P((int, vifi_t, u_int32));
|
||||
extern void report_to_all_neighbors __P((int));
|
||||
extern int report_next_chunk __P((void));
|
||||
extern void blaster_alloc __P((vifi_t));
|
||||
extern void add_vif_to_routes __P((vifi_t));
|
||||
extern void delete_vif_from_routes __P((vifi_t));
|
||||
extern void add_neighbor_to_routes __P((vifi_t, int));
|
||||
extern void delete_neighbor_from_routes __P((u_int32,
|
||||
vifi_t, int));
|
||||
extern void dump_routes __P((FILE *fp));
|
||||
|
||||
/* vif.c */
|
||||
extern void init_vifs __P((void));
|
||||
extern void zero_vif __P((struct uvif *, int));
|
||||
extern void init_installvifs __P((void));
|
||||
extern void check_vif_state __P((void));
|
||||
extern void send_on_vif __P((struct uvif *, u_int32, int, int));
|
||||
extern vifi_t find_vif __P((u_int32, u_int32));
|
||||
extern void age_vifs __P((void));
|
||||
extern void dump_vifs __P((FILE *));
|
||||
extern void stop_all_vifs __P((void));
|
||||
extern struct listaddr *neighbor_info __P((vifi_t, u_int32));
|
||||
extern void accept_group_report __P((u_int32, u_int32,
|
||||
u_int32, int));
|
||||
extern void query_groups __P((void));
|
||||
extern void probe_for_neighbors __P((void));
|
||||
extern struct listaddr *update_neighbor __P((vifi_t, u_int32, int, char *, int,
|
||||
u_int32));
|
||||
extern void accept_neighbor_request __P((u_int32, u_int32));
|
||||
extern void accept_neighbor_request2 __P((u_int32, u_int32));
|
||||
extern void accept_info_request __P((u_int32, u_int32,
|
||||
u_char *, int));
|
||||
extern void accept_info_reply __P((u_int32, u_int32,
|
||||
u_char *, int));
|
||||
extern void accept_neighbors __P((u_int32, u_int32,
|
||||
u_char *, int, u_int32));
|
||||
extern void accept_neighbors2 __P((u_int32, u_int32,
|
||||
u_char *, int, u_int32));
|
||||
extern void accept_leave_message __P((u_int32, u_int32,
|
||||
u_int32));
|
||||
extern void accept_membership_query __P((u_int32, u_int32,
|
||||
u_int32, int));
|
||||
|
||||
/* config.c */
|
||||
extern void config_vifs_from_kernel __P((void));
|
||||
|
||||
/* cfparse.y */
|
||||
extern void config_vifs_from_file __P((void));
|
||||
|
||||
/* inet.c */
|
||||
extern int inet_valid_host __P((u_int32));
|
||||
extern int inet_valid_mask __P((u_int32));
|
||||
extern int inet_valid_subnet __P((u_int32, u_int32));
|
||||
extern char * inet_fmt __P((u_int32, char *));
|
||||
extern char * inet_fmts __P((u_int32, u_int32, char *));
|
||||
extern u_int32 inet_parse __P((char *, int));
|
||||
extern int inet_cksum __P((u_short *, u_int));
|
||||
|
||||
/* prune.c */
|
||||
extern unsigned kroutes;
|
||||
extern void determine_forwvifs __P((struct gtable *));
|
||||
extern void send_prune_or_graft __P((struct gtable *));
|
||||
extern void add_table_entry __P((u_int32, u_int32));
|
||||
extern void del_table_entry __P((struct rtentry *,
|
||||
u_int32, u_int));
|
||||
extern void update_table_entry __P((struct rtentry *, u_int32));
|
||||
extern int find_src_grp __P((u_int32, u_int32, u_int32));
|
||||
extern void init_ktable __P((void));
|
||||
extern void steal_sources __P((struct rtentry *));
|
||||
extern void reset_neighbor_state __P((vifi_t, u_int32));
|
||||
extern int grplst_mem __P((vifi_t, u_int32));
|
||||
extern void free_all_prunes __P((void));
|
||||
extern void age_table_entry __P((void));
|
||||
extern void dump_cache __P((FILE *));
|
||||
extern void update_lclgrp __P((vifi_t, u_int32));
|
||||
extern void delete_lclgrp __P((vifi_t, u_int32));
|
||||
extern void chkgrp_graft __P((vifi_t, u_int32));
|
||||
extern void accept_prune __P((u_int32, u_int32, char *, int));
|
||||
extern void accept_graft __P((u_int32, u_int32, char *, int));
|
||||
extern void accept_g_ack __P((u_int32, u_int32, char *, int));
|
||||
/* u_int is promoted u_char */
|
||||
extern void accept_mtrace __P((u_int32, u_int32,
|
||||
u_int32, char *, u_int, int));
|
||||
|
||||
/* kern.c */
|
||||
extern void k_set_rcvbuf __P((int, int));
|
||||
extern void k_hdr_include __P((int));
|
||||
extern void k_set_ttl __P((int));
|
||||
extern void k_set_loop __P((int));
|
||||
extern void k_set_if __P((u_int32));
|
||||
extern void k_join __P((u_int32, u_int32));
|
||||
extern void k_leave __P((u_int32, u_int32));
|
||||
extern void k_init_dvmrp __P((void));
|
||||
extern void k_stop_dvmrp __P((void));
|
||||
extern void k_add_vif __P((vifi_t, struct uvif *));
|
||||
extern void k_del_vif __P((vifi_t));
|
||||
extern void k_add_rg __P((u_int32, struct gtable *));
|
||||
extern int k_del_rg __P((u_int32, struct gtable *));
|
||||
extern int k_get_version __P((void));
|
||||
|
||||
#ifdef SNMP
|
||||
/* prune.c */
|
||||
extern struct gtable * find_grp __P((u_int32));
|
||||
extern struct stable * find_grp_src __P((struct gtable *, u_int32));
|
||||
extern int next_grp_src_mask __P((struct gtable **,
|
||||
struct stable **, u_int32,
|
||||
u_int32, u_int32));
|
||||
extern void refresh_sg __P((struct sioc_sg_req *, struct gtable *,
|
||||
struct stable *));
|
||||
extern int next_child __P((struct gtable **, struct stable **,
|
||||
u_int32, u_int32, u_int32,
|
||||
vifi_t *));
|
||||
|
||||
/* route.c */
|
||||
extern struct rtentry * snmp_find_route __P((u_int32, u_int32));
|
||||
extern int next_route __P((struct rtentry **, u_int32, u_int32));
|
||||
extern int next_route_child __P((struct rtentry **,
|
||||
u_int32, u_int32, vifi_t *));
|
||||
#endif
|
||||
|
||||
#ifdef RSRR
|
||||
/* prune.c */
|
||||
extern struct gtable *kernel_table;
|
||||
extern struct gtable *gtp;
|
||||
|
||||
/* rsrr.c */
|
||||
extern void rsrr_init __P((void));
|
||||
extern void rsrr_clean __P((void));
|
||||
extern void rsrr_cache_send __P((struct gtable *, int));
|
||||
extern void rsrr_cache_clean __P((struct gtable *));
|
||||
#endif /* RSRR */
|
@ -1,172 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
* dvmrp.h,v 3.8.4.5 1997/11/18 23:25:57 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
* A DVMRP message consists of an IP header + an IGMP header + (for some types)
|
||||
* zero or more bytes of data.
|
||||
*
|
||||
* For REPORT messages, the data is route information; the route information
|
||||
* consists of one or more lists of the following form:
|
||||
*
|
||||
* (mask, (origin, metric), (origin, metric), ...)
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* "mask" is the subnet mask for all the origins in the list.
|
||||
* It is always THREE bytes long, containing the low-order
|
||||
* three bytes of the mask (the high-order byte is always
|
||||
* 0xff and therefore need not be transmitted).
|
||||
*
|
||||
* "origin" is the number of a subnet from which multicast datagrams
|
||||
* may originate. It is from one to four bytes long,
|
||||
* depending on the value of "mask":
|
||||
* if all bytes of the mask are zero
|
||||
* the subnet number is one byte long
|
||||
* else if the low-order two bytes of the mask are zero
|
||||
* the subnet number is two bytes long
|
||||
* else if the lowest-order byte of the mask is zero
|
||||
* the subnet number is three bytes long,
|
||||
* else
|
||||
* the subnet number is four bytes long.
|
||||
*
|
||||
* "metric" is a one-byte value consisting of two subfields:
|
||||
* - the high-order bit is a flag which, when set, indicates
|
||||
* the last (origin, metric) pair of a list.
|
||||
* - the low-order seven bits contain the routing metric for
|
||||
* the corresponding origin, relative to the sender of the
|
||||
* DVMRP report. The metric may have the value of UNREACHABLE
|
||||
* added to it as a "split horizon" indication (so called
|
||||
* "poisoned reverse").
|
||||
*
|
||||
* Within a list, the origin subnet numbers must be in ascending order, and
|
||||
* the lists themselves are in order of increasing mask value. A message may
|
||||
* not exceed 576 bytes, the default maximum IP reassembly size, including
|
||||
* the IP and IGMP headers; the route information may be split across more
|
||||
* than one message if necessary, by terminating a list in one message and
|
||||
* starting a new list in the next message (repeating the same mask value,
|
||||
* if necessary).
|
||||
*
|
||||
* For NEIGHBORS messages, the data is neighboring-router information
|
||||
* consisting of one or more lists of the following form:
|
||||
*
|
||||
* (local-addr, metric, threshold, ncount, neighbor, neighbor, ...)
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* "local-addr" is the sending router's address as seen by the neighbors
|
||||
* in this list; it is always four bytes long.
|
||||
* "metric" is a one-byte unsigned value, the TTL `cost' of forwarding
|
||||
* packets to any of the neighbors on this list.
|
||||
* "threshold" is a one-byte unsigned value, a lower bound on the TTL a
|
||||
* packet must have to be forwarded to any of the neighbors on
|
||||
* this list.
|
||||
* "ncount" is the number of neighbors in this list.
|
||||
* "neighbor" is the address of a neighboring router, four bytes long.
|
||||
*
|
||||
* As with REPORT messages, NEIGHBORS messages should not exceed 576 bytes,
|
||||
* including the IP and IGMP headers; split longer messages by terminating the
|
||||
* list in one and continuing in another, repeating the local-addr, etc., if
|
||||
* necessary.
|
||||
*
|
||||
* For NEIGHBORS2 messages, the data is identical to NEIGHBORS except
|
||||
* there is a flags byte before the neighbor count:
|
||||
*
|
||||
* (local-addr, metric, threshold, flags, ncount, neighbor, neighbor, ...)
|
||||
*/
|
||||
|
||||
/*
|
||||
* DVMRP message types (carried in the "code" field of an IGMP header)
|
||||
*/
|
||||
#define DVMRP_PROBE 1 /* for finding neighbors */
|
||||
#define DVMRP_REPORT 2 /* for reporting some or all routes */
|
||||
#define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */
|
||||
/* of this router's neighbors. */
|
||||
#define DVMRP_NEIGHBORS 4 /* response to such a request */
|
||||
#define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */
|
||||
#define DVMRP_NEIGHBORS2 6
|
||||
#define DVMRP_PRUNE 7 /* prune message */
|
||||
#define DVMRP_GRAFT 8 /* graft message */
|
||||
#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */
|
||||
#define DVMRP_INFO_REQUEST 10 /* information request */
|
||||
#define DVMRP_INFO_REPLY 11 /* information reply */
|
||||
|
||||
/*
|
||||
* 'flags' byte values in DVMRP_NEIGHBORS2 reply.
|
||||
*/
|
||||
#define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */
|
||||
#define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */
|
||||
#define DVMRP_NF_PIM 0x04 /* neighbor is a PIM neighbor */
|
||||
#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */
|
||||
#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */
|
||||
#define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */
|
||||
#define DVMRP_NF_LEAF 0x80 /* Neighbor reports that it is a leaf */
|
||||
|
||||
/*
|
||||
* Request/reply types for info queries/replies
|
||||
*/
|
||||
#define DVMRP_INFO_VERSION 1 /* version string */
|
||||
#define DVMRP_INFO_NEIGHBORS 2 /* neighbors2 data */
|
||||
|
||||
/*
|
||||
* Limit on length of route data
|
||||
*/
|
||||
#define MAX_IP_PACKET_LEN 576
|
||||
#define MIN_IP_HEADER_LEN 20
|
||||
#define MAX_IP_HEADER_LEN 60
|
||||
#define MAX_DVMRP_DATA_LEN \
|
||||
( MAX_IP_PACKET_LEN - MAX_IP_HEADER_LEN - IGMP_MINLEN )
|
||||
|
||||
/*
|
||||
* Various protocol constants (all times in seconds)
|
||||
*/
|
||||
/* address for multicast DVMRP msgs */
|
||||
#define INADDR_DVMRP_GROUP (u_int32)0xe0000004 /* 224.0.0.4 */
|
||||
/*
|
||||
* The IGMPv2 <netinet/in.h> defines INADDR_ALLRTRS_GROUP, but earlier
|
||||
* ones don't, so we define it conditionally here.
|
||||
*/
|
||||
#ifndef INADDR_ALLRTRS_GROUP
|
||||
/* address for multicast mtrace msg */
|
||||
#define INADDR_ALLRTRS_GROUP (u_int32)0xe0000002 /* 224.0.0.2 */
|
||||
#endif
|
||||
|
||||
#define ROUTE_MAX_REPORT_DELAY 5 /* max delay for reporting changes */
|
||||
/* (This is the timer interrupt */
|
||||
/* interval; all times must be */
|
||||
/* multiples of this value.) */
|
||||
|
||||
#define ROUTE_REPORT_INTERVAL 60 /* periodic route report interval */
|
||||
#define ROUTE_SWITCH_TIME 140 /* time to switch to equivalent gw */
|
||||
#define ROUTE_EXPIRE_TIME 200 /* time to mark route invalid */
|
||||
#define ROUTE_DISCARD_TIME 340 /* time to garbage collect route */
|
||||
|
||||
#define LEAF_CONFIRMATION_TIME 200 /* time to consider subnet a leaf */
|
||||
|
||||
#define NEIGHBOR_PROBE_INTERVAL 10 /* periodic neighbor probe interval */
|
||||
#define NEIGHBOR_EXPIRE_TIME 30 /* time to consider neighbor gone */
|
||||
#define OLD_NEIGHBOR_EXPIRE_TIME 140 /* time to consider neighbor gone */
|
||||
|
||||
#define UNREACHABLE 32 /* "infinity" metric, must be <= 64 */
|
||||
#define DEFAULT_METRIC 1 /* default subnet/tunnel metric */
|
||||
#define DEFAULT_THRESHOLD 1 /* default subnet/tunnel threshold */
|
||||
|
||||
#define MAX_RATE_LIMIT 100000 /* max rate limit */
|
||||
#define DEFAULT_PHY_RATE_LIMIT 0 /* default phyint rate limit */
|
||||
#define DEFAULT_TUN_RATE_LIMIT 0 /* default tunnel rate limit */
|
||||
|
||||
#define DEFAULT_CACHE_LIFETIME 300 /* kernel route entry discard time */
|
||||
#define MIN_CACHE_LIFETIME 60 /* minimum allowed cache lifetime */
|
||||
#define AVERAGE_PRUNE_LIFETIME 7200 /* average lifetime of prunes sent */
|
||||
#define MIN_PRUNE_LIFETIME 120 /* minimum allowed prune lifetime */
|
||||
#define GRAFT_TIMEOUT_VAL 5 /* retransmission time for grafts */
|
||||
#define PRUNE_REXMIT_VAL 3 /* initial time for prune rexmission*/
|
@ -1,225 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp $";
|
||||
#endif
|
||||
|
||||
static int icmp_socket;
|
||||
|
||||
static void icmp_handler __P((int, fd_set *));
|
||||
static char * icmp_name __P((struct icmp *));
|
||||
|
||||
void
|
||||
init_icmp()
|
||||
{
|
||||
if ((icmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
|
||||
log(LOG_ERR, errno, "ICMP socket");
|
||||
|
||||
register_input_handler(icmp_socket, icmp_handler);
|
||||
|
||||
IF_DEBUG(DEBUG_ICMP)
|
||||
log(LOG_DEBUG, 0, "registering icmp socket fd %d\n", icmp_socket);
|
||||
}
|
||||
|
||||
static void
|
||||
icmp_handler(fd, rfds)
|
||||
int fd;
|
||||
fd_set *rfds;
|
||||
{
|
||||
u_char icmp_buf[RECV_BUF_SIZE];
|
||||
struct sockaddr_in from;
|
||||
int fromlen, recvlen, iphdrlen, ipdatalen;
|
||||
struct icmp *icmp;
|
||||
struct ip *ip;
|
||||
vifi_t i;
|
||||
struct uvif *v;
|
||||
u_int32 src;
|
||||
|
||||
fromlen = sizeof(from);
|
||||
recvlen = recvfrom(icmp_socket, icmp_buf, RECV_BUF_SIZE, 0,
|
||||
(struct sockaddr *)&from, &fromlen);
|
||||
if (recvlen < 0) {
|
||||
if (errno != EINTR)
|
||||
log(LOG_WARNING, errno, "icmp_socket recvfrom");
|
||||
return;
|
||||
}
|
||||
ip = (struct ip *)icmp_buf;
|
||||
iphdrlen = ip->ip_hl << 2;
|
||||
#ifdef RAW_INPUT_IS_RAW
|
||||
ipdatalen = ntohs(ip->ip_len) - iphdrlen;
|
||||
#else
|
||||
ipdatalen = ip->ip_len;
|
||||
#endif
|
||||
if (iphdrlen + ipdatalen != recvlen) {
|
||||
IF_DEBUG(DEBUG_ICMP)
|
||||
log(LOG_DEBUG, 0, "hdr %d data %d != rcv %d", iphdrlen, ipdatalen, recvlen);
|
||||
/* Malformed ICMP, just return. */
|
||||
return;
|
||||
}
|
||||
if (ipdatalen < ICMP_MINLEN + sizeof(struct ip)) {
|
||||
/* Not enough data for us to be interested in it. */
|
||||
return;
|
||||
}
|
||||
src = ip->ip_src.s_addr;
|
||||
icmp = (struct icmp *)(icmp_buf + iphdrlen);
|
||||
IF_DEBUG(DEBUG_ICMP)
|
||||
log(LOG_DEBUG, 0, "got ICMP type %d from %s",
|
||||
icmp->icmp_type, inet_fmt(src, s1));
|
||||
/*
|
||||
* Eventually:
|
||||
* have registry of ICMP listeners, by type, code and ICMP_ID
|
||||
* (and maybe fields of the original packet too -- maybe need a
|
||||
* generalized packet filter!) to allow ping and traceroute
|
||||
* from the monitoring tool.
|
||||
*/
|
||||
switch (icmp->icmp_type) {
|
||||
case ICMP_UNREACH:
|
||||
case ICMP_TIMXCEED:
|
||||
/* Look at returned packet to see if it's us sending on a tunnel */
|
||||
ip = &icmp->icmp_ip;
|
||||
if (ip->ip_p != IPPROTO_IGMP && ip->ip_p != IPPROTO_IPIP)
|
||||
return;
|
||||
for (v = uvifs, i = 0; i < numvifs; v++, i++) {
|
||||
if (ip->ip_src.s_addr == v->uv_lcl_addr &&
|
||||
ip->ip_dst.s_addr == v->uv_dst_addr) {
|
||||
char *p;
|
||||
int n;
|
||||
/*
|
||||
* I sent this packet on this vif.
|
||||
*/
|
||||
n = ++v->uv_icmp_warn;
|
||||
while (n && !(n & 1))
|
||||
n >>= 1;
|
||||
if (n == 1 && ((p = icmp_name(icmp)) != NULL))
|
||||
log(LOG_WARNING, 0, "Received ICMP %s from %s %s %s on vif %d",
|
||||
p, inet_fmt(src, s1), "for traffic sent to",
|
||||
inet_fmt(ip->ip_dst.s_addr, s2),
|
||||
i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return NULL for ICMP informational messages.
|
||||
* Return string describing the error for ICMP errors.
|
||||
*/
|
||||
static char *
|
||||
icmp_name(icmp)
|
||||
struct icmp *icmp;
|
||||
{
|
||||
static char retval[30];
|
||||
|
||||
switch (icmp->icmp_type) {
|
||||
case ICMP_UNREACH:
|
||||
switch (icmp->icmp_code) {
|
||||
case ICMP_UNREACH_NET:
|
||||
return "network unreachable";
|
||||
case ICMP_UNREACH_HOST:
|
||||
return "host unreachable";
|
||||
case ICMP_UNREACH_PROTOCOL:
|
||||
return "protocol unreachable";
|
||||
case ICMP_UNREACH_PORT:
|
||||
return "port unreachable";
|
||||
case ICMP_UNREACH_NEEDFRAG:
|
||||
return "needs fragmentation";
|
||||
case ICMP_UNREACH_SRCFAIL:
|
||||
return "source route failed";
|
||||
#ifndef ICMP_UNREACH_NET_UNKNOWN
|
||||
#define ICMP_UNREACH_NET_UNKNOWN 6
|
||||
#endif
|
||||
case ICMP_UNREACH_NET_UNKNOWN:
|
||||
return "network unknown";
|
||||
#ifndef ICMP_UNREACH_HOST_UNKNOWN
|
||||
#define ICMP_UNREACH_HOST_UNKNOWN 7
|
||||
#endif
|
||||
case ICMP_UNREACH_HOST_UNKNOWN:
|
||||
return "host unknown";
|
||||
#ifndef ICMP_UNREACH_ISOLATED
|
||||
#define ICMP_UNREACH_ISOLATED 8
|
||||
#endif
|
||||
case ICMP_UNREACH_ISOLATED:
|
||||
return "source host isolated";
|
||||
#ifndef ICMP_UNREACH_NET_PROHIB
|
||||
#define ICMP_UNREACH_NET_PROHIB 9
|
||||
#endif
|
||||
case ICMP_UNREACH_NET_PROHIB:
|
||||
return "network access prohibited";
|
||||
#ifndef ICMP_UNREACH_HOST_PROHIB
|
||||
#define ICMP_UNREACH_HOST_PROHIB 10
|
||||
#endif
|
||||
case ICMP_UNREACH_HOST_PROHIB:
|
||||
return "host access prohibited";
|
||||
#ifndef ICMP_UNREACH_TOSNET
|
||||
#define ICMP_UNREACH_TOSNET 11
|
||||
#endif
|
||||
case ICMP_UNREACH_TOSNET:
|
||||
return "bad TOS for net";
|
||||
#ifndef ICMP_UNREACH_TOSHOST
|
||||
#define ICMP_UNREACH_TOSHOST 12
|
||||
#endif
|
||||
case ICMP_UNREACH_TOSHOST:
|
||||
return "bad TOS for host";
|
||||
#ifndef ICMP_UNREACH_FILTER_PROHIB
|
||||
#define ICMP_UNREACH_FILTER_PROHIB 13
|
||||
#endif
|
||||
case ICMP_UNREACH_FILTER_PROHIB:
|
||||
return "prohibited by filter";
|
||||
#ifndef ICMP_UNREACH_HOST_PRECEDENCE
|
||||
#define ICMP_UNREACH_HOST_PRECEDENCE 14
|
||||
#endif
|
||||
case ICMP_UNREACH_HOST_PRECEDENCE:
|
||||
return "host precedence violation";
|
||||
#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
|
||||
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
|
||||
#endif
|
||||
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
|
||||
return "precedence cutoff";
|
||||
default:
|
||||
sprintf(retval, "unreachable code %d", icmp->icmp_code);
|
||||
return retval;
|
||||
}
|
||||
case ICMP_SOURCEQUENCH:
|
||||
return "source quench";
|
||||
case ICMP_REDIRECT:
|
||||
return NULL; /* XXX */
|
||||
case ICMP_TIMXCEED:
|
||||
switch (icmp->icmp_code) {
|
||||
case ICMP_TIMXCEED_INTRANS:
|
||||
return "time exceeded in transit";
|
||||
case ICMP_TIMXCEED_REASS:
|
||||
return "time exceeded in reassembly";
|
||||
default:
|
||||
sprintf(retval, "time exceeded code %d", icmp->icmp_code);
|
||||
return retval;
|
||||
}
|
||||
case ICMP_PARAMPROB:
|
||||
switch (icmp->icmp_code) {
|
||||
#ifndef ICMP_PARAMPROB_OPTABSENT
|
||||
#define ICMP_PARAMPROB_OPTABSENT 1
|
||||
#endif
|
||||
case ICMP_PARAMPROB_OPTABSENT:
|
||||
return "required option absent";
|
||||
default:
|
||||
sprintf(retval, "parameter problem code %d", icmp->icmp_code);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
@ -1,447 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* igmp.c,v 3.8.4.19 1998/01/06 01:57:43 fenner Exp
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
*/
|
||||
char *recv_buf; /* input packet buffer */
|
||||
char *send_buf; /* output packet buffer */
|
||||
int igmp_socket; /* socket for all network I/O */
|
||||
u_int32 allhosts_group; /* All hosts addr in net order */
|
||||
u_int32 allrtrs_group; /* All-Routers " in net order */
|
||||
u_int32 dvmrp_group; /* DVMRP grp addr in net order */
|
||||
u_int32 dvmrp_genid; /* IGMP generation id */
|
||||
|
||||
/*
|
||||
* Local function definitions.
|
||||
*/
|
||||
/* u_char promoted to u_int */
|
||||
static int igmp_log_level __P((u_int type, u_int code));
|
||||
|
||||
/*
|
||||
* Open and initialize the igmp socket, and fill in the non-changing
|
||||
* IP header fields in the output packet buffer.
|
||||
*/
|
||||
void
|
||||
init_igmp()
|
||||
{
|
||||
struct ip *ip;
|
||||
|
||||
recv_buf = malloc(RECV_BUF_SIZE);
|
||||
send_buf = malloc(RECV_BUF_SIZE);
|
||||
|
||||
if ((igmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0)
|
||||
log(LOG_ERR, errno, "IGMP socket");
|
||||
|
||||
k_hdr_include(TRUE); /* include IP header when sending */
|
||||
k_set_rcvbuf(256*1024,48*1024); /* lots of input buffering */
|
||||
k_set_ttl(1); /* restrict multicasts to one hop */
|
||||
k_set_loop(FALSE); /* disable multicast loopback */
|
||||
|
||||
ip = (struct ip *)send_buf;
|
||||
bzero(ip, sizeof(struct ip));
|
||||
/*
|
||||
* Fields zeroed that aren't filled in later:
|
||||
* - IP ID (let the kernel fill it in)
|
||||
* - Offset (we don't send fragments)
|
||||
* - Checksum (let the kernel fill it in)
|
||||
*/
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_tos = 0xc0; /* Internet Control */
|
||||
ip->ip_ttl = MAXTTL; /* applies to unicasts only */
|
||||
ip->ip_p = IPPROTO_IGMP;
|
||||
|
||||
allhosts_group = htonl(INADDR_ALLHOSTS_GROUP);
|
||||
dvmrp_group = htonl(INADDR_DVMRP_GROUP);
|
||||
allrtrs_group = htonl(INADDR_ALLRTRS_GROUP);
|
||||
}
|
||||
|
||||
#define PIM_QUERY 0
|
||||
#define PIM_REGISTER 1
|
||||
#define PIM_REGISTER_STOP 2
|
||||
#define PIM_JOIN_PRUNE 3
|
||||
#define PIM_RP_REACHABLE 4
|
||||
#define PIM_ASSERT 5
|
||||
#define PIM_GRAFT 6
|
||||
#define PIM_GRAFT_ACK 7
|
||||
|
||||
char *
|
||||
igmp_packet_kind(type, code)
|
||||
u_int type, code;
|
||||
{
|
||||
static char unknown[20];
|
||||
|
||||
switch (type) {
|
||||
case IGMP_MEMBERSHIP_QUERY: return "membership query ";
|
||||
case IGMP_V1_MEMBERSHIP_REPORT: return "V1 member report ";
|
||||
case IGMP_V2_MEMBERSHIP_REPORT: return "V2 member report ";
|
||||
case IGMP_V2_LEAVE_GROUP: return "leave message ";
|
||||
case IGMP_DVMRP:
|
||||
switch (code) {
|
||||
case DVMRP_PROBE: return "neighbor probe ";
|
||||
case DVMRP_REPORT: return "route report ";
|
||||
case DVMRP_ASK_NEIGHBORS: return "neighbor request ";
|
||||
case DVMRP_NEIGHBORS: return "neighbor list ";
|
||||
case DVMRP_ASK_NEIGHBORS2: return "neighbor request 2";
|
||||
case DVMRP_NEIGHBORS2: return "neighbor list 2 ";
|
||||
case DVMRP_PRUNE: return "prune message ";
|
||||
case DVMRP_GRAFT: return "graft message ";
|
||||
case DVMRP_GRAFT_ACK: return "graft message ack ";
|
||||
case DVMRP_INFO_REQUEST: return "info request ";
|
||||
case DVMRP_INFO_REPLY: return "info reply ";
|
||||
default:
|
||||
sprintf(unknown, "unknown DVMRP %3d ", code);
|
||||
return unknown;
|
||||
}
|
||||
case IGMP_PIM:
|
||||
switch (code) {
|
||||
case PIM_QUERY: return "PIM Router-Query ";
|
||||
case PIM_REGISTER: return "PIM Register ";
|
||||
case PIM_REGISTER_STOP: return "PIM Register-Stop ";
|
||||
case PIM_JOIN_PRUNE: return "PIM Join/Prune ";
|
||||
case PIM_RP_REACHABLE: return "PIM RP-Reachable ";
|
||||
case PIM_ASSERT: return "PIM Assert ";
|
||||
case PIM_GRAFT: return "PIM Graft ";
|
||||
case PIM_GRAFT_ACK: return "PIM Graft-Ack ";
|
||||
default:
|
||||
sprintf(unknown, "unknown PIM msg%3d", code);
|
||||
return unknown;
|
||||
}
|
||||
case IGMP_MTRACE: return "IGMP trace query ";
|
||||
case IGMP_MTRACE_RESP: return "IGMP trace reply ";
|
||||
default:
|
||||
sprintf(unknown, "unk: 0x%02x/0x%02x ", type, code);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
igmp_debug_kind(type, code)
|
||||
u_int type, code;
|
||||
{
|
||||
switch (type) {
|
||||
case IGMP_MEMBERSHIP_QUERY: return DEBUG_IGMP;
|
||||
case IGMP_V1_MEMBERSHIP_REPORT: return DEBUG_IGMP;
|
||||
case IGMP_V2_MEMBERSHIP_REPORT: return DEBUG_IGMP;
|
||||
case IGMP_V2_LEAVE_GROUP: return DEBUG_IGMP;
|
||||
case IGMP_DVMRP:
|
||||
switch (code) {
|
||||
case DVMRP_PROBE: return DEBUG_PEER;
|
||||
case DVMRP_REPORT: return DEBUG_ROUTE;
|
||||
case DVMRP_ASK_NEIGHBORS: return 0;
|
||||
case DVMRP_NEIGHBORS: return 0;
|
||||
case DVMRP_ASK_NEIGHBORS2: return 0;
|
||||
case DVMRP_NEIGHBORS2: return 0;
|
||||
case DVMRP_PRUNE: return DEBUG_PRUNE;
|
||||
case DVMRP_GRAFT: return DEBUG_PRUNE;
|
||||
case DVMRP_GRAFT_ACK: return DEBUG_PRUNE;
|
||||
case DVMRP_INFO_REQUEST: return 0;
|
||||
case DVMRP_INFO_REPLY: return 0;
|
||||
default: return 0;
|
||||
}
|
||||
case IGMP_PIM:
|
||||
switch (code) {
|
||||
case PIM_QUERY: return 0;
|
||||
case PIM_REGISTER: return 0;
|
||||
case PIM_REGISTER_STOP: return 0;
|
||||
case PIM_JOIN_PRUNE: return 0;
|
||||
case PIM_RP_REACHABLE: return 0;
|
||||
case PIM_ASSERT: return 0;
|
||||
case PIM_GRAFT: return 0;
|
||||
case PIM_GRAFT_ACK: return 0;
|
||||
default: return 0;
|
||||
}
|
||||
case IGMP_MTRACE: return DEBUG_TRACE;
|
||||
case IGMP_MTRACE_RESP: return DEBUG_TRACE;
|
||||
default: return DEBUG_IGMP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a newly received IGMP packet that is sitting in the input
|
||||
* packet buffer.
|
||||
*/
|
||||
void
|
||||
accept_igmp(recvlen)
|
||||
int recvlen;
|
||||
{
|
||||
register u_int32 src, dst, group;
|
||||
struct ip *ip;
|
||||
struct igmp *igmp;
|
||||
int ipdatalen, iphdrlen, igmpdatalen;
|
||||
|
||||
if (recvlen < sizeof(struct ip)) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received packet too short (%u bytes) for IP header", recvlen);
|
||||
return;
|
||||
}
|
||||
|
||||
ip = (struct ip *)recv_buf;
|
||||
src = ip->ip_src.s_addr;
|
||||
dst = ip->ip_dst.s_addr;
|
||||
|
||||
/*
|
||||
* this is most likely a message from the kernel indicating that
|
||||
* a new src grp pair message has arrived and so, it would be
|
||||
* necessary to install a route into the kernel for this.
|
||||
*/
|
||||
if (ip->ip_p == 0) {
|
||||
if (src == 0 || dst == 0)
|
||||
log(LOG_WARNING, 0, "kernel request not accurate");
|
||||
else
|
||||
add_table_entry(src, dst);
|
||||
return;
|
||||
}
|
||||
|
||||
iphdrlen = ip->ip_hl << 2;
|
||||
#ifdef RAW_INPUT_IS_RAW
|
||||
ipdatalen = ntohs(ip->ip_len) - iphdrlen;
|
||||
#else
|
||||
ipdatalen = ip->ip_len;
|
||||
#endif
|
||||
if (iphdrlen + ipdatalen != recvlen) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received packet from %s shorter (%u bytes) than hdr+data length (%u+%u)",
|
||||
inet_fmt(src, s1), recvlen, iphdrlen, ipdatalen);
|
||||
return;
|
||||
}
|
||||
|
||||
igmp = (struct igmp *)(recv_buf + iphdrlen);
|
||||
group = igmp->igmp_group.s_addr;
|
||||
igmpdatalen = ipdatalen - IGMP_MINLEN;
|
||||
if (igmpdatalen < 0) {
|
||||
log(LOG_WARNING, 0,
|
||||
"received IP data field too short (%u bytes) for IGMP, from %s",
|
||||
ipdatalen, inet_fmt(src, s1));
|
||||
return;
|
||||
}
|
||||
|
||||
IF_DEBUG(DEBUG_PKT|igmp_debug_kind(igmp->igmp_type, igmp->igmp_code))
|
||||
log(LOG_DEBUG, 0, "RECV %s from %-15s to %s",
|
||||
igmp_packet_kind(igmp->igmp_type, igmp->igmp_code),
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
|
||||
switch (igmp->igmp_type) {
|
||||
|
||||
case IGMP_MEMBERSHIP_QUERY:
|
||||
accept_membership_query(src, dst, group, igmp->igmp_code);
|
||||
return;
|
||||
|
||||
case IGMP_V1_MEMBERSHIP_REPORT:
|
||||
case IGMP_V2_MEMBERSHIP_REPORT:
|
||||
accept_group_report(src, dst, group, igmp->igmp_type);
|
||||
return;
|
||||
|
||||
case IGMP_V2_LEAVE_GROUP:
|
||||
accept_leave_message(src, dst, group);
|
||||
return;
|
||||
|
||||
case IGMP_DVMRP:
|
||||
group = ntohl(group);
|
||||
|
||||
switch (igmp->igmp_code) {
|
||||
case DVMRP_PROBE:
|
||||
accept_probe(src, dst,
|
||||
(char *)(igmp+1), igmpdatalen, group);
|
||||
return;
|
||||
|
||||
case DVMRP_REPORT:
|
||||
accept_report(src, dst,
|
||||
(char *)(igmp+1), igmpdatalen, group);
|
||||
return;
|
||||
|
||||
case DVMRP_ASK_NEIGHBORS:
|
||||
accept_neighbor_request(src, dst);
|
||||
return;
|
||||
|
||||
case DVMRP_ASK_NEIGHBORS2:
|
||||
accept_neighbor_request2(src, dst);
|
||||
return;
|
||||
|
||||
case DVMRP_NEIGHBORS:
|
||||
accept_neighbors(src, dst, (u_char *)(igmp+1), igmpdatalen,
|
||||
group);
|
||||
return;
|
||||
|
||||
case DVMRP_NEIGHBORS2:
|
||||
accept_neighbors2(src, dst, (u_char *)(igmp+1), igmpdatalen,
|
||||
group);
|
||||
return;
|
||||
|
||||
case DVMRP_PRUNE:
|
||||
accept_prune(src, dst, (char *)(igmp+1), igmpdatalen);
|
||||
return;
|
||||
|
||||
case DVMRP_GRAFT:
|
||||
accept_graft(src, dst, (char *)(igmp+1), igmpdatalen);
|
||||
return;
|
||||
|
||||
case DVMRP_GRAFT_ACK:
|
||||
accept_g_ack(src, dst, (char *)(igmp+1), igmpdatalen);
|
||||
return;
|
||||
|
||||
case DVMRP_INFO_REQUEST:
|
||||
accept_info_request(src, dst, (char *)(igmp+1),
|
||||
igmpdatalen);
|
||||
return;
|
||||
|
||||
case DVMRP_INFO_REPLY:
|
||||
accept_info_reply(src, dst, (char *)(igmp+1), igmpdatalen);
|
||||
return;
|
||||
|
||||
default:
|
||||
log(LOG_INFO, 0,
|
||||
"ignoring unknown DVMRP message code %u from %s to %s",
|
||||
igmp->igmp_code, inet_fmt(src, s1),
|
||||
inet_fmt(dst, s2));
|
||||
return;
|
||||
}
|
||||
|
||||
case IGMP_PIM:
|
||||
return;
|
||||
|
||||
case IGMP_MTRACE_RESP:
|
||||
return;
|
||||
|
||||
case IGMP_MTRACE:
|
||||
accept_mtrace(src, dst, group, (char *)(igmp+1),
|
||||
igmp->igmp_code, igmpdatalen);
|
||||
return;
|
||||
|
||||
default:
|
||||
log(LOG_INFO, 0,
|
||||
"ignoring unknown IGMP message type %x from %s to %s",
|
||||
igmp->igmp_type, inet_fmt(src, s1),
|
||||
inet_fmt(dst, s2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some IGMP messages are more important than others. This routine
|
||||
* determines the logging level at which to log a send error (often
|
||||
* "No route to host"). This is important when there is asymmetric
|
||||
* reachability and someone is trying to, i.e., mrinfo me periodically.
|
||||
*/
|
||||
static int
|
||||
igmp_log_level(type, code)
|
||||
u_int type, code;
|
||||
{
|
||||
switch (type) {
|
||||
case IGMP_MTRACE_RESP:
|
||||
return LOG_INFO;
|
||||
|
||||
case IGMP_DVMRP:
|
||||
switch (code) {
|
||||
case DVMRP_NEIGHBORS:
|
||||
case DVMRP_NEIGHBORS2:
|
||||
return LOG_INFO;
|
||||
}
|
||||
}
|
||||
return LOG_WARNING;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct an IGMP message in the output packet buffer. The caller may
|
||||
* have already placed data in that buffer, of length 'datalen'.
|
||||
*/
|
||||
void
|
||||
build_igmp(src, dst, type, code, group, datalen)
|
||||
u_int32 src, dst;
|
||||
int type, code;
|
||||
u_int32 group;
|
||||
int datalen;
|
||||
{
|
||||
struct ip *ip;
|
||||
struct igmp *igmp;
|
||||
extern int curttl;
|
||||
|
||||
ip = (struct ip *)send_buf;
|
||||
ip->ip_src.s_addr = src;
|
||||
ip->ip_dst.s_addr = dst;
|
||||
ip->ip_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;
|
||||
#ifdef RAW_OUTPUT_IS_RAW
|
||||
ip->ip_len = htons(ip->ip_len);
|
||||
#endif
|
||||
if (IN_MULTICAST(ntohl(dst))) {
|
||||
ip->ip_ttl = curttl;
|
||||
} else {
|
||||
ip->ip_ttl = MAXTTL;
|
||||
}
|
||||
|
||||
igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN);
|
||||
igmp->igmp_type = type;
|
||||
igmp->igmp_code = code;
|
||||
igmp->igmp_group.s_addr = group;
|
||||
igmp->igmp_cksum = 0;
|
||||
igmp->igmp_cksum = inet_cksum((u_short *)igmp,
|
||||
IGMP_MINLEN + datalen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call build_igmp() to build an IGMP message in the output packet buffer.
|
||||
* Then send the message from the interface with IP address 'src' to
|
||||
* destination 'dst'.
|
||||
*/
|
||||
void
|
||||
send_igmp(src, dst, type, code, group, datalen)
|
||||
u_int32 src, dst;
|
||||
int type, code;
|
||||
u_int32 group;
|
||||
int datalen;
|
||||
{
|
||||
struct sockaddr_in sdst;
|
||||
int setloop = 0;
|
||||
|
||||
build_igmp(src, dst, type, code, group, datalen);
|
||||
|
||||
if (IN_MULTICAST(ntohl(dst))) {
|
||||
k_set_if(src);
|
||||
if (type != IGMP_DVMRP || dst == allhosts_group) {
|
||||
setloop = 1;
|
||||
k_set_loop(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
bzero(&sdst, sizeof(sdst));
|
||||
sdst.sin_family = AF_INET;
|
||||
#ifdef HAVE_SA_LEN
|
||||
sdst.sin_len = sizeof(sdst);
|
||||
#endif
|
||||
sdst.sin_addr.s_addr = dst;
|
||||
if (sendto(igmp_socket, send_buf,
|
||||
MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen, 0,
|
||||
(struct sockaddr *)&sdst, sizeof(sdst)) < 0) {
|
||||
if (errno == ENETDOWN)
|
||||
check_vif_state();
|
||||
else
|
||||
log(igmp_log_level(type, code), errno,
|
||||
"sendto to %s on %s",
|
||||
inet_fmt(dst, s1), inet_fmt(src, s2));
|
||||
}
|
||||
|
||||
if (setloop)
|
||||
k_set_loop(FALSE);
|
||||
|
||||
IF_DEBUG(DEBUG_PKT|igmp_debug_kind(type, code))
|
||||
log(LOG_DEBUG, 0, "SENT %s from %-15s to %s",
|
||||
igmp_packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" :
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* igmpv2.h,v 3.8.4.1 1997/11/18 23:25:58 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants for IGMP Version 2. Several of these, especially the
|
||||
* robustness variable, should be variables and not constants.
|
||||
*/
|
||||
#define IGMP_ROBUSTNESS_VARIABLE 2
|
||||
#define IGMP_QUERY_INTERVAL 125
|
||||
#define IGMP_QUERY_RESPONSE_INTERVAL 10
|
||||
#define IGMP_GROUP_MEMBERSHIP_INTERVAL (IGMP_ROBUSTNESS_VARIABLE * \
|
||||
IGMP_QUERY_INTERVAL + \
|
||||
IGMP_QUERY_RESPONSE_INTERVAL)
|
||||
#define IGMP_OTHER_QUERIER_PRESENT_INTERVAL (IGMP_ROBUSTNESS_VARIABLE * \
|
||||
IGMP_QUERY_INTERVAL + \
|
||||
IGMP_QUERY_RESPONSE_INTERVAL / 2)
|
||||
/* Round to the nearest TIMER_INTERVAL */
|
||||
#define IGMP_STARTUP_QUERY_INTERVAL (((IGMP_QUERY_INTERVAL / 4) \
|
||||
/ TIMER_INTERVAL) * TIMER_INTERVAL)
|
||||
#define IGMP_STARTUP_QUERY_COUNT IGMP_ROBUSTNESS_VARIABLE
|
||||
#define IGMP_LAST_MEMBER_QUERY_INTERVAL 1
|
||||
#define IGMP_LAST_MEMBER_QUERY_COUNT IGMP_ROBUSTNESS_VARIABLE
|
||||
|
||||
/*
|
||||
* OLD_AGE_THRESHOLD is the number of IGMP_QUERY_INTERVAL's to remember the
|
||||
* presence of an IGMPv1 group member. According to the IGMPv2 specification,
|
||||
* routers remember this presence for [Robustness Variable] * [Query Interval] +
|
||||
* [Query Response Interval]. However, OLD_AGE_THRESHOLD is in units of
|
||||
* [Query Interval], so doesn't have sufficient resolution to represent
|
||||
* [Query Response Interval]. When the timer mechanism gets an efficient
|
||||
* method of refreshing timers, this should get fixed.
|
||||
*/
|
||||
#define OLD_AGE_THRESHOLD IGMP_ROBUSTNESS_VARIABLE
|
@ -1,235 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* inet.c,v 3.8.4.2 1998/01/06 01:57:44 fenner Exp
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
*/
|
||||
char s1[19]; /* buffers to hold the string representations */
|
||||
char s2[19]; /* of IP addresses, to be passed to inet_fmt() */
|
||||
char s3[19]; /* or inet_fmts(). */
|
||||
char s4[19];
|
||||
|
||||
|
||||
/*
|
||||
* Verify that a given IP address is credible as a host address.
|
||||
* (Without a mask, cannot detect addresses of the form {subnet,0} or
|
||||
* {subnet,-1}.)
|
||||
*/
|
||||
int
|
||||
inet_valid_host(naddr)
|
||||
u_int32 naddr;
|
||||
{
|
||||
register u_int32 addr;
|
||||
|
||||
addr = ntohl(naddr);
|
||||
|
||||
return (!(IN_MULTICAST(addr) ||
|
||||
IN_BADCLASS (addr) ||
|
||||
(addr & 0xff000000) == 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a given netmask is plausible;
|
||||
* make sure that it is a series of 1's followed by
|
||||
* a series of 0's with no discontiguous 1's.
|
||||
*/
|
||||
int
|
||||
inet_valid_mask(mask)
|
||||
u_int32 mask;
|
||||
{
|
||||
if (~(((mask & -mask) - 1) | mask) != 0) {
|
||||
/* Mask is not contiguous */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a given subnet number and mask pair are credible.
|
||||
*
|
||||
* With CIDR, almost any subnet and mask are credible. mrouted still
|
||||
* can't handle aggregated class A's, so we still check that, but
|
||||
* otherwise the only requirements are that the subnet address is
|
||||
* within the [ABC] range and that the host bits of the subnet
|
||||
* are all 0.
|
||||
*/
|
||||
int
|
||||
inet_valid_subnet(nsubnet, nmask)
|
||||
u_int32 nsubnet, nmask;
|
||||
{
|
||||
register u_int32 subnet, mask;
|
||||
|
||||
subnet = ntohl(nsubnet);
|
||||
mask = ntohl(nmask);
|
||||
|
||||
if ((subnet & mask) != subnet) return (FALSE);
|
||||
|
||||
if (subnet == 0)
|
||||
return (mask == 0);
|
||||
|
||||
if (IN_CLASSA(subnet)) {
|
||||
if (mask < 0xff000000 ||
|
||||
(subnet & 0xff000000) == 0x7f000000 ||
|
||||
(subnet & 0xff000000) == 0x00000000) return (FALSE);
|
||||
}
|
||||
else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) {
|
||||
/* Above Class C address space */
|
||||
return (FALSE);
|
||||
}
|
||||
if (subnet & ~mask) {
|
||||
/* Host bits are set in the subnet */
|
||||
return (FALSE);
|
||||
}
|
||||
if (!inet_valid_mask(mask)) {
|
||||
/* Netmask is not contiguous */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert an IP address in u_long (network) format into a printable string.
|
||||
*/
|
||||
char *
|
||||
inet_fmt(addr, s)
|
||||
u_int32 addr;
|
||||
char *s;
|
||||
{
|
||||
register u_char *a;
|
||||
|
||||
a = (u_char *)&addr;
|
||||
sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert an IP subnet number in u_long (network) format into a printable
|
||||
* string including the netmask as a number of bits.
|
||||
*/
|
||||
char *
|
||||
inet_fmts(addr, mask, s)
|
||||
u_int32 addr, mask;
|
||||
char *s;
|
||||
{
|
||||
register u_char *a, *m;
|
||||
int bits;
|
||||
|
||||
if ((addr == 0) && (mask == 0)) {
|
||||
sprintf(s, "default");
|
||||
return (s);
|
||||
}
|
||||
a = (u_char *)&addr;
|
||||
m = (u_char *)&mask;
|
||||
bits = 33 - ffs(ntohl(mask));
|
||||
|
||||
if (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3],
|
||||
bits);
|
||||
else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d", a[0], a[1], a[2], bits);
|
||||
else if (m[1] != 0) sprintf(s, "%u.%u/%d", a[0], a[1], bits);
|
||||
else sprintf(s, "%u/%d", a[0], bits);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the printable string representation of an IP address into the
|
||||
* u_long (network) format. Return 0xffffffff on error. (To detect the
|
||||
* legal address with that value, you must explicitly compare the string
|
||||
* with "255.255.255.255".)
|
||||
*/
|
||||
u_int32
|
||||
inet_parse(s,n)
|
||||
char *s;
|
||||
int n;
|
||||
{
|
||||
u_int32 a = 0;
|
||||
u_int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
|
||||
int i;
|
||||
char c;
|
||||
|
||||
i = sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c);
|
||||
if (i < n || i > 4 || a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
|
||||
return (0xffffffff);
|
||||
|
||||
((u_char *)&a)[0] = a0;
|
||||
((u_char *)&a)[1] = a1;
|
||||
((u_char *)&a)[2] = a2;
|
||||
((u_char *)&a)[3] = a3;
|
||||
|
||||
return (a);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* inet_cksum extracted from:
|
||||
* P I N G . C
|
||||
*
|
||||
* Author -
|
||||
* Mike Muuss
|
||||
* U. S. Army Ballistic Research Laboratory
|
||||
* December, 1983
|
||||
* Modified at Uc Berkeley
|
||||
*
|
||||
* (ping.c) Status -
|
||||
* Public Domain. Distribution Unlimited.
|
||||
*
|
||||
* I N _ C K S U M
|
||||
*
|
||||
* Checksum routine for Internet Protocol family headers (C Version)
|
||||
*
|
||||
*/
|
||||
int
|
||||
inet_cksum(addr, len)
|
||||
u_short *addr;
|
||||
u_int len;
|
||||
{
|
||||
register int nleft = (int)len;
|
||||
register u_short *w = addr;
|
||||
u_short answer = 0;
|
||||
register int sum = 0;
|
||||
|
||||
/*
|
||||
* Our algorithm is simple, using a 32 bit accumulator (sum),
|
||||
* we add sequential 16 bit words to it, and at the end, fold
|
||||
* back all the carry bits from the top 16 bits into the lower
|
||||
* 16 bits.
|
||||
*/
|
||||
while (nleft > 1) {
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
/* mop up an odd byte, if necessary */
|
||||
if (nleft == 1) {
|
||||
*(u_char *) (&answer) = *(u_char *)w ;
|
||||
sum += answer;
|
||||
}
|
||||
|
||||
/*
|
||||
* add back carry outs from top 16 bits to low 16 bits
|
||||
*/
|
||||
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
|
||||
sum += (sum >> 16); /* add carry */
|
||||
answer = ~sum; /* truncate to 16 bits */
|
||||
return (answer);
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
*/
|
||||
#ifdef notyet
|
||||
int raw_socket; /* socket for raw network I/O */
|
||||
#endif
|
||||
/*
|
||||
*XXX For now, we just use the IGMP socket to send packets.
|
||||
* This is legal in BSD, because the protocol # is not checked
|
||||
* on raw sockets. The k_* interfaces need to gain a socket
|
||||
* argument so that we can call them on the raw_socket also.
|
||||
*/
|
||||
#define raw_socket igmp_socket
|
||||
|
||||
/*
|
||||
* Private variables.
|
||||
*/
|
||||
static int rawid = 0;
|
||||
|
||||
/*
|
||||
* Open and initialize the raw socket.
|
||||
*/
|
||||
void
|
||||
init_ipip()
|
||||
{
|
||||
#ifdef notyet
|
||||
if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
|
||||
log(LOG_ERR, errno, "Raw IP socket");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and fill in static IP header for encapsulating on a tunnel.
|
||||
*/
|
||||
void
|
||||
init_ipip_on_vif(v)
|
||||
struct uvif *v;
|
||||
{
|
||||
struct ip *ip;
|
||||
|
||||
ip = v->uv_encap_hdr = (struct ip *)malloc(sizeof(struct ip));
|
||||
if (ip == NULL)
|
||||
log(LOG_ERR, 0, "out of memory");
|
||||
bzero(ip, sizeof(struct ip));
|
||||
/*
|
||||
* Fields zeroed that aren't filled in later:
|
||||
* - IP ID (let the kernel fill it in)
|
||||
* - Offset (we don't send fragments)
|
||||
* - Checksum (let the kernel fill it in)
|
||||
*/
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_tos = 0xc0; /* Internet Control */
|
||||
ip->ip_ttl = MAXTTL; /* applies to unicasts only */
|
||||
ip->ip_p = IPPROTO_IPIP;
|
||||
ip->ip_src.s_addr = v->uv_lcl_addr;
|
||||
ip->ip_dst.s_addr = v->uv_rmt_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call build_igmp() to build an IGMP message in the output packet buffer.
|
||||
* Then fill in the fields of the IP packet that build_igmp() left for the
|
||||
* kernel to fill in, and encapsulate the original packet with the
|
||||
* pre-created ip header for this vif.
|
||||
*/
|
||||
void
|
||||
send_ipip(src, dst, type, code, group, datalen, v)
|
||||
u_int32 src, dst;
|
||||
int type, code;
|
||||
u_int32 group;
|
||||
int datalen;
|
||||
struct uvif *v;
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
struct sockaddr_in sdst;
|
||||
struct ip *ip;
|
||||
|
||||
build_igmp(src, dst, type, code, group, datalen);
|
||||
ip = (struct ip *)send_buf;
|
||||
#ifndef RAW_OUTPUT_IS_RAW
|
||||
ip->ip_len = htons(ip->ip_len);
|
||||
#endif
|
||||
ip->ip_id = htons(rawid++);
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = inet_cksum((u_short *)ip, ip->ip_hl << 2);
|
||||
|
||||
ip = v->uv_encap_hdr;
|
||||
ip->ip_len = 2 * MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;
|
||||
#ifdef RAW_OUTPUT_IS_RAW
|
||||
ip->ip_len = htons(ip->ip_len);
|
||||
#endif
|
||||
|
||||
bzero(&sdst, sizeof(sdst));
|
||||
sdst.sin_family = AF_INET;
|
||||
#ifdef HAVE_SA_LEN
|
||||
sdst.sin_len = sizeof(sdst);
|
||||
#endif
|
||||
sdst.sin_addr = ip->ip_dst;
|
||||
|
||||
iov[0].iov_base = (caddr_t)v->uv_encap_hdr;
|
||||
iov[0].iov_len = sizeof(struct ip);
|
||||
iov[1].iov_base = (caddr_t)send_buf;
|
||||
iov[1].iov_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;
|
||||
|
||||
bzero(&msg, sizeof(msg));
|
||||
msg.msg_name = (caddr_t)&sdst;
|
||||
msg.msg_namelen = sizeof(sdst);
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
if (sendmsg(raw_socket, &msg, 0) < 0) {
|
||||
if (errno == ENETDOWN)
|
||||
check_vif_state();
|
||||
else
|
||||
log(LOG_WARNING, errno,
|
||||
"sendmsg to %s on %s",
|
||||
inet_fmt(sdst.sin_addr.s_addr, s1), inet_fmt(src, s2));
|
||||
}
|
||||
|
||||
IF_DEBUG(DEBUG_PKT|igmp_debug_kind(type, code))
|
||||
log(LOG_DEBUG, 0, "SENT %s from %-15s to %s encaped to %s",
|
||||
igmp_packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" :
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2),
|
||||
inet_fmt(sdst.sin_addr.s_addr, s3));
|
||||
}
|
@ -1,344 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* kern.c,v 3.8.4.10 1998/01/06 02:00:51 fenner Exp
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
int curttl = 0;
|
||||
|
||||
void k_set_rcvbuf(bufsize, minsize)
|
||||
int bufsize;
|
||||
int minsize;
|
||||
{
|
||||
int delta = bufsize / 2;
|
||||
int iter = 0;
|
||||
|
||||
/*
|
||||
* Set the socket buffer. If we can't set it as large as we
|
||||
* want, search around to try to find the highest acceptable
|
||||
* value. The highest acceptable value being smaller than
|
||||
* minsize is a fatal error.
|
||||
*/
|
||||
if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&bufsize, sizeof(bufsize)) < 0) {
|
||||
bufsize -= delta;
|
||||
while (1) {
|
||||
iter++;
|
||||
if (delta > 1)
|
||||
delta /= 2;
|
||||
|
||||
if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&bufsize, sizeof(bufsize)) < 0) {
|
||||
bufsize -= delta;
|
||||
} else {
|
||||
if (delta < 1024)
|
||||
break;
|
||||
bufsize += delta;
|
||||
}
|
||||
}
|
||||
if (bufsize < minsize) {
|
||||
log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
|
||||
bufsize, minsize);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
IF_DEBUG(DEBUG_KERN)
|
||||
log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
|
||||
bufsize, iter);
|
||||
}
|
||||
|
||||
|
||||
void k_hdr_include(bool)
|
||||
int bool;
|
||||
{
|
||||
#ifdef IP_HDRINCL
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL,
|
||||
(char *)&bool, sizeof(bool)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void k_set_ttl(t)
|
||||
int t;
|
||||
{
|
||||
#ifndef RAW_OUTPUT_IS_RAW
|
||||
u_char ttl;
|
||||
|
||||
ttl = t;
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
(char *)&ttl, sizeof(ttl)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);
|
||||
#endif
|
||||
curttl = t;
|
||||
}
|
||||
|
||||
|
||||
void k_set_loop(l)
|
||||
int l;
|
||||
{
|
||||
u_char loop;
|
||||
|
||||
loop = l;
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP,
|
||||
(char *)&loop, sizeof(loop)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);
|
||||
}
|
||||
|
||||
|
||||
void k_set_if(ifa)
|
||||
u_int32 ifa;
|
||||
{
|
||||
struct in_addr adr;
|
||||
|
||||
adr.s_addr = ifa;
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&adr, sizeof(adr)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",
|
||||
inet_fmt(ifa, s1));
|
||||
}
|
||||
|
||||
|
||||
void k_join(grp, ifa)
|
||||
u_int32 grp;
|
||||
u_int32 ifa;
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
|
||||
mreq.imr_multiaddr.s_addr = grp;
|
||||
mreq.imr_interface.s_addr = ifa;
|
||||
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(char *)&mreq, sizeof(mreq)) < 0)
|
||||
log(LOG_WARNING, errno, "can't join group %s on interface %s",
|
||||
inet_fmt(grp, s1), inet_fmt(ifa, s2));
|
||||
}
|
||||
|
||||
|
||||
void k_leave(grp, ifa)
|
||||
u_int32 grp;
|
||||
u_int32 ifa;
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
|
||||
mreq.imr_multiaddr.s_addr = grp;
|
||||
mreq.imr_interface.s_addr = ifa;
|
||||
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
||||
(char *)&mreq, sizeof(mreq)) < 0)
|
||||
log(LOG_WARNING, errno, "can't leave group %s on interface %s",
|
||||
inet_fmt(grp, s1), inet_fmt(ifa, s2));
|
||||
}
|
||||
|
||||
|
||||
void k_init_dvmrp()
|
||||
{
|
||||
#ifdef OLD_KERNEL
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
|
||||
(char *)NULL, 0) < 0)
|
||||
#else
|
||||
int v=1;
|
||||
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
|
||||
(char *)&v, sizeof(int)) < 0)
|
||||
#endif
|
||||
log(LOG_ERR, errno, "can't enable Multicast routing in kernel");
|
||||
}
|
||||
|
||||
|
||||
void k_stop_dvmrp()
|
||||
{
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE,
|
||||
(char *)NULL, 0) < 0)
|
||||
log(LOG_WARNING, errno, "can't disable Multicast routing in kernel");
|
||||
}
|
||||
|
||||
|
||||
void k_add_vif(vifi, v)
|
||||
vifi_t vifi;
|
||||
struct uvif *v;
|
||||
{
|
||||
struct vifctl vc;
|
||||
|
||||
vc.vifc_vifi = vifi;
|
||||
vc.vifc_flags = v->uv_flags & VIFF_KERNEL_FLAGS;
|
||||
vc.vifc_threshold = v->uv_threshold;
|
||||
vc.vifc_rate_limit = v->uv_rate_limit;
|
||||
vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr;
|
||||
vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr;
|
||||
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF,
|
||||
(char *)&vc, sizeof(vc)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF on vif %d", vifi);
|
||||
}
|
||||
|
||||
|
||||
void k_del_vif(vifi)
|
||||
vifi_t vifi;
|
||||
{
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF,
|
||||
(char *)&vifi, sizeof(vifi)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adds a (source, mcastgrp) entry to the kernel
|
||||
*/
|
||||
void k_add_rg(origin, g)
|
||||
u_int32 origin;
|
||||
struct gtable *g;
|
||||
{
|
||||
struct mfcctl mc;
|
||||
vifi_t i;
|
||||
|
||||
#ifdef DEBUG_MFC
|
||||
md_log(MD_ADD, origin, g->gt_mcastgrp);
|
||||
#endif
|
||||
/* copy table values so that setsockopt can process it */
|
||||
mc.mfcc_origin.s_addr = origin;
|
||||
#ifdef OLD_KERNEL
|
||||
mc.mfcc_originmask.s_addr = 0xffffffff;
|
||||
#endif
|
||||
mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
|
||||
mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF;
|
||||
for (i = 0; i < numvifs; i++)
|
||||
mc.mfcc_ttls[i] = g->gt_ttls[i];
|
||||
|
||||
/* write to kernel space */
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC,
|
||||
(char *)&mc, sizeof(mc)) < 0) {
|
||||
#ifdef DEBUG_MFC
|
||||
md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
|
||||
#endif
|
||||
log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC",
|
||||
inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deletes a (source, mcastgrp) entry from the kernel
|
||||
*/
|
||||
int k_del_rg(origin, g)
|
||||
u_int32 origin;
|
||||
struct gtable *g;
|
||||
{
|
||||
struct mfcctl mc;
|
||||
int retval;
|
||||
|
||||
#ifdef DEBUG_MFC
|
||||
md_log(MD_DEL, origin, g->gt_mcastgrp);
|
||||
#endif
|
||||
/* copy table values so that setsockopt can process it */
|
||||
mc.mfcc_origin.s_addr = origin;
|
||||
#ifdef OLD_KERNEL
|
||||
mc.mfcc_originmask.s_addr = 0xffffffff;
|
||||
#endif
|
||||
mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
|
||||
|
||||
/* write to kernel space */
|
||||
if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC,
|
||||
(char *)&mc, sizeof(mc))) < 0) {
|
||||
#ifdef DEBUG_MFC
|
||||
md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
|
||||
#endif
|
||||
log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC of (%s %s)",
|
||||
inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the kernel's idea of what version of mrouted needs to run with it.
|
||||
*/
|
||||
int k_get_version()
|
||||
{
|
||||
#ifdef OLD_KERNEL
|
||||
return -1;
|
||||
#else
|
||||
int vers;
|
||||
int len = sizeof(vers);
|
||||
|
||||
if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION,
|
||||
(char *)&vers, &len) < 0)
|
||||
log(LOG_ERR, errno,
|
||||
"getsockopt MRT_VERSION: perhaps your kernel is too old");
|
||||
|
||||
return vers;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Get packet counters
|
||||
*/
|
||||
int
|
||||
k_get_vif_count(vifi, icount, ocount, ibytes, obytes)
|
||||
vifi_t vifi;
|
||||
int *icount, *ocount, *ibytes, *obytes;
|
||||
{
|
||||
struct sioc_vif_req vreq;
|
||||
int retval = 0;
|
||||
|
||||
vreq.vifi = vifi;
|
||||
if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&vreq) < 0) {
|
||||
log(LOG_WARNING, errno, "SIOCGETVIFCNT on vif %d", vifi);
|
||||
vreq.icount = vreq.ocount = vreq.ibytes =
|
||||
vreq.obytes = 0xffffffff;
|
||||
retval = 1;
|
||||
}
|
||||
if (icount)
|
||||
*icount = vreq.icount;
|
||||
if (ocount)
|
||||
*ocount = vreq.ocount;
|
||||
if (ibytes)
|
||||
*ibytes = vreq.ibytes;
|
||||
if (obytes)
|
||||
*obytes = vreq.obytes;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get counters for a desired source and group.
|
||||
*/
|
||||
int
|
||||
k_get_sg_count(src, grp, pktcnt, bytecnt, wrong_if)
|
||||
u_int32 src;
|
||||
u_int32 grp;
|
||||
struct sg_count *retval;
|
||||
{
|
||||
struct sioc_sg_req sgreq;
|
||||
int retval = 0;
|
||||
|
||||
sgreq.src.s_addr = src;
|
||||
sgreq.grp.s_addr = grp;
|
||||
if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sgreq) < 0) {
|
||||
log(LOG_WARNING, errno, "SIOCGETSGCNT on (%s %s)",
|
||||
inet_fmt(src, s1), inet_fmt(grp, s2));
|
||||
sgreq.pktcnt = sgreq.bytecnt = sgreq.wrong_if = 0xffffffff;
|
||||
return 1;
|
||||
}
|
||||
if (pktcnt)
|
||||
*pktcnt = sgreq.pktcnt;
|
||||
if (bytecnt)
|
||||
*bytecnt = sgreq.bytecnt;
|
||||
if (wrong_if)
|
||||
*wrong_if = sgreq.wrong_if;
|
||||
return retval;
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,96 +0,0 @@
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 8, 1995
|
||||
.Dt MAP-MBONE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm map-mbone
|
||||
.Nd multicast connection mapper
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl d Ar debug_level
|
||||
.Op Fl f
|
||||
.Op Fl g
|
||||
.Op Fl n
|
||||
.Op Fl r Ar retry_count
|
||||
.Op Fl t Ar timeout_count
|
||||
.Op Ar starting_router
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
attempts to display all multicast routers that are reachable from the multicast
|
||||
.Ar starting_router .
|
||||
If not specified on the command line, the default multicast
|
||||
.Ar starting_router
|
||||
is the localhost.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
traverses neighboring multicast routers by sending the ASK_NEIGHBORS IGMP
|
||||
message to the multicast starting_router.
|
||||
If this multicast router responds,
|
||||
the version number and a list of their neighboring multicast router addresses is
|
||||
part of that response.
|
||||
If the responding router has recent multicast version
|
||||
number, then
|
||||
.Nm
|
||||
requests additional information such as metrics, thresholds, and flags from the
|
||||
multicast router.
|
||||
For each new occurrence of neighboring multicast router in
|
||||
the reply and provided the flooding option has been selected, then
|
||||
.Nm
|
||||
asks each of this multicast router for a list of neighbors.
|
||||
This search
|
||||
for unique routers will continue until no new neighboring multicast routers
|
||||
are reported.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl d
|
||||
Set the debug level.
|
||||
When the debug level is greater than the
|
||||
default value of 0, addition debugging messages are printed.
|
||||
Regardless of
|
||||
the debug level, an error condition, will always write an error message and will
|
||||
cause
|
||||
.Nm
|
||||
to terminate.
|
||||
Non-zero debug levels have the following effects:
|
||||
.Bl -tag -width indent
|
||||
.It "level 1"
|
||||
packet warnings are printed to stderr.
|
||||
.It "level 2"
|
||||
all level 1 messages plus notifications down networks are printed to stderr.
|
||||
.It "level 3"
|
||||
all level 2 messages plus notifications of all packet
|
||||
timeouts are printed to stderr.
|
||||
.El
|
||||
.It Fl f
|
||||
Set flooding option.
|
||||
Flooding allows the recursive search
|
||||
of neighboring multicast routers and is enable by default when starting_router
|
||||
is not used.
|
||||
.It Fl g
|
||||
Set graphing in GraphEd format.
|
||||
.It Fl n
|
||||
Disable the DNS lookup for the multicast routers names.
|
||||
.It Fl r Ar retry_count
|
||||
Set the neighbor query retry limit.
|
||||
Default is 1 retry.
|
||||
.It Fl t Ar timeout_count
|
||||
Set the number of seconds to wait for a neighbor query
|
||||
reply before retrying.
|
||||
Default timeout is 2 seconds.
|
||||
.El
|
||||
.Sh IMPORTANT NOTE
|
||||
The
|
||||
.Nm
|
||||
utility must be run as root.
|
||||
.Sh SEE ALSO
|
||||
.Xr mrinfo 8 ,
|
||||
.Xr mrouted 8 ,
|
||||
.Xr mtrace 8
|
||||
.Sh AUTHORS
|
||||
.An Pavel Curtis
|
@ -1,15 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
S= ${.CURDIR}/..
|
||||
.PATH: $S
|
||||
|
||||
PROG= map-mbone
|
||||
MAN= map-mbone.8
|
||||
SRCS= mapper.c
|
||||
|
||||
CFLAGS+= -I$S
|
||||
|
||||
DPADD= ${LIBMROUTED}
|
||||
LDADD= ${LIBMROUTED}
|
||||
|
||||
.include <bsd.prog.mk>
|
File diff suppressed because it is too large
Load Diff
@ -1,91 +0,0 @@
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 8, 1995
|
||||
.Dt MRINFO 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mrinfo
|
||||
.Nd display configuration info from a multicast router
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl d Ar debug_level
|
||||
.Op Fl r Ar retry_count
|
||||
.Op Fl t Ar timeout_count
|
||||
.Ar multicast_router
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
attempts to display the configuration information from the multicast router
|
||||
.Ar multicast_router .
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility uses the ASK_NEIGHBORS IGMP message to the specified multicast router.
|
||||
If this
|
||||
multicast router responds, the version number and a list of their neighboring
|
||||
multicast router addresses is part of that response.
|
||||
If the responding router
|
||||
has a recent multicast version number, then
|
||||
.Nm
|
||||
requests additional information such as metrics, thresholds, and flags from the
|
||||
multicast router.
|
||||
Once the specified multicast router responds, the
|
||||
configuration is displayed to the standard output.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl d Ar debug_level
|
||||
Set the debug level.
|
||||
When the debug level is greater than the
|
||||
default value of 0, addition debugging messages are printed.
|
||||
Regardless of
|
||||
the debug level, an error condition, will always write an error message and will
|
||||
cause
|
||||
.Nm
|
||||
to terminate.
|
||||
Non-zero debug levels have the following effects:
|
||||
.Bl -tag -width indent
|
||||
.It "level 1"
|
||||
packet warnings are printed to stderr.
|
||||
.It "level 2"
|
||||
all level 1 messages plus notifications down networks are printed to stderr.
|
||||
.It "level 3"
|
||||
all level 2 messages plus notifications of all packet
|
||||
timeouts are printed to stderr.
|
||||
.El
|
||||
.It Fl r Ar retry_count
|
||||
Set the neighbor query retry limit.
|
||||
Default is 3 retries.
|
||||
.It Fl t Ar timeout_count
|
||||
Set the number of seconds to wait for a neighbor query
|
||||
reply.
|
||||
Default timeout is 4 seconds.
|
||||
.El
|
||||
.Sh SAMPLE OUTPUT
|
||||
.Bd -literal
|
||||
$ mrinfo mbone.phony.dom.net
|
||||
127.148.176.10 (mbone.phony.dom.net) [version 3.3]:
|
||||
127.148.176.10 -> 0.0.0.0 (?) [1/1/querier]
|
||||
127.148.176.10 -> 127.0.8.4 (mbone2.phony.dom.net) [1/45/tunnel]
|
||||
127.148.176.10 -> 105.1.41.9 (momoney.com) [1/32/tunnel/down]
|
||||
127.148.176.10 -> 143.192.152.119 (mbone.dipu.edu) [1/32/tunnel]
|
||||
.Ed
|
||||
.Pp
|
||||
For each neighbor of the queried multicast router, the IP of the queried router
|
||||
is displayed, followed by the IP and name of the neighbor.
|
||||
In square brackets
|
||||
the metric (cost of connection), the threshold (multicast ttl) is displayed.
|
||||
If
|
||||
the queried multicast router has a newer version number, the type (tunnel,
|
||||
srcrt) and status (disabled, down) of the connection is displayed.
|
||||
.Sh IMPORTANT NOTE
|
||||
The
|
||||
.Nm
|
||||
utility must be run as root.
|
||||
.Sh SEE ALSO
|
||||
.Xr map-mbone 8 ,
|
||||
.Xr mrouted 8 ,
|
||||
.Xr mtrace 8
|
||||
.Sh AUTHORS
|
||||
.An Van Jacobson
|
@ -1,636 +0,0 @@
|
||||
/*
|
||||
* This tool requests configuration info from a multicast router
|
||||
* and prints the reply (if any). Invoke it as:
|
||||
*
|
||||
* mrinfo router-name-or-address
|
||||
*
|
||||
* Written Wed Mar 24 1993 by Van Jacobson (adapted from the
|
||||
* multicast mapper written by Pavel Curtis).
|
||||
*
|
||||
* The lawyers insist we include the following UC copyright notice.
|
||||
* The mapper from which this is derived contained a Xerox copyright
|
||||
* notice which follows the UC one. Try not to get depressed noting
|
||||
* that the legal gibberish is larger than the program.
|
||||
*
|
||||
* Copyright (c) 1993 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the Computer Systems
|
||||
* Engineering Group at Lawrence Berkeley Laboratory.
|
||||
* 4. Neither the name of the University nor of the Laboratory 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.
|
||||
* ---------------------------------
|
||||
* Copyright (c) Xerox Corporation 1992. All rights reserved.
|
||||
*
|
||||
* License is granted to copy, to use, and to make and to use derivative works
|
||||
* for research and evaluation purposes, provided that Xerox is acknowledged
|
||||
* in all documentation pertaining to any such copy or derivative work. Xerox
|
||||
* grants no other licenses expressed or implied. The Xerox trade name should
|
||||
* not be used in any advertising without its written permission.
|
||||
*
|
||||
* XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
|
||||
* MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE FOR
|
||||
* ANY PARTICULAR PURPOSE. The software is provided "as is" without express
|
||||
* or implied warranty of any kind.
|
||||
*
|
||||
* These notices must be retained in any copies of any part of this software.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
/* original rcsid:
|
||||
"@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)";
|
||||
*/
|
||||
#endif
|
||||
|
||||
#include <err.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include "defs.h"
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEOUT 4 /* How long to wait before retrying requests */
|
||||
#define DEFAULT_RETRIES 3 /* How many times to ask each router */
|
||||
|
||||
u_int32 our_addr, target_addr = 0; /* in NET order */
|
||||
int debug = 0;
|
||||
int nflag = 0;
|
||||
int retries = DEFAULT_RETRIES;
|
||||
int timeout = DEFAULT_TIMEOUT;
|
||||
int target_level = 0;
|
||||
vifi_t numvifs; /* to keep loader happy */
|
||||
/* (see COPY_TABLES macro called in kern.c) */
|
||||
|
||||
char * inet_name __P((u_int32 addr));
|
||||
void ask __P((u_int32 dst));
|
||||
void ask2 __P((u_int32 dst));
|
||||
int get_number __P((int *var, int deflt, char ***pargv,
|
||||
int *pargc));
|
||||
u_int32 host_addr __P((char *name));
|
||||
static void usage __P((void));
|
||||
|
||||
/* to shut up -Wstrict-prototypes */
|
||||
int main __P((int argc, char *argv[]));
|
||||
|
||||
|
||||
char *
|
||||
inet_name(addr)
|
||||
u_int32 addr;
|
||||
{
|
||||
struct hostent *e;
|
||||
struct in_addr in;
|
||||
|
||||
if (addr == 0)
|
||||
return "local";
|
||||
|
||||
if (nflag ||
|
||||
(e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == NULL) {
|
||||
in.s_addr = addr;
|
||||
return (inet_ntoa(in));
|
||||
}
|
||||
return (e->h_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log errors and other messages to stderr, according to the severity of the
|
||||
* message and the current debug level. For errors of severity LOG_ERR or
|
||||
* worse, terminate the program.
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
void
|
||||
log(int severity, int syserr, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap, format);
|
||||
#else
|
||||
void
|
||||
log(severity, syserr, format, va_alist)
|
||||
int severity, syserr;
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char fmt[100];
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
switch (debug) {
|
||||
case 0:
|
||||
if (severity > LOG_WARNING)
|
||||
return;
|
||||
case 1:
|
||||
if (severity > LOG_NOTICE)
|
||||
return;
|
||||
case 2:
|
||||
if (severity > LOG_INFO)
|
||||
return;
|
||||
default:
|
||||
fmt[0] = '\0';
|
||||
if (severity == LOG_WARNING)
|
||||
strcpy(fmt, "warning - ");
|
||||
strncat(fmt, format, sizeof(fmt)-strlen(fmt));
|
||||
fmt[sizeof(fmt)-1]='\0';
|
||||
vfprintf(stderr, fmt, ap);
|
||||
if (syserr == 0)
|
||||
fprintf(stderr, "\n");
|
||||
else if (syserr < sys_nerr)
|
||||
fprintf(stderr, ": %s\n", sys_errlist[syserr]);
|
||||
else
|
||||
fprintf(stderr, ": errno %d\n", syserr);
|
||||
}
|
||||
|
||||
if (severity <= LOG_ERR)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a neighbors-list request.
|
||||
*/
|
||||
void
|
||||
ask(dst)
|
||||
u_int32 dst;
|
||||
{
|
||||
send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS,
|
||||
htonl(MROUTED_LEVEL), 0);
|
||||
}
|
||||
|
||||
void
|
||||
ask2(dst)
|
||||
u_int32 dst;
|
||||
{
|
||||
send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2,
|
||||
htonl(MROUTED_LEVEL), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an incoming neighbor-list message.
|
||||
*/
|
||||
void
|
||||
accept_neighbors(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
u_char *ep = p + datalen;
|
||||
#define GET_ADDR(a) (a = ((u_int32)*p++ << 24), a += ((u_int32)*p++ << 16),\
|
||||
a += ((u_int32)*p++ << 8), a += *p++)
|
||||
|
||||
printf("%s (%s):\n", inet_fmt(src, s1), inet_name(src));
|
||||
while (p < ep) {
|
||||
register u_int32 laddr;
|
||||
register u_char metric;
|
||||
register u_char thresh;
|
||||
register int ncount;
|
||||
|
||||
GET_ADDR(laddr);
|
||||
laddr = htonl(laddr);
|
||||
metric = *p++;
|
||||
thresh = *p++;
|
||||
ncount = *p++;
|
||||
while (--ncount >= 0) {
|
||||
register u_int32 neighbor;
|
||||
GET_ADDR(neighbor);
|
||||
neighbor = htonl(neighbor);
|
||||
printf(" %s -> ", inet_fmt(laddr, s1));
|
||||
printf("%s (%s) [%d/%d]\n", inet_fmt(neighbor, s1),
|
||||
inet_name(neighbor), metric, thresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
accept_neighbors2(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
u_char *ep = p + datalen;
|
||||
u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */
|
||||
/* well, only possibly_broken_cisco, but that's too long to type. */
|
||||
u_int majvers = level & 0xff;
|
||||
u_int minvers = (level >> 8) & 0xff;
|
||||
|
||||
printf("%s (%s) [", inet_fmt(src, s1), inet_name(src));
|
||||
if (majvers == 3 && minvers == 0xff)
|
||||
printf("DVMRPv3 compliant");
|
||||
else
|
||||
printf("version %d.%d", majvers, minvers);
|
||||
printf ("]:\n");
|
||||
|
||||
while (p < ep) {
|
||||
register u_char metric;
|
||||
register u_char thresh;
|
||||
register u_char flags;
|
||||
register int ncount;
|
||||
register u_int32 laddr = *(u_int32*)p;
|
||||
|
||||
p += 4;
|
||||
metric = *p++;
|
||||
thresh = *p++;
|
||||
flags = *p++;
|
||||
ncount = *p++;
|
||||
if (broken_cisco && ncount == 0) /* dumb Ciscos */
|
||||
ncount = 1;
|
||||
if (broken_cisco && ncount > 15) /* dumb Ciscos */
|
||||
ncount = ncount & 0xf;
|
||||
while (--ncount >= 0 && p < ep) {
|
||||
register u_int32 neighbor = *(u_int32*)p;
|
||||
p += 4;
|
||||
printf(" %s -> ", inet_fmt(laddr, s1));
|
||||
printf("%s (%s) [%d/%d", inet_fmt(neighbor, s1),
|
||||
inet_name(neighbor), metric, thresh);
|
||||
if (flags & DVMRP_NF_TUNNEL)
|
||||
printf("/tunnel");
|
||||
if (flags & DVMRP_NF_SRCRT)
|
||||
printf("/srcrt");
|
||||
if (flags & DVMRP_NF_PIM)
|
||||
printf("/pim");
|
||||
if (flags & DVMRP_NF_QUERIER)
|
||||
printf("/querier");
|
||||
if (flags & DVMRP_NF_DISABLED)
|
||||
printf("/disabled");
|
||||
if (flags & DVMRP_NF_DOWN)
|
||||
printf("/down");
|
||||
if (flags & DVMRP_NF_LEAF)
|
||||
printf("/leaf");
|
||||
printf("]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
get_number(var, deflt, pargv, pargc)
|
||||
int *var, *pargc, deflt;
|
||||
char ***pargv;
|
||||
{
|
||||
if ((*pargv)[0][2] == '\0') { /* Get the value from the next
|
||||
* argument */
|
||||
if (*pargc > 1 && isdigit((*pargv)[1][0])) {
|
||||
(*pargv)++, (*pargc)--;
|
||||
*var = atoi((*pargv)[0]);
|
||||
return 1;
|
||||
} else if (deflt >= 0) {
|
||||
*var = deflt;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
} else { /* Get value from the rest of this argument */
|
||||
if (isdigit((*pargv)[0][2])) {
|
||||
*var = atoi((*pargv)[0] + 2);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: mrinfo [-n] [-t timeout] [-r retries] [router]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int tries;
|
||||
int trynew;
|
||||
struct timeval et;
|
||||
struct hostent *hp;
|
||||
struct hostent bogus;
|
||||
char *host;
|
||||
int curaddr;
|
||||
|
||||
if (geteuid() != 0)
|
||||
errx(1, "must be root");
|
||||
|
||||
init_igmp();
|
||||
setuid(getuid());
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
argv++, argc--;
|
||||
while (argc > 0 && argv[0][0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
case 'd':
|
||||
if (!get_number(&debug, DEFAULT_DEBUG, &argv, &argc))
|
||||
usage();
|
||||
break;
|
||||
case 'n':
|
||||
++nflag;
|
||||
break;
|
||||
case 'r':
|
||||
if (!get_number(&retries, -1, &argv, &argc))
|
||||
usage();
|
||||
break;
|
||||
case 't':
|
||||
if (!get_number(&timeout, -1, &argv, &argc))
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argv++, argc--;
|
||||
}
|
||||
if (argc > 1)
|
||||
usage();
|
||||
if (argc == 1)
|
||||
host = argv[0];
|
||||
else
|
||||
host = "127.0.0.1";
|
||||
|
||||
if ((target_addr = inet_addr(host)) != -1) {
|
||||
hp = &bogus;
|
||||
hp->h_length = sizeof(target_addr);
|
||||
hp->h_addr_list = (char **)malloc(2 * sizeof(char *));
|
||||
hp->h_addr_list[0] = malloc(hp->h_length);
|
||||
memcpy(hp->h_addr_list[0], &target_addr, hp->h_length);
|
||||
hp->h_addr_list[1] = 0;
|
||||
} else
|
||||
hp = gethostbyname(host);
|
||||
|
||||
if (hp == NULL || hp->h_length != sizeof(target_addr))
|
||||
errx(1, "%s: no such host", argv[0]);
|
||||
if (debug)
|
||||
fprintf(stderr, "Debug level %u\n", debug);
|
||||
|
||||
/* Check all addresses; mrouters often have unreachable interfaces */
|
||||
for (curaddr = 0; hp->h_addr_list[curaddr] != NULL; curaddr++) {
|
||||
memcpy(&target_addr, hp->h_addr_list[curaddr], hp->h_length);
|
||||
{ /* Find a good local address for us. */
|
||||
int udp;
|
||||
struct sockaddr_in addr;
|
||||
int addrlen = sizeof(addr);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
#ifdef HAVE_SA_LEN
|
||||
addr.sin_len = sizeof addr;
|
||||
#endif
|
||||
addr.sin_addr.s_addr = target_addr;
|
||||
addr.sin_port = htons(2000); /* any port over 1024 will
|
||||
* do... */
|
||||
if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0
|
||||
|| connect(udp, (struct sockaddr *) & addr, sizeof(addr)) < 0
|
||||
|| getsockname(udp, (struct sockaddr *) & addr, &addrlen) < 0)
|
||||
err(-1, "determining local address");
|
||||
close(udp);
|
||||
our_addr = addr.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
tries = 0;
|
||||
trynew = 1;
|
||||
/*
|
||||
* New strategy: send 'ask2' for two timeouts, then fall back
|
||||
* to 'ask', since it's not very likely that we are going to
|
||||
* find someone who only responds to 'ask' these days
|
||||
*/
|
||||
ask2(target_addr);
|
||||
|
||||
gettimeofday(&et, 0);
|
||||
et.tv_sec += timeout;
|
||||
|
||||
/* Main receive loop */
|
||||
for (;;) {
|
||||
fd_set fds;
|
||||
struct timeval tv, now;
|
||||
int count, recvlen, dummy = 0;
|
||||
register u_int32 src, dst, group;
|
||||
struct ip *ip;
|
||||
struct igmp *igmp;
|
||||
int ipdatalen, iphdrlen, igmpdatalen;
|
||||
|
||||
if (igmp_socket >= FD_SETSIZE)
|
||||
log(LOG_ERR, 0, "descriptor too big");
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(igmp_socket, &fds);
|
||||
|
||||
gettimeofday(&now, 0);
|
||||
tv.tv_sec = et.tv_sec - now.tv_sec;
|
||||
tv.tv_usec = et.tv_usec - now.tv_usec;
|
||||
|
||||
if (tv.tv_usec < 0) {
|
||||
tv.tv_usec += 1000000L;
|
||||
--tv.tv_sec;
|
||||
}
|
||||
if (tv.tv_sec < 0)
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
|
||||
count = select(igmp_socket + 1, &fds, 0, 0, &tv);
|
||||
|
||||
if (count < 0) {
|
||||
if (errno != EINTR)
|
||||
warn("select");
|
||||
continue;
|
||||
} else if (count == 0) {
|
||||
log(LOG_DEBUG, 0, "Timed out receiving neighbor lists");
|
||||
if (++tries > retries)
|
||||
break;
|
||||
/* If we've tried ASK_NEIGHBORS2 twice with
|
||||
* no response, fall back to ASK_NEIGHBORS
|
||||
*/
|
||||
if (tries == 2 && target_level == 0)
|
||||
trynew = 0;
|
||||
if (target_level == 0 && trynew == 0)
|
||||
ask(target_addr);
|
||||
else
|
||||
ask2(target_addr);
|
||||
gettimeofday(&et, 0);
|
||||
et.tv_sec += timeout;
|
||||
continue;
|
||||
}
|
||||
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
|
||||
0, NULL, &dummy);
|
||||
if (recvlen <= 0) {
|
||||
if (recvlen && errno != EINTR)
|
||||
warn("recvfrom");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recvlen < sizeof(struct ip)) {
|
||||
log(LOG_WARNING, 0,
|
||||
"packet too short (%u bytes) for IP header",
|
||||
recvlen);
|
||||
continue;
|
||||
}
|
||||
ip = (struct ip *) recv_buf;
|
||||
if (ip->ip_p == 0)
|
||||
continue; /* Request to install cache entry */
|
||||
src = ip->ip_src.s_addr;
|
||||
dst = ip->ip_dst.s_addr;
|
||||
iphdrlen = ip->ip_hl << 2;
|
||||
#ifdef RAW_INPUT_IS_RAW
|
||||
ipdatalen = ntohs(ip->ip_len) - iphdrlen;
|
||||
#else
|
||||
ipdatalen = ip->ip_len;
|
||||
#endif
|
||||
if (iphdrlen + ipdatalen != recvlen) {
|
||||
log(LOG_WARNING, 0,
|
||||
"packet shorter (%u bytes) than hdr+data length (%u+%u)",
|
||||
recvlen, iphdrlen, ipdatalen);
|
||||
continue;
|
||||
}
|
||||
igmp = (struct igmp *) (recv_buf + iphdrlen);
|
||||
group = igmp->igmp_group.s_addr;
|
||||
igmpdatalen = ipdatalen - IGMP_MINLEN;
|
||||
if (igmpdatalen < 0) {
|
||||
log(LOG_WARNING, 0,
|
||||
"IP data field too short (%u bytes) for IGMP, from %s",
|
||||
ipdatalen, inet_fmt(src, s1));
|
||||
continue;
|
||||
}
|
||||
if (igmp->igmp_type != IGMP_DVMRP)
|
||||
continue;
|
||||
|
||||
switch (igmp->igmp_code) {
|
||||
case DVMRP_NEIGHBORS:
|
||||
case DVMRP_NEIGHBORS2:
|
||||
if (src != target_addr) {
|
||||
warnx("got reply from %s instead of %s",
|
||||
inet_fmt(src, s1), inet_fmt(target_addr, s1));
|
||||
/*continue;*/
|
||||
}
|
||||
break;
|
||||
default:
|
||||
continue; /* ignore all other DVMRP messages */
|
||||
}
|
||||
|
||||
switch (igmp->igmp_code) {
|
||||
|
||||
case DVMRP_NEIGHBORS:
|
||||
if (group) {
|
||||
/* knows about DVMRP_NEIGHBORS2 msg */
|
||||
if (target_level == 0) {
|
||||
target_level = ntohl(group);
|
||||
ask2(target_addr);
|
||||
}
|
||||
} else {
|
||||
accept_neighbors(src, dst, (u_char *)(igmp + 1),
|
||||
igmpdatalen, ntohl(group));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case DVMRP_NEIGHBORS2:
|
||||
accept_neighbors2(src, dst, (u_char *)(igmp + 1),
|
||||
igmpdatalen, ntohl(group));
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* dummies */
|
||||
void accept_probe(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_group_report(src, dst, group, r_type)
|
||||
u_int32 src, dst, group;
|
||||
int r_type;
|
||||
{
|
||||
}
|
||||
void accept_neighbor_request2(src, dst)
|
||||
u_int32 src, dst;
|
||||
{
|
||||
}
|
||||
void accept_report(src, dst, p, datalen, level)
|
||||
u_int32 src, dst, level;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_neighbor_request(src, dst)
|
||||
u_int32 src, dst;
|
||||
{
|
||||
}
|
||||
void accept_prune(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_graft(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_g_ack(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void add_table_entry(origin, mcastgrp)
|
||||
u_int32 origin, mcastgrp;
|
||||
{
|
||||
}
|
||||
void check_vif_state()
|
||||
{
|
||||
}
|
||||
void accept_leave_message(src, dst, group)
|
||||
u_int32 src, dst, group;
|
||||
{
|
||||
}
|
||||
void accept_mtrace(src, dst, group, data, no, datalen)
|
||||
u_int32 src, dst, group;
|
||||
char *data;
|
||||
u_int no;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_membership_query(src, dst, group, tmo)
|
||||
u_int32 src, dst, group;
|
||||
int tmo;
|
||||
{
|
||||
}
|
||||
void accept_info_request(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
||||
void accept_info_reply(src, dst, p, datalen)
|
||||
u_int32 src, dst;
|
||||
u_char *p;
|
||||
int datalen;
|
||||
{
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
S= ${.CURDIR}/..
|
||||
.PATH: $S
|
||||
|
||||
PROG= mrinfo
|
||||
MAN= mrinfo.8
|
||||
BINOWN= root
|
||||
BINMODE= 4555
|
||||
|
||||
CFLAGS+= -I$S
|
||||
|
||||
DPADD= ${LIBMROUTED}
|
||||
LDADD= ${LIBMROUTED}
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,665 +0,0 @@
|
||||
.\"COPYRIGHT 1989 by The Board of Trustees of Leland Stanford Junior University.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 8, 1995
|
||||
.Dt MROUTED 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mrouted
|
||||
.Nd IP multicast routing daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl c Ar config_file
|
||||
.Op Fl d Op Ar debug_level
|
||||
.Op Fl p
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is an implementation of the Distance-Vector Multicast Routing
|
||||
Protocol (DVMRP), an earlier version of which is specified in RFC-1075.
|
||||
It maintains topological knowledge via a distance-vector routing protocol
|
||||
(like RIP, described in RFC-1058), upon which it implements a multicast
|
||||
datagram forwarding algorithm called Reverse Path Multicasting.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility forwards a multicast datagram along a shortest (reverse) path tree
|
||||
rooted at the subnet on which the datagram originates.
|
||||
The multicast
|
||||
delivery tree may be thought of as a broadcast delivery tree that has
|
||||
been pruned back so that it does not extend beyond those subnetworks
|
||||
that have members of the destination group.
|
||||
Hence, datagrams
|
||||
are not forwarded along those branches which have no listeners of the
|
||||
multicast group.
|
||||
The IP time-to-live of a multicast datagram can be
|
||||
used to limit the range of multicast datagrams.
|
||||
.Pp
|
||||
In order to support multicasting among subnets that are separated by (unicast)
|
||||
routers that do not support IP multicasting,
|
||||
.Nm
|
||||
includes support for
|
||||
"tunnels", which are virtual point-to-point links between pairs of
|
||||
multicast routers
|
||||
located anywhere in an internet.
|
||||
IP multicast packets are encapsulated for
|
||||
transmission through tunnels, so that they look like normal unicast datagrams
|
||||
to intervening routers and subnets.
|
||||
The encapsulation
|
||||
is added on entry to a tunnel, and stripped off
|
||||
on exit from a tunnel.
|
||||
The packets are encapsulated using the IP-in-IP protocol
|
||||
(IP protocol number 4).
|
||||
Older versions of
|
||||
.Nm
|
||||
tunneled using IP source routing, which puts a heavy load on some
|
||||
types of routers.
|
||||
This version does not support IP source route tunnelling.
|
||||
.Pp
|
||||
The tunnelling mechanism allows
|
||||
.Nm
|
||||
to establish a virtual internet, for
|
||||
the purpose of multicasting only, which is independent of the physical
|
||||
internet, and which may span multiple Autonomous Systems.
|
||||
This capability
|
||||
is intended for experimental support of internet multicasting only, pending
|
||||
widespread support for multicast routing by the regular (unicast) routers.
|
||||
The
|
||||
.Nm
|
||||
utility suffers from the well-known scaling problems of any distance-vector
|
||||
routing protocol, and does not (yet) support hierarchical multicast routing.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
handles multicast routing only; there may or may not be unicast routing
|
||||
software running on the same machine as
|
||||
.Nm .
|
||||
With the use of tunnels, it
|
||||
is not necessary for
|
||||
.Nm
|
||||
to have access to more than one physical subnet
|
||||
in order to perform multicast forwarding.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c Ar config_file
|
||||
Specify an alternative file for configuration commands.
|
||||
Default is
|
||||
.Pa /etc/mrouted.conf .
|
||||
.It Fl d Op Ar debug_level
|
||||
If no
|
||||
.Fl d
|
||||
option is given, or if the debug level is specified as 0,
|
||||
.Nm
|
||||
detaches from the invoking terminal.
|
||||
Otherwise, it remains attached to the
|
||||
invoking terminal and responsive to signals from that terminal.
|
||||
Regardless of the debug level,
|
||||
.Nm
|
||||
always writes warning and error messages to the system
|
||||
log daemon.
|
||||
The
|
||||
.Fl debug-level
|
||||
argument is a comma-separated list of any of the following:
|
||||
.Bl -tag -width indent
|
||||
.It "packet"
|
||||
Display the type, source and destination of all packets sent or received.
|
||||
.It "pruning"
|
||||
Display more information about prunes sent or received.
|
||||
.It "routing"
|
||||
Display more information about routing update packets sent or received.
|
||||
.It "route_detail"
|
||||
Display routing updates in excruciating detail.
|
||||
This is generally way too
|
||||
much information.
|
||||
.It "neighbors"
|
||||
Display information about neighbor discovery.
|
||||
.It "cache"
|
||||
Display insertions, deletions and refreshes of entries in
|
||||
the kernel forwarding cache.
|
||||
.It "timeout"
|
||||
Debug timeouts and periodic processes.
|
||||
.It "interface"
|
||||
Display information about interfaces and their configuration.
|
||||
.It "membership"
|
||||
Display information about group memberships on physical interfaces.
|
||||
.It "traceroute"
|
||||
Display information about multicast traceroute requests
|
||||
passing through this router.
|
||||
.It "igmp"
|
||||
Display IGMP operation including group membership and querier election.
|
||||
.It "icmp"
|
||||
Monitor ICMP handling.
|
||||
.It "rsrr"
|
||||
Monitor RSRR operation.
|
||||
.El
|
||||
.Pp
|
||||
Upon startup,
|
||||
.Nm
|
||||
writes its pid to the file
|
||||
.Pa /var/run/mrouted.pid .
|
||||
.El
|
||||
.Sh CONFIGURATION
|
||||
The
|
||||
.Nm
|
||||
utility automatically configures itself to forward on all multicast-capable
|
||||
interfaces, i.e., interfaces that have the IFF_MULTICAST flag set (excluding
|
||||
the loopback "interface"), and it finds other DVMRP routers directly reachable
|
||||
via those interfaces.
|
||||
To override the default configuration, or to add
|
||||
tunnel links to other multicast routers,
|
||||
configuration commands may be placed in
|
||||
.Pa /etc/mrouted.conf
|
||||
(or an alternative file, specified by the
|
||||
.Fl c
|
||||
option).
|
||||
.Pp
|
||||
The file format is free-form; whitespace (including newlines) is not
|
||||
significant.
|
||||
The file begins with commands that apply to
|
||||
.Nm Ns 's
|
||||
overall operation or set defaults.
|
||||
.Bl -tag -width indent
|
||||
.It cache_lifetime Ar secs
|
||||
Specifies, in seconds, the lifetime of a multicast forwarding cache
|
||||
entry in the kernel.
|
||||
Multicast forwarding cache entries in the kernel
|
||||
are checked every
|
||||
.Ar secs
|
||||
seconds, and are refreshed if the source is still
|
||||
active or deleted if not.
|
||||
Care should be taken when setting this value,
|
||||
as a low value can keep the kernel cache small at the cost of "thrashing"
|
||||
the cache for periodic senders, but high values can cause the kernel
|
||||
cache to grow unacceptably large.
|
||||
The default is 300 seconds (5 minutes).
|
||||
.It prune_lifetime Ar secs
|
||||
Specifies, in seconds, the average lifetime of prunes that are sent towards
|
||||
parents.
|
||||
The actual lifetimes will be randomized in the range
|
||||
[.5\fIsecs\fP,1.5\fIsecs\fP].
|
||||
The default is 7200 (2 hours).
|
||||
Smaller values
|
||||
cause less state to be kept both at this router and the parent, at the
|
||||
cost of more frequent broadcasts.
|
||||
However, some routers (e.g.\&
|
||||
.Nm
|
||||
<3.3
|
||||
and all currently known versions of cisco's IOS) do not use the
|
||||
DVMRP generation ID to determine that a neighbor has rebooted.
|
||||
Prunes
|
||||
sent towards these neighbors should be kept short, in order to shorten
|
||||
the time to recover from a reboot.
|
||||
For use in this situation, the
|
||||
prune_lifetime keyword may be specified on an interface as described
|
||||
below.
|
||||
.It noflood
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
uses a DVMRP optimization to prevent having to keep individual routing tables
|
||||
for each neighbor; part of this optimization is that
|
||||
.Nm
|
||||
assumes that it is the forwarder for each of its attached subnets on
|
||||
startup.
|
||||
This can cause duplicates for a short period (approximately
|
||||
one full route report interval), since both the router that just
|
||||
started up and the proper forwarder will be forwarding traffic.
|
||||
This
|
||||
behavior can be turned off with the noflood keyword;
|
||||
.Nm
|
||||
will not assume that it is the forwarder on startup.
|
||||
Turning on noflood can cause black holes on restart, which will generally
|
||||
last approximately one full route report interval.
|
||||
The noflood keyword can also be specified on individual interfaces.
|
||||
.It rexmit_prunes Ar [on|off]
|
||||
Default is to retransmit prunes on all point-to-point interfaces
|
||||
(including tunnels) but no multi-access interfaces.
|
||||
This option
|
||||
may be used to make the default on (or off) for all interfaces.
|
||||
The rexmit_prunes keyword can also be specified on individual interfaces.
|
||||
.It name Ar "boundary-name scoped-addr/mask-len"
|
||||
Associates
|
||||
.Ar boundary-name
|
||||
with the boundary described by
|
||||
.Ar scoped-addr/mask-len ,
|
||||
to help make interface configurations
|
||||
more readable and reduce repetition in the configuration file.
|
||||
.El
|
||||
.Pp
|
||||
The second section of the configuration file, which may optionally
|
||||
be empty, describes options that apply to physical interfaces.
|
||||
.Bl -tag -width indent
|
||||
.It phyint Ar "local-addr|ifname"
|
||||
The phyint command does nothing by itself; it is simply a place holder
|
||||
which interface-specific commands may follow.
|
||||
An interface address or
|
||||
name may be specified.
|
||||
.It disable
|
||||
Disables multicast forwarding on this interface.
|
||||
By default,
|
||||
.Nm
|
||||
discovers all locally attached multicast capable interfaces and forwards
|
||||
on all of them.
|
||||
.It netmask Ar netmask
|
||||
If the kernel's netmask does not accurately reflect
|
||||
the subnet (e.g.\& you are using proxy-ARP in lieu of IP subnetting), use the
|
||||
netmask command to describe the real netmask.
|
||||
.It altnet Ar network/mask-len
|
||||
If a phyint is attached to multiple IP subnets, describe each additional subnet
|
||||
with the altnet keyword.
|
||||
This command may be specified multiple times
|
||||
to describe multiple subnets.
|
||||
.It igmpv1
|
||||
If there are any IGMPv1 routers on the phyint, use the \fBigmpv1\fP
|
||||
keyword to force
|
||||
.Nm
|
||||
into IGMPv1 mode.
|
||||
All routers on the phyint
|
||||
must use the same version of IGMP.
|
||||
.It force_leaf
|
||||
Force
|
||||
.Nm
|
||||
to ignore other routers on this interface.
|
||||
.Nm
|
||||
will never send or accept neighbor probes or
|
||||
route reports on this interface.
|
||||
.El
|
||||
.Pp
|
||||
In addition, the common vif commands described later may all be used on
|
||||
a phyint.
|
||||
.Pp
|
||||
The third section of the configuration file, also optional, describes
|
||||
the configuration of any DVMRP tunnels this router might have.
|
||||
.Bl -tag -width indent
|
||||
.It tunnel Ar "local-addr|ifname" Ar "remote-addr|remote-hostname"
|
||||
This command establishes a DVMRP tunnel between this host (on the interface
|
||||
described by
|
||||
.Ar local-addr
|
||||
or
|
||||
.Ar ifname )
|
||||
and a remote host (identified by
|
||||
.Ar remote-addr
|
||||
or
|
||||
.Ar remote-hostname ) .
|
||||
A remote hostname may only be used if
|
||||
it maps to a single IP address.
|
||||
A tunnel must be configured on both routers before it can be used.
|
||||
.Pp
|
||||
Be careful that the unicast route to the remote address goes out the
|
||||
interface specified by the
|
||||
.Ar "local-addr|ifname"
|
||||
argument.
|
||||
Some UNIX
|
||||
kernels rewrite the source address of
|
||||
.Nm Ns 's
|
||||
packets on their way out to contain the address of the transmission
|
||||
interface.
|
||||
This is best assured via a static host route.
|
||||
.El
|
||||
.Pp
|
||||
The common vif commands described below
|
||||
may all be used on tunnels or phyints.
|
||||
.Bl -tag -width indent
|
||||
.It metric Ar m
|
||||
The metric is the "cost" associated with receiving a datagram on the given
|
||||
interface or tunnel; it may be used to influence the choice of routes.
|
||||
The metric defaults to 1.
|
||||
Metrics should be kept as small as possible,
|
||||
because DVMRP cannot route along paths with a sum of metrics greater
|
||||
than 31.
|
||||
.It advert_metric Ar m
|
||||
The advert_metric is the "cost" associated with sending a datagram
|
||||
on the given interface or tunnel; it may be used to influence the choice
|
||||
of routes.
|
||||
The advert_metric defaults to 0.
|
||||
Note that the effective
|
||||
metric of a link is one end's metric plus the other end's advert_metric.
|
||||
.It threshold Ar t
|
||||
The threshold is the minimum IP time-to-live required for a multicast datagram
|
||||
to be forwarded to the given interface or tunnel.
|
||||
It is used to control the
|
||||
scope of multicast datagrams.
|
||||
(The TTL of forwarded packets is only compared
|
||||
to the threshold, it is not decremented by the threshold.
|
||||
Every multicast
|
||||
router decrements the TTL by exactly 1.)
|
||||
The default threshold is 1.
|
||||
.Pp
|
||||
In general, all multicast routers
|
||||
connected to a particular subnet or tunnel should
|
||||
use the same metric and threshold for that subnet or tunnel.
|
||||
.It rate_limit Ar r
|
||||
The rate_limit option allows the network administrator to specify a
|
||||
certain bandwidth in Kbits/second which would be allocated to multicast
|
||||
traffic.
|
||||
It defaults 0 (unlimited).
|
||||
.It boundary Ar "boundary-name|scoped-addr/mask-len"
|
||||
The boundary option allows an interface
|
||||
to be configured as an administrative boundary for the specified
|
||||
scoped address.
|
||||
Packets belonging to this address will not
|
||||
be forwarded on a scoped interface.
|
||||
The boundary option accepts either
|
||||
a name or a boundary spec.
|
||||
This command may be specified several times
|
||||
on an interface in order to describe multiple boundaries.
|
||||
.It passive
|
||||
No packets will be sent on this link or tunnel until we hear from the other
|
||||
end.
|
||||
This is useful for the "server" end of a tunnel that goes over
|
||||
a dial-on-demand link; configure the "server" end as passive and
|
||||
it will not send its periodic probes until it hears one from the other
|
||||
side, so will not keep the link up.
|
||||
If this option is specified on both
|
||||
ends of a tunnel, the tunnel will never come up.
|
||||
.It noflood
|
||||
As described above, but only applicable to this interface/tunnel.
|
||||
.It prune_lifetime Ar secs
|
||||
As described above, but only applicable to this interface/tunnel.
|
||||
.It rexmit_prunes Ar "[on|off]"
|
||||
As described above, but only applicable to this interface/tunnel.
|
||||
Recall that prune retransmission
|
||||
defaults to on for point-to-point links and tunnels, and to off for
|
||||
multi-access links.
|
||||
.It allow_nonpruners
|
||||
By default,
|
||||
.Nm
|
||||
refuses to peer with DVMRP neighbors that
|
||||
do not claim to support pruning.
|
||||
This option allows such peerings
|
||||
on this interface.
|
||||
.It notransit
|
||||
A specialized case of route filtering; no route learned from an interface
|
||||
marked "notransit" will be advertised on another interface marked
|
||||
"notransit".
|
||||
Marking only a single interface "notransit" has no meaning.
|
||||
.It accept|deny Ar "(route/mask-len [exact])+" Op bidir
|
||||
The
|
||||
.Li accept
|
||||
and
|
||||
.Li deny
|
||||
commands allow rudimentary route filtering.
|
||||
The
|
||||
.Li accept
|
||||
command causes
|
||||
.Nm
|
||||
to accept only the listed routes on the configured interface; the
|
||||
.Li deny
|
||||
command causes
|
||||
.Nm
|
||||
to accept all but the listed routes.
|
||||
Only one of
|
||||
.Li accept
|
||||
or
|
||||
.Li deny
|
||||
commands may be used on a given interface.
|
||||
.Pp
|
||||
The list of routes follows the
|
||||
.Li accept
|
||||
or
|
||||
.Li deny
|
||||
keyword.
|
||||
If the keyword
|
||||
.Ar exact
|
||||
follows a route, then only that route is matched; otherwise, that route
|
||||
and any more specific route is matched.
|
||||
For example,
|
||||
.Li deny 0/0
|
||||
denys all routes, while
|
||||
.Li deny 0/0 exact
|
||||
denys only the default route.
|
||||
The default route may also be specified
|
||||
with the
|
||||
.Li default
|
||||
keyword.
|
||||
.Pp
|
||||
The
|
||||
.Ar bidir
|
||||
keyword enables bidirectional route filtering; the filter will be applied
|
||||
to routes on both output and input.
|
||||
Without the
|
||||
.Ar bidir
|
||||
keyword,
|
||||
.Li accept
|
||||
and
|
||||
.Li deny
|
||||
filters are only applied on input.
|
||||
Poison reverse routes are never
|
||||
filtered out.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility will not initiate execution if it has fewer than two enabled vifs,
|
||||
where a vif (virtual interface) is either a physical multicast-capable
|
||||
interface or a tunnel.
|
||||
It will log a warning if all of its vifs are
|
||||
tunnels; such an
|
||||
.Nm
|
||||
configuration would be better replaced by more
|
||||
direct tunnels (i.e., eliminate the middle man).
|
||||
.Sh "EXAMPLE CONFIGURATION"
|
||||
This is an example configuration for a mythical multicast router at a big
|
||||
school.
|
||||
.Pp
|
||||
.Bd -literal
|
||||
#
|
||||
# mrouted.conf example
|
||||
#
|
||||
# Name our boundaries to make it easier
|
||||
name LOCAL 239.255.0.0/16
|
||||
name EE 239.254.0.0/16
|
||||
#
|
||||
# le1 is our gateway to compsci, don't forward our
|
||||
# local groups to them
|
||||
phyint le1 boundary EE
|
||||
#
|
||||
# le2 is our interface on the classroom net, it has four
|
||||
# different length subnets on it.
|
||||
# note that you can use either an ip address or an
|
||||
# interface name
|
||||
phyint 172.16.12.38 boundary EE altnet 172.16.15.0/26
|
||||
altnet 172.16.15.128/26 altnet 172.16.48.0/24
|
||||
#
|
||||
# atm0 is our ATM interface, which doesn't properly
|
||||
# support multicasting.
|
||||
phyint atm0 disable
|
||||
#
|
||||
# This is an internal tunnel to another EE subnet
|
||||
# Remove the default tunnel rate limit, since this
|
||||
# tunnel is over ethernets
|
||||
tunnel 192.168.5.4 192.168.55.101 metric 1 threshold 1
|
||||
rate_limit 0
|
||||
#
|
||||
# This is our tunnel to the outside world.
|
||||
# Careful with those boundaries, Eugene.
|
||||
tunnel 192.168.5.4 10.11.12.13 metric 1 threshold 32
|
||||
boundary LOCAL boundary EE
|
||||
.Ed
|
||||
.Sh SIGNALS
|
||||
The
|
||||
.Nm
|
||||
utility responds to the following signals:
|
||||
.Bl -tag -width indent
|
||||
.It HUP
|
||||
Restarts
|
||||
.Nm .
|
||||
The configuration file is reread every time this signal is evoked.
|
||||
.It INT
|
||||
Terminate execution gracefully (i.e., by sending
|
||||
good-bye messages to all neighboring routers).
|
||||
.It TERM
|
||||
Same as INT.
|
||||
.It USR1
|
||||
Dump the internal routing tables to
|
||||
.Pa /var/tmp/mrouted.dump .
|
||||
.It USR2
|
||||
Dump the internal cache tables to
|
||||
.Pa /var/tmp/mrouted.cache .
|
||||
.It QUIT
|
||||
Dump the internal routing tables to stderr (only if
|
||||
.Nm
|
||||
was invoked with a non-zero debug level).
|
||||
.El
|
||||
.Pp
|
||||
For convenience in sending signals,
|
||||
.Nm
|
||||
writes its pid to
|
||||
.Pa /var/run/mrouted.pid
|
||||
upon startup.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/tmp/mrouted.cache -compact
|
||||
.It Pa /etc/mrouted.conf
|
||||
.It Pa /var/run/mrouted.pid
|
||||
.It Pa /var/tmp/mrouted.dump
|
||||
.It Pa /var/tmp/mrouted.cache
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The routing tables look like this:
|
||||
.Pp
|
||||
.Bd -literal
|
||||
Virtual Interface Table
|
||||
Vif Local-Address Metric Thresh Flags
|
||||
0 36.2.0.8 subnet: 36.2/16 1 1 querier
|
||||
groups: 224.0.2.1
|
||||
224.0.0.4
|
||||
pkts in: 3456
|
||||
pkts out: 2322323
|
||||
|
||||
1 36.11.0.1 subnet: 36.11/16 1 1 querier
|
||||
groups: 224.0.2.1
|
||||
224.0.1.0
|
||||
224.0.0.4
|
||||
pkts in: 345
|
||||
pkts out: 3456
|
||||
|
||||
2 36.2.0.8 tunnel: 36.8.0.77 3 1
|
||||
peers: 36.8.0.77 (3.255)
|
||||
boundaries: 239.0.1/24
|
||||
: 239.1.2/24
|
||||
pkts in: 34545433
|
||||
pkts out: 234342
|
||||
|
||||
3 36.2.0.8 tunnel: 36.6.8.23 3 16
|
||||
|
||||
Multicast Routing Table (1136 entries)
|
||||
Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs
|
||||
36.2 1 45 0 1* 2 3*
|
||||
36.8 36.8.0.77 4 15 2 0* 1* 3*
|
||||
36.11 1 20 1 0* 2 3*
|
||||
.
|
||||
.
|
||||
.
|
||||
.Ed
|
||||
.Pp
|
||||
In this example, there are four vifs connecting to two subnets and two
|
||||
tunnels.
|
||||
The vif 3 tunnel is not in use (no peer address).
|
||||
The vif 0 and
|
||||
vif 1 subnets have some groups present; tunnels never have any groups.
|
||||
This
|
||||
instance of
|
||||
.Nm
|
||||
is the one responsible for sending periodic group
|
||||
membership queries on the vif 0 and vif 1 subnets, as indicated by the
|
||||
"querier" flags.
|
||||
The list of boundaries indicate the scoped addresses on that
|
||||
interface.
|
||||
A count of the no.
|
||||
of incoming and outgoing packets is also
|
||||
shown at each interface.
|
||||
.Pp
|
||||
Associated with each subnet from which a multicast datagram can originate
|
||||
is the address of the previous hop router (unless the subnet is directly-
|
||||
connected), the metric of the path back to the origin, the amount of time
|
||||
since we last received an update for this subnet, the incoming vif for
|
||||
multicasts from that origin, and a list of outgoing vifs.
|
||||
"*" means that
|
||||
the outgoing vif is connected to a leaf of the broadcast tree rooted at the
|
||||
origin, and a multicast datagram from that origin will be forwarded on that
|
||||
outgoing vif only if there are members of the destination group on that leaf.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility also maintains a copy of the kernel forwarding cache table.
|
||||
Entries
|
||||
are created and deleted by
|
||||
.Nm .
|
||||
.Pp
|
||||
The cache tables look like this:
|
||||
.Pp
|
||||
.Bd -literal
|
||||
Multicast Routing Cache Table (147 entries)
|
||||
Origin Mcast-group CTmr Age Ptmr IVif Forwvifs
|
||||
13.2.116/22 224.2.127.255 3m 2m - 0 1
|
||||
>13.2.116.19
|
||||
>13.2.116.196
|
||||
138.96.48/21 224.2.127.255 5m 2m - 0 1
|
||||
>138.96.48.108
|
||||
128.9.160/20 224.2.127.255 3m 2m - 0 1
|
||||
>128.9.160.45
|
||||
198.106.194/24 224.2.135.190 9m 28s 9m 0P
|
||||
>198.106.194.22
|
||||
.Ed
|
||||
.Pp
|
||||
Each entry is characterized by the origin subnet number and mask and the
|
||||
destination multicast group.
|
||||
.Pp
|
||||
The 'CTmr' field indicates the lifetime
|
||||
of the entry.
|
||||
The entry is deleted from the cache table
|
||||
(or refreshed, if traffic is flowing)
|
||||
when the timer decrements to zero.
|
||||
The 'Age' field is the time since
|
||||
this cache entry was originally created.
|
||||
Since cache entries get refreshed
|
||||
if traffic is flowing, routing entries can grow very old.
|
||||
.Pp
|
||||
The 'Ptmr' field is simply a dash if no prune was sent upstream, or the
|
||||
amount of time until the upstream prune will time out.
|
||||
.Pp
|
||||
The 'Ivif' field indicates the
|
||||
incoming vif for multicast packets from that origin.
|
||||
Each router also
|
||||
maintains a record of the number of prunes received from neighboring
|
||||
routers for a particular source and group.
|
||||
If there are no members of
|
||||
a multicast group on any downward link of the multicast tree for a
|
||||
subnet, a prune message is sent to the upstream router.
|
||||
They are
|
||||
indicated by a "P" after the vif number.
|
||||
.Pp
|
||||
The Forwvifs field shows the
|
||||
interfaces along which datagrams belonging to the source-group are
|
||||
forwarded.
|
||||
A "p" indicates that no datagrams are being forwarded along
|
||||
that interface.
|
||||
An unlisted interface is a leaf subnet with no
|
||||
members of the particular group on that subnet.
|
||||
A "b" on an interface
|
||||
indicates that it is a boundary interface, i.e., traffic will not be
|
||||
forwarded on the scoped address on that interface.
|
||||
.Pp
|
||||
An additional line with a ">" as the first character is printed for
|
||||
each source on the subnet.
|
||||
Note that there can be many sources in
|
||||
one subnet.
|
||||
An additional line with a "<" as the first character is printed
|
||||
describing any prunes received from downstream dependent neighbors
|
||||
for this subnet and group.
|
||||
.Sh SEE ALSO
|
||||
.Xr map-mbone 8 ,
|
||||
.Xr mrinfo 8 ,
|
||||
.Xr mtrace 8
|
||||
.Pp
|
||||
DVMRP is described, along with other multicast routing algorithms, in the
|
||||
paper "Multicast Routing in Internetworks and Extended LANs" by
|
||||
.An S. Deering ,
|
||||
in the Proceedings of the ACM SIGCOMM '88 Conference.
|
||||
.Sh AUTHORS
|
||||
.An Steve Deering ,
|
||||
.An Ajit Thyagarajan ,
|
||||
.An Bill Fenner .
|
@ -1,44 +0,0 @@
|
||||
# $FreeBSD$
|
||||
# mrouted.conf,v 3.8 1995/11/29 22:40:47 fenner Rel
|
||||
#
|
||||
# This is the configuration file for "mrouted", an IP multicast router.
|
||||
# mrouted looks for it in "/etc/mrouted.conf".
|
||||
#
|
||||
# Command formats:
|
||||
#
|
||||
# name <boundname> <scoped-addr>/<mask-len>
|
||||
# cache_lifetime 3600 # seconds
|
||||
# pruning on
|
||||
#
|
||||
# phyint <local-addr> [disable] [metric <m>] [threshold <t>] [rate_limit <b>]
|
||||
# [boundary (<boundname>|<scoped-addr>/<mask-len>)]
|
||||
# [altnet (<subnet>/<mask-len>|<subnet>)]
|
||||
# tunnel <local-addr> <remote-addr> [srcrt] [metric <m>]
|
||||
# [threshold <t>] [rate_limit <b>]
|
||||
# [boundary (<boundname>|<scoped-addr>/<mask-len>)]
|
||||
#
|
||||
# NOTE: any phyint commands MUST precede any tunnel commands
|
||||
# NOTE: the mask-len is the no. of leading 1's in the mask
|
||||
# NOTE: rate_limit is in kilobits, and defaults to 500 for tunnels
|
||||
#
|
||||
# Example of named bounary:
|
||||
#name LOCAL 239.255.0.0/16
|
||||
#name EE 239.254.0.0/16 # i.e. the EE dept wants local groups
|
||||
#
|
||||
# Example of use of named boundary
|
||||
#phyint le1 boundary EE # le1 is our interface to comp sci,
|
||||
# # keep them away from our local groups
|
||||
#
|
||||
#
|
||||
# Template tunnel for mcast_install
|
||||
tunnel 128.4.0.77 128.4.0.8 metric 1 threshold 64 rate_limit 500 # <-- REPLACE
|
||||
# boundary LOCAL
|
||||
#
|
||||
# You might want to specify a boundary on your tunnel to the outside world,
|
||||
# as above.
|
||||
#
|
||||
# NOTE: ONLY uncomment the following if you are running mrouted.snmp!
|
||||
#sysName "mymrouter"
|
||||
#sysContact "Me <me@me.com> +x.yyy.zzz-zzzz"
|
||||
#sysVersion "MyOS 4.1.3 and mrouted"
|
||||
#sysLocation "The MBONE"
|
@ -1,19 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
S= ${.CURDIR}/..
|
||||
.PATH: $S
|
||||
|
||||
PROG= mrouted
|
||||
MAN= mrouted.8
|
||||
SRCS= config.c cfparse.y main.c route.c vif.c prune.c callout.c rsrr.c \
|
||||
ipip.c icmp.c vers.c igmp.c inet.c kern.c
|
||||
CLEANFILES+= vers.c
|
||||
|
||||
CFLAGS+= -I$S
|
||||
YFLAGS=
|
||||
|
||||
vers.c: $S/VERSION
|
||||
rm -f vers.c ; \
|
||||
sed 's/.*/char todaysversion[] = "&";/' $S/VERSION > vers.c
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,589 +0,0 @@
|
||||
.\" Copyright (c) 1995 by the University of Southern California
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software and its
|
||||
.\" documentation in source and binary forms for non-commercial purposes
|
||||
.\" and without fee is hereby granted, provided that the above copyright
|
||||
.\" notice appear in all copies and that both the copyright notice and
|
||||
.\" this permission notice appear in supporting documentation, and that
|
||||
.\" any documentation, advertising materials, and other materials related
|
||||
.\" to such distribution and use acknowledge that the software was
|
||||
.\" developed by the University of Southern California, Information
|
||||
.\" Sciences Institute. The name of the University may not be used to
|
||||
.\" endorse or promote products derived from this software without
|
||||
.\" specific prior written permission.
|
||||
.\"
|
||||
.\" THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
|
||||
.\" the suitability of this software for any purpose. THIS SOFTWARE IS
|
||||
.\" PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
.\" INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Other copyrights might apply to parts of this software and are so
|
||||
.\" noted when applicable.
|
||||
.\"
|
||||
.\" This manual page (but not the software) was derived from the
|
||||
.\" manual page for the traceroute program which bears the following
|
||||
.\" copyright notice:
|
||||
.\"
|
||||
.\" Copyright (c) 1988 The Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 8, 1995
|
||||
.Dt MTRACE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mtrace
|
||||
.Nd print multicast path from a source to a receiver
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl e Ar extrahops
|
||||
.Op Fl g Ar gateway
|
||||
.Op Fl i Ar if_addr
|
||||
.Op Fl l
|
||||
.Op Fl M
|
||||
.Op Fl m Ar max_hops
|
||||
.Op Fl n
|
||||
.Op Fl O
|
||||
.Op Fl p
|
||||
.Op Fl P
|
||||
.Op Fl q Ar nqueries
|
||||
.Op Fl r Ar resp_dest
|
||||
.Op Fl s
|
||||
.Op Fl S Ar stat_int
|
||||
.Op Fl t Ar ttl
|
||||
.Op Fl T
|
||||
.Op Fl U
|
||||
.Op Fl v
|
||||
.Op Fl w Ar waittime
|
||||
.Ar source
|
||||
.Op Ar receiver
|
||||
.Op Ar group
|
||||
.Sh DESCRIPTION
|
||||
Assessing problems in the distribution of IP multicast traffic
|
||||
can be difficult.
|
||||
The
|
||||
.Nm
|
||||
utility utilizes a tracing feature implemented in multicast routers that is
|
||||
accessed via an extension to the IGMP protocol.
|
||||
A trace query is
|
||||
passed hop-by-hop along the reverse path from the
|
||||
.Ar receiver
|
||||
to the
|
||||
.Ar source ,
|
||||
collecting hop addresses, packet counts, and routing error conditions
|
||||
along the path, and then the response is returned to the requestor.
|
||||
.Pp
|
||||
The only required parameter is the
|
||||
.Ar source
|
||||
host name or address.
|
||||
The default
|
||||
.Ar receiver
|
||||
is the host running mtrace, and the default
|
||||
.Ar group
|
||||
is 0.0.0.0, which is sufficient if packet loss
|
||||
statistics for a particular multicast group are not needed.
|
||||
These two
|
||||
optional parameters may be specified to test the path to some other
|
||||
receiver in a particular group, subject to some constraints as
|
||||
detailed below.
|
||||
The two parameters can be distinguished because the
|
||||
.Ar receiver
|
||||
is a unicast address and the
|
||||
.Ar group
|
||||
is a multicast address.
|
||||
If the
|
||||
.Fl g
|
||||
flag is specified, the source address defaults to the host running
|
||||
.Nm ,
|
||||
and the receiver defaults to the router being addressed with
|
||||
the
|
||||
.Fl g
|
||||
flag.
|
||||
In this case, there are no required parameters.
|
||||
.Pp
|
||||
NOTE: For Solaris 2.4/2.5, if the multicast interface is not the default
|
||||
interface, the
|
||||
.Fl i
|
||||
option must be used to set the local address.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl e Ar extrahops
|
||||
Try tracing
|
||||
.Ar extrahops
|
||||
hops past a non-responding router.
|
||||
.It Fl g Ar gwy
|
||||
Send the trace query via unicast directly to the multicast router
|
||||
.Ar gwy
|
||||
rather than multicasting the query.
|
||||
This must be the last-hop router on the path from the intended
|
||||
.Ar source
|
||||
to the
|
||||
.Ar receiver .
|
||||
.Pp
|
||||
.Em CAUTION ! !
|
||||
Versions 3.3 and 3.5 of
|
||||
.Nm mrouted
|
||||
will crash if a trace query is received via a
|
||||
unicast packet and
|
||||
.Nm mrouted
|
||||
has no route for the
|
||||
.Ar source
|
||||
address.
|
||||
Therefore, do not use the
|
||||
.Fl g
|
||||
option unless the target
|
||||
.Nm mrouted
|
||||
has been verified to be 3.4 or newer than 3.5.
|
||||
.It Fl i Ar addr
|
||||
Use
|
||||
.Ar addr
|
||||
as the local interface address (on a multi-homed host) for sending the
|
||||
trace query and as the default for the
|
||||
.Ar receiver
|
||||
and the response destination.
|
||||
.It Fl l
|
||||
Loop indefinitely printing packet rate and loss statistics for the
|
||||
multicast path every 10 seconds (see
|
||||
.Fl S Ar stat_int ) .
|
||||
.It Fl M
|
||||
Always request the response using multicast rather than attempting
|
||||
unicast for the last half of the tries.
|
||||
.It Fl m Ar n
|
||||
Set to
|
||||
.Ar n
|
||||
the maximum number of hops that will be traced from the
|
||||
.Ar receiver
|
||||
back toward the
|
||||
.Ar source .
|
||||
The default is 32 hops (infinity for the DVMRP routing protocol).
|
||||
.It Fl n
|
||||
Print hop addresses numerically rather than symbolically and numerically
|
||||
(saves a nameserver address-to-name lookup for each router found on the
|
||||
path).
|
||||
.It Fl q Ar n
|
||||
Set the maximum number of query attempts for any hop to
|
||||
.Ar n .
|
||||
The default is 3.
|
||||
.It Fl O
|
||||
Do not use the Router-Alert IP option on those requests which need it.
|
||||
Some versions of Cisco's IOS cannot handle
|
||||
multicast traceroutes with IP options, so it may be necessary to use the
|
||||
.Fl O
|
||||
flag if the last-hop router is a Cisco.
|
||||
.It Fl p
|
||||
Listen passively for multicast responses from traces initiated by
|
||||
others.
|
||||
This works best when run on a multicast router.
|
||||
.It Fl P
|
||||
Loop indefinitely collecting the path every 10 seconds (see
|
||||
.Fl S Ar stat_int )
|
||||
and printing it when it changes.
|
||||
Do not print any statistics.
|
||||
.It Fl r Ar host
|
||||
Send the trace response to
|
||||
.Ar host
|
||||
rather than to the host on which
|
||||
.Nm
|
||||
is being run, or to a multicast address other than the one registered
|
||||
for this purpose (224.0.1.32).
|
||||
.It Fl s
|
||||
Print a short form output including only the multicast path and not
|
||||
the packet rate and loss statistics.
|
||||
.It Fl S Ar n
|
||||
Change the interval between statistics gathering traces to
|
||||
.Ar n
|
||||
seconds (default 10 seconds).
|
||||
.It Fl t Ar ttl
|
||||
Set the
|
||||
.Ar ttl
|
||||
(time-to-live, or number of hops) for multicast trace queries and
|
||||
responses.
|
||||
The default is 127, except for local queries to the "all
|
||||
routers" multicast group which use ttl 1.
|
||||
.It Fl T
|
||||
"Tunnel statistics" mode; show loss rates for overall traffic.
|
||||
These statistics can be extremely misleading.
|
||||
.It Fl U
|
||||
Always request the response using unicast rather than attempting
|
||||
multicast first.
|
||||
.It Fl v
|
||||
Verbose mode; show hop times on the initial trace and statistics display.
|
||||
Also show the route that was used to forward the initial trace.
|
||||
.It Fl w Ar n
|
||||
Set the time to wait for a trace response to
|
||||
.Ar n
|
||||
seconds (default 3 seconds).
|
||||
.El
|
||||
.Sh USAGE
|
||||
.Ss "How It Works"
|
||||
The technique used by the
|
||||
.Nm traceroute
|
||||
utility to trace unicast network paths will not work for IP multicast
|
||||
because ICMP responses are specifically forbidden for multicast traffic.
|
||||
Instead, a tracing feature has been built into the multicast routers.
|
||||
This technique has the advantage that additional information about
|
||||
packet rates and losses can be accumulated while the number of packets
|
||||
sent is minimized.
|
||||
.Pp
|
||||
Since multicast uses
|
||||
reverse path forwarding, the trace is run backwards from the
|
||||
.Ar receiver
|
||||
to the
|
||||
.Ar source .
|
||||
A trace query packet is sent to the last
|
||||
hop multicast router (the leaf router for the desired
|
||||
.Ar receiver
|
||||
address).
|
||||
The last hop router builds a trace response packet, fills in
|
||||
a report for its hop, and forwards the trace packet using unicast to
|
||||
the router it believes is the previous hop for packets originating
|
||||
from the specified
|
||||
.Ar source .
|
||||
Each router along the path adds its report and forwards the packet.
|
||||
When the trace response packet reaches the first hop router (the router
|
||||
that is directly connected to the source's net), that router sends the
|
||||
completed response to the response destination address specified in
|
||||
the trace query.
|
||||
.Pp
|
||||
If some multicast router along the path does not implement the
|
||||
multicast traceroute feature or if there is some outage, then no
|
||||
response will be returned.
|
||||
To solve this problem, the trace query
|
||||
includes a maximum hop count field to limit the number of hops traced
|
||||
before the response is returned.
|
||||
That allows a partial path to be
|
||||
traced.
|
||||
.Pp
|
||||
The reports inserted by each router contain not only the address of
|
||||
the hop, but also the ttl required to forward and some flags to indicate
|
||||
routing errors, plus counts of the total number of packets on the
|
||||
incoming and outgoing interfaces and those forwarded for the specified
|
||||
.Ar group .
|
||||
Taking differences in these counts for two traces separated in time
|
||||
and comparing the output packet counts from one hop with the input
|
||||
packet counts of the next hop allows the calculation of packet rate
|
||||
and packet loss statistics for each hop to isolate congestion
|
||||
problems.
|
||||
.Ss Finding the Last-Hop Router
|
||||
The trace query must be sent to the multicast router which is the
|
||||
last hop on the path from the
|
||||
.Ar source
|
||||
to the
|
||||
.Ar receiver .
|
||||
If the receiver is on the local subnet (as determined using the subnet
|
||||
mask), then the default method is to multicast the trace query to
|
||||
all-routers.mcast.net (224.0.0.2) with a ttl of 1.
|
||||
Otherwise, the
|
||||
trace query is multicast to the
|
||||
.Ar group
|
||||
address since the last hop router will be a member of that group if
|
||||
the receiver is.
|
||||
Therefore it is necessary to specify a group that
|
||||
the intended receiver has joined.
|
||||
This multicast is sent with a
|
||||
default ttl of 127, which may not be sufficient for all cases (changed
|
||||
with the
|
||||
.Fl t
|
||||
option).
|
||||
If the last hop router is known, it may also be addressed directly
|
||||
using the
|
||||
.Fl g
|
||||
option).
|
||||
Alternatively, if it is desired to trace a group that the
|
||||
receiver has not joined, but it is known that the last-hop router is a
|
||||
member of another group, the
|
||||
.Fl g
|
||||
option may also be used to specify a different multicast address for the
|
||||
trace query.
|
||||
.Pp
|
||||
When tracing from a multihomed host or router, the default receiver
|
||||
address may not be the desired interface for the path from the source.
|
||||
In that case, the desired interface should be specified explicitly as
|
||||
the
|
||||
.Ar receiver .
|
||||
.Ss Directing the Response
|
||||
By default,
|
||||
.Nm
|
||||
first attempts to trace the full reverse path, unless the number of
|
||||
hops to trace is explicitly set with the
|
||||
.Fl m
|
||||
option.
|
||||
If there is no response within a 3 second timeout interval
|
||||
(changed with the
|
||||
.Fl w
|
||||
option), a "*" is printed and the probing switches to hop-by-hop mode.
|
||||
Trace queries are issued starting with a maximum hop count of one and
|
||||
increasing by one until the full path is traced or no response is
|
||||
received.
|
||||
At each hop, multiple probes are sent (default is three,
|
||||
changed with
|
||||
.Fl q
|
||||
option).
|
||||
The first half of the attempts (default is two) are made with
|
||||
the reply address set to standard multicast address, mtrace.mcast.net
|
||||
(224.0.1.32) with the ttl set to 32 more than what is needed to pass the
|
||||
thresholds seen so far along the path to the receiver.
|
||||
For each
|
||||
additional attempt, the ttl is increased by another 32 each time up to
|
||||
a maximum of 192.
|
||||
Since the desired router may not be able to send a
|
||||
multicast reply, the remainder of the attempts request that the
|
||||
response be sent via unicast to the host running
|
||||
.Nm .
|
||||
Alternatively, the multicast ttl may be set explicitly with the
|
||||
.Fl t
|
||||
option, the initial multicast attempts can be forced to use unicast
|
||||
instead with the
|
||||
.Fl U
|
||||
option, the final unicast attempts can be forced to use multicast
|
||||
instead with the
|
||||
.Fl M
|
||||
option, or if you specify
|
||||
.Fl UM ,
|
||||
.Nm
|
||||
will first attempt using unicast and then multicast.
|
||||
For each attempt,
|
||||
if no response is received within the timeout, a "*" is printed.
|
||||
After
|
||||
the specified number of attempts have failed,
|
||||
.Nm
|
||||
will try to query the next hop router with a DVMRP_ASK_NEIGHBORS2
|
||||
request (as used by the
|
||||
.Nm mrinfo
|
||||
program) to see what kind of router it is.
|
||||
The
|
||||
.Nm
|
||||
utility will try to query three (changed with the
|
||||
.Fl e
|
||||
option) hops past a non-responding router, in the hopes that even
|
||||
though it is not capable of sending a response, it might be capable of
|
||||
forwarding the request on.
|
||||
.Sh EXAMPLES
|
||||
The output of
|
||||
.Nm
|
||||
is in two sections.
|
||||
The first section is a short listing of the hops
|
||||
in the order they are queried, that is, in the reverse of the order
|
||||
from the
|
||||
.Ar source
|
||||
to the
|
||||
.Ar receiver .
|
||||
For each hop, a line is printed showing the hop number (counted
|
||||
negatively to indicate that this is the reverse path); the multicast
|
||||
routing protocol (DVMRP, MOSPF, PIM, etc.); the threshold required to
|
||||
forward data (to the previous hop in the listing as indicated by the
|
||||
up-arrow character); and the cumulative delay for the query to reach
|
||||
that hop (valid only if the clocks are synchronized).
|
||||
This first
|
||||
section ends with a line showing the round-trip time which measures
|
||||
the interval from when the query is issued until the response is
|
||||
received, both derived from the local system clock, and the total
|
||||
ttl required for a packet to travel along this path.
|
||||
A sample use and
|
||||
output might be:
|
||||
.Pp
|
||||
.Bd -literal
|
||||
oak.isi.edu 80# mtrace -l caraway.lcs.mit.edu 224.2.0.3
|
||||
Mtrace from 18.26.0.170 to 128.9.160.100 via group 224.2.0.3
|
||||
Querying full reverse path...
|
||||
0 oak.isi.edu (128.9.160.100)
|
||||
-1 cub.isi.edu (128.9.160.153) DVMRP thresh^ 1 3 ms
|
||||
-2 la.dart.net (140.173.128.1) DVMRP thresh^ 1 14 ms
|
||||
-3 dc.dart.net (140.173.64.1) DVMRP thresh^ 1 50 ms
|
||||
-4 bbn.dart.net (140.173.32.1) DVMRP thresh^ 1 63 ms
|
||||
-5 mit.dart.net (140.173.48.2) DVMRP thresh^ 1 71 ms
|
||||
-6 caraway.lcs.mit.edu (18.26.0.170)
|
||||
Round trip time 124 ms; total ttl of 6 required.
|
||||
.Ed
|
||||
.Pp
|
||||
If a hop reports that it is using the default route to forward packets,
|
||||
the word
|
||||
.Em [default]
|
||||
is printed after that hop.
|
||||
If the
|
||||
.Fl v
|
||||
flag is supplied, the route being used to forward packets is printed
|
||||
in the form
|
||||
.Em [18.26.0/24] .
|
||||
.Pp
|
||||
The second section provides a pictorial view of the path in the
|
||||
forward direction with data flow indicated by arrows pointing downward
|
||||
and the query path indicated by arrows pointing upward.
|
||||
For each hop,
|
||||
both the entry and exit addresses of the router are shown if
|
||||
different, along with the initial ttl required on the packet in order
|
||||
to be forwarded at this hop and the propagation delay across the hop
|
||||
assuming that the routers at both ends have synchronized clocks.
|
||||
The right half of this section is composed of two sets of statistics.
|
||||
The first column contains the average packet rate for all traffic at
|
||||
each hop.
|
||||
The remaining columns are the
|
||||
number of packets lost, the number of packets sent, the percentage
|
||||
lost, and the average packet rate at each hop.
|
||||
These statistics are
|
||||
calculated from differences between traces and from hop to hop as
|
||||
explained above.
|
||||
The first group shows the statistics for all traffic
|
||||
flowing out the interface at one hop and in the interface at the next
|
||||
hop.
|
||||
The second group shows the statistics only for traffic forwarded
|
||||
from the specified
|
||||
.Ar source
|
||||
to the specified
|
||||
.Ar group .
|
||||
The first group of statistics may be expanded to include loss rates
|
||||
using the
|
||||
.Fl T
|
||||
option.
|
||||
However, these numbers can be extremely misleading and require
|
||||
detailed knowledge of the routers involved to be interpreted properly.
|
||||
.Pp
|
||||
These statistics are shown on one or two lines for each hop.
|
||||
Without
|
||||
any options, this second section of the output is printed only once,
|
||||
approximately 10 seconds after the initial trace.
|
||||
One line is shown
|
||||
for each hop showing the statistics over that 10-second period.
|
||||
If
|
||||
the
|
||||
.Fl l
|
||||
option is given, the second section is repeated every 10 seconds and
|
||||
two lines are shown for each hop.
|
||||
The first line shows the statistics
|
||||
for the last 10 seconds, and the second line shows the cumulative
|
||||
statistics over the period since the initial trace, which is 101
|
||||
seconds in the example below.
|
||||
The second section of the output is
|
||||
omitted if the
|
||||
.Fl s
|
||||
option is set or if no multicast group is specified.
|
||||
.Pp
|
||||
.Bd -literal
|
||||
Waiting to accumulate statistics... Results after 101 seconds:
|
||||
|
||||
Source Response Dest Overall Packet Statistics For Traffic From
|
||||
18.26.0.170 128.9.160.100 Packet 18.26.0.170 To 224.2.0.3
|
||||
| __/ rtt 125 ms Rate Lost/Sent = Pct Rate
|
||||
v / hop 65 ms ------- ---------------------
|
||||
18.26.0.144
|
||||
140.173.48.2 mit.dart.net
|
||||
| ^ ttl 1 0 pps 0/2 = --% 0 pps
|
||||
v | hop 8 ms 0 pps 0/18 = 0% 0 pps
|
||||
140.173.48.1
|
||||
140.173.32.1 bbn.dart.net
|
||||
| ^ ttl 2 0 pps 0/2 = --% 0 pps
|
||||
v | hop 12 ms 0 pps 0/18 = 0% 0 pps
|
||||
140.173.32.2
|
||||
140.173.64.1 dc.dart.net
|
||||
| ^ ttl 3 27 pps 0/2 = --% 0 pps
|
||||
v | hop 34 ms 26 pps 0/18 = 0% 0 pps
|
||||
140.173.64.2
|
||||
140.173.128.1 la.dart.net
|
||||
| ^ ttl 4 83 pps 0/2 = --% 0 pps
|
||||
v | hop 11 ms 79 pps 0/18 = 0% 0 pps
|
||||
140.173.128.2
|
||||
128.9.160.153 cub.isi.edu
|
||||
| \\__ ttl 5 83 pps ?/2 0 pps
|
||||
v \\ hop -8 ms 79 pps ?/18 0 pps
|
||||
128.9.160.100 128.9.160.100
|
||||
Receiver Query Source
|
||||
.Ed
|
||||
.Pp
|
||||
Because the packet counts may be changing as the trace query is
|
||||
propagating, there may be small errors (off by 1 or 2) in these
|
||||
statistics.
|
||||
However, those errors should not accumulate, so the
|
||||
cumulative statistics line should increase in accuracy as a new trace
|
||||
is run every 10 seconds.
|
||||
There are two sources of larger errors, both
|
||||
of which show up as negative losses:
|
||||
.Pp
|
||||
If the input to a node is from a multi-access network with more than
|
||||
one other node attached, then the input count will be (close to) the
|
||||
sum of the output counts from all the attached nodes, but the output
|
||||
count from the previous hop on the traced path will be only part of
|
||||
that.
|
||||
Hence the output count minus the input count will be negative.
|
||||
.Pp
|
||||
In release 3.3 of the DVMRP multicast forwarding software for SunOS
|
||||
and other systems, a multicast packet generated on a router will be
|
||||
counted as having come in an interface even though it did not.
|
||||
This
|
||||
creates the negative loss that can be seen in the example above.
|
||||
.Pp
|
||||
Note that these negative losses may mask positive losses.
|
||||
.Pp
|
||||
In the example, there is also one negative hop time.
|
||||
This simply
|
||||
indicates a lack of synchronization between the system clocks across
|
||||
that hop.
|
||||
This example also illustrates how the percentage loss is
|
||||
shown as two dashes when the number of packets sent is less than 10
|
||||
because the percentage would not be statistically valid.
|
||||
.Pp
|
||||
A second example shows a trace to a receiver that is not local; the
|
||||
query is sent to the last-hop router with the
|
||||
.Fl g
|
||||
option.
|
||||
In this example, the trace of the full reverse path resulted
|
||||
in no response because there was a node running an old version of
|
||||
.Nm mrouted
|
||||
that did not implement the multicast traceroute function, so
|
||||
.Nm
|
||||
switched to hop-by-hop mode.
|
||||
The
|
||||
.Dq Output pruned
|
||||
error code
|
||||
indicates that traffic for group 224.2.143.24 would not be forwarded.
|
||||
.Pp
|
||||
.Bd -literal
|
||||
oak.isi.edu 108# mtrace -g 140.173.48.2 204.62.246.73 \\
|
||||
butter.lcs.mit.edu 224.2.143.24
|
||||
Mtrace from 204.62.246.73 to 18.26.0.151 via group 224.2.143.24
|
||||
Querying full reverse path... * switching to hop-by-hop:
|
||||
0 butter.lcs.mit.edu (18.26.0.151)
|
||||
-1 jam.lcs.mit.edu (18.26.0.144) DVMRP thresh^ 1 33 ms Output pruned
|
||||
-2 bbn.dart.net (140.173.48.1) DVMRP thresh^ 1 36 ms
|
||||
-3 dc.dart.net (140.173.32.2) DVMRP thresh^ 1 44 ms
|
||||
-4 darpa.dart.net (140.173.240.2) DVMRP thresh^ 16 47 ms
|
||||
-5 * * * noc.hpc.org (192.187.8.2) [mrouted 2.2] didn't respond
|
||||
Round trip time 95 ms
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr map-mbone 8 ,
|
||||
.Xr mrinfo 8 ,
|
||||
.Xr mrouted 8 ,
|
||||
.Xr traceroute 8
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
Implemented by
|
||||
.An Steve Casner
|
||||
based on an initial prototype written by
|
||||
.An Ajit Thyagarajan .
|
||||
The multicast traceroute mechanism was designed by
|
||||
.An Van Jacobson
|
||||
with help from
|
||||
.An Steve Casner ,
|
||||
.An Steve Deering ,
|
||||
.An Dino Farinacci ,
|
||||
and
|
||||
.An Deb Agrawal ;
|
||||
it was implemented in
|
||||
.Nm mrouted
|
||||
by
|
||||
.An Ajit Thyagarajan
|
||||
and
|
||||
.An Bill Fenner .
|
||||
The option syntax and the output format of
|
||||
.Nm
|
||||
are modeled after the unicast
|
||||
.Nm traceroute
|
||||
program written by
|
||||
.An Van Jacobson .
|
||||
.Sh BUGS
|
||||
Statistics collection in passive mode does not always produce the same output
|
||||
as when actively collecting data.
|
File diff suppressed because it is too large
Load Diff
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Multicast traceroute related definitions
|
||||
*
|
||||
* mtrace.h,v 5.2 1998/12/04 04:48:21 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
* NetBSD renamed the mtrace packet types.
|
||||
*/
|
||||
#if !defined(IGMP_MTRACE_RESP) && defined(IGMP_MTRACE_REPLY)
|
||||
#define IGMP_MTRACE_RESP IGMP_MTRACE_REPLY
|
||||
#define IGMP_MTRACE IGMP_MTRACE_QUERY
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The packet format for a traceroute request.
|
||||
*/
|
||||
struct tr_query {
|
||||
u_int32 tr_src; /* traceroute source */
|
||||
u_int32 tr_dst; /* traceroute destination */
|
||||
u_int32 tr_raddr; /* traceroute response address */
|
||||
u_int32 tr_rttlqid; /* response ttl and qid */
|
||||
};
|
||||
|
||||
#define TR_SETTTL(x, ttl) (x = (x & 0x00ffffff) | ((ttl) << 24))
|
||||
#define TR_GETTTL(x) (((x) >> 24) & 0xff)
|
||||
#define TR_SETQID(x, qid) (x = (x & 0xff000000) | ((qid) & 0x00ffffff))
|
||||
#define TR_GETQID(x) ((x) & 0x00ffffff)
|
||||
|
||||
/*
|
||||
* Traceroute response format. A traceroute response has a tr_query at the
|
||||
* beginning, followed by one tr_resp for each hop taken.
|
||||
*/
|
||||
struct tr_resp {
|
||||
u_int32 tr_qarr; /* query arrival time */
|
||||
u_int32 tr_inaddr; /* incoming interface address */
|
||||
u_int32 tr_outaddr; /* outgoing interface address */
|
||||
u_int32 tr_rmtaddr; /* parent address in source tree */
|
||||
u_int32 tr_vifin; /* input packet count on interface */
|
||||
u_int32 tr_vifout; /* output packet count on interface */
|
||||
u_int32 tr_pktcnt; /* total incoming packets for src-grp */
|
||||
u_char tr_rproto; /* routing protocol deployed on router */
|
||||
u_char tr_fttl; /* ttl required to forward on outvif */
|
||||
u_char tr_smask; /* subnet mask for src addr */
|
||||
u_char tr_rflags; /* forwarding error codes */
|
||||
};
|
||||
|
||||
/* defs within mtrace */
|
||||
#define QLEN sizeof(struct tr_query)
|
||||
#define RLEN sizeof(struct tr_resp)
|
||||
|
||||
/* fields for tr_rflags (forwarding error codes) */
|
||||
#define TR_NO_ERR 0
|
||||
#define TR_WRONG_IF 1
|
||||
#define TR_PRUNED 2
|
||||
#define TR_OPRUNED 3
|
||||
#define TR_SCOPED 4
|
||||
#define TR_NO_RTE 5
|
||||
#define TR_NO_FWD 7
|
||||
#define TR_HIT_RP 8
|
||||
#define TR_RPF_IF 9
|
||||
#define TR_NO_MULTI 10
|
||||
#define TR_NO_SPACE 0x81
|
||||
#define TR_OLD_ROUTER 0x82
|
||||
#define TR_ADMIN_PROHIB 0x83
|
||||
|
||||
/* fields for tr_rproto (routing protocol) */
|
||||
#define PROTO_DVMRP 1
|
||||
#define PROTO_MOSPF 2
|
||||
#define PROTO_PIM 3
|
||||
#define PROTO_CBT 4
|
||||
#define PROTO_PIM_SPECIAL 5
|
||||
#define PROTO_PIM_STATIC 6
|
||||
#define PROTO_DVMRP_STATIC 7
|
||||
#define PROTO_PIM_BGP4PLUS 8
|
||||
#define PROTO_CBT_SPECIAL 9
|
||||
#define PROTO_CBT_STATIC 10
|
||||
#define PROTO_PIM_ASSERT 11
|
||||
|
||||
#define VAL_TO_MASK(x, i) { \
|
||||
x = htonl(~((1 << (32 - (i))) - 1)); \
|
||||
};
|
||||
|
||||
#if defined(__STDC__) || defined(__GNUC__)
|
||||
#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
|
||||
#else
|
||||
#define JAN_1970 2208988800L /* 1970 - 1900 in seconds */
|
||||
#define const /**/
|
||||
#endif
|
@ -1,13 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
S= ${.CURDIR}/..
|
||||
.PATH: $S
|
||||
|
||||
PROG= mtrace
|
||||
MAN= mtrace.8
|
||||
BINOWN= root
|
||||
BINMODE= 4555
|
||||
|
||||
CFLAGS+= -I$S
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
* pathnames.h,v 3.8 1995/11/29 22:36:57 fenner Rel
|
||||
*/
|
||||
|
||||
#define _PATH_MROUTED_CONF "/etc/mrouted.conf"
|
||||
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#define _PATH_MROUTED_PID "/var/run/mrouted.pid"
|
||||
#define _PATH_MROUTED_GENID "/var/run/mrouted.genid"
|
||||
#define _PATH_MROUTED_DUMP "/var/tmp/mrouted.dump"
|
||||
#define _PATH_MROUTED_CACHE "/var/tmp/mrouted.cache"
|
||||
#else
|
||||
#define _PATH_MROUTED_PID "/etc/mrouted.pid"
|
||||
#define _PATH_MROUTED_GENID "/etc/mrouted.genid"
|
||||
#define _PATH_MROUTED_DUMP "/usr/tmp/mrouted.dump"
|
||||
#define _PATH_MROUTED_CACHE "/usr/tmp/mrouted.cache"
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
* prune.h,v 3.8.4.5 1998/02/27 22:45:43 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
* Group table
|
||||
*
|
||||
* Each group entry is a member of two doubly-linked lists:
|
||||
*
|
||||
* a) A list hanging off of the routing table entry for this source (rt_groups)
|
||||
* sorted by group address under the routing entry (gt_next, gt_prev)
|
||||
* b) An independent list pointed to by kernel_table, which is a list of
|
||||
* active source,group's (gt_gnext, gt_gprev).
|
||||
*
|
||||
*/
|
||||
struct gtable {
|
||||
struct gtable *gt_next; /* pointer to the next entry */
|
||||
struct gtable *gt_prev; /* back pointer for linked list */
|
||||
struct gtable *gt_gnext; /* fwd pointer for group list */
|
||||
struct gtable *gt_gprev; /* rev pointer for group list */
|
||||
u_int32 gt_mcastgrp; /* multicast group associated */
|
||||
vifbitmap_t gt_scope; /* scoped interfaces */
|
||||
u_char gt_ttls[MAXVIFS]; /* ttl vector for forwarding */
|
||||
vifbitmap_t gt_grpmems; /* forw. vifs for src, grp */
|
||||
int gt_prsent_timer; /* prune timer for this group */
|
||||
int gt_timer; /* timer for this group entry */
|
||||
time_t gt_ctime; /* time of entry creation */
|
||||
u_char gt_grftsnt; /* graft sent/retransmit timer */
|
||||
nbrbitmap_t gt_prunes; /* bitmap of neighbors who pruned */
|
||||
struct stable *gt_srctbl; /* source table */
|
||||
struct ptable *gt_pruntbl; /* prune table */
|
||||
struct rtentry *gt_route; /* parent route */
|
||||
int gt_rexmit_timer; /* timer for prune retransmission */
|
||||
int gt_prune_rexmit; /* time til prune retransmission */
|
||||
#ifdef RSRR
|
||||
struct rsrr_cache *gt_rsrr_cache; /* RSRR cache */
|
||||
#endif /* RSRR */
|
||||
};
|
||||
|
||||
/*
|
||||
* Source table
|
||||
*
|
||||
* When source-based prunes exist, there will be a struct ptable here as well.
|
||||
*/
|
||||
struct stable
|
||||
{
|
||||
struct stable *st_next; /* pointer to the next entry */
|
||||
u_int32 st_origin; /* host origin of multicasts */
|
||||
u_long st_pktcnt; /* packet count for src-grp entry */
|
||||
u_long st_savpkt; /* saved pkt cnt when no krnl entry */
|
||||
time_t st_ctime; /* kernel entry creation time */
|
||||
};
|
||||
|
||||
/*
|
||||
* structure to store incoming prunes. Can hang off of either group or source.
|
||||
*/
|
||||
struct ptable
|
||||
{
|
||||
struct ptable *pt_next; /* pointer to the next entry */
|
||||
u_int32 pt_router; /* router that sent this prune */
|
||||
vifi_t pt_vifi; /* vif prune received on */
|
||||
int pt_index; /* neighbor index of router */
|
||||
int pt_timer; /* timer for prune */
|
||||
};
|
||||
|
||||
#define MIN_PRUNE_LIFE TIMER_INTERVAL /* min prune lifetime to bother with */
|
||||
|
||||
/*
|
||||
* The packet format for a traceroute request.
|
||||
*/
|
||||
struct tr_query {
|
||||
u_int32 tr_src; /* traceroute source */
|
||||
u_int32 tr_dst; /* traceroute destination */
|
||||
u_int32 tr_raddr; /* traceroute response address */
|
||||
#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
struct {
|
||||
u_int qid : 24; /* traceroute query id */
|
||||
u_int ttl : 8; /* traceroute response ttl */
|
||||
} q;
|
||||
#else
|
||||
struct {
|
||||
u_int ttl : 8; /* traceroute response ttl */
|
||||
u_int qid : 24; /* traceroute query id */
|
||||
} q;
|
||||
#endif /* BYTE_ORDER */
|
||||
};
|
||||
|
||||
#define tr_rttl q.ttl
|
||||
#define tr_qid q.qid
|
||||
|
||||
/*
|
||||
* Traceroute response format. A traceroute response has a tr_query at the
|
||||
* beginning, followed by one tr_resp for each hop taken.
|
||||
*/
|
||||
struct tr_resp {
|
||||
u_int32 tr_qarr; /* query arrival time */
|
||||
u_int32 tr_inaddr; /* incoming interface address */
|
||||
u_int32 tr_outaddr; /* outgoing interface address */
|
||||
u_int32 tr_rmtaddr; /* parent address in source tree */
|
||||
u_int32 tr_vifin; /* input packet count on interface */
|
||||
u_int32 tr_vifout; /* output packet count on interface */
|
||||
u_int32 tr_pktcnt; /* total incoming packets for src-grp */
|
||||
u_char tr_rproto; /* routing protocol deployed on router */
|
||||
u_char tr_fttl; /* ttl required to forward on outvif */
|
||||
u_char tr_smask; /* subnet mask for src addr */
|
||||
u_char tr_rflags; /* forwarding error codes */
|
||||
};
|
||||
|
||||
/* defs within mtrace */
|
||||
#define QUERY 1
|
||||
#define RESP 2
|
||||
#define QLEN sizeof(struct tr_query)
|
||||
#define RLEN sizeof(struct tr_resp)
|
||||
|
||||
/* fields for tr_rflags (forwarding error codes) */
|
||||
#define TR_NO_ERR 0
|
||||
#define TR_WRONG_IF 1
|
||||
#define TR_PRUNED 2
|
||||
#define TR_OPRUNED 3
|
||||
#define TR_SCOPED 4
|
||||
#define TR_NO_RTE 5
|
||||
#define TR_NO_FWD 7
|
||||
#define TR_NO_SPACE 0x81
|
||||
#define TR_OLD_ROUTER 0x82
|
||||
|
||||
/* fields for tr_rproto (routing protocol) */
|
||||
#define PROTO_DVMRP 1
|
||||
#define PROTO_MOSPF 2
|
||||
#define PROTO_PIM 3
|
||||
#define PROTO_CBT 4
|
||||
|
||||
#define MASK_TO_VAL(x, i) { \
|
||||
u_int32 _x = ntohl(x); \
|
||||
(i) = 1; \
|
||||
while ((_x) <<= 1) \
|
||||
(i)++; \
|
||||
};
|
||||
|
||||
#define VAL_TO_MASK(x, i) { \
|
||||
x = i ? htonl(~((1 << (32 - (i))) - 1)) : 0; \
|
||||
};
|
||||
|
||||
#define NBR_VERS(n) (((n)->al_pv << 8) + (n)->al_mv)
|
File diff suppressed because it is too large
Load Diff
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
* route.h,v 3.8.4.6 1997/07/01 23:02:35 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routing Table Entry, one per subnet from which a multicast could originate.
|
||||
* (Note: all addresses, subnet numbers and masks are kept in NETWORK order.)
|
||||
*
|
||||
* The Routing Table is stored as a doubly-linked list of these structures,
|
||||
* ordered by decreasing value of rt_originmask and, secondarily, by
|
||||
* decreasing value of rt_origin within each rt_originmask value.
|
||||
* This data structure is efficient for generating route reports, whether
|
||||
* full or partial, for processing received full reports, for clearing the
|
||||
* CHANGED flags, and for periodically advancing the timers in all routes.
|
||||
* It is not so efficient for updating a small number of routes in response
|
||||
* to a partial report. In a stable topology, the latter are rare; if they
|
||||
* turn out to be costing a lot, we can add an auxiliary hash table for
|
||||
* faster access to arbitrary route entries.
|
||||
*/
|
||||
struct rtentry {
|
||||
struct rtentry *rt_next; /* link to next entry MUST BE FIRST */
|
||||
u_int32 rt_origin; /* subnet origin of multicasts */
|
||||
u_int32 rt_originmask; /* subnet mask for origin */
|
||||
short rt_originwidth; /* # bytes of origin subnet number */
|
||||
u_char rt_metric; /* cost of route back to origin */
|
||||
u_char rt_flags; /* RTF_ flags defined below */
|
||||
u_int32 rt_gateway; /* first-hop gateway back to origin */
|
||||
vifi_t rt_parent; /* incoming vif (ie towards origin) */
|
||||
vifbitmap_t rt_children; /* outgoing children vifs */
|
||||
u_int32 *rt_dominants; /* per vif dominant gateways */
|
||||
nbrbitmap_t rt_subordinates; /* bitmap of subordinate gateways */
|
||||
nbrbitmap_t rt_subordadv; /* recently advertised subordinates */
|
||||
u_int rt_timer; /* for timing out the route entry */
|
||||
struct rtentry *rt_prev; /* link to previous entry */
|
||||
struct gtable *rt_groups; /* link to active groups */
|
||||
};
|
||||
|
||||
#define RTF_CHANGED 0x01 /* route changed but not reported */
|
||||
#define RTF_HOLDDOWN 0x04 /* this route is in holddown */
|
||||
|
||||
#define ALL_ROUTES 0 /* possible arguments to report() */
|
||||
#define CHANGED_ROUTES 1 /* and report_to_all_neighbors() */
|
||||
|
||||
#define RT_FMT(r, s) inet_fmts((r)->rt_origin, (r)->rt_originmask, s)
|
@ -1,485 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation in source and binary forms for non-commercial purposes
|
||||
* and without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both the copyright notice and
|
||||
* this permission notice appear in supporting documentation. and that
|
||||
* any documentation, advertising materials, and other materials related
|
||||
* to such distribution and use acknowledge that the software was
|
||||
* developed by the University of Southern California, Information
|
||||
* Sciences Institute. The name of the University may not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
|
||||
* the suitability of this software for any purpose. THIS SOFTWARE IS
|
||||
* PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Other copyrights might apply to parts of this software and are so
|
||||
* noted when applicable.
|
||||
*/
|
||||
|
||||
/* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
|
||||
* April 1995.
|
||||
*/
|
||||
|
||||
/* May 1995 -- Added support for Route Change Notification */
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef RSRR
|
||||
|
||||
#include "defs.h"
|
||||
#include <sys/param.h>
|
||||
#ifdef HAVE_SA_LEN
|
||||
#include <stddef.h> /* for offsetof */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
*/
|
||||
int rsrr_socket; /* interface to reservation protocol */
|
||||
|
||||
/*
|
||||
* Global RSRR variables.
|
||||
*/
|
||||
char rsrr_recv_buf[RSRR_MAX_LEN]; /* RSRR receive buffer */
|
||||
char rsrr_send_buf[RSRR_MAX_LEN]; /* RSRR send buffer */
|
||||
|
||||
struct sockaddr_un client_addr;
|
||||
int client_length = sizeof(client_addr);
|
||||
|
||||
|
||||
/*
|
||||
* Procedure definitions needed internally.
|
||||
*/
|
||||
static void rsrr_accept __P((int recvlen));
|
||||
static void rsrr_accept_iq __P((void));
|
||||
static int rsrr_accept_rq __P((struct rsrr_rq *route_query, int flags,
|
||||
struct gtable *gt_notify));
|
||||
static void rsrr_read __P((int, fd_set *));
|
||||
static int rsrr_send __P((int sendlen));
|
||||
static void rsrr_cache __P((struct gtable *gt,
|
||||
struct rsrr_rq *route_query));
|
||||
|
||||
/* Initialize RSRR socket */
|
||||
void
|
||||
rsrr_init()
|
||||
{
|
||||
int servlen;
|
||||
struct sockaddr_un serv_addr;
|
||||
|
||||
if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
|
||||
log(LOG_ERR, errno, "Can't create RSRR socket");
|
||||
|
||||
unlink(RSRR_SERV_PATH);
|
||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
serv_addr.sun_family = AF_UNIX;
|
||||
strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
|
||||
#ifdef HAVE_SA_LEN
|
||||
servlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
strlen(serv_addr.sun_path);
|
||||
serv_addr.sun_len = servlen;
|
||||
#else
|
||||
servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
|
||||
#endif
|
||||
|
||||
if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
|
||||
log(LOG_ERR, errno, "Can't bind RSRR socket");
|
||||
|
||||
if (register_input_handler(rsrr_socket, rsrr_read) < 0)
|
||||
log(LOG_WARNING, 0, "Couldn't register RSRR as an input handler");
|
||||
}
|
||||
|
||||
/* Read a message from the RSRR socket */
|
||||
static void
|
||||
rsrr_read(f, rfd)
|
||||
int f;
|
||||
fd_set *rfd;
|
||||
{
|
||||
register int rsrr_recvlen;
|
||||
|
||||
bzero((char *) &client_addr, sizeof(client_addr));
|
||||
rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
|
||||
0, (struct sockaddr *)&client_addr, &client_length);
|
||||
if (rsrr_recvlen < 0) {
|
||||
if (errno != EINTR)
|
||||
log(LOG_ERR, errno, "RSRR recvfrom");
|
||||
return;
|
||||
}
|
||||
rsrr_accept(rsrr_recvlen);
|
||||
}
|
||||
|
||||
/* Accept a message from the reservation protocol and take
|
||||
* appropriate action.
|
||||
*/
|
||||
static void
|
||||
rsrr_accept(recvlen)
|
||||
int recvlen;
|
||||
{
|
||||
struct rsrr_header *rsrr;
|
||||
struct rsrr_rq *route_query;
|
||||
|
||||
if (recvlen < RSRR_HEADER_LEN) {
|
||||
log(LOG_WARNING, 0,
|
||||
"Received RSRR packet of %d bytes, which is less than min size",
|
||||
recvlen);
|
||||
return;
|
||||
}
|
||||
|
||||
rsrr = (struct rsrr_header *) rsrr_recv_buf;
|
||||
|
||||
if (rsrr->version > RSRR_MAX_VERSION) {
|
||||
log(LOG_WARNING, 0,
|
||||
"Received RSRR packet version %d, which I don't understand",
|
||||
rsrr->version);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rsrr->version) {
|
||||
case 1:
|
||||
switch (rsrr->type) {
|
||||
case RSRR_INITIAL_QUERY:
|
||||
/* Send Initial Reply to client */
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Received Initial Query\n");
|
||||
rsrr_accept_iq();
|
||||
break;
|
||||
case RSRR_ROUTE_QUERY:
|
||||
/* Check size */
|
||||
if (recvlen < RSRR_RQ_LEN) {
|
||||
log(LOG_WARNING, 0,
|
||||
"Received Route Query of %d bytes, which is too small",
|
||||
recvlen);
|
||||
break;
|
||||
}
|
||||
/* Get the query */
|
||||
route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0,
|
||||
"Received Route Query for src %s grp %s notification %d",
|
||||
inet_fmt(route_query->source_addr.s_addr, s1),
|
||||
inet_fmt(route_query->dest_addr.s_addr,s2),
|
||||
BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
|
||||
/* Send Route Reply to client */
|
||||
rsrr_accept_rq(route_query,rsrr->flags,NULL);
|
||||
break;
|
||||
default:
|
||||
log(LOG_WARNING, 0,
|
||||
"Received RSRR packet type %d, which I don't handle",
|
||||
rsrr->type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log(LOG_WARNING, 0,
|
||||
"Received RSRR packet version %d, which I don't understand",
|
||||
rsrr->version);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send an Initial Reply to the reservation protocol. */
|
||||
static void
|
||||
rsrr_accept_iq()
|
||||
{
|
||||
struct rsrr_header *rsrr;
|
||||
struct rsrr_vif *vif_list;
|
||||
struct uvif *v;
|
||||
int vifi, sendlen;
|
||||
|
||||
/* Check for space. There should be room for plenty of vifs,
|
||||
* but we should check anyway.
|
||||
*/
|
||||
if (numvifs > RSRR_MAX_VIFS) {
|
||||
log(LOG_WARNING, 0,
|
||||
"Can't send RSRR Route Reply because %d is too many vifs",
|
||||
numvifs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up message */
|
||||
rsrr = (struct rsrr_header *) rsrr_send_buf;
|
||||
rsrr->version = 1;
|
||||
rsrr->type = RSRR_INITIAL_REPLY;
|
||||
rsrr->flags = 0;
|
||||
rsrr->num = numvifs;
|
||||
|
||||
vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN);
|
||||
|
||||
/* Include the vif list. */
|
||||
for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) {
|
||||
vif_list[vifi].id = vifi;
|
||||
vif_list[vifi].status = 0;
|
||||
if (v->uv_flags & VIFF_DISABLED)
|
||||
BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
|
||||
vif_list[vifi].threshold = v->uv_threshold;
|
||||
vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr;
|
||||
}
|
||||
|
||||
/* Get the size. */
|
||||
sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
|
||||
|
||||
/* Send it. */
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Send RSRR Initial Reply");
|
||||
rsrr_send(sendlen);
|
||||
}
|
||||
|
||||
/* Send a Route Reply to the reservation protocol. The Route Query
|
||||
* contains the query to which we are responding. The flags contain
|
||||
* the incoming flags from the query or, for route change
|
||||
* notification, the flags that should be set for the reply. The
|
||||
* kernel table entry contains the routing info to use for a route
|
||||
* change notification.
|
||||
*/
|
||||
static int
|
||||
rsrr_accept_rq(route_query,flags,gt_notify)
|
||||
struct rsrr_rq *route_query;
|
||||
int flags;
|
||||
struct gtable *gt_notify;
|
||||
{
|
||||
struct rsrr_header *rsrr;
|
||||
struct rsrr_rr *route_reply;
|
||||
struct gtable *gt,local_g;
|
||||
struct rtentry *r;
|
||||
int sendlen;
|
||||
u_long mcastgrp;
|
||||
|
||||
/* Set up message */
|
||||
rsrr = (struct rsrr_header *) rsrr_send_buf;
|
||||
rsrr->version = 1;
|
||||
rsrr->type = RSRR_ROUTE_REPLY;
|
||||
rsrr->flags = 0;
|
||||
rsrr->num = 0;
|
||||
|
||||
route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
|
||||
route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr;
|
||||
route_reply->source_addr.s_addr = route_query->source_addr.s_addr;
|
||||
route_reply->query_id = route_query->query_id;
|
||||
|
||||
/* Blank routing entry for error. */
|
||||
route_reply->in_vif = 0;
|
||||
route_reply->reserved = 0;
|
||||
route_reply->out_vif_bm = 0;
|
||||
|
||||
/* Get the size. */
|
||||
sendlen = RSRR_RR_LEN;
|
||||
|
||||
/* If kernel table entry is defined, then we are sending a Route Reply
|
||||
* due to a Route Change Notification event. Use the kernel table entry
|
||||
* to supply the routing info.
|
||||
*/
|
||||
if (gt_notify) {
|
||||
/* Set flags */
|
||||
rsrr->flags = flags;
|
||||
/* Include the routing entry. */
|
||||
route_reply->in_vif = gt_notify->gt_route->rt_parent;
|
||||
if (BIT_TST(flags,RSRR_NOTIFICATION_BIT))
|
||||
route_reply->out_vif_bm = gt_notify->gt_grpmems;
|
||||
else
|
||||
route_reply->out_vif_bm = 0;
|
||||
} else if (find_src_grp(route_query->source_addr.s_addr, 0,
|
||||
route_query->dest_addr.s_addr)) {
|
||||
|
||||
/* Found kernel entry. Code taken from add_table_entry() */
|
||||
gt = gtp ? gtp->gt_gnext : kernel_table;
|
||||
|
||||
/* Include the routing entry. */
|
||||
route_reply->in_vif = gt->gt_route->rt_parent;
|
||||
route_reply->out_vif_bm = gt->gt_grpmems;
|
||||
|
||||
/* Cache reply if using route change notification. */
|
||||
if BIT_TST(flags,RSRR_NOTIFICATION_BIT) {
|
||||
rsrr_cache(gt,route_query);
|
||||
BIT_SET(rsrr->flags,RSRR_NOTIFICATION_BIT);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* No kernel entry; use routing table. */
|
||||
r = determine_route(route_query->source_addr.s_addr);
|
||||
|
||||
if (r != NULL) {
|
||||
/* We need to mimic what will happen if a data packet
|
||||
* is forwarded by multicast routing -- the kernel will
|
||||
* make an upcall and mrouted will install a route in the kernel.
|
||||
* Our outgoing vif bitmap should reflect what that table
|
||||
* will look like. Grab code from add_table_entry().
|
||||
* This is gross, but it's probably better to be accurate.
|
||||
*/
|
||||
|
||||
gt = &local_g;
|
||||
mcastgrp = route_query->dest_addr.s_addr;
|
||||
|
||||
gt->gt_mcastgrp = mcastgrp;
|
||||
gt->gt_grpmems = 0;
|
||||
gt->gt_scope = 0;
|
||||
gt->gt_route = r;
|
||||
|
||||
/* obtain the multicast group membership list */
|
||||
determine_forwvifs(gt);
|
||||
|
||||
/* Include the routing entry. */
|
||||
route_reply->in_vif = gt->gt_route->rt_parent;
|
||||
route_reply->out_vif_bm = gt->gt_grpmems;
|
||||
|
||||
} else {
|
||||
/* Set error bit. */
|
||||
BIT_SET(rsrr->flags,RSRR_ERROR_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "%sSend RSRR Route Reply for src %s dst %s in vif %d out vif %d\n",
|
||||
gt_notify ? "Route Change: " : "",
|
||||
inet_fmt(route_reply->source_addr.s_addr,s1),
|
||||
inet_fmt(route_reply->dest_addr.s_addr,s2),
|
||||
route_reply->in_vif,route_reply->out_vif_bm);
|
||||
|
||||
/* Send it. */
|
||||
return rsrr_send(sendlen);
|
||||
}
|
||||
|
||||
/* Send an RSRR message. */
|
||||
static int
|
||||
rsrr_send(sendlen)
|
||||
int sendlen;
|
||||
{
|
||||
int error;
|
||||
|
||||
/* Send it. */
|
||||
error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
|
||||
(struct sockaddr *)&client_addr, client_length);
|
||||
|
||||
/* Check for errors. */
|
||||
if (error < 0) {
|
||||
log(LOG_WARNING, errno, "Failed send on RSRR socket");
|
||||
} else if (error != sendlen) {
|
||||
log(LOG_WARNING, 0,
|
||||
"Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Cache a message being sent to a client. Currently only used for
|
||||
* caching Route Reply messages for route change notification.
|
||||
*/
|
||||
static void
|
||||
rsrr_cache(gt,route_query)
|
||||
struct gtable *gt;
|
||||
struct rsrr_rq *route_query;
|
||||
{
|
||||
struct rsrr_cache *rc, **rcnp;
|
||||
struct rsrr_header *rsrr;
|
||||
|
||||
rsrr = (struct rsrr_header *) rsrr_send_buf;
|
||||
|
||||
rcnp = >->gt_rsrr_cache;
|
||||
while ((rc = *rcnp) != NULL) {
|
||||
if ((rc->route_query.source_addr.s_addr ==
|
||||
route_query->source_addr.s_addr) &&
|
||||
(rc->route_query.dest_addr.s_addr ==
|
||||
route_query->dest_addr.s_addr) &&
|
||||
(!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) {
|
||||
/* Cache entry already exists.
|
||||
* Check if route notification bit has been cleared.
|
||||
*/
|
||||
if (!BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)) {
|
||||
/* Delete cache entry. */
|
||||
*rcnp = rc->next;
|
||||
free(rc);
|
||||
} else {
|
||||
/* Update */
|
||||
rc->route_query.query_id = route_query->query_id;
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0,
|
||||
"Update cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id, rc->client_addr.sun_path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rcnp = &rc->next;
|
||||
}
|
||||
|
||||
/* Cache entry doesn't already exist. Create one and insert at
|
||||
* front of list.
|
||||
*/
|
||||
rc = (struct rsrr_cache *) malloc(sizeof(struct rsrr_cache));
|
||||
if (rc == NULL)
|
||||
log(LOG_ERR, 0, "ran out of memory");
|
||||
rc->route_query.source_addr.s_addr = route_query->source_addr.s_addr;
|
||||
rc->route_query.dest_addr.s_addr = route_query->dest_addr.s_addr;
|
||||
rc->route_query.query_id = route_query->query_id;
|
||||
strcpy(rc->client_addr.sun_path, client_addr.sun_path);
|
||||
rc->client_length = client_length;
|
||||
rc->next = gt->gt_rsrr_cache;
|
||||
gt->gt_rsrr_cache = rc;
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id,rc->client_addr.sun_path);
|
||||
}
|
||||
|
||||
/* Send all the messages in the cache. Currently this is used to send
|
||||
* all the cached Route Reply messages for route change notification.
|
||||
*/
|
||||
void
|
||||
rsrr_cache_send(gt,notify)
|
||||
struct gtable *gt;
|
||||
int notify;
|
||||
{
|
||||
struct rsrr_cache *rc, **rcnp;
|
||||
int flags = 0;
|
||||
|
||||
if (notify)
|
||||
BIT_SET(flags,RSRR_NOTIFICATION_BIT);
|
||||
|
||||
rcnp = >->gt_rsrr_cache;
|
||||
while ((rc = *rcnp) != NULL) {
|
||||
if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) {
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id,rc->client_addr.sun_path);
|
||||
/* Delete cache entry. */
|
||||
*rcnp = rc->next;
|
||||
free(rc);
|
||||
} else {
|
||||
rcnp = &rc->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean the cache by deleting all entries. */
|
||||
void
|
||||
rsrr_cache_clean(gt)
|
||||
struct gtable *gt;
|
||||
{
|
||||
struct rsrr_cache *rc,*rc_next;
|
||||
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "cleaning cache for group %s\n",
|
||||
inet_fmt(gt->gt_mcastgrp, s1));
|
||||
rc = gt->gt_rsrr_cache;
|
||||
while (rc) {
|
||||
rc_next = rc->next;
|
||||
free(rc);
|
||||
rc = rc_next;
|
||||
}
|
||||
gt->gt_rsrr_cache = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rsrr_clean()
|
||||
{
|
||||
unlink(RSRR_SERV_PATH);
|
||||
}
|
||||
|
||||
#endif /* RSRR */
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation in source and binary forms for non-commercial purposes
|
||||
* and without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both the copyright notice and
|
||||
* this permission notice appear in supporting documentation. and that
|
||||
* any documentation, advertising materials, and other materials related
|
||||
* to such distribution and use acknowledge that the software was
|
||||
* developed by the University of Southern California, Information
|
||||
* Sciences Institute. The name of the University may not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
|
||||
* the suitability of this software for any purpose. THIS SOFTWARE IS
|
||||
* PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Other copyrights might apply to parts of this software and are so
|
||||
* noted when applicable.
|
||||
*/
|
||||
|
||||
#define RSRR_SERV_PATH "/var/run/rsrr_svr"
|
||||
/* Note this needs to be 14 chars for 4.3 BSD compatibility */
|
||||
/* Note This appears to be unused */
|
||||
#define RSRR_CLI_PATH "/var/run/rsrr_cli"
|
||||
|
||||
#define RSRR_MAX_LEN 2048
|
||||
#define RSRR_HEADER_LEN (sizeof(struct rsrr_header))
|
||||
#define RSRR_RQ_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rq))
|
||||
#define RSRR_RR_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rr))
|
||||
#define RSRR_VIF_LEN (sizeof(struct rsrr_vif))
|
||||
|
||||
/* Current maximum number of vifs. */
|
||||
#define RSRR_MAX_VIFS 32
|
||||
|
||||
/* Maximum acceptable version */
|
||||
#define RSRR_MAX_VERSION 1
|
||||
|
||||
/* RSRR message types */
|
||||
#define RSRR_ALL_TYPES 0
|
||||
#define RSRR_INITIAL_QUERY 1
|
||||
#define RSRR_INITIAL_REPLY 2
|
||||
#define RSRR_ROUTE_QUERY 3
|
||||
#define RSRR_ROUTE_REPLY 4
|
||||
|
||||
/* RSRR Initial Reply (Vif) Status bits
|
||||
* Each definition represents the position of the bit from right to left.
|
||||
*
|
||||
* Right-most bit is the disabled bit, set if the vif is administratively
|
||||
* disabled.
|
||||
*/
|
||||
#define RSRR_DISABLED_BIT 0
|
||||
/* All other bits are zeroes */
|
||||
|
||||
/* RSRR Route Query/Reply flag bits
|
||||
* Each definition represents the position of the bit from right to left.
|
||||
*
|
||||
* Right-most bit is the Route Change Notification bit, set if the
|
||||
* reservation protocol wishes to receive notification of
|
||||
* a route change for the source-destination pair listed in the query.
|
||||
* Notification is in the form of an unsolicitied Route Reply.
|
||||
*/
|
||||
#define RSRR_NOTIFICATION_BIT 0
|
||||
/* Next bit indicates an error returning the Route Reply. */
|
||||
#define RSRR_ERROR_BIT 1
|
||||
/* All other bits are zeroes */
|
||||
|
||||
/* Definition of an RSRR message header.
|
||||
* An Initial Query uses only the header, and an Initial Reply uses
|
||||
* the header and a list of vifs.
|
||||
*/
|
||||
struct rsrr_header {
|
||||
u_char version; /* RSRR Version, currently 1 */
|
||||
u_char type; /* type of message, as defined above */
|
||||
u_char flags; /* flags; defined by type */
|
||||
u_char num; /* number; defined by type */
|
||||
};
|
||||
|
||||
/* Definition of a vif as seen by the reservation protocol.
|
||||
*
|
||||
* Routing gives the reservation protocol a list of vifs in the
|
||||
* Initial Reply.
|
||||
*
|
||||
* We explicitly list the ID because we can't assume that all routing
|
||||
* protocols will use the same numbering scheme.
|
||||
*
|
||||
* The status is a bitmask of status flags, as defined above. It is the
|
||||
* responsibility of the reservation protocol to perform any status checks
|
||||
* if it uses the MULTICAST_VIF socket option.
|
||||
*
|
||||
* The threshold indicates the ttl an outgoing packet needs in order to
|
||||
* be forwarded. The reservation protocol must perform this check itself if
|
||||
* it uses the MULTICAST_VIF socket option.
|
||||
*
|
||||
* The local address is the address of the physical interface over which
|
||||
* packets are sent.
|
||||
*/
|
||||
struct rsrr_vif {
|
||||
u_char id; /* vif id */
|
||||
u_char threshold; /* vif threshold ttl */
|
||||
u_short status; /* vif status bitmask */
|
||||
struct in_addr local_addr; /* vif local address */
|
||||
};
|
||||
|
||||
/* Definition of an RSRR Route Query.
|
||||
*
|
||||
* The query asks routing for the forwarding entry for a particular
|
||||
* source and destination. The query ID uniquely identifies the query
|
||||
* for the reservation protocol. Thus, the combination of the client's
|
||||
* address and the query ID forms a unique identifier for routing.
|
||||
* Flags are defined above.
|
||||
*/
|
||||
struct rsrr_rq {
|
||||
struct in_addr dest_addr; /* destination */
|
||||
struct in_addr source_addr; /* source */
|
||||
u_long query_id; /* query ID */
|
||||
};
|
||||
|
||||
/* Definition of an RSRR Route Reply.
|
||||
*
|
||||
* Routing uses the reply to give the reservation protocol the
|
||||
* forwarding entry for a source-destination pair. Routing copies the
|
||||
* query ID from the query and fills in the incoming vif and a bitmask
|
||||
* of the outgoing vifs.
|
||||
* Flags are defined above.
|
||||
*/
|
||||
struct rsrr_rr {
|
||||
struct in_addr dest_addr; /* destination */
|
||||
struct in_addr source_addr; /* source */
|
||||
u_long query_id; /* query ID */
|
||||
u_short in_vif; /* incoming vif */
|
||||
u_short reserved; /* reserved */
|
||||
u_long out_vif_bm; /* outgoing vif bitmask */
|
||||
};
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation in source and binary forms for non-commercial purposes
|
||||
* and without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both the copyright notice and
|
||||
* this permission notice appear in supporting documentation. and that
|
||||
* any documentation, advertising materials, and other materials related
|
||||
* to such distribution and use acknowledge that the software was
|
||||
* developed by the University of Southern California, Information
|
||||
* Sciences Institute. The name of the University may not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
|
||||
* the suitability of this software for any purpose. THIS SOFTWARE IS
|
||||
* PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Other copyrights might apply to parts of this software and are so
|
||||
* noted when applicable.
|
||||
*/
|
||||
|
||||
/* RSRR things that are only needed by mrouted. */
|
||||
|
||||
/* Cache of Route Query messages, distinguished by source,
|
||||
* destination, and client addresses. Cache is flushed by RSRR client
|
||||
* -- it sends notification when an unwanted Route Reply is received.
|
||||
* Since this only happens during route changes, it is more likely
|
||||
* that the cache will be flushed when the kernel table entry is
|
||||
* deleted. */
|
||||
struct rsrr_cache {
|
||||
struct rsrr_rq route_query; /* Cached Route Query */
|
||||
struct sockaddr_un client_addr; /* Client address */
|
||||
int client_length; /* Length of client */
|
||||
struct rsrr_cache *next; /* next cache item */
|
||||
};
|
||||
|
@ -1,13 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
S= ${.CURDIR}/..
|
||||
.PATH: $S
|
||||
|
||||
PROG= testrsrr
|
||||
NO_MAN=
|
||||
|
||||
CFLAGS+= -I$S
|
||||
|
||||
install:
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 1995 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that both the above copyright notice and this
|
||||
* permission notice appear in all copies, that both the above
|
||||
* copyright notice and this permission notice appear in all
|
||||
* supporting documentation, and that the name of M.I.T. not be used
|
||||
* in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. M.I.T. makes
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||
* SHALL M.I.T. 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$
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "rsrr.h"
|
||||
|
||||
char sunpath[MAXPATHLEN];
|
||||
int s;
|
||||
|
||||
void exitfn(void) {
|
||||
close(s);
|
||||
unlink(sunpath);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct sockaddr_un sun;
|
||||
char buf[RSRR_MAX_LEN];
|
||||
struct rsrr_header *rh;
|
||||
struct rsrr_vif *rvp;
|
||||
int i;
|
||||
|
||||
s = socket(PF_LOCAL, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
err(EX_OSERR, "socket(PF_LOCAL, SOCK_DGRAM, 0)");
|
||||
}
|
||||
|
||||
sun.sun_family = AF_LOCAL;
|
||||
snprintf(sunpath, sizeof sun.sun_path, "/tmp/testrsrr.%lu",
|
||||
(unsigned long)getpid());
|
||||
strcpy(sun.sun_path, sunpath);
|
||||
sun.sun_len = (offsetof(struct sockaddr_un, sun_path)
|
||||
+ strlen(sunpath));
|
||||
|
||||
if (bind(s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
|
||||
err(EX_OSERR, "bind: %s", sunpath);
|
||||
}
|
||||
|
||||
atexit(exitfn); /* clean up if we exit on error */
|
||||
|
||||
strcpy(sun.sun_path, RSRR_SERV_PATH);
|
||||
sun.sun_len = (offsetof(struct sockaddr_un, sun_path)
|
||||
+ strlen(sunpath));
|
||||
|
||||
if (connect(s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
|
||||
err(EX_OSERR, "connect: %s", RSRR_SERV_PATH);
|
||||
}
|
||||
|
||||
rh = (struct rsrr_header *)buf;
|
||||
rh->version = RSRR_MAX_VERSION;
|
||||
rh->type = RSRR_INITIAL_QUERY;
|
||||
rh->flags = 0;
|
||||
rh->num = 0;
|
||||
|
||||
if (write(s, rh, sizeof *rh) == (ssize_t)-1) {
|
||||
err(EX_OSERR, "write(initial query)");
|
||||
}
|
||||
|
||||
if (read(s, buf, sizeof buf) == (ssize_t)-1) {
|
||||
err(EX_OSERR, "read(initial reply)");
|
||||
}
|
||||
|
||||
if (rh->version != RSRR_MAX_VERSION) {
|
||||
errx(EX_PROTOCOL, "bad remote version %d", rh->version);
|
||||
}
|
||||
|
||||
if (rh->type != RSRR_INITIAL_REPLY) {
|
||||
errx(EX_PROTOCOL, "remote returned unexpected message type %d",
|
||||
rh->type);
|
||||
}
|
||||
|
||||
if (rh->flags) {
|
||||
printf("confusing flags: %d\n", rh->flags);
|
||||
}
|
||||
|
||||
printf("There are %d vifs configured:\n", rh->num);
|
||||
|
||||
printf(" Vif Thresh Status Local address\n");
|
||||
for(i = 0, rvp = (struct rsrr_vif *)(rh + 1); i < rh->num; i++,rvp++) {
|
||||
printf(" %3d %6d %6d %s\n", rvp->id, rvp->threshold,
|
||||
rvp->status, inet_ntoa(rvp->local_addr));
|
||||
}
|
||||
exit(0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,237 +0,0 @@
|
||||
/*
|
||||
* The mrouted program is covered by the license in the accompanying file
|
||||
* named "LICENSE". Use of the mrouted program represents acceptance of
|
||||
* the terms and conditions listed in that file.
|
||||
*
|
||||
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
* vif.h,v 3.8.4.26 1998/01/14 21:21:19 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Bitmap handling functions.
|
||||
* These should be fast but generic. bytes can be slow to zero and compare,
|
||||
* words are hard to make generic. Thus two sets of macros (yuk).
|
||||
*/
|
||||
|
||||
/*
|
||||
* The VIFM_ functions should migrate out of <netinet/ip_mroute.h>, since
|
||||
* the kernel no longer uses vifbitmaps.
|
||||
*/
|
||||
#ifndef VIFM_SET
|
||||
typedef u_long vifbitmap_t;
|
||||
|
||||
#define VIFM_SET(n, m) ((m) |= (1 << (n)))
|
||||
#define VIFM_CLR(n, m) ((m) &= ~(1 << (n)))
|
||||
#define VIFM_ISSET(n, m) ((m) & (1 << (n)))
|
||||
#define VIFM_CLRALL(m) ((m) = 0x00000000)
|
||||
#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom))
|
||||
#define VIFM_SAME(m1, m2) ((m1) == (m2))
|
||||
#endif
|
||||
/*
|
||||
* And <netinet/ip_mroute.h> was missing some required functions anyway
|
||||
*/
|
||||
#ifndef VIFM_SETALL
|
||||
#define VIFM_SETALL(m) ((m) = ~0)
|
||||
#endif
|
||||
#define VIFM_ISSET_ONLY(n, m) ((m) == (1 << (n)))
|
||||
#define VIFM_ISEMPTY(m) ((m) == 0)
|
||||
#define VIFM_CLR_MASK(m, mask) ((m) &= ~(mask))
|
||||
#define VIFM_SET_MASK(m, mask) ((m) |= (mask))
|
||||
|
||||
/*
|
||||
* Neighbor bitmaps are, for efficiency, implemented as a struct
|
||||
* containing two variables of a native machine type. If you
|
||||
* have a native type that's bigger than a long, define it below.
|
||||
*/
|
||||
#define NBRTYPE u_long
|
||||
#define NBRBITS sizeof(NBRTYPE) * 8
|
||||
|
||||
typedef struct {
|
||||
NBRTYPE hi;
|
||||
NBRTYPE lo;
|
||||
} nbrbitmap_t;
|
||||
#define MAXNBRS 2 * NBRBITS
|
||||
#define NO_NBR MAXNBRS
|
||||
|
||||
#define NBRM_SET(n, m) (((n) < NBRBITS) ? ((m).lo |= (1 << (n))) : \
|
||||
((m).hi |= (1 << (n - NBRBITS))))
|
||||
#define NBRM_CLR(n, m) (((n) < NBRBITS) ? ((m).lo &= ~(1 << (n))) : \
|
||||
((m).hi &= ~(1 << (n - NBRBITS))))
|
||||
#define NBRM_ISSET(n, m) (((n) < NBRBITS) ? ((m).lo & (1 << (n))) : \
|
||||
((m).hi & (1 << ((n) - NBRBITS))))
|
||||
#define NBRM_CLRALL(m) ((m).lo = (m).hi = 0)
|
||||
#define NBRM_COPY(mfrom, mto) ((mto).lo = (mfrom).lo, (mto).hi = (mfrom).hi)
|
||||
#define NBRM_SAME(m1, m2) (((m1).lo == (m2).lo) && ((m1).hi == (m2).hi))
|
||||
#define NBRM_ISEMPTY(m) (((m).lo == 0) && ((m).hi == 0))
|
||||
#define NBRM_SETMASK(m, mask) (((m).lo |= (mask).lo),((m).hi |= (mask).hi))
|
||||
#define NBRM_CLRMASK(m, mask) (((m).lo &= ~(mask).lo),((m).hi &= ~(mask).hi))
|
||||
#define NBRM_MASK(m, mask) (((m).lo &= (mask).lo),((m).hi &= (mask).hi))
|
||||
#define NBRM_ISSETMASK(m, mask) (((m).lo & (mask).lo) || ((m).hi & (mask).hi))
|
||||
#define NBRM_ISSETALLMASK(m, mask)\
|
||||
((((m).lo & (mask).lo) == (mask).lo) && \
|
||||
(((m).hi & (mask).hi) == (mask).hi))
|
||||
/*
|
||||
* This macro is TRUE if all the subordinates have been pruned, or if
|
||||
* there are no subordinates on this vif.
|
||||
* The arguments is the map of subordinates, the map of neighbors on the
|
||||
* vif, and the map of received prunes.
|
||||
*/
|
||||
#define SUBS_ARE_PRUNED(sub, vifmask, prunes) \
|
||||
(((sub).lo & (vifmask).lo) == ((prunes).lo & (vifmask).lo & (sub).lo) && \
|
||||
((sub).hi & (vifmask).hi) == ((prunes).hi & (vifmask).hi & (sub).hi))
|
||||
|
||||
struct blastinfo {
|
||||
char * bi_buf; /* Pointer to malloced storage */
|
||||
char * bi_cur; /* The update to process next */
|
||||
char * bi_end; /* The place to put the next update */
|
||||
int bi_len; /* Size of malloced storage */
|
||||
int bi_timer; /* Timer to run process_blaster_report */
|
||||
};
|
||||
|
||||
/*
|
||||
* User level Virtual Interface structure
|
||||
*
|
||||
* A "virtual interface" is either a physical, multicast-capable interface
|
||||
* (called a "phyint") or a virtual point-to-point link (called a "tunnel").
|
||||
* (Note: all addresses, subnet numbers and masks are kept in NETWORK order.)
|
||||
*/
|
||||
struct uvif {
|
||||
u_int uv_flags; /* VIFF_ flags defined below */
|
||||
u_char uv_metric; /* cost of this vif */
|
||||
u_char uv_admetric; /* advertised cost of this vif */
|
||||
u_char uv_threshold; /* min ttl required to forward on vif */
|
||||
u_int uv_rate_limit; /* rate limit on this vif */
|
||||
u_int32 uv_lcl_addr; /* local address of this vif */
|
||||
u_int32 uv_rmt_addr; /* remote end-point addr (tunnels only) */
|
||||
u_int32 uv_dst_addr; /* destination for DVMRP messages */
|
||||
u_int32 uv_subnet; /* subnet number (phyints only) */
|
||||
u_int32 uv_subnetmask; /* subnet mask (phyints only) */
|
||||
u_int32 uv_subnetbcast;/* subnet broadcast addr (phyints only) */
|
||||
char uv_name[IFNAMSIZ]; /* interface name */
|
||||
struct listaddr *uv_groups; /* list of local groups (phyints only) */
|
||||
struct listaddr *uv_neighbors; /* list of neighboring routers */
|
||||
nbrbitmap_t uv_nbrmap; /* bitmap of active neighboring routers */
|
||||
struct listaddr *uv_querier; /* IGMP querier on vif */
|
||||
int uv_igmpv1_warn;/* To rate-limit IGMPv1 warnings */
|
||||
int uv_prune_lifetime; /* Prune lifetime or 0 for default */
|
||||
struct vif_acl *uv_acl; /* access control list of groups */
|
||||
int uv_leaf_timer; /* time until this vif is considrd leaf */
|
||||
struct phaddr *uv_addrs; /* Additional subnets on this vif */
|
||||
struct vif_filter *uv_filter; /* Route filters on this vif */
|
||||
struct blastinfo uv_blaster; /* Info about route blasters */
|
||||
int uv_nbrup; /* Counter for neighbor up events */
|
||||
int uv_icmp_warn; /* To rate-limit ICMP warnings */
|
||||
u_int uv_nroutes; /* # of routes with this vif as parent */
|
||||
struct ip *uv_encap_hdr; /* Pre-formed header to encapsulate msgs*/
|
||||
};
|
||||
|
||||
#define uv_blasterbuf uv_blaster.bi_buf
|
||||
#define uv_blastercur uv_blaster.bi_cur
|
||||
#define uv_blasterend uv_blaster.bi_end
|
||||
#define uv_blasterlen uv_blaster.bi_len
|
||||
#define uv_blastertimer uv_blaster.bi_timer
|
||||
|
||||
#define VIFF_KERNEL_FLAGS (VIFF_TUNNEL|VIFF_SRCRT)
|
||||
#define VIFF_DOWN 0x000100 /* kernel state of interface */
|
||||
#define VIFF_DISABLED 0x000200 /* administratively disabled */
|
||||
#define VIFF_QUERIER 0x000400 /* I am the subnet's querier */
|
||||
#define VIFF_ONEWAY 0x000800 /* Maybe one way interface */
|
||||
#define VIFF_LEAF 0x001000 /* all neighbors are leaves */
|
||||
#define VIFF_IGMPV1 0x002000 /* Act as an IGMPv1 Router */
|
||||
#define VIFF_REXMIT_PRUNES 0x004000 /* retransmit prunes */
|
||||
#define VIFF_PASSIVE 0x008000 /* passive tunnel */
|
||||
#define VIFF_ALLOW_NONPRUNERS 0x010000 /* ok to peer with nonprunrs */
|
||||
#define VIFF_NOFLOOD 0x020000 /* don't flood on this vif */
|
||||
#define VIFF_NOTRANSIT 0x040000 /* don't transit these vifs */
|
||||
#define VIFF_BLASTER 0x080000 /* nbr on vif blasts routes */
|
||||
#define VIFF_FORCE_LEAF 0x100000 /* ignore nbrs on this vif */
|
||||
#define VIFF_OTUNNEL 0x200000 /* DVMRP msgs "beside" tunnel*/
|
||||
|
||||
#define AVOID_TRANSIT(v, r) \
|
||||
(((r)->rt_parent != NO_VIF) && \
|
||||
((r)->rt_gateway != 0) && \
|
||||
(uvifs[(v)].uv_flags & VIFF_NOTRANSIT) && \
|
||||
(uvifs[(r)->rt_parent].uv_flags & VIFF_NOTRANSIT))
|
||||
|
||||
struct phaddr {
|
||||
struct phaddr *pa_next;
|
||||
u_int32 pa_subnet; /* extra subnet */
|
||||
u_int32 pa_subnetmask; /* netmask of extra subnet */
|
||||
u_int32 pa_subnetbcast; /* broadcast of extra subnet */
|
||||
};
|
||||
|
||||
struct vif_acl {
|
||||
struct vif_acl *acl_next; /* next acl member */
|
||||
u_int32 acl_addr; /* Group address */
|
||||
u_int32 acl_mask; /* Group addr. mask */
|
||||
};
|
||||
|
||||
struct vif_filter {
|
||||
int vf_type;
|
||||
#define VFT_ACCEPT 1
|
||||
#define VFT_DENY 2
|
||||
int vf_flags;
|
||||
#define VFF_BIDIR 1
|
||||
struct vf_element *vf_filter;
|
||||
};
|
||||
|
||||
struct vf_element {
|
||||
struct vf_element *vfe_next;
|
||||
u_int32 vfe_addr;
|
||||
u_int32 vfe_mask;
|
||||
int vfe_flags;
|
||||
#define VFEF_EXACT 0x0001
|
||||
};
|
||||
|
||||
struct listaddr {
|
||||
struct listaddr *al_next; /* link to next addr, MUST BE FIRST */
|
||||
u_int32 al_addr; /* local group or neighbor address */
|
||||
u_long al_timer; /* for timing out group or neighbor */
|
||||
time_t al_ctime; /* entry creation time */
|
||||
union {
|
||||
struct {
|
||||
u_int32 alur_genid; /* generation id for neighbor */
|
||||
u_int alur_nroutes; /* # of routes w/ nbr as parent */
|
||||
u_char alur_pv; /* router protocol version */
|
||||
u_char alur_mv; /* router mrouted version */
|
||||
u_char alur_index; /* neighbor index */
|
||||
} alu_router;
|
||||
struct {
|
||||
u_int32 alug_reporter; /* a host which reported membership */
|
||||
u_long alug_timerid; /* timer for group membership */
|
||||
u_long alug_query; /* timer for repeated leave query */
|
||||
u_char alug_old; /* time since heard old report */
|
||||
} alu_group;
|
||||
} al_alu;
|
||||
u_short al_flags; /* flags related to this neighbor */
|
||||
};
|
||||
#define al_genid al_alu.alu_router.alur_genid
|
||||
#define al_nroutes al_alu.alu_router.alur_nroutes
|
||||
#define al_pv al_alu.alu_router.alur_pv
|
||||
#define al_mv al_alu.alu_router.alur_mv
|
||||
#define al_index al_alu.alu_router.alur_index
|
||||
#define al_reporter al_alu.alu_group.alug_reporter
|
||||
#define al_old al_alu.alu_group.alug_old
|
||||
#define al_timerid al_alu.alu_group.alug_timerid
|
||||
#define al_query al_alu.alu_group.alug_query
|
||||
|
||||
#define NBRF_LEAF 0x0001 /* This neighbor is a leaf */
|
||||
#define NBRF_GENID 0x0100 /* I know this neighbor's genid */
|
||||
#define NBRF_WAITING 0x0200 /* Waiting for peering to come up */
|
||||
#define NBRF_ONEWAY 0x0400 /* One-way peering */
|
||||
#define NBRF_TOOOLD 0x0800 /* Too old (policy decision) */
|
||||
#define NBRF_TOOMANYROUTES 0x1000 /* Neighbor is spouting routes */
|
||||
#define NBRF_NOTPRUNING 0x2000 /* Neighbor doesn't appear to prune */
|
||||
|
||||
/*
|
||||
* Don't peer with neighbors with any of these flags set
|
||||
*/
|
||||
#define NBRF_DONTPEER (NBRF_WAITING|NBRF_ONEWAY|NBRF_TOOOLD| \
|
||||
NBRF_TOOMANYROUTES|NBRF_NOTPRUNING)
|
||||
|
||||
#define NO_VIF ((vifi_t)MAXVIFS) /* An invalid vif index */
|
Loading…
Reference in New Issue
Block a user