aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce M Simpson <bms@FreeBSD.org>2006-09-29 10:40:53 +0000
committerBruce M Simpson <bms@FreeBSD.org>2006-09-29 10:40:53 +0000
commitaa805a5eb75cf1e9bf970db6bc7fb75159cf6908 (patch)
treee56d5fc72f962232dc433104ccb2a45a0f4e3069
parent13b3ebf134bec33cecfaeffdde8cd9d7abde6b43 (diff)
downloadsrc-aa805a5eb75cf1e9bf970db6bc7fb75159cf6908.tar.gz
src-aa805a5eb75cf1e9bf970db6bc7fb75159cf6908.zip
Remove mrouted from -CURRENT.
Discussed with: fenner, net@
Notes
Notes: svn path=/head/; revision=162781
-rw-r--r--usr.sbin/mrouted/LICENSE48
-rw-r--r--usr.sbin/mrouted/Makefile5
-rw-r--r--usr.sbin/mrouted/Makefile.inc7
-rw-r--r--usr.sbin/mrouted/RELEASE493
-rw-r--r--usr.sbin/mrouted/VERSION1
-rw-r--r--usr.sbin/mrouted/callout.c250
-rw-r--r--usr.sbin/mrouted/cfparse.y927
-rw-r--r--usr.sbin/mrouted/common/Makefile12
-rw-r--r--usr.sbin/mrouted/config.c127
-rw-r--r--usr.sbin/mrouted/defs.h365
-rw-r--r--usr.sbin/mrouted/dvmrp.h172
-rw-r--r--usr.sbin/mrouted/icmp.c225
-rw-r--r--usr.sbin/mrouted/igmp.c447
-rw-r--r--usr.sbin/mrouted/igmpv2.h42
-rw-r--r--usr.sbin/mrouted/inet.c235
-rw-r--r--usr.sbin/mrouted/ipip.c145
-rw-r--r--usr.sbin/mrouted/kern.c344
-rw-r--r--usr.sbin/mrouted/main.c1064
-rw-r--r--usr.sbin/mrouted/map-mbone.896
-rw-r--r--usr.sbin/mrouted/map-mbone/Makefile15
-rw-r--r--usr.sbin/mrouted/mapper.c1048
-rw-r--r--usr.sbin/mrouted/mrinfo.891
-rw-r--r--usr.sbin/mrouted/mrinfo.c636
-rw-r--r--usr.sbin/mrouted/mrinfo/Makefile16
-rw-r--r--usr.sbin/mrouted/mrouted.8665
-rw-r--r--usr.sbin/mrouted/mrouted.conf44
-rw-r--r--usr.sbin/mrouted/mrouted/Makefile19
-rw-r--r--usr.sbin/mrouted/mtrace.8589
-rw-r--r--usr.sbin/mrouted/mtrace.c3177
-rw-r--r--usr.sbin/mrouted/mtrace.h89
-rw-r--r--usr.sbin/mrouted/mtrace/Makefile13
-rw-r--r--usr.sbin/mrouted/pathnames.h26
-rw-r--r--usr.sbin/mrouted/prune.c2619
-rw-r--r--usr.sbin/mrouted/prune.h152
-rw-r--r--usr.sbin/mrouted/route.c1475
-rw-r--r--usr.sbin/mrouted/route.h53
-rw-r--r--usr.sbin/mrouted/rsrr.c485
-rw-r--r--usr.sbin/mrouted/rsrr.h139
-rw-r--r--usr.sbin/mrouted/rsrr_var.h41
-rw-r--r--usr.sbin/mrouted/testrsrr/Makefile13
-rw-r--r--usr.sbin/mrouted/testrsrr/testrsrr.c125
-rw-r--r--usr.sbin/mrouted/vif.c1862
-rw-r--r--usr.sbin/mrouted/vif.h237
43 files changed, 0 insertions, 18634 deletions
diff --git a/usr.sbin/mrouted/LICENSE b/usr.sbin/mrouted/LICENSE
deleted file mode 100644
index ef7da470b117..000000000000
--- a/usr.sbin/mrouted/LICENSE
+++ /dev/null
@@ -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.
diff --git a/usr.sbin/mrouted/Makefile b/usr.sbin/mrouted/Makefile
deleted file mode 100644
index 43fe8b10ac70..000000000000
--- a/usr.sbin/mrouted/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-SUBDIR= common mrouted mrinfo map-mbone mtrace testrsrr
-
-.include <bsd.subdir.mk>
diff --git a/usr.sbin/mrouted/Makefile.inc b/usr.sbin/mrouted/Makefile.inc
deleted file mode 100644
index 6ecd80dd0d3d..000000000000
--- a/usr.sbin/mrouted/Makefile.inc
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-
-CFLAGS+= -DRSRR -Dlog=logit
-
-LIBMROUTED= ${.OBJDIR}/../common/libmrouted.a
-
-.include "../Makefile.inc"
diff --git a/usr.sbin/mrouted/RELEASE b/usr.sbin/mrouted/RELEASE
deleted file mode 100644
index 979065011f28..000000000000
--- a/usr.sbin/mrouted/RELEASE
+++ /dev/null
@@ -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.
diff --git a/usr.sbin/mrouted/VERSION b/usr.sbin/mrouted/VERSION
deleted file mode 100644
index a0ba149f7950..000000000000
--- a/usr.sbin/mrouted/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-3.9-beta3+IOS12
diff --git a/usr.sbin/mrouted/callout.c b/usr.sbin/mrouted/callout.c
deleted file mode 100644
index 8b8ea9c7156a..000000000000
--- a/usr.sbin/mrouted/callout.c
+++ /dev/null
@@ -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 */
diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y
deleted file mode 100644
index 9ab1f629aa13..000000000000
--- a/usr.sbin/mrouted/cfparse.y
+++ /dev/null
@@ -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);
-}
diff --git a/usr.sbin/mrouted/common/Makefile b/usr.sbin/mrouted/common/Makefile
deleted file mode 100644
index 903b50b2404b..000000000000
--- a/usr.sbin/mrouted/common/Makefile
+++ /dev/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>
diff --git a/usr.sbin/mrouted/config.c b/usr.sbin/mrouted/config.c
deleted file mode 100644
index 9f83fb71ae42..000000000000
--- a/usr.sbin/mrouted/config.c
+++ /dev/null
@@ -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);
-}
diff --git a/usr.sbin/mrouted/defs.h b/usr.sbin/mrouted/defs.h
deleted file mode 100644
index 40b9cf0a7300..000000000000
--- a/usr.sbin/mrouted/defs.h
+++ /dev/null
@@ -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 */
diff --git a/usr.sbin/mrouted/dvmrp.h b/usr.sbin/mrouted/dvmrp.h
deleted file mode 100644
index 2f11872216c0..000000000000
--- a/usr.sbin/mrouted/dvmrp.h
+++ /dev/null
@@ -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*/
diff --git a/usr.sbin/mrouted/icmp.c b/usr.sbin/mrouted/icmp.c
deleted file mode 100644
index 72efa0ac745b..000000000000
--- a/usr.sbin/mrouted/icmp.c
+++ /dev/null
@@ -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;
-}
diff --git a/usr.sbin/mrouted/igmp.c b/usr.sbin/mrouted/igmp.c
deleted file mode 100644
index f3430355cb15..000000000000
--- a/usr.sbin/mrouted/igmp.c
+++ /dev/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));
-}
diff --git a/usr.sbin/mrouted/igmpv2.h b/usr.sbin/mrouted/igmpv2.h
deleted file mode 100644
index 5f5ae27e68e8..000000000000
--- a/usr.sbin/mrouted/igmpv2.h
+++ /dev/null
@@ -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
diff --git a/usr.sbin/mrouted/inet.c b/usr.sbin/mrouted/inet.c
deleted file mode 100644
index 53aad7c63a94..000000000000
--- a/usr.sbin/mrouted/inet.c
+++ /dev/null
@@ -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);
-}
diff --git a/usr.sbin/mrouted/ipip.c b/usr.sbin/mrouted/ipip.c
deleted file mode 100644
index 6e88d932d3b4..000000000000
--- a/usr.sbin/mrouted/ipip.c
+++ /dev/null
@@ -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));
-}
diff --git a/usr.sbin/mrouted/kern.c b/usr.sbin/mrouted/kern.c
deleted file mode 100644
index 716b4794180b..000000000000
--- a/usr.sbin/mrouted/kern.c
+++ /dev/null
@@ -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
diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c
deleted file mode 100644
index 75589903ebbc..000000000000
--- a/usr.sbin/mrouted/main.c
+++ /dev/null
@@ -1,1064 +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.
- *
- *
- * main.c,v 3.8.4.29 1998/03/01 01:49:00 fenner Exp
- */
-
-/*
- * Written by Steve Deering, Stanford University, February 1989.
- *
- * (An earlier version of DVMRP was implemented by David Waitzman of
- * BBN STC by extending Berkeley's routed program. Some of Waitzman's
- * extensions have been incorporated into mrouted, but none of the
- * original routed code has been adopted.)
- */
-
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
-#include <err.h>
-#include "defs.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-#include <fcntl.h>
-#include <paths.h>
-
-#ifdef SNMP
-#include "snmp.h"
-#endif
-
-extern char *configfilename;
-char versionstring[100];
-
-static char pidfilename[] = _PATH_MROUTED_PID;
-static char dumpfilename[] = _PATH_MROUTED_DUMP;
-static char cachefilename[] = _PATH_MROUTED_CACHE;
-static char genidfilename[] = _PATH_MROUTED_GENID;
-
-static int haveterminal = 1;
-int did_final_init = 0;
-
-static int sighandled = 0;
-#define GOT_SIGINT 0x01
-#define GOT_SIGHUP 0x02
-#define GOT_SIGUSR1 0x04
-#define GOT_SIGUSR2 0x08
-
-int cache_lifetime = DEFAULT_CACHE_LIFETIME;
-int prune_lifetime = AVERAGE_PRUNE_LIFETIME;
-
-int debug = 0;
-char *progname;
-time_t mrouted_init_time;
-
-#ifdef SNMP
-#define NHANDLERS 34
-#else
-#define NHANDLERS 2
-#endif
-
-static struct ihandler {
- int fd; /* File descriptor */
- ihfunc_t func; /* Function to call with &fd_set */
-} ihandlers[NHANDLERS];
-static int nhandlers = 0;
-
-static struct debugname {
- char *name;
- int level;
- int nchars;
-} debugnames[] = {
- { "packet", DEBUG_PKT, 2 },
- { "pkt", DEBUG_PKT, 3 },
- { "pruning", DEBUG_PRUNE, 1 },
- { "prunes", DEBUG_PRUNE, 1 },
- { "routing", DEBUG_ROUTE, 1 },
- { "routes", DEBUG_ROUTE, 1 },
- { "route_detail", DEBUG_RTDETAIL, 6 },
- { "rtdetail", DEBUG_RTDETAIL, 2 },
- { "peers", DEBUG_PEER, 2 },
- { "neighbors", DEBUG_PEER, 1 },
- { "cache", DEBUG_CACHE, 1 },
- { "timeout", DEBUG_TIMEOUT, 1 },
- { "callout", DEBUG_TIMEOUT, 2 },
- { "interface", DEBUG_IF, 2 },
- { "vif", DEBUG_IF, 1 },
- { "membership", DEBUG_MEMBER, 1 },
- { "groups", DEBUG_MEMBER, 1 },
- { "traceroute", DEBUG_TRACE, 2 },
- { "mtrace", DEBUG_TRACE, 2 },
- { "igmp", DEBUG_IGMP, 1 },
- { "icmp", DEBUG_ICMP, 2 },
- { "rsrr", DEBUG_RSRR, 2 },
- { "3", 0xffffffff, 1 } /* compat. */
-};
-
-/*
- * Forward declarations.
- */
-static void final_init __P((void *));
-static void fasttimer __P((void *));
-static void timer __P((void *));
-static void dump __P((void));
-static void dump_version __P((FILE *));
-static void fdump __P((void));
-static void cdump __P((void));
-static void restart __P((void));
-static void handler __P((int));
-static void cleanup __P((void));
-static void resetlogging __P((void *));
-static void usage __P((void));
-
-/* To shut up gcc -Wstrict-prototypes */
-int main __P((int argc, char **argv));
-
-int
-register_input_handler(fd, func)
- int fd;
- ihfunc_t func;
-{
- if (nhandlers >= NHANDLERS)
- return -1;
-
- ihandlers[nhandlers].fd = fd;
- ihandlers[nhandlers++].func = func;
-
- return 0;
-}
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- register int recvlen;
- int dummy;
- FILE *fp;
- struct timeval tv, difftime, curtime, lasttime, *timeout;
- u_int32 prev_genid;
- int vers;
- fd_set rfds, readers;
- int nfds, n, i, secs;
- extern char todaysversion[];
- struct sigaction sa;
-#ifdef SNMP
- struct timeval timeout, *tvp = &timeout;
- struct timeval sched, *svp = &sched, now, *nvp = &now;
- int index, block;
-#endif
-
- setlinebuf(stderr);
-
- if (geteuid() != 0)
- errx(1, "must be root");
-
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- argv++, argc--;
- while (argc > 0 && *argv[0] == '-') {
- if (strcmp(*argv, "-d") == 0) {
- if (argc > 1 && *(argv + 1)[0] != '-') {
- char *p,*q;
- int i, len;
- struct debugname *d;
-
- argv++, argc--;
- debug = 0;
- p = *argv; q = NULL;
- while (p) {
- q = strchr(p, ',');
- if (q)
- *q++ = '\0';
- len = strlen(p);
- for (i = 0, d = debugnames;
- i < sizeof(debugnames) / sizeof(debugnames[0]);
- i++, d++)
- if (len >= d->nchars && strncmp(d->name, p, len) == 0)
- break;
- if (i == sizeof(debugnames) / sizeof(debugnames[0])) {
- int j = 0xffffffff;
- int k = 0;
- fprintf(stderr, "Valid debug levels: ");
- for (i = 0, d = debugnames;
- i < sizeof(debugnames) / sizeof(debugnames[0]);
- i++, d++) {
- if ((j & d->level) == d->level) {
- if (k++)
- putc(',', stderr);
- fputs(d->name, stderr);
- j &= ~d->level;
- }
- }
- putc('\n', stderr);
- usage();
- }
- debug |= d->level;
- p = q;
- }
- } else
- debug = DEFAULT_DEBUG;
- } else if (strcmp(*argv, "-c") == 0) {
- if (argc > 1) {
- argv++, argc--;
- configfilename = *argv;
- } else
- usage();
- } else if (strcmp(*argv, "-p") == 0) {
- log(LOG_WARNING, 0, "disabling pruning is no longer supported");
-#ifdef SNMP
- } else if (strcmp(*argv, "-P") == 0) {
- if (argc > 1 && isdigit(*(argv + 1)[0])) {
- argv++, argc--;
- dest_port = atoi(*argv);
- } else
- dest_port = DEFAULT_PORT;
-#endif
- } else
- usage();
- argv++, argc--;
- }
-
- if (argc > 0)
- usage();
-
- if (debug != 0) {
- struct debugname *d;
- char c;
- int tmpd = debug;
-
- fprintf(stderr, "debug level 0x%x ", debug);
- c = '(';
- for (d = debugnames; d < debugnames +
- sizeof(debugnames) / sizeof(debugnames[0]); d++) {
- if ((tmpd & d->level) == d->level) {
- tmpd &= ~d->level;
- fprintf(stderr, "%c%s", c, d->name);
- c = ',';
- }
- }
- fprintf(stderr, ")\n");
- }
-
-#ifdef LOG_DAEMON
- (void)openlog("mrouted", LOG_PID, LOG_DAEMON);
- (void)setlogmask(LOG_UPTO(LOG_NOTICE));
-#else
- (void)openlog("mrouted", LOG_PID);
-#endif
- sprintf(versionstring, "mrouted version %s", todaysversion);
-
- log(LOG_DEBUG, 0, "%s starting", versionstring);
-
-#ifdef SYSV
- srand48(time(NULL));
-#endif
-
- /*
- * Get generation id
- */
- gettimeofday(&tv, 0);
- dvmrp_genid = tv.tv_sec;
-
- fp = fopen(genidfilename, "r");
- if (fp != NULL) {
- fscanf(fp, "%d", &prev_genid);
- if (prev_genid == dvmrp_genid)
- dvmrp_genid++;
- (void) fclose(fp);
- }
-
- fp = fopen(genidfilename, "w");
- if (fp != NULL) {
- fprintf(fp, "%d", dvmrp_genid);
- (void) fclose(fp);
- }
-
- /* Start up the log rate-limiter */
- resetlogging(NULL);
-
- callout_init();
- init_igmp();
- init_icmp();
- init_ipip();
- init_routes();
- init_ktable();
-#ifndef OLD_KERNEL
- /*
- * Unfortunately, you can't k_get_version() unless you've
- * k_init_dvmrp()'d. Now that we want to move the
- * k_init_dvmrp() to later in the initialization sequence,
- * we have to do the disgusting hack of initializing,
- * getting the version, then stopping the kernel multicast
- * forwarding.
- */
- k_init_dvmrp();
- vers = k_get_version();
- k_stop_dvmrp();
- /*XXX
- * This function must change whenever the kernel version changes
- */
- if ((((vers >> 8) & 0xff) != 3) ||
- ((vers & 0xff) != 5))
- log(LOG_ERR, 0, "kernel (v%d.%d)/mrouted (v%d.%d) version mismatch",
- (vers >> 8) & 0xff, vers & 0xff,
- PROTOCOL_VERSION, MROUTED_VERSION);
-#endif
-
-#ifdef SNMP
- if (i = snmp_init())
- return i;
-
- gettimeofday(nvp, 0);
- if (nvp->tv_usec < 500000L){
- svp->tv_usec = nvp->tv_usec + 500000L;
- svp->tv_sec = nvp->tv_sec;
- } else {
- svp->tv_usec = nvp->tv_usec - 500000L;
- svp->tv_sec = nvp->tv_sec + 1;
- }
-#endif /* SNMP */
-
- init_vifs();
-
-#ifdef RSRR
- rsrr_init();
-#endif /* RSRR */
-
- sa.sa_handler = handler;
- sa.sa_flags = 0; /* Interrupt system calls */
- sigemptyset(&sa.sa_mask);
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGUSR1, &sa, NULL);
- sigaction(SIGUSR2, &sa, NULL);
-
- if (igmp_socket >= FD_SETSIZE)
- log(LOG_ERR, 0, "descriptor too big");
- FD_ZERO(&readers);
- FD_SET(igmp_socket, &readers);
- nfds = igmp_socket + 1;
- for (i = 0; i < nhandlers; i++) {
- if (ihandlers[i].fd >= FD_SETSIZE)
- log(LOG_ERR, 0, "descriptor too big");
- FD_SET(ihandlers[i].fd, &readers);
- if (ihandlers[i].fd >= nfds)
- nfds = ihandlers[i].fd + 1;
- }
-
- IF_DEBUG(DEBUG_IF)
- dump_vifs(stderr);
- IF_DEBUG(DEBUG_ROUTE)
- dump_routes(stderr);
-
- /* schedule first timer interrupt */
- timer_setTimer(1, fasttimer, NULL);
- timer_setTimer(TIMER_INTERVAL, timer, NULL);
-
- if (debug == 0) {
- /*
- * Detach from the terminal
- */
- int t;
-
- haveterminal = 0;
- if (fork()) exit(0);
- (void)close(0);
- (void)close(1);
- (void)close(2);
- (void)open("/", 0);
- (void)dup2(0, 1);
- (void)dup2(0, 2);
-#if defined(SYSV) || defined(linux)
- (void)setpgrp();
-#else
-#ifdef TIOCNOTTY
- t = open(_PATH_TTY, 2);
- if (t >= 0) {
- (void)ioctl(t, TIOCNOTTY, (char *)0);
- (void)close(t);
- }
-#else
- if (setsid() < 0)
- perror("setsid");
-#endif
-#endif
- }
-
- fp = fopen(pidfilename, "w");
- if (fp != NULL) {
- fprintf(fp, "%d\n", (int)getpid());
- (void) fclose(fp);
- }
-
- /* XXX HACK
- * This will cause black holes for the first few seconds after startup,
- * since we are exchanging routes but not actually forwarding.
- * However, it eliminates much of the startup transient.
- *
- * It's possible that we can set a flag which says not to report any
- * routes (just accept reports) until this timer fires, and then
- * do a report_to_all_neighbors(ALL_ROUTES) immediately before
- * turning on DVMRP.
- */
- timer_setTimer(10, final_init, NULL);
-
- /*
- * Main receive loop.
- */
- dummy = 0;
- difftime.tv_usec = 0;
- gettimeofday(&curtime, NULL);
- lasttime = curtime;
- for(;;) {
- bcopy((char *)&readers, (char *)&rfds, sizeof(rfds));
- secs = timer_nextTimer();
- if (secs == -1)
- timeout = NULL;
- else {
- timeout = &tv;
- timeout->tv_sec = secs;
- timeout->tv_usec = 0;
- }
-#ifdef SNMP
- THIS IS BROKEN
- if (nvp->tv_sec > svp->tv_sec
- || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
- alarmTimer(nvp);
- eventTimer(nvp);
- if (nvp->tv_usec < 500000L){
- svp->tv_usec = nvp->tv_usec + 500000L;
- svp->tv_sec = nvp->tv_sec;
- } else {
- svp->tv_usec = nvp->tv_usec - 500000L;
- svp->tv_sec = nvp->tv_sec + 1;
- }
- }
-
- tvp = &timeout;
- tvp->tv_sec = 0;
- tvp->tv_usec = 500000L;
-
- block = 0;
- snmp_select_info(&nfds, &rfds, tvp, &block);
- if (block == 1)
- tvp = NULL; /* block without timeout */
- if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0)
-#endif
- if (sighandled) {
- if (sighandled & GOT_SIGINT) {
- sighandled &= ~GOT_SIGINT;
- break;
- }
- if (sighandled & GOT_SIGHUP) {
- sighandled &= ~GOT_SIGHUP;
- restart();
- }
- if (sighandled & GOT_SIGUSR1) {
- sighandled &= ~GOT_SIGUSR1;
- fdump();
- }
- if (sighandled & GOT_SIGUSR2) {
- sighandled &= ~GOT_SIGUSR2;
- cdump();
- }
- }
- if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
- if (errno != EINTR)
- log(LOG_WARNING, errno, "select failed");
- continue;
- }
-
- if (n > 0) {
- if (FD_ISSET(igmp_socket, &rfds)) {
- recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, NULL, &dummy);
- if (recvlen < 0) {
- if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
- continue;
- }
- accept_igmp(recvlen);
- }
-
- for (i = 0; i < nhandlers; i++) {
- if (FD_ISSET(ihandlers[i].fd, &rfds)) {
- (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
- }
- }
- }
-
-#ifdef SNMP
- THIS IS BROKEN
- snmp_read(&rfds);
- snmp_timeout(); /* poll */
-#endif
- /*
- * Handle timeout queue.
- *
- * If select + packet processing took more than 1 second,
- * or if there is a timeout pending, age the timeout queue.
- *
- * If not, collect usec in difftime to make sure that the
- * time doesn't drift too badly.
- *
- * If the timeout handlers took more than 1 second,
- * age the timeout queue again. XXX This introduces the
- * potential for infinite loops!
- */
- do {
- /*
- * If the select timed out, then there's no other
- * activity to account for and we don't need to
- * call gettimeofday.
- */
- if (n == 0) {
- curtime.tv_sec = lasttime.tv_sec + secs;
- curtime.tv_usec = lasttime.tv_usec;
- n = -1; /* don't do this next time through the loop */
- } else
- gettimeofday(&curtime, NULL);
- difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
- difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
- while (difftime.tv_usec >= 1000000) {
- difftime.tv_sec++;
- difftime.tv_usec -= 1000000;
- }
- if (difftime.tv_usec < 0) {
- difftime.tv_sec--;
- difftime.tv_usec += 1000000;
- }
- lasttime = curtime;
- if (secs == 0 || difftime.tv_sec > 0)
- age_callout_queue(difftime.tv_sec);
- secs = -1;
- } while (difftime.tv_sec > 0);
- }
- log(LOG_NOTICE, 0, "%s exiting", versionstring);
- cleanup();
- exit(0);
-}
-
-static void
-usage()
-{
- fprintf(stderr,
- "usage: mrouted [-p] [-c configfile] [-d [debug_level]]\n");
- exit(1);
-}
-
-static void
-final_init(i)
- void *i;
-{
- char *s = (char *)i;
-
- log(LOG_NOTICE, 0, "%s%s", versionstring, s ? s : "");
- if (s)
- free(s);
-
- k_init_dvmrp(); /* enable DVMRP routing in kernel */
-
- /*
- * Install the vifs in the kernel as late as possible in the
- * initialization sequence.
- */
- init_installvifs();
-
- time(&mrouted_init_time);
- did_final_init = 1;
-}
-
-/*
- * routine invoked every second. Its main goal is to cycle through
- * the routing table and send partial updates to all neighbors at a
- * rate that will cause the entire table to be sent in ROUTE_REPORT_INTERVAL
- * seconds. Also, every TIMER_INTERVAL seconds it calls timer() to
- * do all the other time-based processing.
- */
-static void
-fasttimer(i)
- void *i;
-{
- static unsigned int tlast;
- static unsigned int nsent;
- register unsigned int t = tlast + 1;
- register int n;
-
- /*
- * if we're in the last second, send everything that's left.
- * otherwise send at least the fraction we should have sent by now.
- */
- if (t >= ROUTE_REPORT_INTERVAL) {
- register int nleft = nroutes - nsent;
- while (nleft > 0) {
- if ((n = report_next_chunk()) <= 0)
- break;
- nleft -= n;
- }
- tlast = 0;
- nsent = 0;
- } else {
- register unsigned int ncum = nroutes * t / ROUTE_REPORT_INTERVAL;
- while (nsent < ncum) {
- if ((n = report_next_chunk()) <= 0)
- break;
- nsent += n;
- }
- tlast = t;
- }
-
- timer_setTimer(1, fasttimer, NULL);
-}
-
-/*
- * The 'virtual_time' variable is initialized to a value that will cause the
- * first invocation of timer() to send a probe or route report to all vifs
- * and send group membership queries to all subnets for which this router is
- * querier. This first invocation occurs approximately TIMER_INTERVAL seconds
- * after the router starts up. Note that probes for neighbors and queries
- * for group memberships are also sent at start-up time, as part of initial-
- * ization. This repetition after a short interval is desirable for quickly
- * building up topology and membership information in the presence of possible
- * packet loss.
- *
- * 'virtual_time' advances at a rate that is only a crude approximation of
- * real time, because it does not take into account any time spent processing,
- * and because the timer intervals are sometimes shrunk by a random amount to
- * avoid unwanted synchronization with other routers.
- */
-
-u_long virtual_time = 0;
-
-
-/*
- * Timer routine. Performs periodic neighbor probing, route reporting, and
- * group querying duties, and drives various timers in routing entries and
- * virtual interface data structures.
- */
-static void
-timer(i)
- void *i;
-{
- age_routes(); /* Advance the timers in the route entries */
- age_vifs(); /* Advance the timers for neighbors */
- age_table_entry(); /* Advance the timers for the cache entries */
-
- if (virtual_time % IGMP_QUERY_INTERVAL == 0) {
- /*
- * Time to query the local group memberships on all subnets
- * for which this router is the elected querier.
- */
- query_groups();
- }
-
- if (virtual_time % NEIGHBOR_PROBE_INTERVAL == 0) {
- /*
- * Time to send a probe on all vifs from which no neighbors have
- * been heard. Also, check if any inoperative interfaces have now
- * come up. (If they have, they will also be probed as part of
- * their initialization.)
- */
- probe_for_neighbors();
-
- if (vifs_down)
- check_vif_state();
- }
-
- delay_change_reports = FALSE;
- if (routes_changed) {
- /*
- * Some routes have changed since the last timer interrupt, but
- * have not been reported yet. Report the changed routes to all
- * neighbors.
- */
- report_to_all_neighbors(CHANGED_ROUTES);
- }
-
-#ifdef SNMP
- sync_timer();
-#endif
-
- /*
- * Advance virtual time
- */
- virtual_time += TIMER_INTERVAL;
- timer_setTimer(TIMER_INTERVAL, timer, NULL);
-}
-
-
-static void
-cleanup()
-{
- static int in_cleanup = 0;
-
- if (!in_cleanup) {
- in_cleanup++;
-#ifdef RSRR
- rsrr_clean();
-#endif /* RSRR */
- expire_all_routes();
- report_to_all_neighbors(ALL_ROUTES);
- if (did_final_init)
- k_stop_dvmrp();
- }
-}
-
-/*
- * Signal handler. Take note of the fact that the signal arrived
- * so that the main loop can take care of it.
- */
-static void
-handler(sig)
- int sig;
-{
- switch (sig) {
- case SIGINT:
- case SIGTERM:
- sighandled |= GOT_SIGINT;
- break;
-
- case SIGHUP:
- sighandled |= GOT_SIGHUP;
- break;
-
- case SIGUSR1:
- sighandled |= GOT_SIGUSR1;
- break;
-
- case SIGUSR2:
- sighandled |= GOT_SIGUSR2;
- break;
- }
-}
-
-/*
- * Dump internal data structures to stderr.
- */
-static void
-dump()
-{
- dump_vifs(stderr);
- dump_routes(stderr);
-}
-
-static void
-dump_version(fp)
- FILE *fp;
-{
- time_t t;
-
- time(&t);
- fprintf(fp, "%s ", versionstring);
- if (did_final_init)
- fprintf(fp, "up %s",
- scaletime(t - mrouted_init_time));
- else
- fprintf(fp, "(not yet initialized)");
- fprintf(fp, " %s\n", ctime(&t));
-}
-
-/*
- * Dump internal data structures to a file.
- */
-static void
-fdump()
-{
- FILE *fp;
-
- fp = fopen(dumpfilename, "w");
- if (fp != NULL) {
- dump_version(fp);
- dump_vifs(fp);
- dump_routes(fp);
- (void) fclose(fp);
- }
-}
-
-
-/*
- * Dump local cache contents to a file.
- */
-static void
-cdump()
-{
- FILE *fp;
-
- fp = fopen(cachefilename, "w");
- if (fp != NULL) {
- dump_version(fp);
- dump_cache(fp);
- (void) fclose(fp);
- }
-}
-
-
-/*
- * Restart mrouted
- */
-static void
-restart()
-{
- char *s;
-
- s = (char *)malloc(sizeof(" restart"));
- if (s == NULL)
- log(LOG_ERR, 0, "out of memory");
- strcpy(s, " restart");
-
- /*
- * reset all the entries
- */
- free_all_prunes();
- free_all_routes();
- free_all_callouts();
- stop_all_vifs();
- k_stop_dvmrp();
- close(igmp_socket);
- close(udp_socket);
- did_final_init = 0;
-
- /*
- * start processing again
- */
- dvmrp_genid++;
-
- init_igmp();
- init_routes();
- init_ktable();
- init_vifs();
- /*XXX Schedule final_init() as main does? */
- final_init(s);
-
- /* schedule timer interrupts */
- timer_setTimer(1, fasttimer, NULL);
- timer_setTimer(TIMER_INTERVAL, timer, NULL);
-}
-
-#define LOG_MAX_MSGS 20 /* if > 20/minute then shut up for a while */
-#define LOG_SHUT_UP 600 /* shut up for 10 minutes */
-static int log_nmsgs = 0;
-
-static void
-resetlogging(arg)
- void *arg;
-{
- int nxttime = 60;
- void *narg = NULL;
-
- if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) {
- nxttime = LOG_SHUT_UP;
- narg = (void *)&log_nmsgs; /* just need some valid void * */
- syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes",
- LOG_SHUT_UP / 60);
- } else {
- log_nmsgs = 0;
- }
-
- timer_setTimer(nxttime, resetlogging, narg);
-}
-
-char *
-scaletime(t)
- u_long t;
-{
-#define SCALETIMEBUFLEN 20
- static char buf1[20];
- static char buf2[20];
- static char *buf = buf1;
- char *p;
-
- p = buf;
- if (buf == buf1)
- buf = buf2;
- else
- buf = buf1;
-
- /* XXX snprintf */
- sprintf(p, "%2ld:%02ld:%02ld", t / 3600, (t % 3600) / 60, t % 60);
- p[SCALETIMEBUFLEN - 1] = '\0';
- return p;
-}
-
-#ifdef RINGBUFFER
-#define NLOGMSGS 10000
-#define LOGMSGSIZE 200
-char *logmsg[NLOGMSGS];
-static int logmsgno = 0;
-
-void
-printringbuf()
-{
- FILE *f;
- int i;
-
- f = fopen("/var/tmp/mrouted.log", "a");
- if (f == NULL) {
- log(LOG_ERR, errno, "can't open /var/tmp/mrouted.log");
- /*NOTREACHED*/
- }
- fprintf(f, "--------------------------------------------\n");
-
- i = (logmsgno + 1) % NLOGMSGS;
-
- while (i != logmsgno) {
- if (*logmsg[i]) {
- fprintf(f, "%s\n", logmsg[i]);
- *logmsg[i] = '\0';
- }
- i = (i + 1) % NLOGMSGS;
- }
-
- fclose(f);
-}
-#endif
-
-/*
- * Log errors and other messages to the system log daemon and 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;
- static char fmt[211] = "warning - ";
- char *msg;
- struct timeval now;
- time_t now_sec;
- struct tm *thyme;
-#ifdef RINGBUFFER
- static int ringbufinit = 0;
-#endif
-
- va_start(ap, format);
-#else
-/*VARARGS3*/
-void
-log(severity, syserr, format, va_alist)
- int severity, syserr;
- char *format;
- va_dcl
-{
- va_list ap;
- static char fmt[311] = "warning - ";
- char *msg;
- char tbuf[20];
- struct timeval now;
- time_t now_sec;
- struct tm *thyme;
-#ifdef RINGBUFFER
- static int ringbufinit = 0;
-#endif
-
- va_start(ap);
-#endif
- vsnprintf(&fmt[10], sizeof(fmt) - 10, format, ap);
- va_end(ap);
- msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
-
-#ifdef RINGBUFFER
- if (!ringbufinit) {
- int i;
-
- for (i = 0; i < NLOGMSGS; i++) {
- logmsg[i] = malloc(LOGMSGSIZE);
- if (logmsg[i] == 0) {
- syslog(LOG_ERR, "out of memory");
- exit(-1);
- }
- *logmsg[i] = 0;
- }
- ringbufinit = 1;
- }
- gettimeofday(&now,NULL);
- now_sec = now.tv_sec;
- thyme = localtime(&now_sec);
- snprintf(logmsg[logmsgno++], LOGMSGSIZE, "%02d:%02d:%02d.%03ld %s err %d",
- thyme->tm_hour, thyme->tm_min, thyme->tm_sec,
- now.tv_usec / 1000, msg, syserr);
- logmsgno %= NLOGMSGS;
- if (severity <= LOG_NOTICE)
-#endif
- /*
- * Log to stderr if we haven't forked yet and it's a warning or worse,
- * or if we're debugging.
- */
- if (haveterminal && (debug || severity <= LOG_WARNING)) {
- gettimeofday(&now,NULL);
- now_sec = now.tv_sec;
- thyme = localtime(&now_sec);
- if (!debug)
- fprintf(stderr, "%s: ", progname);
- fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour,
- thyme->tm_min, thyme->tm_sec, now.tv_usec / 1000, msg);
- 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);
- }
-
- /*
- * Always log things that are worse than warnings, no matter what
- * the log_nmsgs rate limiter says.
- * Only count things worse than debugging in the rate limiter
- * (since if you put daemon.debug in syslog.conf you probably
- * actually want to log the debugging messages so they shouldn't
- * be rate-limited)
- */
- if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
- if (severity < LOG_DEBUG)
- log_nmsgs++;
- if (syserr != 0) {
- errno = syserr;
- syslog(severity, "%s: %m", msg);
- } else
- syslog(severity, "%s", msg);
- }
-
- if (severity <= LOG_ERR) exit(-1);
-}
-
-#ifdef DEBUG_MFC
-void
-md_log(what, origin, mcastgrp)
- int what;
- u_int32 origin, mcastgrp;
-{
- static FILE *f = NULL;
- struct timeval tv;
- u_int32 buf[4];
-
- if (!f) {
- if ((f = fopen("/tmp/mrouted.clog", "w")) == NULL) {
- log(LOG_ERR, errno, "open /tmp/mrouted.clog");
- }
- }
-
- gettimeofday(&tv, NULL);
- buf[0] = tv.tv_sec;
- buf[1] = what;
- buf[2] = origin;
- buf[3] = mcastgrp;
-
- fwrite(buf, sizeof(u_int32), 4, f);
-}
-#endif
diff --git a/usr.sbin/mrouted/map-mbone.8 b/usr.sbin/mrouted/map-mbone.8
deleted file mode 100644
index a6e9e5841c27..000000000000
--- a/usr.sbin/mrouted/map-mbone.8
+++ /dev/null
@@ -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
diff --git a/usr.sbin/mrouted/map-mbone/Makefile b/usr.sbin/mrouted/map-mbone/Makefile
deleted file mode 100644
index f99247b62500..000000000000
--- a/usr.sbin/mrouted/map-mbone/Makefile
+++ /dev/null
@@ -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>
diff --git a/usr.sbin/mrouted/mapper.c b/usr.sbin/mrouted/mapper.c
deleted file mode 100644
index 8fdbad0687e0..000000000000
--- a/usr.sbin/mrouted/mapper.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-/* Mapper for connections between MRouteD multicast routers.
- * Written by Pavel Curtis <Pavel@PARC.Xerox.Com>
- *
- * mapper.c,v 3.8.4.3 1998/01/06 01:57:47 fenner Exp
- */
-
-/*
- * 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$";
-#endif /* not lint */
-
-#include <err.h>
-#include <string.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 2 /* How long to wait before retrying requests */
-#define DEFAULT_RETRIES 1 /* How many times to ask each router */
-
-
-/* All IP addresses are stored in the data structure in NET order. */
-
-typedef struct neighbor {
- struct neighbor *next;
- u_int32 addr; /* IP address in NET order */
- u_char metric; /* TTL cost of forwarding */
- u_char threshold; /* TTL threshold to forward */
- u_short flags; /* flags on connection */
-#define NF_PRESENT 0x8000 /* True if flags are meaningful */
-} Neighbor;
-
-typedef struct interface {
- struct interface *next;
- u_int32 addr; /* IP address of the interface in NET order */
- Neighbor *neighbors; /* List of neighbors' IP addresses */
-} Interface;
-
-typedef struct node {
- u_int32 addr; /* IP address of this entry in NET order */
- u_int32 version; /* which mrouted version is running */
- int tries; /* How many requests sent? -1 for aliases */
- union {
- struct node *alias; /* If alias, to what? */
- struct interface *interfaces; /* Else, neighbor data */
- } u;
- struct node *left, *right;
-} Node;
-
-
-Node *routers = 0;
-u_int32 our_addr, target_addr = 0; /* in NET order */
-int debug = 0;
-int retries = DEFAULT_RETRIES;
-int timeout = DEFAULT_TIMEOUT;
-int show_names = TRUE;
-vifi_t numvifs; /* to keep loader happy */
- /* (see COPY_TABLES macro called in kern.c) */
-
-Node * find_node __P((u_int32 addr, Node **ptr));
-Interface * find_interface __P((u_int32 addr, Node *node));
-Neighbor * find_neighbor __P((u_int32 addr, Node *node));
-int main __P((int argc, char *argv[]));
-void ask __P((u_int32 dst));
-void ask2 __P((u_int32 dst));
-int retry_requests __P((Node *node));
-char * inet_name __P((u_int32 addr));
-void print_map __P((Node *node));
-char * graph_name __P((u_int32 addr, char *buf, int len));
-void graph_edges __P((Node *node));
-void elide_aliases __P((Node *node));
-void graph_map __P((void));
-int get_number __P((int *var, int deflt, char ***pargv,
- int *pargc));
-u_int32 host_addr __P((char *name));
-static void usage __P((void));
-
-
-Node *find_node(addr, ptr)
- u_int32 addr;
- Node **ptr;
-{
- Node *n = *ptr;
-
- if (!n) {
- *ptr = n = (Node *) malloc(sizeof(Node));
- n->addr = addr;
- n->version = 0;
- n->tries = 0;
- n->u.interfaces = 0;
- n->left = n->right = 0;
- return n;
- } else if (addr == n->addr)
- return n;
- else if (addr < n->addr)
- return find_node(addr, &(n->left));
- else
- return find_node(addr, &(n->right));
-}
-
-
-Interface *find_interface(addr, node)
- u_int32 addr;
- Node *node;
-{
- Interface *ifc;
-
- for (ifc = node->u.interfaces; ifc; ifc = ifc->next)
- if (ifc->addr == addr)
- return ifc;
-
- ifc = (Interface *) malloc(sizeof(Interface));
- ifc->addr = addr;
- ifc->next = node->u.interfaces;
- node->u.interfaces = ifc;
- ifc->neighbors = 0;
-
- return ifc;
-}
-
-
-Neighbor *find_neighbor(addr, node)
- u_int32 addr;
- Node *node;
-{
- Interface *ifc;
-
- for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
- Neighbor *nb;
-
- for (nb = ifc->neighbors; nb; nb = nb->next)
- if (nb->addr == addr)
- return nb;
- }
-
- return 0;
-}
-
-
-/*
- * 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
-/*VARARGS3*/
-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 group membership report.
- */
-void accept_group_report(src, dst, group, r_type)
- u_int32 src, dst, group;
- int r_type;
-{
- log(LOG_INFO, 0, "ignoring IGMP group membership report from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-
-/*
- * Process an incoming neighbor probe message.
- */
-void accept_probe(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- char *p;
- int datalen;
-{
- log(LOG_INFO, 0, "ignoring DVMRP probe from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-
-/*
- * Process an incoming route report message.
- */
-void accept_report(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- char *p;
- int datalen;
-{
- log(LOG_INFO, 0, "ignoring DVMRP routing report from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-
-/*
- * Process an incoming neighbor-list request message.
- */
-void accept_neighbor_request(src, dst)
- u_int32 src, dst;
-{
- if (src != our_addr)
- log(LOG_INFO, 0,
- "ignoring spurious DVMRP neighbor request from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-void accept_neighbor_request2(src, dst)
- u_int32 src, dst;
-{
- if (src != our_addr)
- log(LOG_INFO, 0,
- "ignoring spurious DVMRP neighbor request2 from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-
-/*
- * Process an incoming neighbor-list message.
- */
-void accept_neighbors(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- u_char *p;
- int datalen;
-{
- Node *node = find_node(src, &routers);
-
- if (node->tries == 0) /* Never heard of 'em; must have hit them at */
- node->tries = 1; /* least once, though...*/
- else if (node->tries == -1) /* follow alias link */
- node = node->u.alias;
-
-#define GET_ADDR(a) (a = ((u_int32)*p++ << 24), a += ((u_int32)*p++ << 16),\
- a += ((u_int32)*p++ << 8), a += *p++)
-
- /* if node is running a recent mrouted, ask for additional info */
- if (level != 0) {
- node->version = level;
- node->tries = 1;
- ask2(src);
- return;
- }
-
- if (debug > 3) {
- int i;
-
- fprintf(stderr, " datalen = %d\n", datalen);
- for (i = 0; i < datalen; i++) {
- if ((i & 0xF) == 0)
- fprintf(stderr, " ");
- fprintf(stderr, " %02x", p[i]);
- if ((i & 0xF) == 0xF)
- fprintf(stderr, "\n");
- }
- if ((datalen & 0xF) != 0xF)
- fprintf(stderr, "\n");
- }
-
- while (datalen > 0) { /* loop through interfaces */
- u_int32 ifc_addr;
- u_char metric, threshold, ncount;
- Node *ifc_node;
- Interface *ifc;
- Neighbor *old_neighbors;
-
- if (datalen < 4 + 3) {
- log(LOG_WARNING, 0, "received truncated interface record from %s",
- inet_fmt(src, s1));
- return;
- }
-
- GET_ADDR(ifc_addr);
- ifc_addr = htonl(ifc_addr);
- metric = *p++;
- threshold = *p++;
- ncount = *p++;
- datalen -= 4 + 3;
-
- /* Fix up any alias information */
- ifc_node = find_node(ifc_addr, &routers);
- if (ifc_node->tries == 0) { /* new node */
- ifc_node->tries = -1;
- ifc_node->u.alias = node;
- } else if (ifc_node != node
- && (ifc_node->tries > 0 || ifc_node->u.alias != node)) {
- /* must merge two hosts' nodes */
- Interface *ifc_i, *next_ifc_i;
-
- if (ifc_node->tries == -1) {
- Node *tmp = ifc_node->u.alias;
-
- ifc_node->u.alias = node;
- ifc_node = tmp;
- }
-
- /* Merge ifc_node (foo_i) into node (foo_n) */
-
- if (ifc_node->tries > node->tries)
- node->tries = ifc_node->tries;
-
- for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) {
- Neighbor *nb_i, *next_nb_i, *nb_n;
- Interface *ifc_n = find_interface(ifc_i->addr, node);
-
- old_neighbors = ifc_n->neighbors;
- for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) {
- next_nb_i = nb_i->next;
- for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next)
- if (nb_i->addr == nb_n->addr) {
- if (nb_i->metric != nb_n->metric
- || nb_i->threshold != nb_n->threshold)
- log(LOG_WARNING, 0,
- "inconsistent %s for neighbor %s of %s",
- "metric/threshold",
- inet_fmt(nb_i->addr, s1),
- inet_fmt(node->addr, s2));
- free(nb_i);
- break;
- }
- if (!nb_n) { /* no match for this neighbor yet */
- nb_i->next = ifc_n->neighbors;
- ifc_n->neighbors = nb_i;
- }
- }
-
- next_ifc_i = ifc_i->next;
- free(ifc_i);
- }
-
- ifc_node->tries = -1;
- ifc_node->u.alias = node;
- }
-
- ifc = find_interface(ifc_addr, node);
- old_neighbors = ifc->neighbors;
-
- /* Add the neighbors for this interface */
- while (ncount--) {
- u_int32 neighbor;
- Neighbor *nb;
- Node *n_node;
-
- if (datalen < 4) {
- log(LOG_WARNING, 0, "received truncated neighbor list from %s",
- inet_fmt(src, s1));
- return;
- }
-
- GET_ADDR(neighbor);
- neighbor = htonl(neighbor);
- datalen -= 4;
-
- for (nb = old_neighbors; nb; nb = nb->next)
- if (nb->addr == neighbor) {
- if (metric != nb->metric || threshold != nb->threshold)
- log(LOG_WARNING, 0,
- "inconsistent %s for neighbor %s of %s",
- "metric/threshold",
- inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2));
- goto next_neighbor;
- }
-
- nb = (Neighbor *) malloc(sizeof(Neighbor));
- nb->next = ifc->neighbors;
- ifc->neighbors = nb;
- nb->addr = neighbor;
- nb->metric = metric;
- nb->threshold = threshold;
- nb->flags = 0;
-
- n_node = find_node(neighbor, &routers);
- if (n_node->tries == 0 && !target_addr) { /* it's a new router */
- ask(neighbor);
- n_node->tries = 1;
- }
-
- next_neighbor: ;
- }
- }
-}
-
-void accept_neighbors2(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- u_char *p;
- int datalen;
-{
- Node *node = find_node(src, &routers);
- u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */
- /* well, only possibly_broken_cisco, but that's too long to type. */
-
- if (node->tries == 0) /* Never heard of 'em; must have hit them at */
- node->tries = 1; /* least once, though...*/
- else if (node->tries == -1) /* follow alias link */
- node = node->u.alias;
-
- while (datalen > 0) { /* loop through interfaces */
- u_int32 ifc_addr;
- u_char metric, threshold, ncount, flags;
- Node *ifc_node;
- Interface *ifc;
- Neighbor *old_neighbors;
-
- if (datalen < 4 + 4) {
- log(LOG_WARNING, 0, "received truncated interface record from %s",
- inet_fmt(src, s1));
- return;
- }
-
- ifc_addr = *(u_int32*)p;
- p += 4;
- metric = *p++;
- threshold = *p++;
- flags = *p++;
- ncount = *p++;
- datalen -= 4 + 4;
-
- if (broken_cisco && ncount == 0) /* dumb Ciscos */
- ncount = 1;
- if (broken_cisco && ncount > 15) /* dumb Ciscos */
- ncount = ncount & 0xf;
-
- /* Fix up any alias information */
- ifc_node = find_node(ifc_addr, &routers);
- if (ifc_node->tries == 0) { /* new node */
- ifc_node->tries = -1;
- ifc_node->u.alias = node;
- } else if (ifc_node != node
- && (ifc_node->tries > 0 || ifc_node->u.alias != node)) {
- /* must merge two hosts' nodes */
- Interface *ifc_i, *next_ifc_i;
-
- if (ifc_node->tries == -1) {
- Node *tmp = ifc_node->u.alias;
-
- ifc_node->u.alias = node;
- ifc_node = tmp;
- }
-
- /* Merge ifc_node (foo_i) into node (foo_n) */
-
- if (ifc_node->tries > node->tries)
- node->tries = ifc_node->tries;
-
- for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) {
- Neighbor *nb_i, *next_nb_i, *nb_n;
- Interface *ifc_n = find_interface(ifc_i->addr, node);
-
- old_neighbors = ifc_n->neighbors;
- for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) {
- next_nb_i = nb_i->next;
- for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next)
- if (nb_i->addr == nb_n->addr) {
- if (nb_i->metric != nb_n->metric
- || nb_i->threshold != nb_i->threshold)
- log(LOG_WARNING, 0,
- "inconsistent %s for neighbor %s of %s",
- "metric/threshold",
- inet_fmt(nb_i->addr, s1),
- inet_fmt(node->addr, s2));
- free(nb_i);
- break;
- }
- if (!nb_n) { /* no match for this neighbor yet */
- nb_i->next = ifc_n->neighbors;
- ifc_n->neighbors = nb_i;
- }
- }
-
- next_ifc_i = ifc_i->next;
- free(ifc_i);
- }
-
- ifc_node->tries = -1;
- ifc_node->u.alias = node;
- }
-
- ifc = find_interface(ifc_addr, node);
- old_neighbors = ifc->neighbors;
-
- /* Add the neighbors for this interface */
- while (ncount-- && datalen > 0) {
- u_int32 neighbor;
- Neighbor *nb;
- Node *n_node;
-
- if (datalen < 4) {
- log(LOG_WARNING, 0, "received truncated neighbor list from %s",
- inet_fmt(src, s1));
- return;
- }
-
- neighbor = *(u_int32*)p;
- p += 4;
- datalen -= 4;
- if (neighbor == 0)
- /* make leaf nets point to themselves */
- neighbor = ifc_addr;
-
- for (nb = old_neighbors; nb; nb = nb->next)
- if (nb->addr == neighbor) {
- if (metric != nb->metric || threshold != nb->threshold)
- log(LOG_WARNING, 0,
- "inconsistent %s for neighbor %s of %s",
- "metric/threshold",
- inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2));
- goto next_neighbor;
- }
-
- nb = (Neighbor *) malloc(sizeof(Neighbor));
- nb->next = ifc->neighbors;
- ifc->neighbors = nb;
- nb->addr = neighbor;
- nb->metric = metric;
- nb->threshold = threshold;
- nb->flags = flags | NF_PRESENT;
-
- n_node = find_node(neighbor, &routers);
- if (n_node->tries == 0 && !target_addr) { /* it's a new router */
- ask(neighbor);
- n_node->tries = 1;
- }
-
- next_neighbor: ;
- }
- }
-}
-
-
-void check_vif_state()
-{
- log(LOG_NOTICE, 0, "network marked down...");
-}
-
-
-int retry_requests(node)
- Node *node;
-{
- int result;
-
- if (node) {
- result = retry_requests(node->left);
- if (node->tries > 0 && node->tries < retries) {
- if (node->version)
- ask2(node->addr);
- else
- ask(node->addr);
- node->tries++;
- result = 1;
- }
- return retry_requests(node->right) || result;
- } else
- return 0;
-}
-
-
-char *inet_name(addr)
- u_int32 addr;
-{
- struct hostent *e;
-
- e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
-
- return e ? e->h_name : 0;
-}
-
-
-void print_map(node)
- Node *node;
-{
- if (node) {
- char *name, *addr;
-
- print_map(node->left);
-
- addr = inet_fmt(node->addr, s1);
- if (!target_addr
- || (node->tries >= 0 && node->u.interfaces)
- || (node->tries == -1
- && node->u.alias->tries >= 0
- && node->u.alias->u.interfaces)) {
- if (show_names && (name = inet_name(node->addr)))
- printf("%s (%s):", addr, name);
- else
- printf("%s:", addr);
- if (node->tries < 0)
- printf(" alias for %s\n\n", inet_fmt(node->u.alias->addr, s1));
- else if (!node->u.interfaces)
- printf(" no response to query\n\n");
- else {
- Interface *ifc;
-
- if (node->version)
- printf(" <v%d.%d>", node->version & 0xff,
- (node->version >> 8) & 0xff);
- printf("\n");
- for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
- Neighbor *nb;
- char *ifc_name = inet_fmt(ifc->addr, s1);
- int ifc_len = strlen(ifc_name);
- int count = 0;
-
- printf(" %s:", ifc_name);
- for (nb = ifc->neighbors; nb; nb = nb->next) {
- if (count > 0)
- printf("%*s", ifc_len + 5, "");
- printf(" %s", inet_fmt(nb->addr, s1));
- if (show_names && (name = inet_name(nb->addr)))
- printf(" (%s)", name);
- printf(" [%d/%d", nb->metric, nb->threshold);
- if (nb->flags) {
- u_short flags = nb->flags;
- if (flags & DVMRP_NF_TUNNEL)
- printf("/tunnel");
- if (flags & DVMRP_NF_SRCRT)
- printf("/srcrt");
- if (flags & DVMRP_NF_QUERIER)
- printf("/querier");
- if (flags & DVMRP_NF_DISABLED)
- printf("/disabled");
- if (flags & DVMRP_NF_DOWN)
- printf("/down");
- }
- printf("]\n");
- count++;
- }
- }
- printf("\n");
- }
- }
- print_map(node->right);
- }
-}
-
-
-char *graph_name(addr, buf, len)
- u_int32 addr;
- char *buf;
- int len;
-{
- char *name;
-
- if (len < sizeof("255.255.255.255")) {
- fprintf(stderr,
-"Buffer too small in graph_name, provided %d bytes, but needed %d.\n",
- len, sizeof("255.255.255.255"));
- return NULL;
- }
- if (show_names && (name = inet_name(addr))) {
- strncpy(buf, name, len - 1);
- buf[len - 1] = '\0';
- } else
- inet_fmt(addr, buf);
-
- return buf;
-}
-
-
-void graph_edges(node)
- Node *node;
-{
- Interface *ifc;
- Neighbor *nb;
- char name[100];
-
- if (node) {
- graph_edges(node->left);
- if (node->tries >= 0) {
- printf(" %d {$ NP %d0 %d0 $} \"%s%s\" \n",
- (int) node->addr,
- node->addr & 0xFF, (node->addr >> 8) & 0xFF,
- graph_name(node->addr, name, sizeof(name)),
- node->u.interfaces ? "" : "*");
- for (ifc = node->u.interfaces; ifc; ifc = ifc->next)
- for (nb = ifc->neighbors; nb; nb = nb->next) {
- Node *nb_node = find_node(nb->addr, &routers);
- Neighbor *nb2;
-
- if (nb_node->tries < 0)
- nb_node = nb_node->u.alias;
-
- if (node != nb_node &&
- (!(nb2 = find_neighbor(node->addr, nb_node))
- || node->addr < nb_node->addr)) {
- printf(" %d \"%d/%d",
- nb_node->addr, nb->metric, nb->threshold);
- if (nb2 && (nb2->metric != nb->metric
- || nb2->threshold != nb->threshold))
- printf(",%d/%d", nb2->metric, nb2->threshold);
- if (nb->flags & NF_PRESENT)
- printf("%s%s",
- nb->flags & DVMRP_NF_SRCRT ? "" :
- nb->flags & DVMRP_NF_TUNNEL ? "E" : "P",
- nb->flags & DVMRP_NF_DOWN ? "D" : "");
- printf("\"\n");
- }
- }
- printf(" ;\n");
- }
- graph_edges(node->right);
- }
-}
-
-void elide_aliases(node)
- Node *node;
-{
- if (node) {
- elide_aliases(node->left);
- if (node->tries >= 0) {
- Interface *ifc;
-
- for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
- Neighbor *nb;
-
- for (nb = ifc->neighbors; nb; nb = nb->next) {
- Node *nb_node = find_node(nb->addr, &routers);
-
- if (nb_node->tries < 0)
- nb->addr = nb_node->u.alias->addr;
- }
- }
- }
- elide_aliases(node->right);
- }
-}
-
-void graph_map()
-{
- time_t now = time(0);
- char *nowstr = ctime(&now);
-
- nowstr[24] = '\0'; /* Kill the newline at the end */
- elide_aliases(routers);
- printf("GRAPH \"Multicast Router Connectivity: %s\" = UNDIRECTED\n",
- nowstr);
- graph_edges(routers);
- printf("END\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;
- }
- }
-}
-
-
-u_int32 host_addr(name)
- char *name;
-{
- struct hostent *e = gethostbyname(name);
- int addr;
-
- if (e && e->h_length == sizeof(addr))
- memcpy(&addr, e->h_addr_list[0], e->h_length);
- else {
- addr = inet_addr(name);
- if (addr == -1)
- addr = 0;
- }
-
- return addr;
-}
-
-
-int main(argc, argv)
- int argc;
- char *argv[];
-{
- int flood = FALSE, graph = FALSE;
-
- 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 'f':
- flood = TRUE;
- break;
- case 'g':
- graph = TRUE;
- break;
- case 'n':
- show_names = FALSE;
- 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();
- } else if (argc == 1 && !(target_addr = host_addr(argv[0])))
- errx(2, "unknown host: %s", argv[0]);
-
- if (debug)
- fprintf(stderr, "Debug level %u\n", debug);
-
- { /* 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 = dvmrp_group;
- 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;
- }
-
- /* Send initial seed message to all local routers */
- ask(target_addr ? target_addr : allhosts_group);
-
- if (target_addr) {
- Node *n = find_node(target_addr, &routers);
-
- n->tries = 1;
-
- if (flood)
- target_addr = 0;
- }
-
- /* Main receive loop */
- for(;;) {
- fd_set fds;
- struct timeval tv;
- int count, recvlen, dummy = 0;
-
- if (igmp_socket >= FD_SETSIZE)
- log(LOG_ERR, 0, "descriptor too big");
- FD_ZERO(&fds);
- FD_SET(igmp_socket, &fds);
-
- tv.tv_sec = timeout;
- 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 (retry_requests(routers))
- continue;
- else
- break;
- }
-
- recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, NULL, &dummy);
- if (recvlen >= 0)
- accept_igmp(recvlen);
- else if (errno != EINTR)
- warn("recvfrom");
- }
-
- printf("\n");
-
- if (graph)
- graph_map();
- else {
- if (!target_addr)
- printf("Multicast Router Connectivity:\n\n");
- print_map(routers);
- }
-
- exit(0);
-}
-
-static void
-usage()
-{
- fprintf(stderr, "%s\n%s\n",
- "usage: map-mbone [-f] [-g] [-n] [-t timeout] [-r retries]",
- " [-d [debug-level]] [router]");
- exit(1);
-}
-
-/* dummies */
-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 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;
-{
-}
diff --git a/usr.sbin/mrouted/mrinfo.8 b/usr.sbin/mrouted/mrinfo.8
deleted file mode 100644
index 94f8f0a16755..000000000000
--- a/usr.sbin/mrouted/mrinfo.8
+++ /dev/null
@@ -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
diff --git a/usr.sbin/mrouted/mrinfo.c b/usr.sbin/mrouted/mrinfo.c
deleted file mode 100644
index 1df65770eba5..000000000000
--- a/usr.sbin/mrouted/mrinfo.c
+++ /dev/null
@@ -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;
-{
-}
diff --git a/usr.sbin/mrouted/mrinfo/Makefile b/usr.sbin/mrouted/mrinfo/Makefile
deleted file mode 100644
index f111aa981663..000000000000
--- a/usr.sbin/mrouted/mrinfo/Makefile
+++ /dev/null
@@ -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>
diff --git a/usr.sbin/mrouted/mrouted.8 b/usr.sbin/mrouted/mrouted.8
deleted file mode 100644
index 5713914c4fd6..000000000000
--- a/usr.sbin/mrouted/mrouted.8
+++ /dev/null
@@ -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 .
diff --git a/usr.sbin/mrouted/mrouted.conf b/usr.sbin/mrouted/mrouted.conf
deleted file mode 100644
index e9cb04c3ed6e..000000000000
--- a/usr.sbin/mrouted/mrouted.conf
+++ /dev/null
@@ -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"
diff --git a/usr.sbin/mrouted/mrouted/Makefile b/usr.sbin/mrouted/mrouted/Makefile
deleted file mode 100644
index afd3af82342d..000000000000
--- a/usr.sbin/mrouted/mrouted/Makefile
+++ /dev/null
@@ -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>
diff --git a/usr.sbin/mrouted/mtrace.8 b/usr.sbin/mrouted/mtrace.8
deleted file mode 100644
index cd8d67dc70ac..000000000000
--- a/usr.sbin/mrouted/mtrace.8
+++ /dev/null
@@ -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.
diff --git a/usr.sbin/mrouted/mtrace.c b/usr.sbin/mrouted/mtrace.c
deleted file mode 100644
index 9cb53e3dcc6c..000000000000
--- a/usr.sbin/mrouted/mtrace.c
+++ /dev/null
@@ -1,3177 +0,0 @@
-/*
- * mtrace.c
- *
- * This tool traces the branch of a multicast tree from a source to a
- * receiver for a particular multicast group and gives statistics
- * about packet rate and loss for each hop along the path. It can
- * usually be invoked just as
- *
- * mtrace source
- *
- * to trace the route from that source to the local host for a default
- * group when only the route is desired and not group-specific packet
- * counts. See the usage line for more complex forms.
- *
- *
- * Released 4 Apr 1995. This program was adapted by Steve Casner
- * (USC/ISI) from a prototype written by Ajit Thyagarajan (UDel and
- * Xerox PARC). It attempts to parallel in command syntax and output
- * format the unicast traceroute program written by Van Jacobson (LBL)
- * for the parts where that makes sense.
- *
- * 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 any 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.
- *
- * Parts of this software are derived from mrouted, which has the
- * following license:
- *
- * 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.
- *
- *
- * The mtrace program has been modified and improved by Xerox
- * Corporation. Xerox grants to LICENSEE a non-exclusive and
- * non-transferable license to use, copy, and modify the Xerox modified
- * and improved mrouted software on the same terms and conditions which
- * govern the license Stanford and ISI grant with respect to the mtrace
- * program. These terms and conditions are incorporated in this grant
- * by reference and shall be deemed to have been accepted by LICENSEE
- * to cover its relationship with Xerox Corporation with respect to any
- * use of the Xerox improved program.
- *
- * The mtrace program is COPYRIGHT 1998 by Xerox Corporation.
- *
- */
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <memory.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/igmp.h>
-#include <sys/ioctl.h>
-#ifdef SYSV
-#include <sys/sockio.h>
-#endif
-#include <arpa/inet.h>
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-#ifdef SUNOS5
-#include <sys/systeminfo.h>
-#endif
-
-typedef unsigned int u_int32; /* XXX */
-#include "mtrace.h"
-
-#define DEFAULT_TIMEOUT 3 /* How long to wait before retrying requests */
-#define DEFAULT_RETRIES 3 /* How many times to try */
-#define DEFAULT_EXTRAHOPS 3 /* How many hops past a non-responding rtr */
-#define MAXHOPS 60 /* Don't need more hops than this */
-#define UNICAST_TTL 255 /* TTL for unicast response */
-#define MULTICAST_TTL1 127 /* Default TTL for multicast query/response */
-#define MULTICAST_TTL_INC 32 /* TTL increment for increase after timeout */
-#define MULTICAST_TTL_MAX 192 /* Maximum TTL allowed (protect low-BW links */
-
-#define TRUE 1
-#define FALSE 0
-#define DVMRP_ASK_NEIGHBORS2 5 /* DVMRP msg requesting neighbors */
-#define DVMRP_NEIGHBORS2 6 /* reply to above */
-#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */
-#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */
-#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 )
-
-struct resp_buf {
- u_long qtime; /* Time query was issued */
- u_long rtime; /* Time response was received */
- int len; /* Number of reports or length of data */
- struct igmp igmp; /* IGMP header */
- union {
- struct {
- struct tr_query q; /* Query/response header */
- struct tr_resp r[MAXHOPS]; /* Per-hop reports */
- } t;
- char d[MAX_DVMRP_DATA_LEN]; /* Neighbor data */
- } u;
-} base, incr[2];
-
-#define qhdr u.t.q
-#define resps u.t.r
-#define ndata u.d
-
-char *names[MAXHOPS];
-
-/*
- * In mrouted 3.3 and 3.4 (and in some Cisco IOS releases),
- * cache entries can get deleted even if there is traffic
- * flowing, which will reset the per-source/group counters.
- */
-#define BUG_RESET 0x01
-
-/*
- * Also in mrouted 3.3 and 3.4, there's a bug in neighbor
- * version processing which can cause them to believe that
- * the neighbor is constantly resetting. This causes them
- * to constantly delete all their state.
- */
-#define BUG_RESET2X 0x02
-
-/*
- * Pre-3.7 mrouted's forget to byte-swap their reports.
- */
-#define BUG_SWAP 0x04
-
-/*
- * Pre-3.9 mrouted's forgot a parenthesis in the htonl()
- * on the time calculation so supply bogus times.
- */
-#define BUG_BOGUSTIME 0x08
-
-#define BUG_NOPRINT (BUG_RESET | BUG_RESET2X)
-
-int bugs[MAXHOPS]; /* List of bugs noticed at each hop */
-
-struct mtrace {
- struct mtrace *next;
- struct resp_buf base, incr[2];
- struct resp_buf *new, *prev;
- int nresp;
- struct timeval last;
- int bugs[MAXHOPS];
- char *names[MAXHOPS];
- int lastqid;
-};
-
-int timeout = DEFAULT_TIMEOUT;
-int nqueries = DEFAULT_RETRIES;
-int numeric = FALSE;
-int debug = 0;
-int passive = FALSE;
-int multicast = FALSE;
-int unicast = FALSE;
-int statint = 10;
-int verbose = FALSE;
-int tunstats = FALSE;
-int weak = FALSE;
-int extrahops = DEFAULT_EXTRAHOPS;
-int printstats = TRUE;
-int sendopts = TRUE;
-int lossthresh = 0;
-int fflag = FALSE;
-int staticqid = 0;
-
-u_int32 defgrp; /* Default group if not specified */
-u_int32 query_cast; /* All routers multicast addr */
-u_int32 resp_cast; /* Mtrace response multicast addr */
-
-u_int32 lcl_addr = 0; /* This host address, in NET order */
-u_int32 dst_netmask = 0; /* netmask to go with qdst */
-
-/*
- * Query/response parameters, all initialized to zero and set later
- * to default values or from options.
- */
-u_int32 qsrc = 0; /* Source address in the query */
-u_int32 qgrp = 0; /* Group address in the query */
-u_int32 qdst = 0; /* Destination (receiver) address in query */
-u_char qno = 0; /* Max number of hops to query */
-u_int32 raddr = 0; /* Address where response should be sent */
-int qttl = 0; /* TTL for the query packet */
-u_char rttl = 0; /* TTL for the response packet */
-u_int32 gwy = 0; /* User-supplied last-hop router address */
-u_int32 tdst = 0; /* Address where trace is sent (last-hop) */
-
-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(). */
-
-#if !(defined(BSD) && (BSD >= 199103))
-extern int errno;
-extern int sys_nerr;
-extern char * sys_errlist[];
-#endif
-
-#define RECV_BUF_SIZE 8192
-char *send_buf, *recv_buf;
-int igmp_socket;
-u_int32 allrtrs_group;
-char router_alert[4]; /* Router Alert IP Option */
-#ifndef IPOPT_RA
-#define IPOPT_RA 148
-#endif
-#ifdef SUNOS5
-char eol[4]; /* EOL IP Option */
-int ip_addlen = 0; /* Workaround for Option bug #2 */
-#endif
-
-/*
- * max macro, with weird case to avoid conflicts
- */
-#define MaX(a,b) ((a) > (b) ? (a) : (b))
-
-#ifndef __P
-#ifdef __STDC__
-#define __P(x) x
-#else
-#define __P(x) ()
-#endif
-#endif
-
-typedef int (*callback_t) __P((int, u_char *, int, struct igmp *, int,
- struct sockaddr *, int *, struct timeval *));
-
-void init_igmp __P((void));
-void send_igmp __P((u_int32 src, u_int32 dst, int type,
- int code, u_int32 group,
- int datalen));
-int inet_cksum __P((u_short *addr, u_int len));
-void k_set_rcvbuf __P((int bufsize));
-void k_hdr_include __P((int bool));
-void k_set_ttl __P((int t));
-void k_set_loop __P((int l));
-void k_set_if __P((u_int32 ifa));
-void k_join __P((u_int32 grp, u_int32 ifa));
-void k_leave __P((u_int32 grp, u_int32 ifa));
-char * inet_fmt __P((u_int32 addr, char *s));
-char * inet_fmts __P((u_int32 addr, u_int32 mask, char *s));
-char * inet_name __P((u_int32 addr));
-u_int32 host_addr __P((char *name));
-/* u_int is promoted u_char */
-char * proto_type __P((u_int type));
-char * flag_type __P((u_int type));
-
-u_int32 get_netmask __P((int s, u_int32 *dst));
-int get_ttl __P((struct resp_buf *buf));
-int t_diff __P((u_long a, u_long b));
-u_long byteswap __P((u_long v));
-int mtrace_callback __P((int, u_char *, int, struct igmp *,
- int, struct sockaddr *, int *,
- struct timeval *));
-int send_recv __P((u_int32 dst, int type, int code,
- int tries, struct resp_buf *save,
- callback_t callback));
-void passive_mode __P((void));
-char * print_host __P((u_int32 addr));
-char * print_host2 __P((u_int32 addr1, u_int32 addr2));
-void print_trace __P((int idx, struct resp_buf *buf,
- char **names));
-int what_kind __P((struct resp_buf *buf, char *why));
-char * scale __P((int *hop));
-void stat_line __P((struct tr_resp *r, struct tr_resp *s,
- int have_next, int *res));
-void fixup_stats __P((struct resp_buf *base,
- struct resp_buf *prev,
- struct resp_buf *new,
- int *bugs));
-int check_thresh __P((int thresh,
- struct resp_buf *base,
- struct resp_buf *prev,
- struct resp_buf *new));
-int print_stats __P((struct resp_buf *base,
- struct resp_buf *prev,
- struct resp_buf *new,
- int *bugs,
- char **names));
-int path_changed __P((struct resp_buf *base,
- struct resp_buf *new));
-void check_vif_state __P((void));
-
-int main __P((int argc, char *argv[]));
-void log __P((int, int, char *, ...));
-static void usage __P((void));
-
-
-/*
- * 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 = (char *)malloc(RECV_BUF_SIZE);
- if (recv_buf == 0)
- log(LOG_ERR, 0, "Out of memory allocating recv_buf!");
- send_buf = (char *)malloc(RECV_BUF_SIZE);
- if (send_buf == 0)
- log(LOG_ERR, 0, "Out of memory allocating send_buf!");
-
- 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(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;
- ip->ip_hl = sizeof(struct ip) >> 2;
- ip->ip_v = IPVERSION;
- ip->ip_tos = 0;
- ip->ip_off = 0;
- ip->ip_p = IPPROTO_IGMP;
- ip->ip_ttl = MAXTTL; /* applies to unicasts only */
-
-#ifndef INADDR_ALLRTRS_GROUP
-#define INADDR_ALLRTRS_GROUP 0xe0000002 /* 224.0.0.2 */
-#endif
- allrtrs_group = htonl(INADDR_ALLRTRS_GROUP);
-
- router_alert[0] = IPOPT_RA; /* Router Alert */
- router_alert[1] = 4; /* 4 bytes */
- router_alert[2] = 0;
- router_alert[3] = 0;
-}
-
-#ifdef SUNOS5
-void
-checkforsolarisbug()
-{
- u_int32 localhost = htonl(0x7f000001);
-
- eol[0] = IPOPT_EOL;
- eol[1] = IPOPT_EOL;
- eol[2] = IPOPT_EOL;
- eol[3] = IPOPT_EOL;
-
- setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS, eol, sizeof(eol));
- /*
- * Check if the kernel adds the options length to the packet
- * length. Send myself an IGMP packet of type 0 (illegal),
- * with 4 IPOPT_EOL options, my PID (for collision detection)
- * and 4 bytes of zero (so that the checksum works whether
- * the 4 bytes of zero get truncated or not).
- */
- bzero(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN, 8);
- *(int *)(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN) = getpid();
- send_igmp(localhost, localhost, 0, 0, 0, 8);
- while (1) {
- int recvlen, dummy = 0;
-
- recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, NULL, &dummy);
- /* 8 == 4 bytes of options and 4 bytes of PID */
- if (recvlen >= MIN_IP_HEADER_LEN + IGMP_MINLEN + 8) {
- struct ip *ip = (struct ip *)recv_buf;
- struct igmp *igmp;
- int *p;
-
- if (ip->ip_hl != 6 ||
- ip->ip_p != IPPROTO_IGMP ||
- ip->ip_src.s_addr != localhost ||
- ip->ip_dst.s_addr != localhost)
- continue;
-
- igmp = (struct igmp *)(recv_buf + (ip->ip_hl << 2));
- if (igmp->igmp_group.s_addr != 0)
- continue;
- if (igmp->igmp_type != 0 || igmp->igmp_code != 0)
- continue;
-
- p = (int *)((char *)igmp + IGMP_MINLEN);
- if (*p != getpid())
- continue;
-
-#ifdef RAW_INPUT_IS_RAW
- ip->ip_len = ntohs(ip->ip_len);
-#endif
- if (ip->ip_len == IGMP_MINLEN + 4)
- ip_addlen = 4;
- else if (ip->ip_len == IGMP_MINLEN + 8)
- ip_addlen = 0;
- else
- log(LOG_ERR, 0, "while checking for Solaris bug: Sent %d bytes and got back %d!", IGMP_MINLEN + 8, ip->ip_len);
-
- break;
- }
- }
-}
-#endif
-
-/*
- * Construct an IGMP message in the output packet buffer. The caller may
- * have already placed data in that buffer, of length 'datalen'. 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;
- struct ip *ip;
- struct igmp *igmp;
- int setloop = 0;
- static int raset = 0;
- int sendra = 0;
- int sendlen;
-
- 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;
- sendlen = ip->ip_len;
-#ifdef SUNOS5
- ip->ip_len += ip_addlen;
-#endif
-#ifdef RAW_OUTPUT_IS_RAW
- ip->ip_len = htons(ip->ip_len);
-#endif
-
- 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);
-
- if (IN_MULTICAST(ntohl(dst))) {
- k_set_if(src);
- setloop = 1;
- k_set_loop(TRUE);
- if (dst != allrtrs_group)
- sendra = 1;
- }
-
- if (sendopts && sendra && !raset) {
- setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,
- router_alert, sizeof(router_alert));
- raset = 1;
- } else if (!sendra && raset) {
-#ifdef SUNOS5
- /*
- * SunOS5 < 5.6 cannot properly reset the IP_OPTIONS "socket"
- * option. Instead, set up a string of 4 EOL's.
- */
- setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,
- eol, sizeof(eol));
-#else
- setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,
- NULL, 0);
-#endif
- raset = 0;
- }
-
- bzero(&sdst, sizeof(sdst));
- sdst.sin_family = AF_INET;
-#if (defined(BSD) && (BSD >= 199103))
- sdst.sin_len = sizeof(sdst);
-#endif
- sdst.sin_addr.s_addr = dst;
- if (sendto(igmp_socket, send_buf, sendlen, 0,
- (struct sockaddr *)&sdst, sizeof(sdst)) < 0) {
- log(LOG_WARNING, errno, "sendto to %s on %s",
- inet_fmt(dst, s1), inet_fmt(src, s2));
- }
-
- if (setloop)
- k_set_loop(FALSE);
-
- log(LOG_DEBUG, 0, "SENT %s from %-15s to %s",
- type == IGMP_MTRACE ? "mtrace request" : "ask_neighbors",
- src == INADDR_ANY ? "INADDR_ANY" : inet_fmt(src, s1),
- inet_fmt(dst, s2));
-}
-
-/*
- * 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);
-}
-
-void
-k_set_rcvbuf(bufsize)
- int bufsize;
-{
- if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
- (char *)&bufsize, sizeof(bufsize)) < 0)
- log(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize);
-}
-
-
-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;
-{
- 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);
-}
-
-
-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));
-}
-
-/*
- * 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);
-}
-
-char *
-inet_name(addr)
- u_int32 addr;
-{
- struct hostent *e;
-
- e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
-
- return e ? e->h_name : "?";
-}
-
-
-u_int32
-host_addr(name)
- char *name;
-{
- struct hostent *e = (struct hostent *)0;
- u_int32 addr;
- int i, dots = 3;
- char buf[40];
- char *ip = name;
- char *op = buf;
-
- /*
- * Undo BSD's favor -- take fewer than 4 octets as net/subnet address
- * if the name is all numeric.
- */
- for (i = sizeof(buf) - 7; i > 0; --i) {
- if (*ip == '.') --dots;
- else if (*ip == '\0') break;
- else if (!isdigit(*ip)) dots = 0; /* Not numeric, don't add zeroes */
- *op++ = *ip++;
- }
- for (i = 0; i < dots; ++i) {
- *op++ = '.';
- *op++ = '0';
- }
- *op = '\0';
-
- if (dots <= 0)
- e = gethostbyname(name);
- if (e && (e->h_length == sizeof(addr))) {
- memcpy((char *)&addr, e->h_addr_list[0], e->h_length);
- if (e->h_addr_list[1])
- fprintf(stderr, "Warning: %s has multiple addresses, using %s\n",
- name, inet_fmt(addr, s1));
- } else {
- addr = inet_addr(buf);
- if (addr == -1 || (IN_MULTICAST(addr) && dots)) {
- addr = 0;
- printf("Could not parse %s as host name or address\n", name);
- }
- }
- return addr;
-}
-
-
-char *
-proto_type(type)
- u_int type;
-{
- static char buf[80];
-
- switch (type) {
- case PROTO_DVMRP:
- return ("DVMRP");
- case PROTO_MOSPF:
- return ("MOSPF");
- case PROTO_PIM:
- return ("PIM");
- case PROTO_CBT:
- return ("CBT");
- case PROTO_PIM_SPECIAL:
- return ("PIM/Special");
- case PROTO_PIM_STATIC:
- return ("PIM/Static");
- case PROTO_DVMRP_STATIC:
- return ("DVMRP/Static");
- case PROTO_PIM_BGP4PLUS:
- return ("PIM/BGP4+");
- case PROTO_CBT_SPECIAL:
- return ("CBT/Special");
- case PROTO_CBT_STATIC:
- return ("CBT/Static");
- case PROTO_PIM_ASSERT:
- return ("PIM/Assert");
- case 0:
- return ("None");
- default:
- (void) sprintf(buf, "Unknown protocol code %d", type);
- return (buf);
- }
-}
-
-
-char *
-flag_type(type)
- u_int type;
-{
- static char buf[80];
-
- switch (type) {
- case TR_NO_ERR:
- return ("");
- case TR_WRONG_IF:
- return ("Wrong interface");
- case TR_PRUNED:
- return ("Prune sent upstream");
- case TR_OPRUNED:
- return ("Output pruned");
- case TR_SCOPED:
- return ("Hit scope boundary");
- case TR_NO_RTE:
- return ("No route");
- case TR_NO_FWD:
- return ("Not forwarding");
- case TR_HIT_RP:
- return ("Reached RP/Core");
- case TR_RPF_IF:
- return ("RPF Interface");
- case TR_NO_MULTI:
- return ("Multicast disabled");
- case TR_OLD_ROUTER:
- return ("Next router no mtrace");
- case TR_NO_SPACE:
- return ("No space in packet");
- case TR_ADMIN_PROHIB:
- return ("Admin. Prohibited");
- default:
- (void) sprintf(buf, "Unknown error code %d", type);
- return (buf);
- }
-}
-
-/*
- * If destination is on a local net, get the netmask, else set the
- * netmask to all ones. There are two side effects: if the local
- * address was not explicitly set, and if the destination is on a
- * local net, use that one; in either case, verify that the local
- * address is valid.
- */
-u_int32
-get_netmask(s, dst)
- int s;
- u_int32 *dst;
-{
- unsigned int n;
- struct ifconf ifc;
- struct ifreq *ifrp, *ifend;
- u_int32 if_addr, if_mask;
- u_int32 retval = 0xFFFFFFFF;
- int found = FALSE;
- int num_ifreq = 32;
-
- ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
- ifc.ifc_buf = malloc(ifc.ifc_len);
- while (ifc.ifc_buf) {
- if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
- perror("ioctl SIOCGIFCONF");
- return retval;
- }
-
- /*
- * If the buffer was large enough to hold all the addresses
- * then break out, otherwise increase the buffer size and
- * try again.
- *
- * The only way to know that we definitely had enough space
- * is to know that there was enough space for at least one
- * more struct ifreq. ???
- */
- if ((num_ifreq * sizeof(struct ifreq)) >=
- ifc.ifc_len + sizeof(struct ifreq))
- break;
-
- num_ifreq *= 2;
- ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
- ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
- }
- if (ifc.ifc_buf == NULL) {
- fprintf(stderr, "getting interface list: ran out of memory");
- exit(1);
- }
-
- ifrp = (struct ifreq *)ifc.ifc_buf;
- ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
- /*
- * Loop through all of the interfaces.
- */
- for (; ifrp < ifend && !found; ifrp = (struct ifreq *)((char *)ifrp + n)) {
-#if BSD >= 199006
- n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
- if (n < sizeof(*ifrp))
- n = sizeof(*ifrp);
-#else
- n = sizeof(*ifrp);
-#endif
- /*
- * Ignore any interface for an address family other than IP.
- */
- if (ifrp->ifr_addr.sa_family != AF_INET)
- continue;
-
- if_addr = ((struct sockaddr_in *)&(ifrp->ifr_addr))->sin_addr.s_addr;
- if (ioctl(s, SIOCGIFFLAGS, (char *)ifrp) < 0) {
- fprintf(stderr, "SIOCGIFFLAGS on ");
- perror(ifrp->ifr_name);
- continue;
- }
- if ((ifrp->ifr_flags & (IFF_MULTICAST|IFF_UP|IFF_LOOPBACK)) !=
- (IFF_MULTICAST|IFF_UP))
- continue;
- if (*dst == 0)
- *dst = if_addr;
- if (ioctl(s, SIOCGIFNETMASK, (char *)ifrp) >= 0) {
- if_mask = ((struct sockaddr_in *)&(ifrp->ifr_addr))->sin_addr.s_addr;
- if (if_mask != 0 && (*dst & if_mask) == (if_addr & if_mask)) {
- retval = if_mask;
- if (lcl_addr == 0) lcl_addr = if_addr; /* XXX what about aliases? */
- }
- }
- if (lcl_addr == if_addr) found = TRUE;
- }
- if (!found && lcl_addr != 0) {
- printf("Interface address is not valid\n");
- exit(1);
- }
- return (retval);
-}
-
-
-/*
- * Try to pick a TTL that will get past all the thresholds in the path.
- */
-int
-get_ttl(buf)
- struct resp_buf *buf;
-{
- int rno;
- struct tr_resp *b;
- u_int ttl;
-
- if (buf && (rno = buf->len) > 0) {
- b = buf->resps + rno - 1;
- ttl = b->tr_fttl;
-
- while (--rno > 0) {
- --b;
- if (ttl < b->tr_fttl) ttl = b->tr_fttl;
- else ++ttl;
- }
- ttl += MULTICAST_TTL_INC;
- if (ttl < MULTICAST_TTL1) ttl = MULTICAST_TTL1;
- if (ttl > MULTICAST_TTL_MAX) ttl = MULTICAST_TTL_MAX;
- return (ttl);
- } else return(MULTICAST_TTL1);
-}
-
-/*
- * Calculate the difference between two 32-bit NTP timestamps and return
- * the result in milliseconds.
- */
-int
-t_diff(a, b)
- u_long a, b;
-{
- int d = a - b;
-
- return ((d * 125) >> 13);
-}
-
-/*
- * Swap bytes for poor little-endian machines that don't byte-swap
- */
-u_long
-byteswap(v)
- u_long v;
-{
- return ((v << 24) | ((v & 0xff00) << 8) |
- ((v >> 8) & 0xff00) | (v >> 24));
-}
-
-#if 0
-/*
- * XXX incomplete - need private callback data, too?
- * XXX since dst doesn't get passed through?
- */
-int
-neighbors_callback(tmo, buf, buflen, igmp, igmplen, addr, addrlen, ts)
- int tmo;
- u_char *buf;
- int buflen;
- struct igmp *igmp;
- int igmplen;
- struct sockaddr *addr;
- int *addrlen;
- struct timeval *ts;
-{
- int len;
- u_int32 dst;
- struct ip *ip = (struct ip *)buf;
-
- if (tmo)
- return 0;
-
- if (igmp->igmp_code != DVMRP_NEIGHBORS2)
- return 0;
- len = igmplen;
- /*
- * Accept DVMRP_NEIGHBORS2 response if it comes from the
- * address queried or if that address is one of the local
- * addresses in the response.
- */
- if (ip->ip_src.s_addr != dst) {
- u_int32 *p = (u_int32 *)(igmp + 1);
- u_int32 *ep = p + (len >> 2);
- while (p < ep) {
- u_int32 laddr = *p++;
- int n = ntohl(*p++) & 0xFF;
- if (laddr == dst) {
- ep = p + 1; /* ensure p < ep after loop */
- break;
- }
- p += n;
- }
- if (p >= ep)
- return 0;
- }
- return buflen;
-}
-#endif
-
-int
-mtrace_callback(tmo, buf, buflen, igmp, igmplen, addr, addrlen, ts)
- int tmo;
- u_char *buf;
- int buflen;
- struct igmp *igmp;
- int igmplen;
- struct sockaddr *addr;
- int *addrlen;
- struct timeval *ts;
-{
- static u_char *savbuf = NULL;
- static int savbuflen;
- static struct sockaddr *savaddr;
- static int savaddrlen;
- static struct timeval savts;
-
- int len = (igmplen - QLEN) / RLEN;
- struct tr_resp *r = (struct tr_resp *)((struct tr_query *)(igmp + 1) + 1);
-
- if (tmo == 1) {
- /*
- * If we timed out with a packet saved, then return that packet.
- * send_recv won't send this same packet to the callback again.
- */
- if (savbuf) {
- bcopy(savbuf, buf, savbuflen);
- free(savbuf);
- savbuf = NULL;
- bcopy(savaddr, addr, savaddrlen);
- free(savaddr);
- *addrlen = savaddrlen;
- bcopy(&savts, ts, sizeof(savts));
- return savbuflen;
- }
- return 0;
- }
- if (savbuf) {
- free(savbuf);
- savbuf = NULL;
- free(savaddr);
- }
- /*
- * Check for IOS bug described in CSCdi68628, where a router that does
- * not have multicast enabled responds to an mtrace request with a 1-hop
- * error packet.
- * Heuristic is:
- * If there is only one hop reported in the packet,
- * And the protocol code is 0,
- * And there is no previous hop,
- * And the forwarding information is "Not Forwarding",
- * And the router is not on the same subnet as the destination of the
- * trace,
- * then drop this packet. The "#if 0"'d code saves it and returns
- * it on timeout, but timeouts are too common (e.g. routers with
- * limited unicast routing tables, etc).
- */
- if (len == 1 && r->tr_rproto == 0 && r->tr_rmtaddr == 0 &&
- r->tr_rflags == TR_NO_FWD) {
- u_int32 smask;
-
- VAL_TO_MASK(smask, r->tr_smask);
- if ((r->tr_outaddr & smask) != (qdst & smask)) {
-#if 0
- /* XXX should do this silently? */
- fprintf(stderr, "mtrace: probably IOS-buggy packet from %s\n",
- inet_fmt(((struct sockaddr_in *)addr)->sin_addr.s_addr, s1));
- /* Save the packet to return if a timeout occurs. */
- savbuf = (u_char *)malloc(buflen);
- if (savbuf != NULL) {
- bcopy(buf, savbuf, buflen);
- savbuflen = buflen;
- savaddr = (struct sockaddr *)malloc(*addrlen);
- if (savaddr != NULL) {
- bcopy(addr, savaddr, *addrlen);
- savaddrlen = *addrlen;
- bcopy(ts, &savts, sizeof(savts));
- } else {
- free(savbuf);
- savbuf = NULL;
- }
- }
-#endif
- return 0;
- }
- }
- return buflen;
-}
-
-int
-send_recv(dst, type, code, tries, save, callback)
- u_int32 dst;
- int type, code, tries;
- struct resp_buf *save;
- callback_t callback;
-{
- fd_set fds;
- struct timeval tq, tr, tv;
- struct ip *ip;
- struct igmp *igmp;
- struct tr_query *query, *rquery;
- struct tr_resp *r;
- struct sockaddr_in recvaddr;
- u_int32 local, group;
- int ipdatalen, iphdrlen, igmpdatalen;
- int datalen;
- int count, recvlen, socklen = sizeof(recvaddr);
- int len;
- int i;
-
- if (type == IGMP_MTRACE) {
- group = qgrp;
- datalen = sizeof(struct tr_query);
- } else {
- group = htonl(0xff03);
- datalen = 0;
- }
- if (IN_MULTICAST(ntohl(dst))) local = lcl_addr;
- else local = INADDR_ANY;
-
- /*
- * If the reply address was not explictly specified, start off
- * with the standard multicast reply address, or the unicast
- * address of this host if the unicast flag was specified.
- * Then, if there is no response after trying half the tries
- * with multicast, switch to the unicast address of this host
- * if the multicast flag was not specified. If the TTL was
- * also not specified, set a multicast TTL and increase it
- * for every try.
- */
- query = (struct tr_query *)(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
- query->tr_raddr = raddr ? raddr : unicast ? lcl_addr : resp_cast;
- TR_SETTTL(query->tr_rttlqid, rttl ? rttl :
- IN_MULTICAST(ntohl(query->tr_raddr)) ? get_ttl(save) : UNICAST_TTL);
- query->tr_src = qsrc;
- query->tr_dst = qdst;
-
- for (i = tries ; i > 0; --i) {
- int oqid;
-
- if (tries == nqueries && raddr == 0) {
- if (i == (nqueries >> 1)) {
- if (multicast && unicast) {
- query->tr_raddr = resp_cast;
- if (!rttl)
- TR_SETTTL(query->tr_rttlqid, get_ttl(save));
- } else if (!multicast) {
- query->tr_raddr = lcl_addr;
- TR_SETTTL(query->tr_rttlqid, UNICAST_TTL);
- }
- }
- if (i < tries && IN_MULTICAST(ntohl(query->tr_raddr)) &&
- rttl == 0) {
- TR_SETTTL(query->tr_rttlqid,
- TR_GETTTL(query->tr_rttlqid) + MULTICAST_TTL_INC);
- if (TR_GETTTL(query->tr_rttlqid) > MULTICAST_TTL_MAX)
- TR_SETTTL(query->tr_rttlqid, MULTICAST_TTL_MAX);
- }
- }
-
- /*
- * Change the qid for each request sent to avoid being confused
- * by duplicate responses
- */
- oqid = TR_GETQID(query->tr_rttlqid);
- if (staticqid)
- TR_SETQID(query->tr_rttlqid, staticqid);
- else
-#ifdef SYSV
- TR_SETQID(query->tr_rttlqid, ((u_int32)lrand48() >> 8));
-#else
- TR_SETQID(query->tr_rttlqid, ((u_int32)arc4random() >> 8));
-#endif
-
- /*
- * Set timer to calculate delays, then send query
- */
- gettimeofday(&tq, 0);
- send_igmp(local, dst, type, code, group, datalen);
-
- /*
- * Wait for response, discarding false alarms
- */
- while (TRUE) {
- if (igmp_socket >= FD_SETSIZE)
- log(LOG_ERR, 0, "descriptor too big");
- FD_ZERO(&fds);
- FD_SET(igmp_socket, &fds);
- gettimeofday(&tv, 0);
- tv.tv_sec = tq.tv_sec + timeout - tv.tv_sec;
- tv.tv_usec = tq.tv_usec - tv.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, (fd_set *)0, (fd_set *)0,
- &tv);
-
- if (count < 0) {
- if (errno != EINTR) warn("select");
- continue;
- } else if (count == 0) {
- /*
- * Timed out. Notify the callback.
- */
- if (!callback || (recvlen = (callback)(1, recv_buf, 0, NULL, 0, (struct sockaddr *)&recvaddr, &socklen, &tr)) == 0) {
- printf("* ");
- fflush(stdout);
- break;
- }
- } else {
- /*
- * Data is available on the socket, so read it.
- */
- gettimeofday(&tr, 0);
- recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, (struct sockaddr *)&recvaddr, &socklen);
- }
-
- if (recvlen <= 0) {
- if (recvlen && errno != EINTR) warn("recvfrom");
- continue;
- }
-
- if (recvlen < sizeof(struct ip)) {
- warnx("packet too short (%u bytes) for IP header", recvlen);
- continue;
- }
- ip = (struct ip *) recv_buf;
- if (ip->ip_p == 0) /* ignore cache creation requests */
- continue;
-
- iphdrlen = ip->ip_hl << 2;
-#ifdef RAW_INPUT_IS_RAW
- ipdatalen = ntohs(ip->ip_len);
-#else
- ipdatalen = ip->ip_len;
-#endif
- if (iphdrlen + ipdatalen != recvlen) {
- warnx("packet shorter (%u bytes) than hdr+data len (%u+%u)",
- recvlen, iphdrlen, ipdatalen);
- continue;
- }
-
- igmp = (struct igmp *) (recv_buf + iphdrlen);
- igmpdatalen = ipdatalen - IGMP_MINLEN;
- if (igmpdatalen < 0) {
- warnx("IP data field too short (%u bytes) for IGMP from %s",
- ipdatalen, inet_fmt(ip->ip_src.s_addr, s1));
- continue;
- }
-
- switch (igmp->igmp_type) {
-
- case IGMP_DVMRP:
- if (type != IGMP_DVMRP || code != DVMRP_ASK_NEIGHBORS2)
- continue;
- if (igmp->igmp_code != DVMRP_NEIGHBORS2) continue;
- len = igmpdatalen;
- /*
- * Accept DVMRP_NEIGHBORS2 response if it comes from the
- * address queried or if that address is one of the local
- * addresses in the response.
- */
- if (ip->ip_src.s_addr != dst) {
- u_int32 *p = (u_int32 *)(igmp + 1);
- u_int32 *ep = p + (len >> 2);
- while (p < ep) {
- u_int32 laddr = *p++;
- int n = ntohl(*p++) & 0xFF;
- if (laddr == dst) {
- ep = p + 1; /* ensure p < ep after loop */
- break;
- }
- p += n;
- }
- if (p >= ep) continue;
- }
- break;
-
- case IGMP_MTRACE: /* For backward compatibility with 3.3 */
- case IGMP_MTRACE_RESP:
- if (type != IGMP_MTRACE) continue;
- if (igmpdatalen <= QLEN) continue;
- if ((igmpdatalen - QLEN)%RLEN) {
- printf("packet with incomplete responses (%d bytes)\n",
- igmpdatalen);
- continue;
- }
-
- /*
- * Ignore responses that don't match query.
- */
- rquery = (struct tr_query *)(igmp + 1);
- if (rquery->tr_src != qsrc || rquery->tr_dst != qdst)
- continue;
- if (TR_GETQID(rquery->tr_rttlqid) !=
- TR_GETQID(query->tr_rttlqid)) {
- if (verbose && TR_GETQID(rquery->tr_rttlqid) == oqid)
- printf("[D]");
- continue;
- }
- len = (igmpdatalen - QLEN)/RLEN;
- r = (struct tr_resp *)(rquery+1) + len - 1;
-
- /*
- * Ignore trace queries passing through this node when
- * mtrace is run on an mrouter that is in the path
- * (needed only because IGMP_MTRACE is accepted above
- * for backward compatibility with multicast release 3.3).
- */
- if (igmp->igmp_type == IGMP_MTRACE) {
- u_int32 smask;
-
- VAL_TO_MASK(smask, r->tr_smask);
- if (len < code && (r->tr_inaddr & smask) != (qsrc & smask)
- && r->tr_rmtaddr != 0 && !(r->tr_rflags & 0x80))
- continue;
- }
- /*
- * Some routers will return error messages without
- * filling in their addresses. We fill in the address
- * for them.
- */
- if (r->tr_outaddr == 0)
- r->tr_outaddr = recvaddr.sin_addr.s_addr;
-
- /*
- * A match, we'll keep this one.
- */
- if (len > code) {
- warnx("num hops received (%d) exceeds request (%d)",
- len, code);
- }
- rquery->tr_raddr = query->tr_raddr; /* Insure these are */
- TR_SETTTL(rquery->tr_rttlqid, TR_GETTTL(query->tr_rttlqid));
- /* as we sent them */
- break;
-
- default:
- continue;
- }
-
- /*
- * We're pretty sure we want to use this packet now,
- * but if the caller gave a callback function, it might
- * want to handle it instead. Give the callback a chance,
- * unless the select timed out (in which case the only way
- * to get here is because the callback returned a packet).
- */
- if (callback && (count != 0) && ((callback)(0, recv_buf, recvlen, igmp, igmpdatalen, (struct sockaddr*)&recvaddr, &socklen, &tr)) == 0) {
- /*
- * The callback function didn't like this packet.
- * Go try receiving another one.
- */
- continue;
- }
-
- /*
- * Most of the sanity checking done at this point.
- * Return this packet we have been waiting for.
- */
- if (save) {
- save->qtime = ((tq.tv_sec + JAN_1970) << 16) +
- (tq.tv_usec << 10) / 15625;
- save->rtime = ((tr.tv_sec + JAN_1970) << 16) +
- (tr.tv_usec << 10) / 15625;
- save->len = len;
- bcopy((char *)igmp, (char *)&save->igmp, ipdatalen);
- }
- return (recvlen);
- }
- }
- return (0);
-}
-
-/*
- * Most of this code is duplicated elsewhere. I'm not sure if
- * the duplication is absolutely required or not.
- *
- * Ideally, this would keep track of ongoing statistics
- * collection and print out statistics. (& keep track
- * of h-b-h traces and only print the longest) For now,
- * it just snoops on what traces it can.
- */
-void
-passive_mode()
-{
- struct timeval tr;
- time_t tr_sec;
- struct ip *ip;
- struct igmp *igmp;
- struct tr_resp *r;
- struct sockaddr_in recvaddr;
- struct tm *now;
- char timebuf[32];
- int socklen;
- int ipdatalen, iphdrlen, igmpdatalen;
- int len, recvlen;
- int qid;
- u_int32 smask;
- struct mtrace *remembered = NULL, *m, *n, **nn;
- int pc = 0;
-
- if (raddr) {
- if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr);
- } else k_join(htonl(0xE0000120), lcl_addr);
-
- while (1) {
- fflush(stdout); /* make sure previous trace is flushed */
-
- socklen = sizeof(recvaddr);
- recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, (struct sockaddr *)&recvaddr, &socklen);
- gettimeofday(&tr,0);
-
- if (recvlen <= 0) {
- if (recvlen && errno != EINTR) warn("recvfrom");
- continue;
- }
-
- if (recvlen < sizeof(struct ip)) {
- warnx("packet too short (%u bytes) for IP header", recvlen);
- continue;
- }
- ip = (struct ip *) recv_buf;
- if (ip->ip_p == 0) /* ignore cache creation requests */
- continue;
-
- iphdrlen = ip->ip_hl << 2;
-#ifdef RAW_INPUT_IS_RAW
- ipdatalen = ntohs(ip->ip_len);
-#else
- ipdatalen = ip->ip_len;
-#endif
- if (iphdrlen + ipdatalen != recvlen) {
- warnx("packet shorter (%u bytes) than hdr+data len (%u+%u)",
- recvlen, iphdrlen, ipdatalen);
- continue;
- }
-
- igmp = (struct igmp *) (recv_buf + iphdrlen);
- igmpdatalen = ipdatalen - IGMP_MINLEN;
- if (igmpdatalen < 0) {
- warnx("IP data field too short (%u bytes) for IGMP from %s",
- ipdatalen, inet_fmt(ip->ip_src.s_addr, s1));
- continue;
- }
-
- switch (igmp->igmp_type) {
-
- case IGMP_MTRACE: /* For backward compatibility with 3.3 */
- case IGMP_MTRACE_RESP:
- if (igmpdatalen < QLEN) continue;
- if ((igmpdatalen - QLEN)%RLEN) {
- printf("packet with incorrect datalen\n");
- continue;
- }
-
- len = (igmpdatalen - QLEN)/RLEN;
-
- break;
-
- default:
- continue;
- }
-
- base.qtime = ((tr.tv_sec + JAN_1970) << 16) +
- (tr.tv_usec << 10) / 15625;
- base.rtime = ((tr.tv_sec + JAN_1970) << 16) +
- (tr.tv_usec << 10) / 15625;
- base.len = len;
- bcopy((char *)igmp, (char *)&base.igmp, ipdatalen);
- /*
- * If the user specified which traces to monitor,
- * only accept traces that correspond to the
- * request
- */
- if ((qsrc != 0 && qsrc != base.qhdr.tr_src) ||
- (qdst != 0 && qdst != base.qhdr.tr_dst) ||
- (qgrp != 0 && qgrp != igmp->igmp_group.s_addr))
- continue;
-
- /* XXX This should be a hash table */
- /* XXX garbage-collection should be more efficient */
- for (nn = &remembered, n = *nn, m = 0; n; n = *nn) {
- if ((n->base.qhdr.tr_src == base.qhdr.tr_src) &&
- (n->base.qhdr.tr_dst == base.qhdr.tr_dst) &&
- (n->base.igmp.igmp_group.s_addr == igmp->igmp_group.s_addr)) {
- m = n;
- m->last = tr;
- }
- if (tr.tv_sec - n->last.tv_sec > 500) { /* XXX don't hardcode */
- *nn = n->next;
- free(n);
- } else {
- nn = &n->next;
- }
- }
-
- tr_sec = tr.tv_sec;
- now = localtime(&tr_sec);
- strftime(timebuf, sizeof(timebuf), "%b %e %k:%M:%S", now);
- printf("Mtrace %s at %s",
- len == 0 ? "query" :
- igmp->igmp_type == IGMP_MTRACE_RESP ? "response" :
- "in transit",
- timebuf);
- if (len == 0)
- printf(" by %s", inet_fmt(recvaddr.sin_addr.s_addr, s1));
- if (!IN_MULTICAST(base.qhdr.tr_raddr))
- printf(", resp to %s", (len == 0 && recvaddr.sin_addr.s_addr == base.qhdr.tr_raddr) ? "same" : inet_fmt(base.qhdr.tr_raddr, s1));
- else
- printf(", respttl %d", TR_GETTTL(base.qhdr.tr_rttlqid));
- printf(", qid %06x\n", qid = TR_GETQID(base.qhdr.tr_rttlqid));
- printf("packet from %s to %s\n",
- inet_fmt(ip->ip_src.s_addr, s1),
- inet_fmt(ip->ip_dst.s_addr, s2));
-
- printf("from %s to %s via group %s (mxhop=%d)\n",
- inet_fmt(base.qhdr.tr_dst, s1), inet_fmt(base.qhdr.tr_src, s2),
- inet_fmt(igmp->igmp_group.s_addr, s3), igmp->igmp_code);
- if (len == 0) {
- printf("\n");
- continue;
- }
- r = base.resps + base.len - 1;
- /*
- * Some routers will return error messages without
- * filling in their addresses. We fill in the address
- * for them.
- */
- if (r->tr_outaddr == 0)
- r->tr_outaddr = recvaddr.sin_addr.s_addr;
-
- /*
- * If there was a previous trace, it see if this is a
- * statistics candidate.
- */
- if (m && base.len == m->base.len &&
- !(pc = path_changed(&m->base, &base))) {
- /*
- * Some mtrace responders send multiple copies of the same
- * reply. Skip this packet if it's got the same query-id
- * as the last one.
- */
- if (m->lastqid == qid) {
- printf("Skipping duplicate reply\n");
- continue;
- }
-
- m->lastqid = qid;
-
- ++m->nresp;
-
- bcopy(&base, m->new, sizeof(base));
-
- printf("Results after %d seconds:\n\n",
- (int)((m->new->qtime - m->base.qtime) >> 16));
- fixup_stats(&m->base, m->prev, m->new, m->bugs);
- print_stats(&m->base, m->prev, m->new, m->bugs, m->names);
- m->prev = m->new;
- m->new = &m->incr[(m->nresp & 1)];
-
- continue;
- }
-
- if (m == NULL) {
- m = (struct mtrace *)malloc(sizeof(struct mtrace));
- if (m == NULL) {
- fprintf(stderr, "Out of memory!\n");
- continue;
- }
- bzero(m, sizeof(struct mtrace));
- m->next = remembered;
- remembered = m;
- bcopy(&tr, &m->last, sizeof(tr));
- }
-
- /* Either it's a hop-by-hop in progress, or the path changed. */
- if (pc) {
- printf("[Path Changed...]\n");
- bzero(m->bugs, sizeof(m->bugs));
- }
- bcopy(&base, &m->base, sizeof(base));
- m->prev = &m->base;
- m->new = &m->incr[0];
- m->nresp = 0;
-
- printf(" 0 ");
- print_host(base.qhdr.tr_dst);
- printf("\n");
- print_trace(1, &base, m->names);
- VAL_TO_MASK(smask, r->tr_smask);
- if ((r->tr_inaddr & smask) == (base.qhdr.tr_src & smask)) {
- printf("%3d ", -(base.len+1));
- print_host(base.qhdr.tr_src);
- printf("\n");
- } else if (r->tr_rmtaddr != 0) {
- printf("%3d ", -(base.len+1));
- print_host(r->tr_rmtaddr);
- printf(" %s\n", r->tr_rflags == TR_OLD_ROUTER ?
- "doesn't support mtrace"
- : "is the next hop");
- }
- printf("\n");
- }
-}
-
-char *
-print_host(addr)
- u_int32 addr;
-{
- return print_host2(addr, 0);
-}
-
-/*
- * On some routers, one interface has a name and the other doesn't.
- * We always print the address of the outgoing interface, but can
- * sometimes get the name from the incoming interface. This might be
- * confusing but should be slightly more helpful than just a "?".
- */
-char *
-print_host2(addr1, addr2)
- u_int32 addr1, addr2;
-{
- char *name;
-
- if (numeric) {
- printf("%s", inet_fmt(addr1, s1));
- return ("");
- }
- name = inet_name(addr1);
- if (*name == '?' && *(name + 1) == '\0' && addr2 != 0)
- name = inet_name(addr2);
- printf("%s (%s)", name, inet_fmt(addr1, s1));
- return (name);
-}
-
-/*
- * Print responses as received (reverse path from dst to src)
- */
-void
-print_trace(idx, buf, names)
- int idx;
- struct resp_buf *buf;
- char **names;
-{
- struct tr_resp *r;
- char *name;
- int i;
- int hop;
- char *ms;
-
- i = abs(idx);
- r = buf->resps + i - 1;
-
- for (; i <= buf->len; ++i, ++r) {
- if (idx > 0) printf("%3d ", -i);
- name = print_host2(r->tr_outaddr, r->tr_inaddr);
- if (r->tr_rflags != TR_NO_RTE)
- printf(" %s thresh^ %d", proto_type(r->tr_rproto), r->tr_fttl);
- if (verbose) {
- hop = t_diff(ntohl(r->tr_qarr), buf->qtime);
- ms = scale(&hop);
- printf(" %d%s", hop, ms);
- }
- printf(" %s", flag_type(r->tr_rflags));
- if (i > 1 && r->tr_outaddr != (r-1)->tr_rmtaddr) {
- printf(" !RPF!");
- print_host((r-1)->tr_rmtaddr);
- }
- if (r->tr_rflags != TR_NO_RTE) {
- if (r->tr_smask <= 1) /* MASK_TO_VAL() returns 1 for default */
- printf(" [default]");
- else if (verbose) {
- u_int32 smask;
-
- VAL_TO_MASK(smask, r->tr_smask);
- printf(" [%s]", inet_fmts(buf->qhdr.tr_src & smask,
- smask, s1));
- }
- }
- printf("\n");
- if (names[i-1])
- free(names[i-1]);
- names[i-1]=malloc(strlen(name) + 1);
- strcpy(names[i-1], name);
- }
-}
-
-/*
- * See what kind of router is the next hop
- */
-int
-what_kind(buf, why)
- struct resp_buf *buf;
- char *why;
-{
- u_int32 smask;
- int retval;
- int hops = buf->len;
- struct tr_resp *r = buf->resps + hops - 1;
- u_int32 next = r->tr_rmtaddr;
-
- retval = send_recv(next, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0], NULL);
- print_host(next);
- if (retval) {
- u_int32 version = ntohl(incr[0].igmp.igmp_group.s_addr);
- u_int32 *p = (u_int32 *)incr[0].ndata;
- u_int32 *ep = p + (incr[0].len >> 2);
- char *type = "version ";
-
- retval = 0;
- switch (version & 0xFF) {
- case 1:
- type = "proteon/mrouted ";
- retval = 1;
- break;
-
- case 10:
- case 11:
- type = "cisco ";
- }
- printf(" [%s%d.%d] %s\n",
- type, version & 0xFF, (version >> 8) & 0xFF,
- why);
- VAL_TO_MASK(smask, r->tr_smask);
- while (p < ep) {
- u_int32 laddr = *p++;
- int flags = (ntohl(*p) & 0xFF00) >> 8;
- int n = ntohl(*p++) & 0xFF;
- if (!(flags & (DVMRP_NF_DOWN | DVMRP_NF_DISABLED)) &&
- (laddr & smask) == (qsrc & smask)) {
- printf("%3d ", -(hops+2));
- print_host(qsrc);
- printf("\n");
- return 1;
- }
- p += n;
- }
- return retval;
- }
- printf(" %s\n", why);
- return 0;
-}
-
-
-char *
-scale(hop)
- int *hop;
-{
- if (*hop > -1000 && *hop < 10000) return (" ms");
- *hop /= 1000;
- if (*hop > -1000 && *hop < 10000) return (" s ");
- return ("s ");
-}
-
-/*
- * Calculate and print one line of packet loss and packet rate statistics.
- * Checks for count of all ones from mrouted 2.3 that doesn't have counters.
- */
-#define NEITHER 0
-#define INS 1
-#define OUTS 2
-#define BOTH 3
-void
-stat_line(r, s, have_next, rst)
- struct tr_resp *r, *s;
- int have_next;
- int *rst;
-{
- int timediff = (ntohl(s->tr_qarr) - ntohl(r->tr_qarr)) >> 16;
- int v_lost, v_pct;
- int g_lost, g_pct;
- int v_out = ntohl(s->tr_vifout) - ntohl(r->tr_vifout);
- int g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
- int v_pps, g_pps;
- char v_str[8], g_str[8];
- int vhave = NEITHER;
- int ghave = NEITHER;
- int gmissing = NEITHER;
- char whochar;
- int badtime = 0;
-
- if (timediff == 0) {
- badtime = 1;
- /* Might be 32 bits of int seconds instead of 16int+16frac */
- timediff = ntohl(s->tr_qarr) - ntohl(r->tr_qarr);
- if (timediff == 0 || abs(timediff - statint) > statint)
- timediff = 1;
- }
- v_pps = v_out / timediff;
- g_pps = g_out / timediff;
-
-#define STATS_MISSING(x) ((x) == 0xFFFFFFFF)
-
- if (!STATS_MISSING(s->tr_vifout) && !STATS_MISSING(r->tr_vifout))
- vhave |= OUTS;
- if (STATS_MISSING(s->tr_pktcnt) || STATS_MISSING(r->tr_pktcnt))
- gmissing |= OUTS;
- if (!(*rst & BUG_NOPRINT))
- ghave |= OUTS;
-
- if (have_next) {
- --r, --s, --rst;
- if (!STATS_MISSING(s->tr_vifin) && !STATS_MISSING(r->tr_vifin))
- vhave |= INS;
- if (STATS_MISSING(s->tr_pktcnt) || STATS_MISSING(r->tr_pktcnt))
- gmissing |= INS;
- if (!(*rst & BUG_NOPRINT))
- ghave |= INS;
- }
-
- /*
- * Stats can be missing for any number of reasons:
- * - The hop may not be capable of collecting stats
- * - Traffic may be getting dropped at the previous hop
- * and so this hop may not have any state
- *
- * We need a stronger heuristic to tell between these
- * two cases; in case 1 we don't want to print the stats
- * and in case 2 we want to print 100% loss. We used to
- * err on the side of not printing, which is less useful
- * than printing 100% loss and dealing with it.
- */
-#if 0
- /*
- * If both hops report as missing, then it's likely that there's just
- * no traffic flowing.
- *
- * If just one hop is missing, then we really don't have it.
- */
- if (gmissing != BOTH)
- ghave &= ~gmissing;
-#endif
-
- whochar = have_next ? '^' : ' ';
- switch (vhave) {
- case BOTH:
- v_lost = v_out - (ntohl(s->tr_vifin) - ntohl(r->tr_vifin));
- if (v_out) v_pct = v_lost * 100 / v_out;
- else v_pct = 0;
- if (-20 < v_pct && v_pct < 101 && v_out > 10)
- sprintf(v_str, "%3d%%", v_pct);
- else if (v_pct < -900 && v_out > 10)
- sprintf(v_str, "%3dx", (int)(-v_pct / 100. + 1.));
- else if (v_pct <= -20 && v_out > 10)
- sprintf(v_str, "%1.1fx", -v_pct / 100. + 1.);
- else
- memcpy(v_str, " -- ", 5);
-
- if (tunstats)
- printf("%6d/%-5d=%s", v_lost, v_out, v_str);
- else
- printf(" ");
- printf("%4d pps", v_pps);
- if (v_pps && badtime)
- printf("?");
-
- break;
-
- case INS:
- v_out = ntohl(s->tr_vifin) - ntohl(r->tr_vifin);
- v_pps = v_out / timediff;
- whochar = 'v';
- /* FALLTHROUGH */
-
- case OUTS:
- if (tunstats)
- printf(" %c%-5d ", whochar, v_out);
- else
- printf(" %c", whochar);
- printf("%4d pps", v_pps);
- if (v_pps && badtime)
- printf("?");
-
- break;
-
- case NEITHER:
- if (ghave != NEITHER)
- if (tunstats)
- printf(" ");
- else
- printf(" ");
-
- break;
- }
-
- whochar = have_next ? '^' : ' ';
- switch (ghave) {
- case BOTH:
- g_lost = g_out - (ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt));
- if (g_out) g_pct = g_lost * 100 / g_out;
- else g_pct = 0;
- if (-20 < g_pct && g_pct < 101 && g_out > 10)
- sprintf(g_str, "%3d%%", g_pct);
- else if (g_pct < -900 && g_out > 10)
- sprintf(g_str, "%3dx", (int)(-g_pct / 100. + 1.));
- else if (g_pct <= -20 && g_out > 10)
- sprintf(g_str, "%1.1fx", -g_pct / 100. + 1.);
- else
- memcpy(g_str, " -- ", 5);
-
- printf("%s%6d/%-5d=%s%4d pps",
- tunstats ? "" : " ", g_lost, g_out, g_str, g_pps);
- if (g_pps && badtime)
- printf("?");
- printf("\n");
- break;
-
-#if 0
- case INS:
- g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);
- g_pps = g_out / timediff;
- whochar = 'v';
- /* FALLTHROUGH */
-#endif
-
- case OUTS:
- printf("%s ?/%-5d %4d pps",
- tunstats ? "" : " ", g_out, g_pps);
- if (badtime)
- printf("?");
- printf("\n");
- break;
-
- case INS:
- case NEITHER:
- printf("\n");
- break;
- }
-
-
- if (debug > 2) {
- printf("\t\t\t\tv_in: %ld ", (long)ntohl(s->tr_vifin));
- printf("v_out: %ld ", (long)ntohl(s->tr_vifout));
- printf("pkts: %ld\n", (long)ntohl(s->tr_pktcnt));
- printf("\t\t\t\tv_in: %ld ", (long)ntohl(r->tr_vifin));
- printf("v_out: %ld ", (long)ntohl(r->tr_vifout));
- printf("pkts: %ld\n", (long)ntohl(r->tr_pktcnt));
- printf("\t\t\t\tv_in: %ld ",
- (long)(ntohl(s->tr_vifin) - ntohl(r->tr_vifin)));
- printf("v_out: %ld ",
- (long)(ntohl(s->tr_vifout) - ntohl(r->tr_vifout)));
- printf("pkts: %ld ", (long)(ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt)));
- printf("time: %d\n", timediff);
- printf("\t\t\t\treset: %x hoptime: %lx\n", *rst, ntohl(s->tr_qarr));
- }
-}
-
-/*
- * A fixup to check if any pktcnt has been reset, and to fix the
- * byteorder bugs in mrouted 3.6 on little-endian machines.
- *
- * XXX Since periodic traffic sources are likely to have their
- * pktcnt periodically reset, should we save old values when
- * the reset occurs to keep slightly better statistics over
- * the long term? (e.g. SAP)
- */
-void
-fixup_stats(base, prev, new, bugs)
- struct resp_buf *base, *prev, *new;
- int *bugs;
-{
- int rno = base->len;
- struct tr_resp *b = base->resps + rno;
- struct tr_resp *p = prev->resps + rno;
- struct tr_resp *n = new->resps + rno;
- int *r = bugs + rno;
- int res;
- int cleanup = 0;
-
- /* Check for byte-swappers. Only check on the first trace,
- * since long-running traces can wrap around and falsely trigger. */
- while (--rno >= 0) {
-#ifdef TEST_ONLY
- u_int32 nvifout = ntohl(n->tr_vifout);
- u_int32 pvifout = ntohl(p->tr_vifout);
-#endif
- --n; --p; --b;
-#ifdef TEST_ONLY /*XXX this is still buggy, so disable it for release */
- if ((*r & BUG_SWAP) ||
- ((base == prev) &&
- (nvifout - pvifout) > (byteswap(nvifout) - byteswap(pvifout)))) {
- if (1 || debug > 2) {
- printf("ip %s swaps; b %08x p %08x n %08x\n",
- inet_fmt(n->tr_inaddr, s1),
- ntohl(b->tr_vifout), pvifout, nvifout);
- }
- /* This host sends byteswapped reports; swap 'em */
- if (!(*r & BUG_SWAP)) {
- *r |= BUG_SWAP;
- b->tr_qarr = byteswap(b->tr_qarr);
- b->tr_vifin = byteswap(b->tr_vifin);
- b->tr_vifout = byteswap(b->tr_vifout);
- b->tr_pktcnt = byteswap(b->tr_pktcnt);
- }
-
- n->tr_qarr = byteswap(n->tr_qarr);
- n->tr_vifin = byteswap(n->tr_vifin);
- n->tr_vifout = byteswap(n->tr_vifout);
- n->tr_pktcnt = byteswap(n->tr_pktcnt);
- }
-#endif
- /*
- * A missing parenthesis in mrouted 3.5-3.8's prune.c
- * causes extremely bogus time diff's.
- * One half of the time calculation was
- * inside an htonl() and one half wasn't. Therefore, on
- * a little-endian machine, both halves of the calculation
- * would get added together in the little end. Thus, the
- * low-order 2 bytes are either 0000 (no overflow) or
- * 0100 (overflow from the addition).
- *
- * Odds are against these particular bit patterns
- * happening in both prev and new for actual time values.
- */
- if ((*r & BUG_BOGUSTIME) || (((ntohl(n->tr_qarr) & 0xfeff) == 0x0000) &&
- ((ntohl(p->tr_qarr) & 0xfeff) == 0x0000))) {
- *r |= BUG_BOGUSTIME;
- n->tr_qarr = new->rtime;
- p->tr_qarr = prev->rtime;
- b->tr_qarr = base->rtime;
- }
- }
-
- rno = base->len;
- b = base->resps + rno;
- p = prev->resps + rno;
- n = new->resps + rno;
- r = bugs + rno;
-
- while (--rno >= 0) {
- --n; --p; --b; --r;
- /*
- * This hop has reset if:
- * - There were statistics in the base AND previous pass, AND
- * - There are less packets this time than the first time and
- * we didn't reset last time, OR
- * - There are less packets this time than last time, OR
- * - There are no statistics on this pass.
- *
- * The "and we didn't reset last time" is necessary in the
- * first branch of the OR because if the base is large and
- * we reset last time but the constant-resetter-avoidance
- * code kicked in so we delayed the copy of prev to base,
- * new could still be below base so we trigger the
- * constant-resetter code even though it was really only
- * a single reset.
- */
- res = ((b->tr_pktcnt != 0xFFFFFFFF) && (p->tr_pktcnt != 0xFFFFFFFF) &&
- ((!(*r & BUG_RESET) && ntohl(n->tr_pktcnt) < ntohl(b->tr_pktcnt)) ||
- (ntohl(n->tr_pktcnt) < ntohl(p->tr_pktcnt)) ||
- (n->tr_pktcnt == 0xFFFFFFFF)));
- if (debug > 2) {
- printf("\t\tip=%s, r=%d, res=%d\n", inet_fmt(b->tr_inaddr, s1), *r, res);
- if (res)
- printf("\t\tbase=%ld, prev=%ld, new=%ld\n", ntohl(b->tr_pktcnt),
- ntohl(p->tr_pktcnt), ntohl(n->tr_pktcnt));
- }
- if (*r & BUG_RESET) {
- if (res || (*r & BUG_RESET2X)) {
- /*
- * This router appears to be a 3.4 with that nasty ol'
- * neighbor version bug, which causes it to constantly
- * reset. Just nuke the statistics for this node, and
- * don't even bother giving it the benefit of the
- * doubt from now on.
- */
- p->tr_pktcnt = b->tr_pktcnt = n->tr_pktcnt;
- *r |= BUG_RESET2X;
- } else {
- /*
- * This is simply the situation that the original
- * fixup_stats was meant to deal with -- that a
- * 3.3 or 3.4 router deleted a cache entry while
- * traffic was still active.
- */
- *r &= ~BUG_RESET;
- cleanup = 1;
- }
- } else
- if (res)
- *r |= BUG_RESET;
- }
-
- if (cleanup == 0) return;
-
- /*
- * If some hop reset its counters and didn't continue to
- * reset, then we pretend that the previous
- * trace was the first one.
- */
- rno = base->len;
- b = base->resps + rno;
- p = prev->resps + rno;
-
- while (--rno >= 0) (--b)->tr_pktcnt = (--p)->tr_pktcnt;
- base->qtime = prev->qtime;
- base->rtime = prev->rtime;
-}
-
-/*
- * Check per-source losses along path and compare with threshold.
- */
-int
-check_thresh(thresh, base, prev, new)
- int thresh;
- struct resp_buf *base, *prev, *new;
-{
- int rno = base->len - 1;
- struct tr_resp *b = base->resps + rno;
- struct tr_resp *p = prev->resps + rno;
- struct tr_resp *n = new->resps + rno;
- int g_out, g_lost;
-
- while (TRUE) {
- if ((n->tr_inaddr != b->tr_inaddr) ||
- (n->tr_outaddr != b->tr_outaddr) ||
- (n->tr_rmtaddr != b->tr_rmtaddr))
- return 1; /* Route changed */
-
- if (rno-- < 1) break;
- g_out = ntohl(n->tr_pktcnt) - ntohl(p->tr_pktcnt);
- b--; n--; p--;
- g_lost = g_out - (ntohl(n->tr_pktcnt) - ntohl(p->tr_pktcnt));
- if (g_out && ((g_lost * 100 + (g_out >> 1))/ g_out) > thresh) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/*
- * Print responses with statistics for forward path (from src to dst)
- */
-int
-print_stats(base, prev, new, bugs, names)
- struct resp_buf *base, *prev, *new;
- int *bugs;
- char **names;
-{
- int rtt, hop;
- char *ms;
- u_int32 smask;
- int rno = base->len - 1;
- struct tr_resp *b = base->resps + rno;
- struct tr_resp *p = prev->resps + rno;
- struct tr_resp *n = new->resps + rno;
- int *r = bugs + rno;
- u_long resptime = new->rtime;
- u_long qarrtime = ntohl(n->tr_qarr);
- u_int ttl = MaX(1, n->tr_fttl) + 1;
- int first = (base == prev);
-
- VAL_TO_MASK(smask, b->tr_smask);
- printf(" Source Response Dest ");
- if (tunstats)
- printf("Packet Statistics For Only For Traffic\n");
- else
- printf("Overall Packet Statistics For Traffic From\n");
- (void)inet_fmt(base->qhdr.tr_src, s1);
- printf("%-15s %-15s ",
- ((b->tr_inaddr & smask) == (base->qhdr.tr_src & smask)) ?
- s1 : " * * * ",
- inet_fmt(base->qhdr.tr_raddr, s2));
- (void)inet_fmt(base->igmp.igmp_group.s_addr, s2);
- if (tunstats)
- printf("All Multicast Traffic From %s\n", s1);
- else
- printf("Packet %s To %s\n", s1, s2);
- rtt = t_diff(resptime, new->qtime);
- ms = scale(&rtt);
- printf(" %c __/ rtt%5d%s ",
- (first && !verbose) ? 'v' : '|', rtt, ms);
- if (tunstats)
- printf("Lost/Sent = Pct Rate To %s\n", s2);
- else
- printf(" Rate Lost/Sent = Pct Rate\n");
- if (!first || verbose) {
- hop = t_diff(resptime, qarrtime);
- ms = scale(&hop);
- printf(" v / hop%5d%s ", hop, ms);
- if (tunstats)
- printf("--------------------- --------------------\n");
- else
- printf("------- ---------------------\n");
- }
- if ((b->tr_inaddr & smask) != (base->qhdr.tr_src & smask) &&
- b->tr_rmtaddr != 0) {
- printf("%-15s %-14s is the previous hop\n", inet_fmt(b->tr_rmtaddr, s1),
- inet_name(b->tr_rmtaddr));
- printf(" v ^\n");
- }
- if (debug > 2) {
- printf("\t\t\t\tv_in: %ld ", (long)ntohl(n->tr_vifin));
- printf("v_out: %ld ", (long)ntohl(n->tr_vifout));
- printf("pkts: %ld\n", (long)ntohl(n->tr_pktcnt));
- printf("\t\t\t\tv_in: %ld ", (long)ntohl(b->tr_vifin));
- printf("v_out: %ld ", (long)ntohl(b->tr_vifout));
- printf("pkts: %ld\n", (long)ntohl(b->tr_pktcnt));
- printf("\t\t\t\tv_in: %ld ",
- (long)(ntohl(n->tr_vifin) - ntohl(b->tr_vifin)));
- printf("v_out: %ld ",
- (long)(ntohl(n->tr_vifout) - ntohl(b->tr_vifout)));
- printf("pkts: %ld\n",
- (long)(ntohl(n->tr_pktcnt) - ntohl(b->tr_pktcnt)));
- printf("\t\t\t\treset: %x hoptime: %lx\n", *r, (long)ntohl(n->tr_qarr));
- }
-
- while (TRUE) {
- if ((n->tr_inaddr != b->tr_inaddr) ||
- (n->tr_outaddr != b->tr_outaddr) ||
- (n->tr_rmtaddr != b->tr_rmtaddr))
- return 1; /* Route changed */
-
- if ((n->tr_inaddr != n->tr_outaddr) && n->tr_inaddr)
- printf("%-15s\n", inet_fmt(n->tr_inaddr, s1));
- printf("%-15s %-14s %s%s\n", inet_fmt(n->tr_outaddr, s1), names[rno],
- flag_type(n->tr_rflags),
- (*r & BUG_NOPRINT) ? " [reset counters]" : "");
-
- if (rno-- < 1) break;
-
- printf(" %c ^ ttl%5d ", (first && !verbose) ? 'v' : '|',
- ttl);
- stat_line(p, n, TRUE, r);
- if (!first || verbose) {
- resptime = qarrtime;
- qarrtime = ntohl((n-1)->tr_qarr);
- hop = t_diff(resptime, qarrtime);
- ms = scale(&hop);
- printf(" v | hop%5d%s", hop, ms);
- if (first)
- printf("\n");
- else
- stat_line(b, n, TRUE, r);
- }
-
- --b, --p, --n, --r;
- ttl = MaX(ttl, MaX(1, n->tr_fttl) + base->len - rno);
- }
-
- printf(" %c \\__ ttl%5d ", (first && !verbose) ? 'v' : '|',
- ttl);
- stat_line(p, n, FALSE, r);
- if (!first || verbose) {
- hop = t_diff(qarrtime, new->qtime);
- ms = scale(&hop);
- printf(" v \\ hop%5d%s", hop, ms);
- if (first)
- printf("\n");
- else
- stat_line(b, n, FALSE, r);
- }
- printf("%-15s %s\n", inet_fmt(base->qhdr.tr_dst, s1),
- !passive ? inet_fmt(lcl_addr, s2) : " * * * ");
- printf(" Receiver Query Source\n\n");
- return 0;
-}
-
-/*
- * Determine whether or not the path has changed.
- */
-int
-path_changed(base, new)
- struct resp_buf *base, *new;
-{
- int rno = base->len - 1;
- struct tr_resp *b = base->resps + rno;
- struct tr_resp *n = new->resps + rno;
-
- while (rno-- >= 0) {
- if ((n->tr_inaddr != b->tr_inaddr) ||
- (n->tr_outaddr != b->tr_outaddr) ||
- (n->tr_rmtaddr != b->tr_rmtaddr))
- return 1; /* Route changed */
- if ((b->tr_rflags == TR_NO_RTE) &&
- (n->tr_rflags != TR_NO_RTE))
- return 1; /* Route got longer? */
- --n;
- --b;
- }
- return 0;
-}
-
-
-/***************************************************************************
- * main
- ***************************************************************************/
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
- int udp;
- struct sockaddr_in addr;
- int addrlen = sizeof(addr);
- int recvlen;
- struct timeval tv;
- struct resp_buf *prev, *new;
- struct tr_resp *r;
- u_int32 smask;
- int rno;
- int hops, nexthop, tries;
- u_int32 lastout = 0;
- int numstats = 1;
- int waittime;
- int seed;
- int hopbyhop;
- int i;
- int printed = 1;
-
- if (geteuid() != 0)
- errx(1, "must be root");
-
- /*
- * We might get spawned by vat with the audio device open.
- * Close everything but stdin, stdout, stderr.
- */
- for (i = 3; i < 255; i++)
- close(i);
-
- init_igmp();
- setuid(getuid());
-
- argv++, argc--;
- if (argc == 0) usage();
-
- while (argc > 0 && *argv[0] == '-') {
- char *p = *argv++; argc--;
- p++;
- do {
- char c = *p++;
- char *arg = (char *) 0;
- if (isdigit(*p)) {
- arg = p;
- p = "";
- } else if (argc > 0) arg = argv[0];
- switch (c) {
- case 'd': /* Unlisted debug print option */
- if (arg && isdigit(*arg)) {
- debug = atoi(arg);
- if (debug < 0) debug = 0;
- if (debug > 3) debug = 3;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'M': /* Use multicast for reponse */
- multicast = TRUE;
- break;
- case 'U': /* Use unicast for response */
- unicast = TRUE;
- break;
- case 'L': /* Trace w/ loss threshold */
- if (arg && isdigit(*arg)) {
- lossthresh = atoi(arg);
- if (lossthresh < 0)
- lossthresh = 0;
- numstats = 3153600;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- break;
- case 'O': /* Don't use IP options */
- sendopts = FALSE;
- break;
- case 'P': /* Just watch the path */
- printstats = FALSE;
- numstats = 3153600;
- break;
- case 'Q': /* (undoc.) always use this QID */
- if (arg && isdigit(*arg)) {
- staticqid = atoi(arg);
- if (staticqid < 0)
- staticqid = 0;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- break;
- case 'T': /* Print confusing tunnel stats */
- tunstats = TRUE;
- break;
- case 'W': /* Cisco's "weak" mtrace */
- weak = TRUE;
- break;
- case 'V': /* Print version and exit */
- /*
- * FreeBSD wants to have its own Id string, so
- * determination of the version number has to change.
- * XXX Note that this must be changed by hand on importing
- * XXX new versions!
- */
- {
- char *r = strdup(rcsid);
- char *s = strchr(r, ',');
-
- while (s && *(s+1) != 'v')
- s = strchr(s + 1, ',');
-
- if (s) {
- char *q;
-
- s += 3; /* , v sp */
- q = strchr(s, ' ');
- if (q)
- *q = '\0';
- fprintf(stderr, "mtrace version 5.2/%s\n", s);
- } else {
- fprintf(stderr, "mtrace could not determine version number!?\n");
- }
- exit(1);
- }
- break;
- case 'l': /* Loop updating stats indefinitely */
- numstats = 3153600;
- break;
- case 'n': /* Don't reverse map host addresses */
- numeric = TRUE;
- break;
- case 'p': /* Passive listen for traces */
- passive = TRUE;
- break;
- case 'v': /* Verbosity */
- verbose = TRUE;
- break;
- case 's': /* Short form, don't wait for stats */
- numstats = 0;
- break;
- case 'w': /* Time to wait for packet arrival */
- if (arg && isdigit(*arg)) {
- timeout = atoi(arg);
- if (timeout < 1) timeout = 1;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'f': /* first hop */
- if (arg && isdigit(*arg)) {
- qno = atoi(arg);
- if (qno > MAXHOPS) qno = MAXHOPS;
- else if (qno < 1) qno = 0;
- if (arg == argv[0]) argv++, argc--;
- fflag++;
- break;
- } else
- usage();
- case 'm': /* Max number of hops to trace */
- if (arg && isdigit(*arg)) {
- qno = atoi(arg);
- if (qno > MAXHOPS) qno = MAXHOPS;
- else if (qno < 1) qno = 0;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'q': /* Number of query retries */
- if (arg && isdigit(*arg)) {
- nqueries = atoi(arg);
- if (nqueries < 1) nqueries = 1;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'g': /* Last-hop gateway (dest of query) */
- if (arg && (gwy = host_addr(arg))) {
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 't': /* TTL for query packet */
- if (arg && isdigit(*arg)) {
- qttl = atoi(arg);
- if (qttl < 1) qttl = 1;
- rttl = qttl;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'e': /* Extra hops past non-responder */
- if (arg && isdigit(*arg)) {
- extrahops = atoi(arg);
- if (extrahops < 0) extrahops = 0;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'r': /* Dest for response packet */
- if (arg && (raddr = host_addr(arg))) {
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'i': /* Local interface address */
- if (arg && (lcl_addr = host_addr(arg))) {
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- case 'S': /* Stat accumulation interval */
- if (arg && isdigit(*arg)) {
- statint = atoi(arg);
- if (statint < 1) statint = 1;
- if (arg == argv[0]) argv++, argc--;
- break;
- } else
- usage();
- default:
- usage();
- }
- } while (*p);
- }
-
- if (argc > 0 && (qsrc = host_addr(argv[0]))) { /* Source of path */
- if (IN_MULTICAST(ntohl(qsrc))) {
- if (gwy) {
- /* Should probably rewrite arg parsing at some point, as
- * this makes "mtrace -g foo 224.1.2.3 224.2.3.4" valid!... */
- qgrp = qsrc;
- qsrc = 0;
- } else {
- usage();
- }
- }
- argv++, argc--;
- if (argc > 0 && (qdst = host_addr(argv[0]))) { /* Dest of path */
- argv++, argc--;
- if (argc > 0 && (qgrp = host_addr(argv[0]))) { /* Path via group */
- argv++, argc--;
- }
- if (IN_MULTICAST(ntohl(qdst))) {
- u_int32 temp = qdst;
- qdst = qgrp;
- qgrp = temp;
- if (IN_MULTICAST(ntohl(qdst))) usage();
- } else if (qgrp && !IN_MULTICAST(ntohl(qgrp))) usage();
- }
- }
-
- if (passive) {
- passive_mode();
- return(0);
- }
-
- if (argc > 0) {
- usage();
- }
-
-#ifdef SUNOS5
- if (sendopts)
- checkforsolarisbug();
-#endif
-
- /*
- * Set useful defaults for as many parameters as possible.
- */
-
- defgrp = 0; /* Default to no group */
- query_cast = htonl(0xE0000002); /* All routers multicast addr */
- resp_cast = htonl(0xE0000120); /* Mtrace response multicast addr */
- if (qgrp == 0) {
- if (!weak)
- qgrp = defgrp;
- if (printstats && numstats != 0 && !tunstats) {
- /* Stats are useless without a group */
- warnx(
- "WARNING: no multicast group specified, so no statistics printed");
- numstats = 0;
- }
- } else {
- if (weak)
- warnx(
- "WARNING: group was specified so not performing \"weak\" mtrace");
- }
-
- /*
- * Get default local address for multicasts to use in setting defaults.
- */
- addr.sin_family = AF_INET;
-#if (defined(BSD) && (BSD >= 199103))
- addr.sin_len = sizeof(addr);
-#endif
- addr.sin_addr.s_addr = qgrp ? qgrp : query_cast;
- addr.sin_port = htons(2000); /* Any port above 1024 will do */
-
- /*
- * Note that getsockname() can return 0 on some systems
- * (notably SunOS 5.x, x < 6). This is taken care of in
- * get_netmask(). If the default multicast interface (set
- * with the route for 224.0.0.0) is not the same as the
- * hostname, mtrace -i [if_addr] will have to be used.
- */
- 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");
-
-#ifdef SUNOS5
- /*
- * SunOS 5.X prior to SunOS 2.6, getsockname returns 0 for udp socket.
- * This call to sysinfo will return the hostname.
- * If the default multicast interfface (set with the route
- * for 224.0.0.0) is not the same as the hostname,
- * mtrace -i [if_addr] will have to be used.
- */
- if (addr.sin_addr.s_addr == 0) {
- char myhostname[MAXHOSTNAMELEN];
- struct hostent *hp;
- int error;
-
- error = sysinfo(SI_HOSTNAME, myhostname, sizeof(myhostname));
- if (error == -1)
- err(1, "getting my hostname");
-
- hp = gethostbyname(myhostname);
- if (hp == NULL || hp->h_addrtype != AF_INET ||
- hp->h_length != sizeof(addr.sin_addr))
- err(1, "finding IP address for my hostname");
-
- memcpy((char *)&addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
- }
-#endif
-
- /*
- * Default destination for path to be queried is the local host.
- * When gateway specified, default destination is that gateway
- * and default source is local host.
- */
- if (qdst == 0) {
- qdst = lcl_addr ? lcl_addr : addr.sin_addr.s_addr;
- dst_netmask = get_netmask(udp, &qdst);
- if (gwy && (gwy & dst_netmask) != (qdst & dst_netmask) &&
- !IN_MULTICAST(ntohl(gwy)))
- qdst = gwy;
- }
- if (qsrc == 0 && gwy)
- qsrc = lcl_addr ? lcl_addr : addr.sin_addr.s_addr;
- if (qsrc == 0)
- usage();
- if (!dst_netmask)
- dst_netmask = get_netmask(udp, &qdst);
- close(udp);
- if (lcl_addr == 0) lcl_addr = addr.sin_addr.s_addr;
-
- /*
- * Initialize the seed for random query identifiers.
- */
- gettimeofday(&tv, 0);
- seed = tv.tv_usec ^ lcl_addr;
-#ifdef SYSV
- srand48(seed);
-#endif
-
- /*
- * Protect against unicast queries to mrouted versions that might crash.
- * Also use the obsolete "can mtrace" neighbor bit to warn about
- * older implementations.
- */
- if (gwy && !IN_MULTICAST(ntohl(gwy)))
- if (send_recv(gwy, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0], NULL)) {
- int flags = ntohl(incr[0].igmp.igmp_group.s_addr);
- int version = flags & 0xFFFF;
- int info = (flags & 0xFF0000) >> 16;
-
- if (version == 0x0303 || version == 0x0503) {
- printf("Don't use -g to address an mrouted 3.%d, it might crash\n",
- (version >> 8) & 0xFF);
- exit(0);
- }
- if ((info & 0x08) == 0) {
- printf("mtrace: ");
- print_host(gwy);
- printf(" probably doesn't support mtrace, trying anyway...\n");
- }
- }
-
- printf("Mtrace from %s to %s via group %s\n",
- inet_fmt(qsrc, s1), inet_fmt(qdst, s2), inet_fmt(qgrp, s3));
-
- if ((qdst & dst_netmask) == (qsrc & dst_netmask))
- fprintf(stderr, "mtrace: Source & receiver appear to be directly connected\n");
-
- /*
- * If the response is to be a multicast address, make sure we
- * are listening on that multicast address.
- */
- if (raddr) {
- if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr);
- } else k_join(resp_cast, lcl_addr);
-
- memset(&base, 0, sizeof(base));
-
- /*
- * If the destination is on the local net, the last-hop router can
- * be found by multicast to the all-routers multicast group.
- * Otherwise, use the group address that is the subject of the
- * query since by definition the last-hop router will be a member.
- * Set default TTLs for local remote multicasts.
- */
- if (gwy == 0)
- if ((qdst & dst_netmask) == (lcl_addr & dst_netmask)) tdst = query_cast;
- else tdst = qgrp;
- else tdst = gwy;
- if (tdst == 0 && qgrp == 0)
- errx(1, "mtrace: weak mtrace requires -g if destination is not local.\n");
-
- if (IN_MULTICAST(ntohl(tdst))) {
- k_set_loop(1); /* If I am running on a router, I need to hear this */
- if (tdst == query_cast) k_set_ttl(qttl ? qttl : 1);
- else k_set_ttl(qttl ? qttl : MULTICAST_TTL1);
- }
-
- /*
- * Try a query at the requested number of hops or MAXHOPS if unspecified.
- */
- if (qno == 0) {
- hops = MAXHOPS;
- tries = 1;
- printf("Querying full reverse path... ");
- fflush(stdout);
- } else {
- hops = qno;
- tries = nqueries;
- if (fflag)
- printf("Querying full reverse path, starting at hop %d...", qno);
- else
- printf("Querying reverse path, maximum %d hops... ", qno);
- fflush(stdout);
- }
- base.rtime = 0;
- base.len = 0;
- hopbyhop = FALSE;
-
- recvlen = send_recv(tdst, IGMP_MTRACE, hops, tries, &base, mtrace_callback);
-
- /*
- * If the initial query was successful, print it. Otherwise, if
- * the query max hop count is the default of zero, loop starting
- * from one until there is no response for extrahops more hops. The
- * extra hops allow getting past an mtrace-capable mrouter that can't
- * send multicast packets because all phyints are disabled.
- */
- if (recvlen) {
- printf("\n 0 ");
- print_host(qdst);
- printf("\n");
- print_trace(1, &base, names);
- r = base.resps + base.len - 1;
- if (r->tr_rflags == TR_OLD_ROUTER || r->tr_rflags == TR_NO_SPACE ||
- (qno != 0 && r->tr_rmtaddr != 0 && !fflag)) {
- printf("%3d ", -(base.len+1));
- what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ?
- "doesn't support mtrace"
- : "is the next hop");
- } else {
- if (fflag) {
- nexthop = hops = qno;
- goto continuehop;
- }
- VAL_TO_MASK(smask, r->tr_smask);
- if ((r->tr_inaddr & smask) == (qsrc & smask)) {
- printf("%3d ", -(base.len+1));
- print_host(qsrc);
- printf("\n");
- }
- }
- } else if (qno == 0) {
- hopbyhop = TRUE;
- printf("switching to hop-by-hop:\n 0 ");
- print_host(qdst);
- printf("\n");
-
- for (hops = 1, nexthop = 1; hops <= MAXHOPS; ++hops) {
- printf("%3d ", -hops);
- fflush(stdout);
-
- /*
- * After a successful first hop, try switching to the unicast
- * address of the last-hop router instead of multicasting the
- * trace query. This should be safe for mrouted versions 3.3
- * and 3.5 because there is a long route timeout with metric
- * infinity before a route disappears. Switching to unicast
- * reduces the amount of multicast traffic and avoids a bug
- * with duplicate suppression in mrouted 3.5.
- */
- if (hops == 2 && gwy == 0 && lastout != 0 &&
- (recvlen = send_recv(lastout, IGMP_MTRACE, hops, 1, &base, mtrace_callback)))
- tdst = lastout;
- else recvlen = send_recv(tdst, IGMP_MTRACE, hops, nqueries, &base, mtrace_callback);
-
- if (recvlen == 0) {
- /*if (hops == 1) break;*/
- if (hops == nexthop) {
- if (hops == 1) {
- printf("\n");
- } else if (what_kind(&base, "didn't respond")) {
- /* the ask_neighbors determined that the
- * not-responding router is the first-hop. */
- break;
- }
- if (extrahops == 0)
- break;
- } else if (hops < nexthop + extrahops) {
- printf("\n");
- } else {
- printf("...giving up\n");
- break;
- }
- continue;
- }
- if (base.len == hops &&
- (hops == 1 || (base.resps+nexthop-2)->tr_outaddr == lastout)) {
- if (hops == nexthop) {
- print_trace(-hops, &base, names);
- } else {
- printf("\nResuming...\n");
- print_trace(nexthop, &base, names);
- }
- } else {
- if (base.len < hops) {
- /*
- * A shorter trace than requested means a fatal error
- * occurred along the path, or that the route changed
- * to a shorter one.
- *
- * If the trace is longer than the last one we received,
- * then we are resuming from a skipped router (but there
- * is still probably a problem).
- *
- * If the trace is shorter than the last one we
- * received, then the route must have changed (and
- * there is still probably a problem).
- */
- if (nexthop <= base.len) {
- printf("\nResuming...\n");
- print_trace(nexthop, &base, names);
- } else if (nexthop > base.len + 1) {
- hops = base.len;
- printf("\nRoute must have changed...\n");
- print_trace(1, &base, names);
- }
- } else {
- /*
- * The last hop address is not the same as it was.
- * If we didn't know the last hop then we just
- * got the first response from a hop-by-hop trace;
- * if we did know the last hop then
- * the route probably changed underneath us.
- */
- hops = base.len;
- if (lastout != 0)
- printf("\nRoute must have changed...\n");
- else
- printf("\nResuming...\n");
- print_trace(1, &base, names);
- }
- }
-continuehop:
- r = base.resps + base.len - 1;
- lastout = r->tr_outaddr;
-
- if (base.len < hops ||
- r->tr_rmtaddr == 0 ||
- (r->tr_rflags & 0x80)) {
- VAL_TO_MASK(smask, r->tr_smask);
- if (r->tr_rmtaddr) {
- if (hops != nexthop) {
- printf("\n%3d ", -(base.len+1));
- }
- what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ?
- "doesn't support mtrace" :
- "would be the next hop");
- /* XXX could do segmented trace if TR_NO_SPACE */
- } else if (r->tr_rflags == TR_NO_ERR &&
- (r->tr_inaddr & smask) == (qsrc & smask)) {
- printf("%3d ", -(hops + 1));
- print_host(qsrc);
- printf("\n");
- }
- break;
- }
-
- nexthop = hops + 1;
- }
- }
-
- if (base.rtime == 0) {
- printf("Timed out receiving responses\n");
- if (IN_MULTICAST(ntohl(tdst)))
- if (tdst == query_cast)
- printf("Perhaps no local router has a route for source %s\n",
- inet_fmt(qsrc, s1));
- else
- printf("Perhaps receiver %s is not a member of group %s,\n\
-or no router local to it has a route for source %s,\n\
-or multicast at ttl %d doesn't reach its last-hop router for that source\n",
- inet_fmt(qdst, s2), inet_fmt(qgrp, s3), inet_fmt(qsrc, s1),
- qttl ? qttl : MULTICAST_TTL1);
- exit(1);
- }
-
- printf("Round trip time %d ms; ", t_diff(base.rtime, base.qtime));
- {
- struct tr_resp *n = base.resps + base.len - 1;
- u_int ttl = n->tr_fttl + 1;
-
- rno = base.len - 1;
- while (--rno > 0) {
- --n;
- ttl = MaX(ttl, MaX(1, n->tr_fttl) + base.len - rno);
- }
- printf("total ttl of %d required.\n\n",ttl);
- }
-
- /*
- * Use the saved response which was the longest one received,
- * and make additional probes after delay to measure loss.
- */
- raddr = base.qhdr.tr_raddr;
- rttl = TR_GETTTL(base.qhdr.tr_rttlqid);
- gettimeofday(&tv, 0);
- waittime = statint - (((tv.tv_sec + JAN_1970) & 0xFFFF) - (base.qtime >> 16));
- prev = &base;
- new = &incr[numstats&1];
-
- /*
- * Zero out bug-avoidance counters
- */
- memset(bugs, 0, sizeof(bugs));
-
- if (!printstats)
- printf("Monitoring path..");
-
- while (numstats--) {
- if (waittime < 1) printf("\n");
- else {
- if (printstats && (lossthresh == 0 || printed)) {
- printf("Waiting to accumulate statistics...");
- } else {
- printf(".");
- }
- fflush(stdout);
- sleep((unsigned)waittime);
- }
- printed = 0;
- rno = hopbyhop ? base.len : qno ? qno : MAXHOPS;
- recvlen = send_recv(tdst, IGMP_MTRACE, rno, nqueries, new, mtrace_callback);
-
- if (recvlen == 0) {
- printf("Timed out.\n");
- if (numstats) {
- numstats++;
- continue;
- } else
- exit(1);
- }
-
- if (base.len != new->len || path_changed(&base, new)) {
- printf("%s", base.len == new->len ? "Route changed" :
- "Trace length doesn't match");
- if (!printstats)
- printf(" after %d seconds",
- (int)((new->qtime - base.qtime) >> 16));
- printf(":\n");
-printandcontinue:
- print_trace(1, new, names);
- numstats++;
- bcopy(new, &base, sizeof(base));
- nexthop = hops = new->len;
- printf("Continuing with hop-by-hop...\n");
- goto continuehop;
- }
-
- if (printstats) {
- if (new->igmp.igmp_group.s_addr != qgrp ||
- new->qhdr.tr_src != qsrc || new->qhdr.tr_dst != qdst)
- printf("\nWARNING: trace modified en route; statistics may be incorrect\n");
- fixup_stats(&base, prev, new, bugs);
- if ((lossthresh == 0) || check_thresh(lossthresh, &base, prev, new)) {
- printf("Results after %d seconds",
- (int)((new->qtime - base.qtime) >> 16));
- if (lossthresh)
- printf(" (this trace %d seconds)",
- (int)((new->qtime - prev->qtime) >> 16));
- if (verbose) {
- time_t t = time(0);
- struct tm *qr = localtime(&t);
-
- printf(" qid 0x%06x at %2d:%02d:%02d",
- TR_GETQID(base.qhdr.tr_rttlqid),
- qr->tm_hour, qr->tm_min, qr->tm_sec);
- }
- printf(":\n\n");
- printed = 1;
- if (print_stats(&base, prev, new, bugs, names)) {
- printf("This should have been detected earlier, but ");
- printf("Route changed:\n");
- goto printandcontinue;
- }
- }
- }
- prev = new;
- new = &incr[numstats&1];
- waittime = statint;
- }
-
- /*
- * If the response was multicast back, leave the group
- */
- if (raddr) {
- if (IN_MULTICAST(ntohl(raddr))) k_leave(raddr, lcl_addr);
- } else k_leave(resp_cast, lcl_addr);
-
- return (0);
-}
-
-static void
-usage()
-{
- fprintf(stderr, "%s\n%s\n%s\n",
- "usage: mtrace [-MUOPTWVlnpvs] [-e extra_hops] [-f first_hop] [-i if_addr]",
- " [-g gateway] [-m max_hops] [-q nqueries] [-r resp_dest]",
- " [-S statint] [-t ttl] [-w wait] source [receiver] [group]");
- exit(1);
-}
-
-void
-check_vif_state()
-{
- log(LOG_WARNING, errno, "sendto");
-}
-
-/*
- * 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
-/*VARARGS3*/
-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);
-}
diff --git a/usr.sbin/mrouted/mtrace.h b/usr.sbin/mrouted/mtrace.h
deleted file mode 100644
index e67dbd0fa145..000000000000
--- a/usr.sbin/mrouted/mtrace.h
+++ /dev/null
@@ -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
diff --git a/usr.sbin/mrouted/mtrace/Makefile b/usr.sbin/mrouted/mtrace/Makefile
deleted file mode 100644
index ee9adb7c7eb5..000000000000
--- a/usr.sbin/mrouted/mtrace/Makefile
+++ /dev/null
@@ -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>
diff --git a/usr.sbin/mrouted/pathnames.h b/usr.sbin/mrouted/pathnames.h
deleted file mode 100644
index d4fb01d18a15..000000000000
--- a/usr.sbin/mrouted/pathnames.h
+++ /dev/null
@@ -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
diff --git a/usr.sbin/mrouted/prune.c b/usr.sbin/mrouted/prune.c
deleted file mode 100644
index acefaf921f71..000000000000
--- a/usr.sbin/mrouted/prune.c
+++ /dev/null
@@ -1,2619 +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.
- *
- *
- * prune.c,v 3.8.4.59 1998/03/01 02:06:32 fenner Exp
- */
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include "defs.h"
-
-extern int cache_lifetime;
-extern int prune_lifetime;
-extern struct rtentry *routing_table;
-
-extern int phys_vif;
-
-extern int allow_black_holes;
-
-/*
- * randomize value to obtain a value between .5x and 1.5x
- * in order to prevent synchronization
- */
-#ifdef SYSV
-#define JITTERED_VALUE(x) ((x)/2 + (lrand48() % (x)))
-#else
-#define JITTERED_VALUE(x) ((x)/2 + (arc4random() % (x)))
-#endif
-#define CACHE_LIFETIME(x) JITTERED_VALUE(x) /* XXX */
-
-struct gtable *kernel_table; /* ptr to list of kernel grp entries*/
-static struct gtable *kernel_no_route; /* list of grp entries w/o routes */
-struct gtable *gtp; /* pointer for kernel rt entries */
-unsigned int kroutes; /* current number of cache entries */
-
-/****************************************************************************
- Functions that are local to prune.c
-****************************************************************************/
-static int scoped_addr __P((vifi_t vifi, u_int32 addr));
-static void prun_add_ttls __P((struct gtable *gt));
-static int pruning_neighbor __P((vifi_t vifi, u_int32 addr));
-static int can_mtrace __P((vifi_t vifi, u_int32 addr));
-static struct ptable * find_prune_entry __P((u_int32 vr, struct ptable *pt));
-static void remove_sources __P((struct gtable *gt));
-static void rexmit_prune __P((void *arg));
-static void expire_prune __P((vifi_t vifi, struct gtable *gt));
-static void send_prune __P((struct gtable *gt));
-static void send_graft __P((struct gtable *gt));
-static void send_graft_ack __P((u_int32 src, u_int32 dst,
- u_int32 origin, u_int32 grp,
- vifi_t vifi));
-static void update_kernel __P((struct gtable *g));
-
-/*
- * Updates the ttl values for each vif.
- */
-static void
-prun_add_ttls(gt)
- struct gtable *gt;
-{
- struct uvif *v;
- vifi_t vifi;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (VIFM_ISSET(vifi, gt->gt_grpmems))
- gt->gt_ttls[vifi] = v->uv_threshold;
- else
- gt->gt_ttls[vifi] = 0;
- }
-}
-
-/*
- * checks for scoped multicast addresses
- * XXX I want to make the check of allow_black_holes based on ALLOW_BLACK_HOLES
- * but macros are not functions.
- */
-#define GET_SCOPE(gt) { \
- register vifi_t _i; \
- VIFM_CLRALL((gt)->gt_scope); \
- if (allow_black_holes || \
- (ntohl((gt)->gt_mcastgrp) & 0xff000000) == 0xef000000) \
- for (_i = 0; _i < numvifs; _i++) \
- if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
- VIFM_SET(_i, (gt)->gt_scope); \
- } \
- if ((gt)->gt_route == NULL || ((gt)->gt_route->rt_parent != NO_VIF && \
- VIFM_ISSET((gt)->gt_route->rt_parent, (gt)->gt_scope))) \
- VIFM_SETALL((gt)->gt_scope);
-
-#define APPLY_SCOPE(gt) VIFM_CLR_MASK((gt)->gt_grpmems, (gt)->gt_scope)
-
-#define GET_MEMBERSHIP(gt, vifi) { \
- if ((gt)->gt_route && \
- VIFM_ISSET((vifi), (gt)->gt_route->rt_children) && \
- (!SUBS_ARE_PRUNED((gt)->gt_route->rt_subordinates, \
- uvifs[vifi].uv_nbrmap, (gt)->gt_prunes) || \
- grplst_mem((vifi), (gt)->gt_mcastgrp))) \
- VIFM_SET((vifi), (gt)->gt_grpmems); \
- }
-
-static int
-scoped_addr(vifi, addr)
- vifi_t vifi;
- u_int32 addr;
-{
- struct vif_acl *acl;
-
- for (acl = uvifs[vifi].uv_acl; acl; acl = acl->acl_next)
- if ((addr & acl->acl_mask) == acl->acl_addr)
- return 1;
-
- return 0;
-}
-
-/*
- * Determine the list of outgoing vifs, based upon
- * route subordinates, prunes received, and group
- * memberships.
- */
-void
-determine_forwvifs(gt)
- struct gtable *gt;
-{
- vifi_t i;
-
- VIFM_CLRALL(gt->gt_grpmems);
- for (i = 0; i < numvifs; i++) {
- GET_MEMBERSHIP(gt, i);
- }
- GET_SCOPE(gt);
- APPLY_SCOPE(gt);
-}
-
-/*
- * Send a prune or a graft if necessary.
- */
-void
-send_prune_or_graft(gt)
- struct gtable *gt;
-{
- if (VIFM_ISEMPTY(gt->gt_grpmems))
- send_prune(gt);
- else if (gt->gt_prsent_timer)
- send_graft(gt);
-}
-
-/*
- * Determine if mcastgrp has a listener on vifi
- */
-int
-grplst_mem(vifi, mcastgrp)
- vifi_t vifi;
- u_int32 mcastgrp;
-{
- register struct listaddr *g;
- register struct uvif *v;
-
- v = &uvifs[vifi];
-
- for (g = v->uv_groups; g != NULL; g = g->al_next)
- if (mcastgrp == g->al_addr)
- return 1;
-
- return 0;
-}
-
-/*
- * Finds the group entry with the specified source and netmask.
- * If netmask is 0, it uses the route's netmask.
- *
- * Returns TRUE if found a match, and the global variable gtp is left
- * pointing to entry before the found entry.
- * Returns FALSE if no exact match found, gtp is left pointing to before
- * the entry in question belongs, or is NULL if the it belongs at the
- * head of the list.
- */
-int
-find_src_grp(src, mask, grp)
- u_int32 src;
- u_int32 mask;
- u_int32 grp;
-{
- struct gtable *gt;
-
- gtp = NULL;
- gt = kernel_table;
- while (gt != NULL) {
- if (grp == gt->gt_mcastgrp &&
- (mask ? (gt->gt_route->rt_origin == src &&
- gt->gt_route->rt_originmask == mask) :
- ((src & gt->gt_route->rt_originmask) ==
- gt->gt_route->rt_origin)))
- return TRUE;
- if (ntohl(grp) > ntohl(gt->gt_mcastgrp) ||
- (grp == gt->gt_mcastgrp &&
- (ntohl(mask) < ntohl(gt->gt_route->rt_originmask) ||
- (mask == gt->gt_route->rt_originmask &&
- (ntohl(src) > ntohl(gt->gt_route->rt_origin)))))) {
- gtp = gt;
- gt = gt->gt_gnext;
- }
- else break;
- }
- return FALSE;
-}
-
-/*
- * Check if the neighbor supports pruning
- */
-static int
-pruning_neighbor(vifi, addr)
- vifi_t vifi;
- u_int32 addr;
-{
- struct listaddr *n = neighbor_info(vifi, addr);
- int vers;
-
- if (n == NULL)
- return 0;
-
- vers = NBR_VERS(n);
- return (vers >= 0x0300 && ((vers & 0xff00) != 0x0a00));
-}
-
-/*
- * Can the neighbor in question handle multicast traceroute?
- */
-static int
-can_mtrace(vifi, addr)
- vifi_t vifi;
- u_int32 addr;
-{
- struct listaddr *n = neighbor_info(vifi, addr);
- int vers;
-
- if (n == NULL)
- return 1; /* fail "safe" */
-
- vers = NBR_VERS(n);
- return (vers >= 0x0303 && ((vers & 0xff00) != 0x0a00));
-}
-
-/*
- * Returns the prune entry of the router, or NULL if none exists
- */
-static struct ptable *
-find_prune_entry(vr, pt)
- u_int32 vr;
- struct ptable *pt;
-{
- while (pt) {
- if (pt->pt_router == vr)
- return pt;
- pt = pt->pt_next;
- }
-
- return NULL;
-}
-
-/*
- * Remove all the sources hanging off the group table entry from the kernel
- * cache. Remember the packet counts wherever possible, to keep the mtrace
- * counters consistent. This prepares for possible prune retransmission,
- * either on a multi-access network or when a prune that we sent upstream
- * has expired.
- */
-static void
-remove_sources(gt)
- struct gtable *gt;
-{
- struct stable *st;
- struct sioc_sg_req sg_req;
-
- sg_req.grp.s_addr = gt->gt_mcastgrp;
-
- /*
- * call k_del_rg() on every one of the gt->gt_srctbl entries
- * but first save the packet count so that the mtrace packet
- * counters can remain approximately correct. There's a race
- * here but it's minor.
- */
- for (st = gt->gt_srctbl; st; st = st->st_next) {
- if (st->st_ctime == 0)
- continue;
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "rexmit_prune deleting (%s %s) (next is %d sec)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2),
- gt->gt_prune_rexmit);
- sg_req.src.s_addr = st->st_origin;
- if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) < 0) {
- sg_req.pktcnt = 0;
- }
- k_del_rg(st->st_origin, gt);
- st->st_ctime = 0; /* flag that it's not in the kernel any more */
- st->st_savpkt += sg_req.pktcnt;
- kroutes--;
- }
-
- /*
- * Now, add_table_entry will prune when asked to add a cache entry.
- */
-}
-
-/*
- * Prepare for possible prune retransmission
- */
-static void
-rexmit_prune(arg)
- void *arg;
-{
- struct gtable *gt = *(struct gtable **)arg;
-
- free(arg);
-
- gt->gt_rexmit_timer = 0;
-
- /* Make sure we're still not forwarding traffic */
- if (!VIFM_ISEMPTY(gt->gt_grpmems)) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "rexmit_prune (%s %s): gm:%x",
- RT_FMT(gt->gt_route, s1), inet_fmt(gt->gt_mcastgrp, s2),
- gt->gt_grpmems);
- return;
- }
-
- remove_sources(gt);
-}
-
-/*
- * Send a prune message to the dominant router for
- * this source.
- *
- * Record an entry that a prune was sent for this group
- */
-static void
-send_prune(gt)
- struct gtable *gt;
-{
- struct ptable *pt;
- char *p;
- int i;
- int datalen;
- u_int32 dst;
- u_int32 tmp;
- int rexmitting = 0;
- struct uvif *v;
-
- /*
- * Can't process a prune if we don't have an associated route
- * or if the route points to a local interface.
- */
- if (gt->gt_route == NULL || gt->gt_route->rt_parent == NO_VIF ||
- gt->gt_route->rt_gateway == 0)
- return;
-
- /* Don't send a prune to a non-pruning router */
- if (!pruning_neighbor(gt->gt_route->rt_parent, gt->gt_route->rt_gateway))
- return;
-
- v = &uvifs[gt->gt_route->rt_parent];
- /*
- * sends a prune message to the router upstream.
- */
-#if 0
- dst = v->uv_flags & VIFF_TUNNEL ? dvmrp_group : gt->gt_route->rt_gateway; /*XXX*/
-#else
- dst = gt->gt_route->rt_gateway;
-#endif
-
- p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
- datalen = 0;
-
- /*
- * determine prune lifetime, if this isn't a retransmission.
- *
- * Use interface-specified lifetime if there is one.
- */
- if (gt->gt_prsent_timer == 0) {
- int l = prune_lifetime;
-
- if (v->uv_prune_lifetime != 0)
- l = v->uv_prune_lifetime;
-
- gt->gt_prsent_timer = JITTERED_VALUE(l);
- for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next)
- if (pt->pt_timer < gt->gt_prsent_timer)
- gt->gt_prsent_timer = pt->pt_timer;
- } else if (gt->gt_prsent_timer < 0) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "asked to rexmit? (%s,%s)/%d on vif %d to %s with negative time",
- RT_FMT(gt->gt_route, s1), inet_fmt(gt->gt_mcastgrp, s2),
- gt->gt_prsent_timer, gt->gt_route->rt_parent,
- inet_fmt(gt->gt_route->rt_gateway, s3));
- return;
- } else
- rexmitting = 1;
-
- if (rexmitting && !(v->uv_flags & VIFF_REXMIT_PRUNES)) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "not rexmitting prune for (%s %s)/%d on vif %d to %s",
- RT_FMT(gt->gt_route, s1), inet_fmt(gt->gt_mcastgrp, s2),
- gt->gt_prsent_timer, gt->gt_route->rt_parent,
- inet_fmt(gt->gt_route->rt_gateway, s3));
- return;
- }
- if (gt->gt_prsent_timer <= MIN_PRUNE_LIFE) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "not bothering to send prune for (%s,%s)/%d on vif %d to %s because it's too short",
- RT_FMT(gt->gt_route, s1), inet_fmt(gt->gt_mcastgrp, s2),
- gt->gt_prsent_timer, gt->gt_route->rt_parent,
- inet_fmt(gt->gt_route->rt_gateway, s3));
- return;
- }
-
- /*
- * If we have a graft pending, cancel graft retransmission
- */
- gt->gt_grftsnt = 0;
-
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(gt->gt_route->rt_origin))[i];
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(gt->gt_mcastgrp))[i];
- tmp = htonl(gt->gt_prsent_timer);
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(tmp))[i];
- datalen += 12;
-
- send_on_vif(v, dst, DVMRP_PRUNE, datalen);
-
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "%s prune for (%s %s)/%d on vif %d to %s",
- rexmitting ? "rexmitted" : "sent",
- RT_FMT(gt->gt_route, s1), inet_fmt(gt->gt_mcastgrp, s2),
- gt->gt_prsent_timer, gt->gt_route->rt_parent,
- inet_fmt(gt->gt_route->rt_gateway, s3));
-
- if ((v->uv_flags & VIFF_REXMIT_PRUNES) &&
- gt->gt_rexmit_timer == 0 &&
- gt->gt_prsent_timer > gt->gt_prune_rexmit) {
- struct gtable **arg =
- (struct gtable **)malloc(sizeof (struct gtable **));
-
- *arg = gt;
- gt->gt_rexmit_timer = timer_setTimer(
- JITTERED_VALUE(gt->gt_prune_rexmit),
- rexmit_prune, arg);
- gt->gt_prune_rexmit *= 2;
- }
-}
-
-/*
- * a prune was sent upstream
- * so, a graft has to be sent to annul the prune
- * set up a graft timer so that if an ack is not
- * heard within that time, another graft request
- * is sent out.
- */
-static void
-send_graft(gt)
- struct gtable *gt;
-{
- register char *p;
- register int i;
- int datalen;
- u_int32 dst;
-
- /* Can't send a graft without an associated route */
- if (gt->gt_route == NULL || gt->gt_route->rt_parent == NO_VIF) {
- gt->gt_grftsnt = 0;
- return;
- }
-
- gt->gt_prsent_timer = 0;
- gt->gt_prune_rexmit = PRUNE_REXMIT_VAL;
- if (gt->gt_rexmit_timer)
- timer_clearTimer(gt->gt_rexmit_timer);
-
- if (gt->gt_grftsnt == 0)
- gt->gt_grftsnt = 1;
-
-#if 0
- dst = uvifs[gt->gt_route->rt_parent].uv_flags & VIFF_TUNNEL ? dvmrp_group : gt->gt_route->rt_gateway; /*XXX*/
-#else
- dst = gt->gt_route->rt_gateway;
-#endif
-
- p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
- datalen = 0;
-
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(gt->gt_route->rt_origin))[i];
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(gt->gt_mcastgrp))[i];
- datalen += 8;
-
- send_on_vif(&uvifs[gt->gt_route->rt_parent], dst, DVMRP_GRAFT, datalen);
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "sent graft for (%s %s) to %s on vif %d",
- RT_FMT(gt->gt_route, s1), inet_fmt(gt->gt_mcastgrp, s2),
- inet_fmt(gt->gt_route->rt_gateway, s3), gt->gt_route->rt_parent);
-}
-
-/*
- * Send an ack that a graft was received
- */
-static void
-send_graft_ack(src, dst, origin, grp, vifi)
- u_int32 src;
- u_int32 dst;
- u_int32 origin;
- u_int32 grp;
- vifi_t vifi;
-{
- register char *p;
- register int i;
- int datalen;
-
- p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
- datalen = 0;
-
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(origin))[i];
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(grp))[i];
- datalen += 8;
-
- if (vifi == NO_VIF)
- send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT_ACK,
- htonl(MROUTED_LEVEL), datalen);
- else {
-#if 0
- if (uvifs[vifi].uv_flags & VIFF_TUNNEL)
- dst = dvmrp_group; /* XXX */
-#endif
- send_on_vif(&uvifs[vifi], dst, DVMRP_GRAFT_ACK, datalen);
- }
-
- IF_DEBUG(DEBUG_PRUNE)
- if (vifi == NO_VIF)
- log(LOG_DEBUG, 0, "sent graft ack for (%s, %s) to %s",
- inet_fmt(origin, s1), inet_fmt(grp, s2), inet_fmt(dst, s3));
- else
- log(LOG_DEBUG, 0, "sent graft ack for (%s, %s) to %s on vif %d",
- inet_fmt(origin, s1), inet_fmt(grp, s2), inet_fmt(dst, s3), vifi);
-}
-
-/*
- * Update the kernel cache with all the routes hanging off the group entry
- */
-static void
-update_kernel(g)
- struct gtable *g;
-{
- struct stable *st;
-
- for (st = g->gt_srctbl; st; st = st->st_next)
- if (st->st_ctime != 0)
- k_add_rg(st->st_origin, g);
-}
-
-/****************************************************************************
- Functions that are used externally
-****************************************************************************/
-
-#ifdef SNMP
-#include <sys/types.h>
-#include "snmp.h"
-
-/*
- * Find a specific group entry in the group table
- */
-struct gtable *
-find_grp(grp)
- u_int32 grp;
-{
- struct gtable *gt;
-
- for (gt = kernel_table; gt; gt = gt->gt_gnext) {
- if (ntohl(grp) < ntohl(gt->gt_mcastgrp))
- break;
- if (gt->gt_mcastgrp == grp)
- return gt;
- }
- return NULL;
-}
-
-/*
- * Given a group entry and source, find the corresponding source table
- * entry
- */
-struct stable *
-find_grp_src(gt, src)
- struct gtable *gt;
- u_int32 src;
-{
- struct stable *st;
- u_long grp = gt->gt_mcastgrp;
- struct gtable *gtcurr;
-
- for (gtcurr = gt; gtcurr->gt_mcastgrp == grp; gtcurr = gtcurr->gt_gnext) {
- for (st = gtcurr->gt_srctbl; st; st = st->st_next)
- if (st->st_origin == src)
- return st;
- }
- return NULL;
-}
-
-/*
- * Find next entry > specification
- */
-int
-next_grp_src_mask(gtpp, stpp, grp, src, mask)
- struct gtable **gtpp; /* ordered by group */
- struct stable **stpp; /* ordered by source */
- u_int32 grp;
- u_int32 src;
- u_int32 mask;
-{
- struct gtable *gt, *gbest = NULL;
- struct stable *st, *sbest = NULL;
-
- /* Find first group entry >= grp spec */
- (*gtpp) = kernel_table;
- while ((*gtpp) && ntohl((*gtpp)->gt_mcastgrp) < ntohl(grp))
- (*gtpp)=(*gtpp)->gt_gnext;
- if (!(*gtpp))
- return 0; /* no more groups */
-
- for (gt = kernel_table; gt; gt=gt->gt_gnext) {
- /* Since grps are ordered, we can stop when group changes from gbest */
- if (gbest && gbest->gt_mcastgrp != gt->gt_mcastgrp)
- break;
- for (st = gt->gt_srctbl; st; st=st->st_next) {
-
- /* Among those entries > spec, find "lowest" one */
- if (((ntohl(gt->gt_mcastgrp)> ntohl(grp))
- || (ntohl(gt->gt_mcastgrp)==ntohl(grp)
- && ntohl(st->st_origin)> ntohl(src))
- || (ntohl(gt->gt_mcastgrp)==ntohl(grp)
- && ntohl(st->st_origin)==src && 0xFFFFFFFF>ntohl(mask)))
- && (!gbest
- || (ntohl(gt->gt_mcastgrp)< ntohl(gbest->gt_mcastgrp))
- || (ntohl(gt->gt_mcastgrp)==ntohl(gbest->gt_mcastgrp)
- && ntohl(st->st_origin)< ntohl(sbest->st_origin)))) {
- gbest = gt;
- sbest = st;
- }
- }
- }
- (*gtpp) = gbest;
- (*stpp) = sbest;
- return (*gtpp)!=0;
-}
-
-/*
- * Ensure that sg contains current information for the given group,source.
- * This is fetched from the kernel as a unit so that counts for the entry
- * are consistent, i.e. packet and byte counts for the same entry are
- * read at the same time.
- */
-void
-refresh_sg(sg, gt, st)
- struct sioc_sg_req *sg;
- struct gtable *gt;
- struct stable *st;
-{
- static int lastq = -1;
-
- if (quantum != lastq || sg->src.s_addr!=st->st_origin
- || sg->grp.s_addr!=gt->gt_mcastgrp) {
- lastq = quantum;
- sg->src.s_addr = st->st_origin;
- sg->grp.s_addr = gt->gt_mcastgrp;
- ioctl(udp_socket, SIOCGETSGCNT, (char *)sg);
- }
-}
-
-/*
- * Given a routing table entry, and a vifi, find the next entry
- * equal to or greater than those
- */
-int
-next_child(gtpp, stpp, grp, src, mask, vifi)
- struct gtable **gtpp;
- struct stable **stpp;
- u_int32 grp;
- u_int32 src;
- u_int32 mask;
- vifi_t *vifi; /* vif at which to start looking */
-{
- /* Get (G,S,M) entry */
- if (mask!=0xFFFFFFFF
- || !((*gtpp) = find_grp(grp))
- || !((*stpp) = find_grp_src((*gtpp),src)))
- if (!next_grp_src_mask(gtpp, stpp, grp, src, mask))
- return 0;
-
- /* Continue until we get one with a valid next vif */
- do {
- for (; (*gtpp)->gt_route->rt_children && *vifi<numvifs; (*vifi)++)
- if (VIFM_ISSET(*vifi, (*gtpp)->gt_route->rt_children))
- return 1;
- *vifi = 0;
- } while (next_grp_src_mask(gtpp, stpp, (*gtpp)->gt_mcastgrp,
- (*stpp)->st_origin, 0xFFFFFFFF) );
-
- return 0;
-}
-#endif /* SNMP */
-
-/*
- * Initialize the kernel table structure
- */
-void
-init_ktable()
-{
- kernel_table = NULL;
- kernel_no_route = NULL;
- kroutes = 0;
-}
-
-/*
- * Add a new table entry for (origin, mcastgrp)
- */
-void
-add_table_entry(origin, mcastgrp)
- u_int32 origin;
- u_int32 mcastgrp;
-{
- struct rtentry *r;
- struct gtable *gt,**gtnp,*prev_gt;
- struct stable *st,**stnp;
-
- /*
- * Since we have to enable mrouting to get the version number,
- * some cache creation requests can sneak through. Ignore them
- * since we're not going to do useful stuff until we've performed
- * final initialization.
- */
- if (!did_final_init)
- return;
-
-#ifdef DEBUG_MFC
- md_log(MD_MISS, origin, mcastgrp);
-#endif
-
- r = determine_route(origin);
- prev_gt = NULL;
- if (r == NULL) {
- /*
- * Look for it on the no_route table; if it is found then
- * it will be detected as a duplicate below.
- */
- for (gt = kernel_no_route; gt; gt = gt->gt_next)
- if (mcastgrp == gt->gt_mcastgrp &&
- gt->gt_srctbl && gt->gt_srctbl->st_origin == origin)
- break;
- gtnp = &kernel_no_route;
- } else {
- gtnp = &r->rt_groups;
- while ((gt = *gtnp) != NULL) {
- if (gt->gt_mcastgrp >= mcastgrp)
- break;
- gtnp = &gt->gt_next;
- prev_gt = gt;
- }
- }
-
- if (gt == NULL || gt->gt_mcastgrp != mcastgrp) {
- gt = (struct gtable *)malloc(sizeof(struct gtable));
- if (gt == NULL)
- log(LOG_ERR, 0, "ran out of memory");
-
- gt->gt_mcastgrp = mcastgrp;
- gt->gt_timer = CACHE_LIFETIME(cache_lifetime);
- time(&gt->gt_ctime);
- gt->gt_prsent_timer = 0;
- gt->gt_grftsnt = 0;
- gt->gt_srctbl = NULL;
- gt->gt_pruntbl = NULL;
- gt->gt_route = r;
- gt->gt_rexmit_timer = 0;
- NBRM_CLRALL(gt->gt_prunes);
- gt->gt_prune_rexmit = PRUNE_REXMIT_VAL;
-#ifdef RSRR
- gt->gt_rsrr_cache = NULL;
-#endif
-
- /* Calculate forwarding vifs */
- determine_forwvifs(gt);
-
- /* update ttls */
- prun_add_ttls(gt);
-
- gt->gt_next = *gtnp;
- *gtnp = gt;
- if (gt->gt_next)
- gt->gt_next->gt_prev = gt;
- gt->gt_prev = prev_gt;
-
- if (r) {
- if (find_src_grp(r->rt_origin, r->rt_originmask, gt->gt_mcastgrp)) {
- struct gtable *g;
-
- g = gtp ? gtp->gt_gnext : kernel_table;
- log(LOG_WARNING, 0, "Entry for (%s %s) (rt:%x) exists (rt:%x)",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2),
- r, g->gt_route);
- } else {
- if (gtp) {
- gt->gt_gnext = gtp->gt_gnext;
- gt->gt_gprev = gtp;
- gtp->gt_gnext = gt;
- } else {
- gt->gt_gnext = kernel_table;
- gt->gt_gprev = NULL;
- kernel_table = gt;
- }
- if (gt->gt_gnext)
- gt->gt_gnext->gt_gprev = gt;
- }
- } else {
- gt->gt_gnext = gt->gt_gprev = NULL;
- }
- }
-
- stnp = &gt->gt_srctbl;
- while ((st = *stnp) != NULL) {
- if (ntohl(st->st_origin) >= ntohl(origin))
- break;
- stnp = &st->st_next;
- }
-
- if (st == NULL || st->st_origin != origin) {
- st = (struct stable *)malloc(sizeof(struct stable));
- if (st == NULL)
- log(LOG_ERR, 0, "ran out of memory");
-
- st->st_origin = origin;
- st->st_pktcnt = 0;
- st->st_savpkt = 0;
- time(&st->st_ctime);
- st->st_next = *stnp;
- *stnp = st;
- } else {
- if (st->st_ctime == 0) {
- /* An old source which we're keeping around for statistics */
- time(&st->st_ctime);
- } else {
-#ifdef DEBUG_MFC
- md_log(MD_DUPE, origin, mcastgrp);
-#endif
- /* Ignore kernel->mrouted retransmissions */
- if (time(0) - st->st_ctime > 5)
- log(LOG_WARNING, 0, "kernel entry already exists for (%s %s)",
- inet_fmt(origin, s1), inet_fmt(mcastgrp, s2));
- k_add_rg(origin, gt);
- return;
- }
- }
-
- kroutes++;
- k_add_rg(origin, gt);
-
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "add cache entry (%s %s) gm:%x, parent-vif:%d",
- inet_fmt(origin, s1),
- inet_fmt(mcastgrp, s2),
- gt->gt_grpmems, r ? r->rt_parent : -1);
-
- /*
- * If there are no downstream routers that want traffic for
- * this group, send (or retransmit) a prune upstream.
- */
- if (VIFM_ISEMPTY(gt->gt_grpmems))
- send_prune(gt);
-}
-
-/*
- * A router has gone down. Remove prune state pertinent to that router.
- */
-void
-reset_neighbor_state(vifi, addr)
- vifi_t vifi;
- u_int32 addr;
-{
- struct rtentry *r;
- struct gtable *g;
- struct ptable *pt, **ptnp;
- struct stable *st;
-
- for (g = kernel_table; g; g = g->gt_gnext) {
- r = g->gt_route;
-
- /*
- * If neighbor was the parent, remove the prune sent state
- * and all of the source cache info so that prunes get
- * regenerated.
- */
- if (vifi == r->rt_parent) {
- if (addr == r->rt_gateway) {
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "reset_neighbor_state parent reset (%s %s)",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2));
-
- g->gt_prsent_timer = 0;
- g->gt_grftsnt = 0;
- while ((st = g->gt_srctbl) != NULL) {
- g->gt_srctbl = st->st_next;
- if (st->st_ctime != 0) {
- k_del_rg(st->st_origin, g);
- kroutes--;
- }
- free(st);
- }
- }
- } else {
- /*
- * Remove any prunes that this router has sent us.
- */
- ptnp = &g->gt_pruntbl;
- while ((pt = *ptnp) != NULL) {
- if (pt->pt_vifi == vifi && pt->pt_router == addr) {
- NBRM_CLR(pt->pt_index, g->gt_prunes);
- *ptnp = pt->pt_next;
- free(pt);
- } else
- ptnp = &pt->pt_next;
- }
-
- /*
- * And see if we want to forward again.
- */
- if (!VIFM_ISSET(vifi, g->gt_grpmems)) {
- GET_MEMBERSHIP(g, vifi);
- APPLY_SCOPE(g);
- prun_add_ttls(g);
-
- /* Update kernel state */
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
-
- /*
- * If removing this prune causes us to start forwarding
- * (e.g. the neighbor rebooted), and we sent a prune upstream,
- * send a graft to cancel the prune.
- */
- if (!VIFM_ISEMPTY(g->gt_grpmems) && g->gt_prsent_timer)
- send_graft(g);
-
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "reset neighbor state (%s %s) gm:%x",
- RT_FMT(r, s1),
- inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
- }
- }
- }
-}
-
-/*
- * Delete table entry from the kernel
- * del_flag determines how many entries to delete
- */
-void
-del_table_entry(r, mcastgrp, del_flag)
- struct rtentry *r;
- u_int32 mcastgrp;
- u_int del_flag;
-{
- struct gtable *g, *prev_g;
- struct stable *st, *prev_st;
- struct ptable *pt, *prev_pt;
-
- if (del_flag == DEL_ALL_ROUTES) {
- g = r->rt_groups;
- while (g) {
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "del_table_entry deleting (%s %s)",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2));
- st = g->gt_srctbl;
- while (st) {
- if (st->st_ctime != 0) {
- if (k_del_rg(st->st_origin, g) < 0) {
- log(LOG_WARNING, errno,
- "del_table_entry trying to delete (%s, %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(g->gt_mcastgrp, s2));
- }
- kroutes--;
- }
- prev_st = st;
- st = st->st_next;
- free(prev_st);
- }
- g->gt_srctbl = NULL;
-
- pt = g->gt_pruntbl;
- while (pt) {
- prev_pt = pt;
- pt = pt->pt_next;
- free(prev_pt);
- }
- g->gt_pruntbl = NULL;
-
- if (g->gt_gnext)
- g->gt_gnext->gt_gprev = g->gt_gprev;
- if (g->gt_gprev)
- g->gt_gprev->gt_gnext = g->gt_gnext;
- else
- kernel_table = g->gt_gnext;
-
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,0);
- rsrr_cache_clean(g);
-#endif /* RSRR */
- if (g->gt_rexmit_timer)
- timer_clearTimer(g->gt_rexmit_timer);
-
- prev_g = g;
- g = g->gt_next;
- free(prev_g);
- }
- r->rt_groups = NULL;
- }
-
- /*
- * Dummy routine - someday this may be needed, so it is just there
- */
- if (del_flag == DEL_RTE_GROUP) {
- prev_g = (struct gtable *)&r->rt_groups;
- for (g = r->rt_groups; g; g = g->gt_next) {
- if (g->gt_mcastgrp == mcastgrp) {
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "del_table_entry deleting (%s %s)",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2));
- st = g->gt_srctbl;
- while (st) {
- if (st->st_ctime != 0) {
- if (k_del_rg(st->st_origin, g) < 0) {
- log(LOG_WARNING, errno,
- "del_table_entry trying to delete (%s, %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(g->gt_mcastgrp, s2));
- }
- kroutes--;
- }
- prev_st = st;
- st = st->st_next;
- free(prev_st);
- }
- g->gt_srctbl = NULL;
-
- pt = g->gt_pruntbl;
- while (pt) {
- prev_pt = pt;
- pt = pt->pt_next;
- free(prev_pt);
- }
- g->gt_pruntbl = NULL;
-
- if (g->gt_gnext)
- g->gt_gnext->gt_gprev = g->gt_gprev;
- if (g->gt_gprev)
- g->gt_gprev->gt_gnext = g->gt_gnext;
- else
- kernel_table = g->gt_gnext;
-
- if (prev_g != (struct gtable *)&r->rt_groups)
- g->gt_next->gt_prev = prev_g;
- else
- g->gt_next->gt_prev = NULL;
- prev_g->gt_next = g->gt_next;
-
- if (g->gt_rexmit_timer)
- timer_clearTimer(g->gt_rexmit_timer);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,0);
- rsrr_cache_clean(g);
-#endif /* RSRR */
- free(g);
- g = prev_g;
- } else {
- prev_g = g;
- }
- }
- }
-}
-
-/*
- * update kernel table entry when a route entry changes
- */
-void
-update_table_entry(r, old_parent_gw)
- struct rtentry *r;
- u_int32 old_parent_gw;
-{
- struct gtable *g;
- struct ptable *pt, **ptnp;
-
- for (g = r->rt_groups; g; g = g->gt_next) {
- ptnp = &g->gt_pruntbl;
- /*
- * Delete prune entries from non-children, or non-subordinates.
- */
- while ((pt = *ptnp)) {
- if (!VIFM_ISSET(pt->pt_vifi, r->rt_children) ||
- !NBRM_ISSET(pt->pt_index, r->rt_subordinates)) {
-
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "update_table_entry deleting prune for (%s %s) from %s on vif %d -%s%s",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2),
- inet_fmt(pt->pt_router, s3), pt->pt_vifi,
- VIFM_ISSET(pt->pt_vifi, r->rt_children) ? "" : " not a child",
- NBRM_ISSET(pt->pt_index, r->rt_subordinates) ? "" : " not a subordinate");
-
- if (!NBRM_ISSET(pt->pt_index, g->gt_prunes)) {
- log(LOG_WARNING, 0,
- "gt_prunes lost track of (%s %s) from %s on vif %d",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2),
- inet_fmt(pt->pt_router, s3), pt->pt_vifi);
- }
-
- NBRM_CLR(pt->pt_index, g->gt_prunes);
- *ptnp = pt->pt_next;
- free(pt);
- continue;
- }
- ptnp = &((*ptnp)->pt_next);
- }
-
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "updating cache entries (%s %s) old gm:%x",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2),
- g->gt_grpmems);
-
- /*
- * Forget about a prune or graft that we sent previously if we
- * have a new parent router (since the new parent router will
- * know nothing about what I sent to the previous parent). The
- * old parent will forget any prune state it is keeping for us.
- */
- if (old_parent_gw != r->rt_gateway) {
- g->gt_prsent_timer = 0;
- g->gt_grftsnt = 0;
- }
-
- /* Recalculate membership */
- determine_forwvifs(g);
- /* send a prune or graft if needed. */
- send_prune_or_graft(g);
-
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "updating cache entries (%s %s) new gm:%x",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2),
- g->gt_grpmems);
-
- /* update ttls and add entry into kernel */
- prun_add_ttls(g);
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
- }
-}
-
-/*
- * set the forwarding flag for all mcastgrps on this vifi
- */
-void
-update_lclgrp(vifi, mcastgrp)
- vifi_t vifi;
- u_int32 mcastgrp;
-{
- struct rtentry *r;
- struct gtable *g;
-
- IF_DEBUG(DEBUG_MEMBER)
- log(LOG_DEBUG, 0, "group %s joined on vif %d",
- inet_fmt(mcastgrp, s1), vifi);
-
- for (g = kernel_table; g; g = g->gt_gnext) {
- if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp))
- break;
-
- r = g->gt_route;
- if (g->gt_mcastgrp == mcastgrp &&
- VIFM_ISSET(vifi, r->rt_children)) {
-
- VIFM_SET(vifi, g->gt_grpmems);
- APPLY_SCOPE(g);
- if (VIFM_ISEMPTY(g->gt_grpmems))
- continue;
-
- prun_add_ttls(g);
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "update lclgrp (%s %s) gm:%x",
- RT_FMT(r, s1),
- inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
-
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
- }
- }
-}
-
-/*
- * reset forwarding flag for all mcastgrps on this vifi
- */
-void
-delete_lclgrp(vifi, mcastgrp)
- vifi_t vifi;
- u_int32 mcastgrp;
-{
- struct gtable *g;
-
- IF_DEBUG(DEBUG_MEMBER)
- log(LOG_DEBUG, 0, "group %s left on vif %d",
- inet_fmt(mcastgrp, s1), vifi);
-
- for (g = kernel_table; g; g = g->gt_gnext) {
- if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp))
- break;
-
- if (g->gt_mcastgrp == mcastgrp && VIFM_ISSET(vifi, g->gt_grpmems)) {
- if (g->gt_route == NULL ||
- SUBS_ARE_PRUNED(g->gt_route->rt_subordinates,
- uvifs[vifi].uv_nbrmap, g->gt_prunes)) {
- VIFM_CLR(vifi, g->gt_grpmems);
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "delete lclgrp (%s %s) gm:%x",
- RT_FMT(g->gt_route, s1),
- inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
-
- prun_add_ttls(g);
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
-
- /*
- * If there are no more members of this particular group,
- * send prune upstream
- */
- if (VIFM_ISEMPTY(g->gt_grpmems) && g->gt_route->rt_gateway)
- send_prune(g);
- }
- }
- }
-}
-
-/*
- * Takes the prune message received and then strips it to
- * determine the (src, grp) pair to be pruned.
- *
- * Adds the router to the (src, grp) entry then.
- *
- * Determines if further packets have to be sent down that vif
- *
- * Determines if a corresponding prune message has to be generated
- */
-void
-accept_prune(src, dst, p, datalen)
- u_int32 src;
- u_int32 dst;
- char *p;
- int datalen;
-{
- u_int32 prun_src;
- u_int32 prun_grp;
- u_int32 prun_tmr;
- vifi_t vifi;
- int i;
- struct rtentry *r;
- struct gtable *g;
- struct ptable *pt;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF) {
- log(LOG_INFO, 0,
- "ignoring prune report from non-neighbor %s",
- inet_fmt(src, s1));
- return;
- }
-
- /* Check if enough data is present */
- if (datalen < 12)
- {
- log(LOG_WARNING, 0,
- "non-decipherable prune from %s",
- inet_fmt(src, s1));
- return;
- }
-
- for (i = 0; i< 4; i++)
- ((char *)&prun_src)[i] = *p++;
- for (i = 0; i< 4; i++)
- ((char *)&prun_grp)[i] = *p++;
- for (i = 0; i< 4; i++)
- ((char *)&prun_tmr)[i] = *p++;
- prun_tmr = ntohl(prun_tmr);
-
- if (prun_tmr <= MIN_PRUNE_LIFE) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "ignoring prune from %s on vif %d for (%s %s)/%d because its lifetime is too short",
- inet_fmt(src, s1), vifi,
- inet_fmt(prun_src, s2), inet_fmt(prun_grp, s3), prun_tmr);
- return;
- }
-
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "%s on vif %d prunes (%s %s)/%d",
- inet_fmt(src, s1), vifi,
- inet_fmt(prun_src, s2), inet_fmt(prun_grp, s3), prun_tmr);
-
- /*
- * Find the subnet for the prune
- */
- if (find_src_grp(prun_src, 0, prun_grp)) {
- g = gtp ? gtp->gt_gnext : kernel_table;
- r = g->gt_route;
-
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "found grp state, (%s %s), metric is %d, children are %x, subords are %08x%08x",
- RT_FMT(r, s1), inet_fmt(g->gt_mcastgrp, s2), r->rt_metric,
- r->rt_children, r->rt_subordinates.hi, r->rt_subordinates.lo);
- if (!VIFM_ISSET(vifi, r->rt_children)) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_WARNING, 0, "prune received from non-child %s for (%s %s) (dominant on vif %d is %s)",
- inet_fmt(src, s1), inet_fmt(prun_src, s2),
- inet_fmt(prun_grp, s3), vifi,
- inet_fmt(r->rt_dominants[vifi], s4));
-#ifdef RINGBUFFER
- printringbuf();
-#endif
- return;
- }
- if (VIFM_ISSET(vifi, g->gt_scope)) {
- log(LOG_WARNING, 0, "prune received from %s on scoped grp (%s %s)",
- inet_fmt(src, s1), inet_fmt(prun_src, s2),
- inet_fmt(prun_grp, s3));
- return;
- }
- if ((pt = find_prune_entry(src, g->gt_pruntbl)) != NULL) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "%s %d from %s for (%s %s)/%d %s %d %s %x",
- "duplicate prune received on vif",
- vifi, inet_fmt(src, s1), inet_fmt(prun_src, s2),
- inet_fmt(prun_grp, s3), prun_tmr,
- "old timer:", pt->pt_timer, "cur gm:", g->gt_grpmems);
- pt->pt_timer = prun_tmr;
- } else {
- struct listaddr *n = neighbor_info(vifi, src);
-
- if (!n) {
- log(LOG_WARNING, 0, "Prune from non-neighbor %s on vif %d!?",
- inet_fmt(src, s1), vifi);
- return;
- }
-
- /* allocate space for the prune structure */
- pt = (struct ptable *)(malloc(sizeof(struct ptable)));
- if (pt == NULL)
- log(LOG_ERR, 0, "pt: ran out of memory");
-
- pt->pt_vifi = vifi;
- pt->pt_router = src;
- pt->pt_timer = prun_tmr;
-
- pt->pt_next = g->gt_pruntbl;
- g->gt_pruntbl = pt;
-
- if (n) {
- pt->pt_index = n->al_index;
- NBRM_SET(n->al_index, g->gt_prunes);
- }
- }
-
- /*
- * check if any more packets need to be sent on the
- * vif which sent this message
- */
- if (SUBS_ARE_PRUNED(r->rt_subordinates,
- uvifs[vifi].uv_nbrmap, g->gt_prunes) &&
- !grplst_mem(vifi, prun_grp)) {
- nbrbitmap_t tmp;
-
- VIFM_CLR(vifi, g->gt_grpmems);
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "vifnbrs=0x%08x%08x, subord=0x%08x%08x prunes=0x%08x%08x",
- uvifs[vifi].uv_nbrmap.hi,uvifs[vifi].uv_nbrmap.lo,
- r->rt_subordinates.hi, r->rt_subordinates.lo,
- g->gt_prunes.hi, g->gt_prunes.lo);
- /* XXX debugging */
- NBRM_COPY(r->rt_subordinates, tmp);
- NBRM_MASK(tmp, uvifs[vifi].uv_nbrmap);
- if (!NBRM_ISSETALLMASK(g->gt_prunes, tmp))
- log(LOG_WARNING, 0, "subordinate error");
- /* XXX end debugging */
- IF_DEBUG(DEBUG_PRUNE|DEBUG_CACHE)
- log(LOG_DEBUG, 0, "prune (%s %s), stop sending on vif %d, gm:%x",
- RT_FMT(r, s1),
- inet_fmt(g->gt_mcastgrp, s2), vifi, g->gt_grpmems);
-
- prun_add_ttls(g);
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
- }
-
- /*
- * check if all the child routers have expressed no interest
- * in this group and if this group does not exist in the
- * interface
- * Send a prune message then upstream
- */
- if (VIFM_ISEMPTY(g->gt_grpmems) && r->rt_gateway) {
- send_prune(g);
- }
- } else {
- /*
- * There is no kernel entry for this group. Therefore, we can
- * simply ignore the prune, as we are not forwarding this traffic
- * downstream.
- */
- IF_DEBUG(DEBUG_PRUNE|DEBUG_CACHE)
- log(LOG_DEBUG, 0, "%s (%s %s)/%d from %s",
- "prune message received with no kernel entry for",
- inet_fmt(prun_src, s1), inet_fmt(prun_grp, s2),
- prun_tmr, inet_fmt(src, s3));
- return;
- }
-}
-
-/*
- * Checks if this mcastgrp is present in the kernel table
- * If so and if a prune was sent, it sends a graft upwards
- */
-void
-chkgrp_graft(vifi, mcastgrp)
- vifi_t vifi;
- u_int32 mcastgrp;
-{
- struct rtentry *r;
- struct gtable *g;
-
- for (g = kernel_table; g; g = g->gt_gnext) {
- if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp))
- break;
-
- r = g->gt_route;
- if (g->gt_mcastgrp == mcastgrp && VIFM_ISSET(vifi, r->rt_children))
- if (g->gt_prsent_timer) {
- VIFM_SET(vifi, g->gt_grpmems);
-
- /*
- * If the vif that was joined was a scoped vif,
- * ignore it ; don't graft back
- */
- APPLY_SCOPE(g);
- if (VIFM_ISEMPTY(g->gt_grpmems))
- continue;
-
- /* send graft upwards */
- send_graft(g);
-
- /* update cache timer*/
- g->gt_timer = CACHE_LIFETIME(cache_lifetime);
-
- IF_DEBUG(DEBUG_PRUNE|DEBUG_CACHE)
- log(LOG_DEBUG, 0, "chkgrp graft (%s %s) gm:%x",
- RT_FMT(r, s1),
- inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
-
- prun_add_ttls(g);
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
- }
- }
-}
-
-/* determine the multicast group and src
- *
- * if it does, then determine if a prune was sent
- * upstream.
- * if prune sent upstream, send graft upstream and send
- * ack downstream.
- *
- * if no prune sent upstream, change the forwarding bit
- * for this interface and send ack downstream.
- *
- * if no entry exists for this group send ack downstream.
- */
-void
-accept_graft(src, dst, p, datalen)
- u_int32 src;
- u_int32 dst;
- char *p;
- int datalen;
-{
- vifi_t vifi;
- u_int32 graft_src;
- u_int32 graft_grp;
- int i;
- struct rtentry *r;
- struct gtable *g;
- struct ptable *pt, **ptnp;
-
- if (datalen < 8) {
- log(LOG_WARNING, 0,
- "received non-decipherable graft from %s",
- inet_fmt(src, s1));
- return;
- }
-
- for (i = 0; i< 4; i++)
- ((char *)&graft_src)[i] = *p++;
- for (i = 0; i< 4; i++)
- ((char *)&graft_grp)[i] = *p++;
-
- vifi = find_vif(src, dst);
- send_graft_ack(dst, src, graft_src, graft_grp, vifi);
-
- if (vifi == NO_VIF) {
- log(LOG_INFO, 0,
- "ignoring graft for (%s %s) from non-neighbor %s",
- inet_fmt(graft_src, s2), inet_fmt(graft_grp, s3),
- inet_fmt(src, s1));
- return;
- }
-
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "%s on vif %d grafts (%s %s)",
- inet_fmt(src, s1), vifi,
- inet_fmt(graft_src, s2), inet_fmt(graft_grp, s3));
-
- /*
- * Find the subnet for the graft
- */
- if (find_src_grp(graft_src, 0, graft_grp)) {
- g = gtp ? gtp->gt_gnext : kernel_table;
- r = g->gt_route;
-
- if (VIFM_ISSET(vifi, g->gt_scope)) {
- log(LOG_WARNING, 0, "graft received from %s on scoped grp (%s %s)",
- inet_fmt(src, s1), inet_fmt(graft_src, s2),
- inet_fmt(graft_grp, s3));
- return;
- }
-
- ptnp = &g->gt_pruntbl;
- while ((pt = *ptnp) != NULL) {
- if ((pt->pt_vifi == vifi) && (pt->pt_router == src)) {
- NBRM_CLR(pt->pt_index, g->gt_prunes);
- *ptnp = pt->pt_next;
- free(pt);
-
- VIFM_SET(vifi, g->gt_grpmems);
- IF_DEBUG(DEBUG_PRUNE|DEBUG_CACHE)
- log(LOG_DEBUG, 0, "accept graft (%s %s) gm:%x",
- RT_FMT(r, s1),
- inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems);
-
- prun_add_ttls(g);
- update_kernel(g);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(g,1);
-#endif /* RSRR */
- break;
- } else {
- ptnp = &pt->pt_next;
- }
- }
-
- g->gt_timer = CACHE_LIFETIME(cache_lifetime);
-
- if (g->gt_prsent_timer)
- /* send graft upwards */
- send_graft(g);
- } else {
- /*
- * We have no state for the source and group in question.
- * This is fine, since we know that we have no prune state, and
- * grafts are requests to remove prune state.
- */
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "%s (%s %s) from %s",
- "graft received with no kernel entry for",
- inet_fmt(graft_src, s1), inet_fmt(graft_grp, s2),
- inet_fmt(src, s3));
- return;
- }
-}
-
-/*
- * find out which group is involved first of all
- * then determine if a graft was sent.
- * if no graft sent, ignore the message
- * if graft was sent and the ack is from the right
- * source, remove the graft timer so that we don't
- * have send a graft again
- */
-void
-accept_g_ack(src, dst, p, datalen)
- u_int32 src;
- u_int32 dst;
- char *p;
- int datalen;
-{
- struct gtable *g;
- vifi_t vifi;
- u_int32 grft_src;
- u_int32 grft_grp;
- int i;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF) {
- log(LOG_INFO, 0,
- "ignoring graft ack from non-neighbor %s",
- inet_fmt(src, s1));
- return;
- }
-
- if (datalen < 0 || datalen > 8) {
- log(LOG_WARNING, 0,
- "received non-decipherable graft ack from %s",
- inet_fmt(src, s1));
- return;
- }
-
- for (i = 0; i< 4; i++)
- ((char *)&grft_src)[i] = *p++;
- for (i = 0; i< 4; i++)
- ((char *)&grft_grp)[i] = *p++;
-
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "%s on vif %d acks graft (%s, %s)",
- inet_fmt(src, s1), vifi,
- inet_fmt(grft_src, s2), inet_fmt(grft_grp, s3));
-
- /*
- * Find the subnet for the graft ack
- */
- if (find_src_grp(grft_src, 0, grft_grp)) {
- g = gtp ? gtp->gt_gnext : kernel_table;
- g->gt_grftsnt = 0;
- } else {
- log(LOG_WARNING, 0, "%s (%s, %s) from %s",
- "rcvd graft ack with no kernel entry for",
- inet_fmt(grft_src, s1), inet_fmt(grft_grp, s2),
- inet_fmt(src, s3));
-#ifdef RINGBUFFER
- printringbuf();
-#endif
- return;
- }
-}
-
-
-/*
- * free all prune entries and kernel routes
- * normally, this should inform the kernel that all of its routes
- * are going away, but this is only called by restart(), which is
- * about to call MRT_DONE which does that anyway.
- */
-void
-free_all_prunes()
-{
- register struct rtentry *r;
- register struct gtable *g, *prev_g;
- register struct stable *s, *prev_s;
- register struct ptable *p, *prev_p;
-
- for (r = routing_table; r; r = r->rt_next) {
- g = r->rt_groups;
- while (g) {
- s = g->gt_srctbl;
- while (s) {
- prev_s = s;
- s = s->st_next;
- free(prev_s);
- }
-
- p = g->gt_pruntbl;
- while (p) {
- prev_p = p;
- p = p->pt_next;
- free(prev_p);
- }
-
- prev_g = g;
- g = g->gt_next;
- if (prev_g->gt_rexmit_timer)
- timer_clearTimer(prev_g->gt_rexmit_timer);
- free(prev_g);
- }
- r->rt_groups = NULL;
- }
- kernel_table = NULL;
-
- g = kernel_no_route;
- while (g) {
- if (g->gt_srctbl)
- free(g->gt_srctbl);
-
- prev_g = g;
- g = g->gt_next;
- if (prev_g->gt_rexmit_timer)
- timer_clearTimer(prev_g->gt_rexmit_timer);
- free(prev_g);
- }
- kernel_no_route = NULL;
-}
-
-/*
- * When a new route is created, search
- * a) The less-specific part of the routing table
- * b) The route-less kernel table
- * for sources that the new route might want to handle.
- *
- * "Inheriting" these sources might be cleanest, but simply deleting
- * them is easier, and letting the kernel re-request them.
- */
-void
-steal_sources(rt)
- struct rtentry *rt;
-{
- register struct rtentry *rp;
- register struct gtable *gt, **gtnp;
- register struct stable *st, **stnp;
-
- for (rp = rt->rt_next; rp; rp = rp->rt_next) {
- if (rp->rt_groups == NULL)
- continue;
- if ((rt->rt_origin & rp->rt_originmask) == rp->rt_origin) {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "Route for %s stealing sources from %s",
- RT_FMT(rt, s1), RT_FMT(rp, s2));
- for (gt = rp->rt_groups; gt; gt = gt->gt_next) {
- stnp = &gt->gt_srctbl;
- while ((st = *stnp) != NULL) {
- if ((st->st_origin & rt->rt_originmask) == rt->rt_origin) {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "%s stealing (%s %s) from %s",
- RT_FMT(rt, s1),
- inet_fmt(st->st_origin, s3),
- inet_fmt(gt->gt_mcastgrp, s4),
- RT_FMT(rp, s2));
- if (st->st_ctime != 0) {
- if (k_del_rg(st->st_origin, gt) < 0) {
- log(LOG_WARNING, errno, "%s (%s, %s)",
- "steal_sources trying to delete",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- }
- kroutes--;
- }
- *stnp = st->st_next;
- free(st);
- } else {
- stnp = &st->st_next;
- }
- }
- }
- }
- }
-
- gtnp = &kernel_no_route;
- while ((gt = *gtnp) != NULL) {
- if (gt->gt_srctbl && ((gt->gt_srctbl->st_origin & rt->rt_originmask)
- == rt->rt_origin)) {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "%s stealing (%s %s) from %s",
- RT_FMT(rt, s1),
- inet_fmt(gt->gt_srctbl->st_origin, s3),
- inet_fmt(gt->gt_mcastgrp, s4),
- "no_route table");
- if (gt->gt_srctbl->st_ctime != 0) {
- if (k_del_rg(gt->gt_srctbl->st_origin, gt) < 0) {
- log(LOG_WARNING, errno, "%s (%s %s)",
- "steal_sources trying to delete",
- inet_fmt(gt->gt_srctbl->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- }
- kroutes--;
- }
- free(gt->gt_srctbl);
- *gtnp = gt->gt_next;
- if (gt->gt_next)
- gt->gt_next->gt_prev = gt->gt_prev;
- if (gt->gt_rexmit_timer)
- timer_clearTimer(gt->gt_rexmit_timer);
- free(gt);
- } else {
- gtnp = &gt->gt_next;
- }
- }
-}
-
-/*
- * Advance the timers on all the cache entries.
- * If there are any entries whose timers have expired,
- * remove these entries from the kernel cache.
- */
-void
-age_table_entry()
-{
- struct rtentry *r;
- struct gtable *gt, **gtnptr;
- struct stable *st, **stnp;
- struct ptable *pt, **ptnp;
- struct sioc_sg_req sg_req;
-
- IF_DEBUG(DEBUG_PRUNE|DEBUG_CACHE)
- log(LOG_DEBUG, 0, "aging forwarding cache entries");
-
- gtnptr = &kernel_table;
- while ((gt = *gtnptr) != NULL) {
- vifi_t i; /* XXX Debugging */
- int fixit = 0; /* XXX Debugging */
-
- r = gt->gt_route;
-
- /* XXX Debugging... */
- for (i = 0; i < numvifs; i++) {
- /*
- * If we're not sending on this vif,
- * And this group isn't scoped on this vif,
- * And I'm the parent for this route on this vif,
- * And there are subordinates on this vif,
- * And all of the subordinates haven't pruned,
- * YELL LOUDLY
- * and remember to fix it up later
- */
- if (!VIFM_ISSET(i, gt->gt_grpmems) &&
- !VIFM_ISSET(i, gt->gt_scope) &&
- VIFM_ISSET(i, r->rt_children) &&
- NBRM_ISSETMASK(uvifs[i].uv_nbrmap, r->rt_subordinates) &&
- !SUBS_ARE_PRUNED(r->rt_subordinates, uvifs[i].uv_nbrmap, gt->gt_prunes)) {
- log(LOG_WARNING, 0, "(%s %s) is blackholing on vif %d",
- RT_FMT(r, s1), inet_fmt(gt->gt_mcastgrp, s2), i);
- fixit = 1;
- }
- }
- if (fixit) {
- log(LOG_WARNING, 0, "fixing membership for (%s %s) gm:%x",
- RT_FMT(r, s1), inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems);
- determine_forwvifs(gt);
- send_prune_or_graft(gt);
- log(LOG_WARNING, 0, "fixed membership for (%s %s) gm:%x",
- RT_FMT(r, s1), inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems);
-#ifdef RINGBUFFER
- printringbuf();
-#endif
- }
- /*DEBUG2*/
- /* If there are group members,
- * and there are recent sources,
- * and we have a route,
- * and it's not directly connected,
- * and we haven't sent a prune,
- * if there are any cache entries in the kernel
- * [if there aren't we're probably waiting to rexmit],
- * YELL LOUDLY
- * and send a prune
- */
- if (VIFM_ISEMPTY(gt->gt_grpmems) && gt->gt_srctbl && r && r->rt_gateway && gt->gt_prsent_timer == 0) {
- for (st = gt->gt_srctbl; st; st = st->st_next)
- if (st->st_ctime != 0)
- break;
- if (st != NULL) {
- log(LOG_WARNING, 0, "grpmems for (%s %s) is empty but no prune state!", RT_FMT(r, s1), inet_fmt(gt->gt_mcastgrp, s2));
- send_prune_or_graft(gt);
-#ifdef RINGBUFFER
- printringbuf();
-#endif
- }
- }
- /* XXX ...Debugging */
-
- /* advance the timer for the kernel entry */
- gt->gt_timer -= TIMER_INTERVAL;
-
- /* decrement prune timer if need be */
- if (gt->gt_prsent_timer > 0) {
- gt->gt_prsent_timer -= TIMER_INTERVAL;
- if (gt->gt_prsent_timer <= 0) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "upstream prune tmo (%s %s)",
- RT_FMT(r, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- gt->gt_prsent_timer = -1;
- /* Reset the prune retransmission timer to its initial value */
- gt->gt_prune_rexmit = PRUNE_REXMIT_VAL;
- }
- }
-
- /* retransmit graft with exponential backoff */
- if (gt->gt_grftsnt) {
- register int y;
-
- y = ++gt->gt_grftsnt;
- while (y && !(y & 1))
- y >>= 1;
- if (y == 1)
- send_graft(gt);
- }
-
- /*
- * Age prunes
- *
- * If a prune expires, forward again on that vif.
- */
- ptnp = &gt->gt_pruntbl;
- while ((pt = *ptnp) != NULL) {
- if ((pt->pt_timer -= TIMER_INTERVAL) <= 0) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "expire prune (%s %s) from %s on vif %d",
- RT_FMT(r, s1),
- inet_fmt(gt->gt_mcastgrp, s2),
- inet_fmt(pt->pt_router, s3),
- pt->pt_vifi);
- if (gt->gt_prsent_timer > 0) {
- log(LOG_WARNING, 0, "prune (%s %s) from %s on vif %d expires with %d left on prsent timer",
- RT_FMT(r, s1),
- inet_fmt(gt->gt_mcastgrp, s2),
- inet_fmt(pt->pt_router, s3),
- pt->pt_vifi, gt->gt_prsent_timer);
- /* Send a graft to heal the tree. */
- send_graft(gt);
- }
-
- NBRM_CLR(pt->pt_index, gt->gt_prunes);
- expire_prune(pt->pt_vifi, gt);
-
- /* remove the router's prune entry and await new one */
- *ptnp = pt->pt_next;
- free(pt);
- } else {
- ptnp = &pt->pt_next;
- }
- }
-
- /*
- * If the cache entry has expired, delete source table entries for
- * silent sources. If there are no source entries left, and there
- * are no downstream prunes, then the entry is deleted.
- * Otherwise, the cache entry's timer is refreshed.
- */
- if (gt->gt_timer <= 0) {
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "(%s %s) timed out, checking for traffic",
- RT_FMT(gt->gt_route, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- /* Check for traffic before deleting source entries */
- sg_req.grp.s_addr = gt->gt_mcastgrp;
- stnp = &gt->gt_srctbl;
- while ((st = *stnp) != NULL) {
- /*
- * Source entries with no ctime are not actually in the
- * kernel; they have been removed by rexmit_prune() so
- * are safe to remove from the list at this point.
- */
- if (st->st_ctime) {
- sg_req.src.s_addr = st->st_origin;
- if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) < 0) {
- log(LOG_WARNING, errno, "%s (%s %s)",
- "age_table_entry: SIOCGETSGCNT failing for",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- /* Make sure it gets deleted below */
- sg_req.pktcnt = st->st_pktcnt;
- }
- } else {
- sg_req.pktcnt = st->st_pktcnt;
- }
- if (sg_req.pktcnt == st->st_pktcnt) {
- *stnp = st->st_next;
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "age_table_entry deleting (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- if (st->st_ctime != 0) {
- if (k_del_rg(st->st_origin, gt) < 0) {
- log(LOG_WARNING, errno,
- "age_table_entry trying to delete (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- }
- kroutes--;
- }
- free(st);
- } else {
- st->st_pktcnt = sg_req.pktcnt;
- stnp = &st->st_next;
- }
- }
-
- /*
- * Retain the group entry if we have downstream prunes or if
- * there is at least one source in the list that still has
- * traffic, or if our upstream prune timer or graft
- * retransmission timer is running.
- */
- if (gt->gt_pruntbl != NULL || gt->gt_srctbl != NULL ||
- gt->gt_prsent_timer > 0 || gt->gt_grftsnt > 0) {
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "refresh lifetim of cache entry %s%s%s%s(%s, %s)",
- gt->gt_pruntbl ? "(dstrm prunes) " : "",
- gt->gt_srctbl ? "(trfc flow) " : "",
- gt->gt_prsent_timer > 0 ? "(upstrm prune) " : "",
- gt->gt_grftsnt > 0 ? "(grft rexmit) " : "",
- RT_FMT(r, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- gt->gt_timer = CACHE_LIFETIME(cache_lifetime);
- if (gt->gt_prsent_timer == -1) {
- /*
- * The upstream prune timed out. Remove any kernel
- * state.
- */
- gt->gt_prsent_timer = 0;
- if (gt->gt_pruntbl) {
- log(LOG_WARNING, 0, "upstream prune for (%s %s) expires with downstream prunes active",
- RT_FMT(r, s1), inet_fmt(gt->gt_mcastgrp, s2));
- }
- remove_sources(gt);
- }
- gtnptr = &gt->gt_gnext;
- continue;
- }
-
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "timeout cache entry (%s, %s)",
- RT_FMT(r, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
-
- if (gt->gt_prev)
- gt->gt_prev->gt_next = gt->gt_next;
- else
- gt->gt_route->rt_groups = gt->gt_next;
- if (gt->gt_next)
- gt->gt_next->gt_prev = gt->gt_prev;
-
- if (gt->gt_gprev) {
- gt->gt_gprev->gt_gnext = gt->gt_gnext;
- gtnptr = &gt->gt_gprev->gt_gnext;
- } else {
- kernel_table = gt->gt_gnext;
- gtnptr = &kernel_table;
- }
- if (gt->gt_gnext)
- gt->gt_gnext->gt_gprev = gt->gt_gprev;
-
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(gt,0);
- rsrr_cache_clean(gt);
-#endif /* RSRR */
- if (gt->gt_rexmit_timer)
- timer_clearTimer(gt->gt_rexmit_timer);
-
- free((char *)gt);
- } else {
- if (gt->gt_prsent_timer == -1) {
- /*
- * The upstream prune timed out. Remove any kernel
- * state.
- */
- gt->gt_prsent_timer = 0;
- if (gt->gt_pruntbl) {
- log(LOG_WARNING, 0, "upstream prune for (%s %s) expires with downstream prunes active",
- RT_FMT(r, s1), inet_fmt(gt->gt_mcastgrp, s2));
- }
- remove_sources(gt);
- }
- gtnptr = &gt->gt_gnext;
- }
- }
-
- /*
- * When traversing the no_route table, the decision is much easier.
- * Just delete it if it has timed out.
- */
- gtnptr = &kernel_no_route;
- while ((gt = *gtnptr) != NULL) {
- /* advance the timer for the kernel entry */
- gt->gt_timer -= TIMER_INTERVAL;
-
- if (gt->gt_timer < 0) {
- if (gt->gt_srctbl) {
- if (gt->gt_srctbl->st_ctime != 0) {
- if (k_del_rg(gt->gt_srctbl->st_origin, gt) < 0) {
- log(LOG_WARNING, errno, "%s (%s %s)",
- "age_table_entry trying to delete no-route",
- inet_fmt(gt->gt_srctbl->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- }
- kroutes--;
- }
- free(gt->gt_srctbl);
- }
- *gtnptr = gt->gt_next;
- if (gt->gt_next)
- gt->gt_next->gt_prev = gt->gt_prev;
-
- if (gt->gt_rexmit_timer)
- timer_clearTimer(gt->gt_rexmit_timer);
-
- free((char *)gt);
- } else {
- gtnptr = &gt->gt_next;
- }
- }
-}
-
-/*
- * Modify the kernel to forward packets when one or multiple prunes that
- * were received on the vif given by vifi, for the group given by gt,
- * have expired.
- */
-static void
-expire_prune(vifi, gt)
- vifi_t vifi;
- struct gtable *gt;
-{
- /*
- * No need to send a graft, any prunes that we sent
- * will expire before any prunes that we have received.
- * However, in the case that we did make a mistake,
- * send a graft to compensate.
- */
- if (gt->gt_prsent_timer >= MIN_PRUNE_LIFE) {
- IF_DEBUG(DEBUG_PRUNE)
- log(LOG_DEBUG, 0, "prune expired with %d left on %s",
- gt->gt_prsent_timer, "prsent_timer");
- gt->gt_prsent_timer = 0;
- send_graft(gt);
- }
-
- /* modify the kernel entry to forward packets */
- if (!VIFM_ISSET(vifi, gt->gt_grpmems)) {
- struct rtentry *rt = gt->gt_route;
- VIFM_SET(vifi, gt->gt_grpmems);
- IF_DEBUG(DEBUG_CACHE)
- log(LOG_DEBUG, 0, "forw again (%s %s) gm:%x vif:%d",
- RT_FMT(rt, s1),
- inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems, vifi);
-
- prun_add_ttls(gt);
- update_kernel(gt);
-#ifdef RSRR
- /* Send route change notification to reservation protocol. */
- rsrr_cache_send(gt,1);
-#endif /* RSRR */
- }
-}
-
-/*
- * Print the contents of the cache table on file 'fp2'.
- */
-void
-dump_cache(fp2)
- FILE *fp2;
-{
- register struct rtentry *r;
- register struct gtable *gt;
- register struct stable *st;
- register struct ptable *pt;
- register vifi_t i;
- char c;
- register time_t thyme = time(0);
-
- fprintf(fp2,
- "Multicast Routing Cache Table (%d entries)\n%s", kroutes,
- " Origin Mcast-group CTmr Age Ptmr Rx IVif Forwvifs\n");
- fprintf(fp2,
- "<(prunesrc:vif[idx]/tmr) prunebitmap\n%s",
- ">Source Lifetime SavPkt Pkts Bytes RPFf\n");
-
- for (gt = kernel_no_route; gt; gt = gt->gt_next) {
- if (gt->gt_srctbl) {
- fprintf(fp2, " %-18s %-15s %-8s %-8s - -1 (no route)\n",
- inet_fmts(gt->gt_srctbl->st_origin, 0xffffffff, s1),
- inet_fmt(gt->gt_mcastgrp, s2), scaletime(gt->gt_timer),
- scaletime(thyme - gt->gt_ctime));
- fprintf(fp2, ">%s\n", inet_fmt(gt->gt_srctbl->st_origin, s1));
- }
- }
-
- for (gt = kernel_table; gt; gt = gt->gt_gnext) {
- r = gt->gt_route;
- fprintf(fp2, " %-18s %-15s",
- RT_FMT(r, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
-
- fprintf(fp2, " %-8s", scaletime(gt->gt_timer));
-
- fprintf(fp2, " %-8s %-8s ", scaletime(thyme - gt->gt_ctime),
- gt->gt_prsent_timer ? scaletime(gt->gt_prsent_timer) :
- " -");
-
- if (gt->gt_prune_rexmit) {
- int i = gt->gt_prune_rexmit;
- int n = 0;
-
- while (i > PRUNE_REXMIT_VAL) {
- n++;
- i /= 2;
- }
- if (n == 0 && gt->gt_prsent_timer == 0)
- fprintf(fp2, " -");
- else
- fprintf(fp2, "%2d", n);
- } else {
- fprintf(fp2, " -");
- }
-
- fprintf(fp2, " %2u%c%c", r->rt_parent,
- gt->gt_prsent_timer ? 'P' :
- gt->gt_grftsnt ? 'G' : ' ',
- VIFM_ISSET(r->rt_parent, gt->gt_scope) ? 'B' : ' ');
-
- for (i = 0; i < numvifs; ++i) {
- if (VIFM_ISSET(i, gt->gt_grpmems))
- fprintf(fp2, " %u ", i);
- else if (VIFM_ISSET(i, r->rt_children) &&
- NBRM_ISSETMASK(uvifs[i].uv_nbrmap, r->rt_subordinates))
- fprintf(fp2, " %u%c", i,
- VIFM_ISSET(i, gt->gt_scope) ? 'b' :
- SUBS_ARE_PRUNED(r->rt_subordinates,
- uvifs[i].uv_nbrmap, gt->gt_prunes) ? 'p' : '!');
- }
- fprintf(fp2, "\n");
- if (gt->gt_pruntbl) {
- fprintf(fp2, "<");
- c = '(';
- for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) {
- fprintf(fp2, "%c%s:%d[%d]/%d", c, inet_fmt(pt->pt_router, s1),
- pt->pt_vifi, pt->pt_index, pt->pt_timer);
- c = ',';
- }
- fprintf(fp2, ")");
- fprintf(fp2, " 0x%08lx%08lx\n",/*XXX*/
- gt->gt_prunes.hi, gt->gt_prunes.lo);
- }
- for (st = gt->gt_srctbl; st; st = st->st_next) {
- fprintf(fp2, ">%-18s %-8s %6ld", inet_fmt(st->st_origin, s1),
- st->st_ctime ? scaletime(thyme - st->st_ctime) : "-",
- st->st_savpkt);
- if (st->st_ctime) {
- struct sioc_sg_req sg_req;
-
- sg_req.src.s_addr = st->st_origin;
- sg_req.grp.s_addr = gt->gt_mcastgrp;
- if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) < 0) {
- log(LOG_WARNING, errno, "SIOCGETSGCNT on (%s %s)",
- inet_fmt(st->st_origin, s1),
- inet_fmt(gt->gt_mcastgrp, s2));
- } else {
- fprintf(fp2, " %8ld %8ld %4ld", sg_req.pktcnt,
- sg_req.bytecnt, sg_req.wrong_if);
- }
- }
- fprintf(fp2, "\n");
- }
- }
-}
-
-/*
- * Traceroute function which returns traceroute replies to the requesting
- * router. Also forwards the request to downstream routers.
- */
-void
-accept_mtrace(src, dst, group, data, no, datalen)
- u_int32 src;
- u_int32 dst;
- u_int32 group;
- char *data;
- u_int no; /* promoted u_char */
- int datalen;
-{
- u_char type;
- struct rtentry *rt;
- struct gtable *gt;
- struct tr_query *qry;
- struct tr_resp *resp;
- int vifi;
- char *p;
- int rcount;
- int errcode = TR_NO_ERR;
- int resptype;
- struct timeval tp;
- struct sioc_vif_req v_req;
- struct sioc_sg_req sg_req;
-
- /* Remember qid across invocations */
- static u_int32 oqid = 0;
-
- /* timestamp the request/response */
- gettimeofday(&tp, 0);
-
- /*
- * Check if it is a query or a response
- */
- if (datalen == QLEN) {
- type = QUERY;
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
- }
- else if ((datalen - QLEN) % RLEN == 0) {
- type = RESP;
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
- if (IN_MULTICAST(ntohl(dst))) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Dropping multicast response");
- return;
- }
- }
- else {
- log(LOG_WARNING, 0, "%s from %s to %s",
- "Non decipherable traceroute request recieved",
- inet_fmt(src, s1), inet_fmt(dst, s2));
- return;
- }
-
- qry = (struct tr_query *)data;
-
- /*
- * if it is a packet with all reports filled, drop it
- */
- if ((rcount = (datalen - QLEN)/RLEN) == no) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "packet with all reports filled in");
- return;
- }
-
- IF_DEBUG(DEBUG_TRACE) {
- log(LOG_DEBUG, 0, "s: %s g: %s d: %s ", inet_fmt(qry->tr_src, s1),
- inet_fmt(group, s2), inet_fmt(qry->tr_dst, s3));
- log(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl,
- inet_fmt(qry->tr_raddr, s1));
- log(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid);
- }
-
- /* determine the routing table entry for this traceroute */
- rt = determine_route(qry->tr_src);
- IF_DEBUG(DEBUG_TRACE)
- if (rt) {
- log(LOG_DEBUG, 0, "rt parent vif: %d rtr: %s metric: %d",
- rt->rt_parent, inet_fmt(rt->rt_gateway, s1), rt->rt_metric);
- log(LOG_DEBUG, 0, "rt origin %s",
- RT_FMT(rt, s1));
- } else
- log(LOG_DEBUG, 0, "...no route");
-
- /*
- * Query type packet - check if rte exists
- * Check if the query destination is a vif connected to me.
- * and if so, whether I should start response back
- */
- if (type == QUERY) {
- if (oqid == qry->tr_qid) {
- /*
- * If the multicast router is a member of the group being
- * queried, and the query is multicasted, then the router can
- * recieve multiple copies of the same query. If we have already
- * replied to this traceroute, just ignore it this time.
- *
- * This is not a total solution, but since if this fails you
- * only get N copies, N <= the number of interfaces on the router,
- * it is not fatal.
- */
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
- return;
- }
-
- if (rt == NULL) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s",
- inet_fmt(qry->tr_src, s1));
- if (IN_MULTICAST(ntohl(dst)))
- return;
- }
- vifi = find_vif(qry->tr_dst, 0);
-
- if (vifi == NO_VIF) {
- /* The traceroute destination is not on one of my subnet vifs. */
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Destination %s not an interface",
- inet_fmt(qry->tr_dst, s1));
- if (IN_MULTICAST(ntohl(dst)))
- return;
- errcode = TR_WRONG_IF;
- } else if (rt != NULL && !VIFM_ISSET(vifi, rt->rt_children)) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s",
- inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2));
- if (IN_MULTICAST(ntohl(dst)))
- return;
- errcode = TR_WRONG_IF;
- }
- }
- else {
- /*
- * determine which interface the packet came in on
- * RESP packets travel hop-by-hop so this either traversed
- * a tunnel or came from a directly attached mrouter.
- */
- if ((vifi = find_vif(src, dst)) == NO_VIF) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Wrong interface for packet");
- errcode = TR_WRONG_IF;
- }
- }
-
- /* Now that we've decided to send a response, save the qid */
- oqid = qry->tr_qid;
-
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Sending traceroute response");
-
- /* copy the packet to the sending buffer */
- p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
-
- bcopy(data, p, datalen);
-
- p += datalen;
-
- /*
- * If there is no room to insert our reply, coopt the previous hop
- * error indication to relay this fact.
- */
- if (p + sizeof(struct tr_resp) > send_buf + RECV_BUF_SIZE) {
- resp = (struct tr_resp *)p - 1;
- resp->tr_rflags = TR_NO_SPACE;
- rt = NULL;
- goto sendit;
- }
-
- /*
- * fill in initial response fields
- */
- resp = (struct tr_resp *)p;
- bzero(resp, sizeof(struct tr_resp));
- datalen += RLEN;
-
- resp->tr_qarr = htonl(((tp.tv_sec + JAN_1970) << 16) +
- ((tp.tv_usec << 10) / 15625));
-
- resp->tr_rproto = PROTO_DVMRP;
- resp->tr_outaddr = (vifi == NO_VIF) ? dst : uvifs[vifi].uv_lcl_addr;
- resp->tr_fttl = (vifi == NO_VIF) ? 0 : uvifs[vifi].uv_threshold;
- resp->tr_rflags = errcode;
-
- /*
- * obtain # of packets out on interface
- */
- v_req.vifi = vifi;
- if (vifi != NO_VIF && ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
- resp->tr_vifout = htonl(v_req.ocount);
- else
- resp->tr_vifout = 0xffffffff;
-
- /*
- * fill in scoping & pruning information
- */
- if (rt)
- for (gt = rt->rt_groups; gt; gt = gt->gt_next) {
- if (gt->gt_mcastgrp >= group)
- break;
- }
- else
- gt = NULL;
-
- if (gt && gt->gt_mcastgrp == group) {
- struct stable *st;
-
- for (st = gt->gt_srctbl; st; st = st->st_next)
- if (qry->tr_src == st->st_origin)
- break;
-
- sg_req.src.s_addr = qry->tr_src;
- sg_req.grp.s_addr = group;
- if (st && st->st_ctime != 0 &&
- ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0)
- resp->tr_pktcnt = htonl(sg_req.pktcnt + st->st_savpkt);
- else
- resp->tr_pktcnt = htonl(st ? st->st_savpkt : 0xffffffff);
-
- if (VIFM_ISSET(vifi, gt->gt_scope))
- resp->tr_rflags = TR_SCOPED;
- else if (gt->gt_prsent_timer)
- resp->tr_rflags = TR_PRUNED;
- else if (!VIFM_ISSET(vifi, gt->gt_grpmems))
- if (!NBRM_ISEMPTY(uvifs[vifi].uv_nbrmap) &&
- SUBS_ARE_PRUNED(rt->rt_subordinates,
- uvifs[vifi].uv_nbrmap, gt->gt_prunes))
- resp->tr_rflags = TR_OPRUNED;
- else
- resp->tr_rflags = TR_NO_FWD;
- } else {
- if ((vifi != NO_VIF && scoped_addr(vifi, group)) ||
- (rt && scoped_addr(rt->rt_parent, group)))
- resp->tr_rflags = TR_SCOPED;
- else if (rt && !VIFM_ISSET(vifi, rt->rt_children))
- resp->tr_rflags = TR_NO_FWD;
- }
-
- /*
- * if no rte exists, set NO_RTE error
- */
- if (rt == NULL) {
- src = dst; /* the dst address of resp. pkt */
- resp->tr_inaddr = 0;
- resp->tr_rflags = TR_NO_RTE;
- resp->tr_rmtaddr = 0;
- } else {
- /* get # of packets in on interface */
- v_req.vifi = rt->rt_parent;
- if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
- resp->tr_vifin = htonl(v_req.icount);
- else
- resp->tr_vifin = 0xffffffff;
-
- MASK_TO_VAL(rt->rt_originmask, resp->tr_smask);
- src = uvifs[rt->rt_parent].uv_lcl_addr;
- resp->tr_inaddr = src;
- resp->tr_rmtaddr = rt->rt_gateway;
- if (!VIFM_ISSET(vifi, rt->rt_children)) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s",
- inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2));
- resp->tr_rflags = TR_WRONG_IF;
- }
- if (rt->rt_metric >= UNREACHABLE) {
- resp->tr_rflags = TR_NO_RTE;
- /* Hack to send reply directly */
- rt = NULL;
- }
- }
-
-sendit:
- /*
- * if metric is 1 or no. of reports is 1, send response to requestor
- * else send to upstream router. If the upstream router can't handle
- * mtrace, set an error code and send to requestor anyway.
- */
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "rcount:%d, no:%d", rcount, no);
-
- if ((rcount + 1 == no) || (rt == NULL) || (rt->rt_metric == 1)) {
- resptype = IGMP_MTRACE_RESP;
- dst = qry->tr_raddr;
- } else
- if (!can_mtrace(rt->rt_parent, rt->rt_gateway)) {
- dst = qry->tr_raddr;
- resp->tr_rflags = TR_OLD_ROUTER;
- resptype = IGMP_MTRACE_RESP;
- } else {
- dst = rt->rt_gateway;
- resptype = IGMP_MTRACE;
- }
-
- if (IN_MULTICAST(ntohl(dst))) {
- /*
- * Send the reply on a known multicast capable vif.
- * If we don't have one, we can't source any multicasts anyway.
- */
- if (phys_vif != -1) {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Sending reply to %s from %s",
- inet_fmt(dst, s1), inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2));
- k_set_ttl(qry->tr_rttl);
- send_igmp(uvifs[phys_vif].uv_lcl_addr, dst,
- resptype, no, group,
- datalen);
- k_set_ttl(1);
- } else
- log(LOG_INFO, 0, "No enabled phyints -- %s",
- "dropping traceroute reply");
- } else {
- IF_DEBUG(DEBUG_TRACE)
- log(LOG_DEBUG, 0, "Sending %s to %s from %s",
- resptype == IGMP_MTRACE_RESP ? "reply" : "request on",
- inet_fmt(dst, s1), inet_fmt(src, s2));
-
- send_igmp(src, dst,
- resptype, no, group,
- datalen);
- }
- return;
-}
diff --git a/usr.sbin/mrouted/prune.h b/usr.sbin/mrouted/prune.h
deleted file mode 100644
index 375fada1116e..000000000000
--- a/usr.sbin/mrouted/prune.h
+++ /dev/null
@@ -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)
diff --git a/usr.sbin/mrouted/route.c b/usr.sbin/mrouted/route.c
deleted file mode 100644
index b2695395ed92..000000000000
--- a/usr.sbin/mrouted/route.c
+++ /dev/null
@@ -1,1475 +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.
- *
- *
- * route.c,v 3.8.4.41 1998/01/15 00:08:34 fenner Exp
- */
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include "defs.h"
-
-/*
- * This define statement saves a lot of space later
- */
-#define RT_ADDR (struct rtentry *)&routing_table
-
-/*
- * Exported variables.
- */
-int routes_changed; /* 1=>some routes have changed */
-int delay_change_reports; /* 1=>postpone change reports */
-
-
-/*
- * The routing table is shared with prune.c , so must not be static.
- */
-struct rtentry *routing_table; /* pointer to list of route entries */
-
-/*
- * Private variables.
- */
-static struct rtentry *rtp; /* pointer to a route entry */
-static struct rtentry *rt_end; /* pointer to last route entry */
-unsigned int nroutes; /* current number of route entries */
-
-/*
- * Private functions.
- */
-static int init_children_and_leaves __P((struct rtentry *r,
- vifi_t parent, int first));
-static int find_route __P((u_int32 origin, u_int32 mask));
-static void create_route __P((u_int32 origin, u_int32 mask));
-static void discard_route __P((struct rtentry *prev_r));
-static int compare_rts __P((const void *rt1, const void *rt2));
-static int report_chunk __P((int, struct rtentry *start_rt, vifi_t vifi,
- u_int32 dst));
-static void queue_blaster_report __P((vifi_t, u_int32, u_int32, char *,
- int, u_int32));
-static void process_blaster_report __P((void *));
-
-#ifdef SNMP
-#include <sys/types.h>
-#include "snmp.h"
-
-/*
- * Return pointer to a specific route entry. This must be a separate
- * function from find_route() which modifies rtp.
- */
-struct rtentry *
-snmp_find_route(src, mask)
- register u_int32 src, mask;
-{
- register struct rtentry *rt;
-
- for (rt = routing_table; rt; rt = rt->rt_next) {
- if (src == rt->rt_origin && mask == rt->rt_originmask)
- return rt;
- }
- return NULL;
-}
-
-/*
- * Find next route entry > specification
- */
-int
-next_route(rtpp, src, mask)
- struct rtentry **rtpp;
- u_int32 src;
- u_int32 mask;
-{
- struct rtentry *rt, *rbest = NULL;
-
- /* Among all entries > spec, find "lowest" one in order */
- for (rt = routing_table; rt; rt=rt->rt_next) {
- if ((ntohl(rt->rt_origin) > ntohl(src)
- || (ntohl(rt->rt_origin) == ntohl(src)
- && ntohl(rt->rt_originmask) > ntohl(mask)))
- && (!rbest || (ntohl(rt->rt_origin) < ntohl(rbest->rt_origin))
- || (ntohl(rt->rt_origin) == ntohl(rbest->rt_origin)
- && ntohl(rt->rt_originmask) < ntohl(rbest->rt_originmask))))
- rbest = rt;
- }
- (*rtpp) = rbest;
- return (*rtpp)!=0;
-}
-
-/*
- * Given a routing table entry, and a vifi, find the next vifi/entry
- */
-int
-next_route_child(rtpp, src, mask, vifi)
- struct rtentry **rtpp;
- u_int32 src;
- u_int32 mask;
- vifi_t *vifi; /* vif at which to start looking */
-{
- /* Get (S,M) entry */
- if (!((*rtpp) = snmp_find_route(src,mask)))
- if (!next_route(rtpp, src, mask))
- return 0;
-
- /* Continue until we get one with a valid next vif */
- do {
- for (; (*rtpp)->rt_children && *vifi<numvifs; (*vifi)++)
- if (VIFM_ISSET(*vifi, (*rtpp)->rt_children))
- return 1;
- *vifi = 0;
- } while( next_route(rtpp, (*rtpp)->rt_origin, (*rtpp)->rt_originmask) );
-
- return 0;
-}
-#endif
-
-/*
- * Initialize the routing table and associated variables.
- */
-void
-init_routes()
-{
- routing_table = NULL;
- rt_end = RT_ADDR;
- nroutes = 0;
- routes_changed = FALSE;
- delay_change_reports = FALSE;
-}
-
-
-/*
- * Initialize the children bits for route 'r', along with the
- * associated dominant and subordinate data structures.
- * If first is set, initialize dominants, otherwise keep old
- * dominants on non-parent interfaces.
- * XXX Does this need a return value?
- */
-static int
-init_children_and_leaves(r, parent, first)
- register struct rtentry *r;
- register vifi_t parent;
- int first;
-{
- register vifi_t vifi;
- register struct uvif *v;
- vifbitmap_t old_children;
- nbrbitmap_t old_subords;
-
- VIFM_COPY(r->rt_children, old_children);
- NBRM_COPY(r->rt_subordinates, old_subords);
-
- VIFM_CLRALL(r->rt_children);
-
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (first || vifi == parent)
- r->rt_dominants [vifi] = 0;
- if (vifi == parent || uvifs[vifi].uv_flags & VIFF_NOFLOOD ||
- AVOID_TRANSIT(vifi, r) || (!first && r->rt_dominants[vifi]))
- NBRM_CLRMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- else
- NBRM_SETMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
-
- if (vifi != parent && !(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED)) &&
- !(!first && r->rt_dominants[vifi])) {
- VIFM_SET(vifi, r->rt_children);
- }
- }
-
- return (!VIFM_SAME(r->rt_children, old_children) ||
- !NBRM_SAME(r->rt_subordinates, old_subords));
-}
-
-
-/*
- * A new vif has come up -- update the children bitmaps in all route
- * entries to take that into account.
- */
-void
-add_vif_to_routes(vifi)
- register vifi_t vifi;
-{
- register struct rtentry *r;
- register struct uvif *v;
-
- v = &uvifs[vifi];
- for (r = routing_table; r != NULL; r = r->rt_next) {
- if (r->rt_metric != UNREACHABLE &&
- !VIFM_ISSET(vifi, r->rt_children)) {
- VIFM_SET(vifi, r->rt_children);
- r->rt_dominants [vifi] = 0;
- /*XXX isn't uv_nbrmap going to be empty?*/
- NBRM_CLRMASK(r->rt_subordinates, v->uv_nbrmap);
- update_table_entry(r, r->rt_gateway);
- }
- }
-}
-
-
-/*
- * A vif has gone down -- expire all routes that have that vif as parent,
- * and update the children bitmaps in all other route entries to take into
- * account the failed vif.
- */
-void
-delete_vif_from_routes(vifi)
- register vifi_t vifi;
-{
- register struct rtentry *r;
-
- for (r = routing_table; r != NULL; r = r->rt_next) {
- if (r->rt_metric != UNREACHABLE) {
- if (vifi == r->rt_parent) {
- del_table_entry(r, 0, DEL_ALL_ROUTES);
- r->rt_timer = ROUTE_EXPIRE_TIME;
- r->rt_metric = UNREACHABLE;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- }
- else if (VIFM_ISSET(vifi, r->rt_children)) {
- VIFM_CLR(vifi, r->rt_children);
- NBRM_CLRMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- update_table_entry(r, r->rt_gateway);
- }
- else {
- r->rt_dominants[vifi] = 0;
- }
- }
- }
-}
-
-
-/*
- * A new neighbor has come up. If we're flooding on the neighbor's
- * vif, mark that neighbor as subordinate for all routes whose parent
- * is not this vif.
- */
-void
-add_neighbor_to_routes(vifi, index)
- register vifi_t vifi;
- register int index;
-{
- register struct rtentry *r;
- register struct uvif *v;
-
- v = &uvifs[vifi];
- if (v->uv_flags & VIFF_NOFLOOD)
- return;
- for (r = routing_table; r != NULL; r = r->rt_next) {
- if (r->rt_metric != UNREACHABLE && r->rt_parent != vifi &&
- !AVOID_TRANSIT(vifi, r)) {
- NBRM_SET(index, r->rt_subordinates);
- update_table_entry(r, r->rt_gateway);
- }
- }
-}
-
-
-/*
- * A neighbor has failed or become unreachable. If that neighbor was
- * considered a dominant or subordinate router in any route entries,
- * take appropriate action. Expire all routes this neighbor advertised
- * to us.
- */
-void
-delete_neighbor_from_routes(addr, vifi, index)
- register u_int32 addr;
- register vifi_t vifi;
- int index;
-{
- register struct rtentry *r;
- register struct uvif *v;
-
- v = &uvifs[vifi];
- for (r = routing_table; r != NULL; r = r->rt_next) {
- if (r->rt_metric != UNREACHABLE) {
- if (r->rt_parent == vifi && r->rt_gateway == addr) {
- del_table_entry(r, 0, DEL_ALL_ROUTES);
- r->rt_timer = ROUTE_EXPIRE_TIME;
- r->rt_metric = UNREACHABLE;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- } else if (r->rt_dominants[vifi] == addr) {
- VIFM_SET(vifi, r->rt_children);
- r->rt_dominants[vifi] = 0;
- if ((uvifs[vifi].uv_flags & VIFF_NOFLOOD) ||
- AVOID_TRANSIT(vifi, r))
- NBRM_CLRMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- else
- NBRM_SETMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- update_table_entry(r, r->rt_gateway);
- } else if (NBRM_ISSET(index, r->rt_subordinates)) {
- NBRM_CLR(index, r->rt_subordinates);
- update_table_entry(r, r->rt_gateway);
- }
- }
- }
-}
-
-
-/*
- * Prepare for a sequence of ordered route updates by initializing a pointer
- * to the start of the routing table. The pointer is used to remember our
- * position in the routing table in order to avoid searching from the
- * beginning for each update; this relies on having the route reports in
- * a single message be in the same order as the route entries in the routing
- * table.
- */
-void
-start_route_updates()
-{
- rtp = RT_ADDR;
-}
-
-
-/*
- * Starting at the route entry following the one to which 'rtp' points,
- * look for a route entry matching the specified origin and mask. If a
- * match is found, return TRUE and leave 'rtp' pointing at the found entry.
- * If no match is found, return FALSE and leave 'rtp' pointing to the route
- * entry preceding the point at which the new origin should be inserted.
- * This code is optimized for the normal case in which the first entry to
- * be examined is the matching entry.
- */
-static int
-find_route(origin, mask)
- register u_int32 origin, mask;
-{
- register struct rtentry *r;
-
- r = rtp->rt_next;
- while (r != NULL) {
- if (origin == r->rt_origin && mask == r->rt_originmask) {
- rtp = r;
- return (TRUE);
- }
- if (ntohl(mask) < ntohl(r->rt_originmask) ||
- (mask == r->rt_originmask &&
- ntohl(origin) < ntohl(r->rt_origin))) {
- rtp = r;
- r = r->rt_next;
- }
- else break;
- }
- return (FALSE);
-}
-
-/*
- * Create a new routing table entry for the specified origin and link it into
- * the routing table. The shared variable 'rtp' is assumed to point to the
- * routing entry after which the new one should be inserted. It is left
- * pointing to the new entry.
- *
- * Only the origin, originmask, originwidth and flags fields are initialized
- * in the new route entry; the caller is responsible for filling in the the
- * rest.
- */
-static void
-create_route(origin, mask)
- u_int32 origin, mask;
-{
- register struct rtentry *r;
-
- if ((r = (struct rtentry *) malloc(sizeof(struct rtentry) +
- (numvifs * sizeof(u_int32)))) == NULL) {
- log(LOG_ERR, 0, "ran out of memory"); /* fatal */
- }
- r->rt_origin = origin;
- r->rt_originmask = mask;
- if (((char *)&mask)[3] != 0) r->rt_originwidth = 4;
- else if (((char *)&mask)[2] != 0) r->rt_originwidth = 3;
- else if (((char *)&mask)[1] != 0) r->rt_originwidth = 2;
- else r->rt_originwidth = 1;
- r->rt_flags = 0;
- r->rt_dominants = (u_int32 *)(r + 1);
- bzero(r->rt_dominants, numvifs * sizeof(u_int32));
- r->rt_groups = NULL;
- VIFM_CLRALL(r->rt_children);
- NBRM_CLRALL(r->rt_subordinates);
- NBRM_CLRALL(r->rt_subordadv);
-
- r->rt_next = rtp->rt_next;
- rtp->rt_next = r;
- r->rt_prev = rtp;
- if (r->rt_next != NULL)
- (r->rt_next)->rt_prev = r;
- else
- rt_end = r;
- rtp = r;
- ++nroutes;
-}
-
-
-/*
- * Discard the routing table entry following the one to which 'prev_r' points.
- */
-static void
-discard_route(prev_r)
- register struct rtentry *prev_r;
-{
- register struct rtentry *r;
-
- r = prev_r->rt_next;
- uvifs[r->rt_parent].uv_nroutes--;
- /*???nbr???.al_nroutes--;*/
- prev_r->rt_next = r->rt_next;
- if (prev_r->rt_next != NULL)
- (prev_r->rt_next)->rt_prev = prev_r;
- else
- rt_end = prev_r;
- free((char *)r);
- --nroutes;
-}
-
-
-/*
- * Process a route report for a single origin, creating or updating the
- * corresponding routing table entry if necessary. 'src' is either the
- * address of a neighboring router from which the report arrived, or zero
- * to indicate a change of status of one of our own interfaces.
- */
-void
-update_route(origin, mask, metric, src, vifi, n)
- u_int32 origin, mask;
- u_int metric;
- u_int32 src;
- vifi_t vifi;
- struct listaddr *n;
-{
- register struct rtentry *r;
- u_int adj_metric;
-
- /*
- * Compute an adjusted metric, taking into account the cost of the
- * subnet or tunnel over which the report arrived, and normalizing
- * all unreachable/poisoned metrics into a single value.
- */
- if (src != 0 && (metric < 1 || metric >= 2*UNREACHABLE)) {
- log(LOG_WARNING, 0,
- "%s reports out-of-range metric %u for origin %s",
- inet_fmt(src, s1), metric, inet_fmts(origin, mask, s2));
- return;
- }
- adj_metric = metric + uvifs[vifi].uv_metric;
- if (adj_metric > UNREACHABLE) adj_metric = UNREACHABLE;
-
- /*
- * Look up the reported origin in the routing table.
- */
- if (!find_route(origin, mask)) {
- /*
- * Not found.
- * Don't create a new entry if the report says it's unreachable,
- * or if the reported origin and mask are invalid.
- */
- if (adj_metric == UNREACHABLE) {
- return;
- }
- if (src != 0 && !inet_valid_subnet(origin, mask)) {
- log(LOG_WARNING, 0,
- "%s reports an invalid origin (%s) and/or mask (%08x)",
- inet_fmt(src, s1), inet_fmt(origin, s2), ntohl(mask));
- return;
- }
-
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s advertises new route %s",
- inet_fmt(src, s1), inet_fmts(origin, mask, s2));
-
- /*
- * OK, create the new routing entry. 'rtp' will be left pointing
- * to the new entry.
- */
- create_route(origin, mask);
- uvifs[vifi].uv_nroutes++;
- /*n->al_nroutes++;*/
-
- rtp->rt_metric = UNREACHABLE; /* temporary; updated below */
- }
-
- /*
- * We now have a routing entry for the reported origin. Update it?
- */
- r = rtp;
- if (r->rt_metric == UNREACHABLE) {
- /*
- * The routing entry is for a formerly-unreachable or new origin.
- * If the report claims reachability, update the entry to use
- * the reported route.
- */
- if (adj_metric == UNREACHABLE)
- return;
-
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s advertises %s with adj_metric %d (ours was %d)",
- inet_fmt(src, s1), inet_fmts(origin, mask, s2),
- adj_metric, r->rt_metric);
-
- /*
- * Now "steal away" any sources that belong under this route
- * by deleting any cache entries they might have created
- * and allowing the kernel to re-request them.
- *
- * If we haven't performed final initialization yet and are
- * just collecting the routing table, we can't have any
- * sources so we don't perform this step.
- */
- if (did_final_init)
- steal_sources(rtp);
-
- r->rt_parent = vifi;
- r->rt_gateway = src;
- init_children_and_leaves(r, vifi, 1);
-
- r->rt_timer = 0;
- r->rt_metric = adj_metric;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- update_table_entry(r, r->rt_gateway);
- }
- else if (src == r->rt_gateway) {
- /*
- * The report has come either from the interface directly-connected
- * to the origin subnet (src and r->rt_gateway both equal zero) or
- * from the gateway we have chosen as the best first-hop gateway back
- * towards the origin (src and r->rt_gateway not equal zero). Reset
- * the route timer and, if the reported metric has changed, update
- * our entry accordingly.
- */
- r->rt_timer = 0;
-
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s (current parent) advertises %s with adj_metric %d (ours was %d)",
- inet_fmt(src, s1), inet_fmts(origin, mask, s2),
- adj_metric, r->rt_metric);
-
- if (adj_metric == r->rt_metric)
- return;
-
- if (adj_metric == UNREACHABLE) {
- del_table_entry(r, 0, DEL_ALL_ROUTES);
- r->rt_timer = ROUTE_EXPIRE_TIME;
- }
- r->rt_metric = adj_metric;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- }
- else if (src == 0 ||
- (r->rt_gateway != 0 &&
- (adj_metric < r->rt_metric ||
- (adj_metric == r->rt_metric &&
- (ntohl(src) < ntohl(r->rt_gateway) ||
- r->rt_timer >= ROUTE_SWITCH_TIME))))) {
- /*
- * The report is for an origin we consider reachable; the report
- * comes either from one of our own interfaces or from a gateway
- * other than the one we have chosen as the best first-hop gateway
- * back towards the origin. If the source of the update is one of
- * our own interfaces, or if the origin is not a directly-connected
- * subnet and the reported metric for that origin is better than
- * what our routing entry says, update the entry to use the new
- * gateway and metric. We also switch gateways if the reported
- * metric is the same as the one in the route entry and the gateway
- * associated with the route entry has not been heard from recently,
- * or if the metric is the same but the reporting gateway has a lower
- * IP address than the gateway associated with the route entry.
- * Did you get all that?
- */
- u_int32 old_gateway;
- vifi_t old_parent;
- old_gateway = r->rt_gateway;
- old_parent = r->rt_parent;
- r->rt_gateway = src;
- r->rt_parent = vifi;
-
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s (new parent) on vif %d advertises %s with adj_metric %d (old parent was %s on vif %d, metric %d)",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- adj_metric, inet_fmt(old_gateway, s3), old_parent,
- r->rt_metric);
-
- if (old_parent != vifi) {
- init_children_and_leaves(r, vifi, 0);
- uvifs[old_parent].uv_nroutes--;
- uvifs[vifi].uv_nroutes++;
- }
- if (old_gateway != src) {
- update_table_entry(r, old_gateway);
- /*???old_gateway???->al_nroutes--;*/
- /*n->al_nroutes++;*/
- }
- r->rt_timer = 0;
- r->rt_metric = adj_metric;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- }
- else if (vifi != r->rt_parent) {
- /*
- * The report came from a vif other than the route's parent vif.
- * Update the children info, if necessary.
- */
- if (AVOID_TRANSIT(vifi, r)) {
- /*
- * The route's parent is a vif from which we're not supposed
- * to transit onto this vif. Simply ignore the update.
- */
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s on vif %d advertises %s with metric %d (ignored due to NOTRANSIT)",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric);
- } else if (VIFM_ISSET(vifi, r->rt_children)) {
- /*
- * Vif is a child vif for this route.
- */
- if (metric < r->rt_metric ||
- (metric == r->rt_metric &&
- ntohl(src) < ntohl(uvifs[vifi].uv_lcl_addr))) {
- /*
- * Neighbor has lower metric to origin (or has same metric
- * and lower IP address) -- it becomes the dominant router,
- * and vif is no longer a child for me.
- */
- VIFM_CLR(vifi, r->rt_children);
- r->rt_dominants [vifi] = src;
- /* XXX
- * We don't necessarily want to forget about subordinateness
- * so that we can become the dominant quickly if the current
- * dominant fails.
- */
- NBRM_CLRMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- update_table_entry(r, r->rt_gateway);
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s on vif %d becomes dominant for %s with metric %d",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric);
- }
- else if (metric > UNREACHABLE) { /* "poisoned reverse" */
- /*
- * Neighbor considers this vif to be on path to route's
- * origin; record this neighbor as subordinate
- */
- if (!NBRM_ISSET(n->al_index, r->rt_subordinates)) {
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s on vif %d becomes subordinate for %s with poison-reverse metric %d",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric - UNREACHABLE);
- NBRM_SET(n->al_index, r->rt_subordinates);
- update_table_entry(r, r->rt_gateway);
- } else {
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s on vif %d confirms subordinateness for %s with poison-reverse metric %d",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric - UNREACHABLE);
- }
- NBRM_SET(n->al_index, r->rt_subordadv);
- }
- else if (NBRM_ISSET(n->al_index, r->rt_subordinates)) {
- /*
- * Current subordinate no longer considers this vif to be on
- * path to route's origin; it is no longer a subordinate
- * router.
- */
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s on vif %d is no longer a subordinate for %s with metric %d",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric);
- NBRM_CLR(n->al_index, r->rt_subordinates);
- update_table_entry(r, r->rt_gateway);
- }
-
- }
- else if (src == r->rt_dominants[vifi] &&
- (metric > r->rt_metric ||
- (metric == r->rt_metric &&
- ntohl(src) > ntohl(uvifs[vifi].uv_lcl_addr)))) {
- /*
- * Current dominant no longer has a lower metric to origin
- * (or same metric and lower IP address); we adopt the vif
- * as our own child.
- */
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s (current dominant) on vif %d is no longer dominant for %s with metric %d",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric);
- VIFM_SET(vifi, r->rt_children);
- r->rt_dominants[vifi] = 0;
- if (uvifs[vifi].uv_flags & VIFF_NOFLOOD)
- NBRM_CLRMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- else
- NBRM_SETMASK(r->rt_subordinates, uvifs[vifi].uv_nbrmap);
- if (metric > UNREACHABLE) {
- NBRM_SET(n->al_index, r->rt_subordinates);
- NBRM_SET(n->al_index, r->rt_subordadv);
- }
- update_table_entry(r, r->rt_gateway);
- } else {
- IF_DEBUG(DEBUG_RTDETAIL)
- log(LOG_DEBUG, 0, "%s on vif %d advertises %s with metric %d (ignored)",
- inet_fmt(src, s1), vifi, inet_fmts(origin, mask, s2),
- metric);
- }
- }
-}
-
-
-/*
- * On every timer interrupt, advance the timer in each routing entry.
- */
-void
-age_routes()
-{
- register struct rtentry *r;
- register struct rtentry *prev_r;
- extern u_long virtual_time; /* from main.c */
-
- for (prev_r = RT_ADDR, r = routing_table;
- r != NULL;
- prev_r = r, r = r->rt_next) {
-
- if ((r->rt_timer += TIMER_INTERVAL) >= ROUTE_DISCARD_TIME) {
- /*
- * Time to garbage-collect the route entry.
- */
- del_table_entry(r, 0, DEL_ALL_ROUTES);
- discard_route(prev_r);
- r = prev_r;
- }
- else if (r->rt_timer >= ROUTE_EXPIRE_TIME &&
- r->rt_metric != UNREACHABLE) {
- /*
- * Time to expire the route entry. If the gateway is zero,
- * i.e., it is a route to a directly-connected subnet, just
- * set the timer back to zero; such routes expire only when
- * the interface to the subnet goes down.
- */
- if (r->rt_gateway == 0) {
- r->rt_timer = 0;
- }
- else {
- del_table_entry(r, 0, DEL_ALL_ROUTES);
- r->rt_metric = UNREACHABLE;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- }
- }
- else if (virtual_time % (ROUTE_REPORT_INTERVAL * 2) == 0) {
- /*
- * Time out subordinateness that hasn't been reported in
- * the last 2 intervals.
- */
- if (!NBRM_SAME(r->rt_subordinates, r->rt_subordadv)) {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "rt %s sub 0x%08x%08x subadv 0x%08x%08x metric %d",
- RT_FMT(r, s1),
- r->rt_subordinates.hi, r->rt_subordinates.lo,
- r->rt_subordadv.hi, r->rt_subordadv.lo, r->rt_metric);
- NBRM_MASK(r->rt_subordinates, r->rt_subordadv);
- update_table_entry(r, r->rt_gateway);
- }
- NBRM_CLRALL(r->rt_subordadv);
- }
- }
-}
-
-
-/*
- * Mark all routes as unreachable. This function is called only from
- * hup() in preparation for informing all neighbors that we are going
- * off the air. For consistency, we ought also to delete all reachable
- * route entries from the kernel, but since we are about to exit we rely
- * on the kernel to do its own cleanup -- no point in making all those
- * expensive kernel calls now.
- */
-void
-expire_all_routes()
-{
- register struct rtentry *r;
-
- for (r = routing_table; r != NULL; r = r->rt_next) {
- r->rt_metric = UNREACHABLE;
- r->rt_flags |= RTF_CHANGED;
- routes_changed = TRUE;
- }
-}
-
-
-/*
- * Delete all the routes in the routing table.
- */
-void
-free_all_routes()
-{
- register struct rtentry *r;
-
- r = RT_ADDR;
-
- while (r->rt_next)
- discard_route(r);
-}
-
-
-/*
- * Process an incoming neighbor probe message.
- */
-void
-accept_probe(src, dst, p, datalen, level)
- u_int32 src;
- u_int32 dst;
- char *p;
- int datalen;
- u_int32 level;
-{
- vifi_t vifi;
- static struct listaddr *unknowns = NULL;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF) {
- struct listaddr *a, **prev;
- struct listaddr *match = NULL;
- time_t now = time(0);
-
- for (prev = &unknowns, a = *prev; a; a = *prev) {
- if (a->al_addr == src)
- match = a;
- if (a->al_ctime + 2 * a->al_timer < now) {
- /* We haven't heard from it in a long time */
- *prev = a->al_next;
- free(a);
- } else {
- prev = &a->al_next;
- }
- }
- if (match == NULL) {
- match = *prev = (struct listaddr *)malloc(sizeof(struct listaddr));
- match->al_next = NULL;
- match->al_addr = src;
- match->al_timer = OLD_NEIGHBOR_EXPIRE_TIME;
- match->al_ctime = now - match->al_timer;
- }
-
- if (match->al_ctime + match->al_timer <= now) {
- log(LOG_WARNING, 0,
- "ignoring probe from non-neighbor %s, check for misconfigured tunnel or routing on %s",
- inet_fmt(src, s1), s1);
- match->al_timer *= 2;
- } else
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0,
- "ignoring probe from non-neighbor %s (%d seconds until next warning)", inet_fmt(src, s1), match->al_ctime + match->al_timer - now);
- return;
- }
-
- update_neighbor(vifi, src, DVMRP_PROBE, p, datalen, level);
-}
-
-struct newrt {
- u_int32 mask;
- u_int32 origin;
- int metric;
- int pad;
-};
-
-static int
-compare_rts(rt1, rt2)
- const void *rt1;
- const void *rt2;
-{
- register struct newrt *r1 = (struct newrt *)rt1;
- register struct newrt *r2 = (struct newrt *)rt2;
- register u_int32 m1 = ntohl(r1->mask);
- register u_int32 m2 = ntohl(r2->mask);
- register u_int32 o1, o2;
-
- if (m1 > m2)
- return (-1);
- if (m1 < m2)
- return (1);
-
- /* masks are equal */
- o1 = ntohl(r1->origin);
- o2 = ntohl(r2->origin);
- if (o1 > o2)
- return (-1);
- if (o1 < o2)
- return (1);
- return (0);
-}
-
-void
-blaster_alloc(vifi)
- vifi_t vifi;
-{
- register struct uvif *v;
-
- v = &uvifs[vifi];
- if (v->uv_blasterbuf)
- free(v->uv_blasterbuf);
-
- v->uv_blasterlen = 64*1024;
- v->uv_blasterbuf = malloc(v->uv_blasterlen);
- v->uv_blastercur = v->uv_blasterend = v->uv_blasterbuf;
- if (v->uv_blastertimer)
- timer_clearTimer(v->uv_blastertimer);
- v->uv_blastertimer = 0;
-}
-
-struct blaster_hdr {
- u_int32 bh_src;
- u_int32 bh_dst;
- u_int32 bh_level;
- int bh_datalen;
-};
-
-/*
- * Queue a route report from a route-blaster.
- * If the timer isn't running to process these reports,
- * start it.
- */
-static void
-queue_blaster_report(vifi, src, dst, p, datalen, level)
- vifi_t vifi;
- u_int32 src, dst, level;
- register char *p;
- register int datalen;
-{
- register struct blaster_hdr *bh;
- register struct uvif *v;
- int bblen = sizeof(*bh) + ((datalen + 3) & ~3);
-
- v = &uvifs[vifi];
- if (v->uv_blasterend - v->uv_blasterbuf +
- bblen > v->uv_blasterlen) {
- int end = v->uv_blasterend - v->uv_blasterbuf;
- int cur = v->uv_blastercur - v->uv_blasterbuf;
-
- v->uv_blasterlen *= 2;
- IF_DEBUG(DEBUG_IF)
- log(LOG_DEBUG, 0, "increasing blasterbuf to %d bytes",
- v->uv_blasterlen);
- v->uv_blasterbuf = realloc(v->uv_blasterbuf,
- v->uv_blasterlen);
- if (v->uv_blasterbuf == NULL) {
- log(LOG_WARNING, ENOMEM, "turning off blaster on vif %d", vifi);
- v->uv_blasterlen = 0;
- v->uv_blasterend = v->uv_blastercur = NULL;
- v->uv_flags &= ~VIFF_BLASTER;
- return;
- }
- v->uv_blasterend = v->uv_blasterbuf + end;
- v->uv_blastercur = v->uv_blasterbuf + cur;
- }
- bh = (struct blaster_hdr *)v->uv_blasterend;
- bh->bh_src = src;
- bh->bh_dst = dst;
- bh->bh_level = level;
- bh->bh_datalen = datalen;
- bcopy(p, (char *)(bh + 1), datalen);
- v->uv_blasterend += bblen;
-
- if (v->uv_blastertimer == 0) {
- int *i = (int *)malloc(sizeof(int *));
-
- if (i == NULL)
- log(LOG_ERR, 0, "out of memory");
-
- *i = vifi;
-
- v->uv_blastertimer = timer_setTimer(5,
- process_blaster_report, i);
- }
-}
-
-/*
- * Periodic process; process up to 5 of the routes in the route-blaster
- * queue. If there are more routes remaining, reschedule myself to run
- * in 1 second.
- */
-static void
-process_blaster_report(vifip)
- void *vifip;
-{
- vifi_t vifi = *(int *)vifip;
- register struct uvif *v;
- register struct blaster_hdr *bh;
- int i;
-
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "processing vif %d blasted routes", vifi);
- v = &uvifs[vifi];
- for (i = 0; i < 5; i++) {
- if (v->uv_blastercur >= v->uv_blasterend)
- break;
- bh = (struct blaster_hdr *)v->uv_blastercur;
- v->uv_blastercur += sizeof(*bh) + ((bh->bh_datalen + 3) & ~3);
- accept_report(bh->bh_src, bh->bh_dst, (char *)(bh + 1),
- -bh->bh_datalen, bh->bh_level);
- }
-
- if (v->uv_blastercur >= v->uv_blasterend) {
- v->uv_blastercur = v->uv_blasterbuf;
- v->uv_blasterend = v->uv_blasterbuf;
- v->uv_blastertimer = 0;
- free(vifip);
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "finish processing vif %d blaster", vifi);
- } else {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "more blasted routes to come on vif %d", vifi);
- v->uv_blastertimer = timer_setTimer(1,
- process_blaster_report, vifip);
- }
-}
-
-/*
- * Process an incoming route report message.
- * If the report arrived on a vif marked as a "blaster", then just
- * queue it and return; queue_blaster_report() will schedule it for
- * processing later. If datalen is negative, then this is actually
- * a queued report so actually process it instead of queueing it.
- */
-void
-accept_report(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- register char *p;
- register int datalen;
-{
- vifi_t vifi;
- register int width, i, nrt = 0;
- int metric;
- u_int32 mask;
- u_int32 origin;
- struct newrt rt[4096];
- struct listaddr *nbr;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF) {
- log(LOG_INFO, 0,
- "ignoring route report from non-neighbor %s", inet_fmt(src, s1));
- return;
- }
-
- if (uvifs[vifi].uv_flags & VIFF_BLASTER)
- if (datalen > 0) {
- queue_blaster_report(vifi, src, dst, p, datalen, level);
- return;
- } else {
- datalen = -datalen;
- }
-
- if (!(nbr = update_neighbor(vifi, src, DVMRP_REPORT, NULL, 0, level)))
- return;
-
- if (datalen > 2*4096) {
- log(LOG_INFO, 0,
- "ignoring oversize (%d bytes) route report from %s",
- datalen, inet_fmt(src, s1));
- return;
- }
-
- while (datalen > 0) { /* Loop through per-mask lists. */
-
- if (datalen < 3) {
- log(LOG_WARNING, 0,
- "received truncated route report from %s",
- inet_fmt(src, s1));
- return;
- }
- ((u_char *)&mask)[0] = 0xff; width = 1;
- if ((((u_char *)&mask)[1] = *p++) != 0) width = 2;
- if ((((u_char *)&mask)[2] = *p++) != 0) width = 3;
- if ((((u_char *)&mask)[3] = *p++) != 0) width = 4;
- if (!inet_valid_mask(ntohl(mask))) {
- log(LOG_WARNING, 0,
- "%s reports bogus netmask 0x%08x (%s)",
- inet_fmt(src, s1), ntohl(mask), inet_fmt(mask, s2));
- return;
- }
- datalen -= 3;
-
- do { /* Loop through (origin, metric) pairs */
- if (datalen < width + 1) {
- log(LOG_WARNING, 0,
- "received truncated route report from %s",
- inet_fmt(src, s1));
- return;
- }
- origin = 0;
- for (i = 0; i < width; ++i)
- ((char *)&origin)[i] = *p++;
- metric = *p++;
- datalen -= width + 1;
- rt[nrt].mask = mask;
- rt[nrt].origin = origin;
- rt[nrt].metric = (metric & 0x7f);
- ++nrt;
- } while (!(metric & 0x80));
- }
-
- qsort((char*)rt, nrt, sizeof(rt[0]), compare_rts);
- start_route_updates();
- /*
- * If the last entry is default, change mask from 0xff000000 to 0
- */
- if (rt[nrt-1].origin == 0)
- rt[nrt-1].mask = 0;
-
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "Updating %d routes from %s to %s", nrt,
- inet_fmt(src, s1), inet_fmt(dst, s2));
- for (i = 0; i < nrt; ++i) {
- if (i != 0 && rt[i].origin == rt[i-1].origin &&
- rt[i].mask == rt[i-1].mask) {
- log(LOG_WARNING, 0, "%s reports duplicate route for %s",
- inet_fmt(src, s1), inet_fmts(rt[i].origin, rt[i].mask, s2));
- continue;
- }
- /* Only filter non-poisoned updates. */
- if (uvifs[vifi].uv_filter && rt[i].metric < UNREACHABLE) {
- struct vf_element *vfe;
- int match = 0;
-
- for (vfe = uvifs[vifi].uv_filter->vf_filter; vfe; vfe = vfe->vfe_next) {
- if (vfe->vfe_flags & VFEF_EXACT) {
- if ((vfe->vfe_addr == rt[i].origin) &&
- (vfe->vfe_mask == rt[i].mask)) {
- match = 1;
- break;
- }
- } else {
- if ((rt[i].origin & vfe->vfe_mask) == vfe->vfe_addr) {
- match = 1;
- break;
- }
- }
- }
- if ((uvifs[vifi].uv_filter->vf_type == VFT_ACCEPT && match == 0) ||
- (uvifs[vifi].uv_filter->vf_type == VFT_DENY && match == 1)) {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "%s skipped on vif %d because it %s %s",
- inet_fmts(rt[i].origin, rt[i].mask, s1),
- vifi,
- match ? "matches" : "doesn't match",
- match ? inet_fmts(vfe->vfe_addr, vfe->vfe_mask, s2) :
- "the filter");
-#if 0
- rt[i].metric += vfe->vfe_addmetric;
- if (rt[i].metric > UNREACHABLE)
-#endif
- rt[i].metric = UNREACHABLE;
- }
- }
- update_route(rt[i].origin, rt[i].mask, rt[i].metric,
- src, vifi, nbr);
- }
-
- if (routes_changed && !delay_change_reports)
- report_to_all_neighbors(CHANGED_ROUTES);
-}
-
-
-/*
- * Send a route report message to destination 'dst', via virtual interface
- * 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES.
- */
-void
-report(which_routes, vifi, dst)
- int which_routes;
- vifi_t vifi;
- u_int32 dst;
-{
- register struct rtentry *r;
- register int i;
-
- r = rt_end;
- while (r != RT_ADDR) {
- i = report_chunk(which_routes, r, vifi, dst);
- while (i-- > 0)
- r = r->rt_prev;
- }
-}
-
-
-/*
- * Send a route report message to all neighboring routers.
- * 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES.
- */
-void
-report_to_all_neighbors(which_routes)
- int which_routes;
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct rtentry *r;
- int routes_changed_before;
-
- /*
- * Remember the state of the global routes_changed flag before
- * generating the reports, and clear the flag.
- */
- routes_changed_before = routes_changed;
- routes_changed = FALSE;
-
-
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (!NBRM_ISEMPTY(v->uv_nbrmap)) {
- report(which_routes, vifi, v->uv_dst_addr);
- }
- }
-
- /*
- * If there were changed routes before we sent the reports AND
- * if no new changes occurred while sending the reports, clear
- * the change flags in the individual route entries. If changes
- * did occur while sending the reports, new reports will be
- * generated at the next timer interrupt.
- */
- if (routes_changed_before && !routes_changed) {
- for (r = routing_table; r != NULL; r = r->rt_next) {
- r->rt_flags &= ~RTF_CHANGED;
- }
- }
-
- /*
- * Set a flag to inhibit further reports of changed routes until the
- * next timer interrupt. This is to alleviate update storms.
- */
- delay_change_reports = TRUE;
-}
-
-/*
- * Send a route report message to destination 'dst', via virtual interface
- * 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES.
- */
-static int
-report_chunk(which_routes, start_rt, vifi, dst)
- int which_routes;
- register struct rtentry *start_rt;
- vifi_t vifi;
- u_int32 dst;
-{
- register struct rtentry *r;
- register char *p;
- register int i;
- register int nrt = 0;
- struct uvif *v = &uvifs[vifi];
- int datalen = 0;
- int width = 0;
- u_int32 mask = 0;
- u_int32 src;
- int admetric = v->uv_admetric;
- int metric;
-
- src = v->uv_lcl_addr;
- p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
-
- for (r = start_rt; r != RT_ADDR; r = r->rt_prev) {
- if (which_routes == CHANGED_ROUTES && !(r->rt_flags & RTF_CHANGED)) {
- nrt++;
- continue;
- }
-
- /*
- * Do not poison-reverse a route for a directly-connected
- * subnetwork on that subnetwork. This can cause loops when
- * some router on the subnetwork is misconfigured.
- */
- if (r->rt_gateway == 0 && r->rt_parent == vifi) {
- nrt++;
- continue;
- }
-
- if (v->uv_filter && v->uv_filter->vf_flags & VFF_BIDIR) {
- struct vf_element *vfe;
- int match = 0;
-
- for (vfe = v->uv_filter->vf_filter; vfe; vfe = vfe->vfe_next) {
- if (vfe->vfe_flags & VFEF_EXACT) {
- if ((vfe->vfe_addr == r->rt_origin) &&
- (vfe->vfe_mask == r->rt_originmask)) {
- match = 1;
- break;
- }
- } else {
- if ((r->rt_origin & vfe->vfe_mask) == vfe->vfe_addr) {
- match = 1;
- break;
- }
- }
- }
- if ((v->uv_filter->vf_type == VFT_ACCEPT && match == 0) ||
- (v->uv_filter->vf_type == VFT_DENY && match == 1)) {
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_DEBUG, 0, "%s not reported on vif %d because it %s %s",
- RT_FMT(r, s1), vifi,
- match ? "matches" : "doesn't match",
- match ? inet_fmts(vfe->vfe_addr, vfe->vfe_mask, s2) :
- "the filter");
- nrt++;
- continue;
- }
- }
-
- /*
- * If there is no room for this route in the current message,
- * send it & return how many routes we sent.
- */
- if (datalen + ((r->rt_originmask == mask) ?
- (width + 1) :
- (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) {
- *(p-1) |= 0x80;
- send_on_vif(v, 0, DVMRP_REPORT, datalen);
- return (nrt);
- }
-
- if (r->rt_originmask != mask || datalen == 0) {
- mask = r->rt_originmask;
- width = r->rt_originwidth;
- if (datalen != 0) *(p-1) |= 0x80;
- *p++ = ((char *)&mask)[1];
- *p++ = ((char *)&mask)[2];
- *p++ = ((char *)&mask)[3];
- datalen += 3;
- }
- for (i = 0; i < width; ++i)
- *p++ = ((char *)&(r->rt_origin))[i];
-
- metric = r->rt_metric + admetric;
- if (metric > UNREACHABLE)
- metric = UNREACHABLE;
- if (r->rt_parent != vifi && AVOID_TRANSIT(vifi, r))
- metric = UNREACHABLE;
- *p++ = (r->rt_parent == vifi && metric != UNREACHABLE) ?
- (char)(metric + UNREACHABLE) : /* "poisoned reverse" */
- (char)(metric);
- ++nrt;
- datalen += width + 1;
- }
- if (datalen != 0) {
- *(p-1) |= 0x80;
- send_on_vif(v, 0, DVMRP_REPORT, datalen);
- }
- return (nrt);
-}
-
-/*
- * send the next chunk of our routing table to all neighbors.
- * return the length of the smallest chunk we sent out.
- */
-int
-report_next_chunk()
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct rtentry *sr;
- register int i, n = 0, min = 20000;
- static int start_rt;
-
- if (nroutes <= 0)
- return (0);
-
- /*
- * find this round's starting route.
- */
- for (sr = rt_end, i = start_rt; --i >= 0; ) {
- sr = sr->rt_prev;
- if (sr == RT_ADDR)
- sr = rt_end;
- }
-
- /*
- * send one chunk of routes starting at this round's start to
- * all our neighbors.
- */
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (!NBRM_ISEMPTY(v->uv_nbrmap)) {
- n = report_chunk(ALL_ROUTES, sr, vifi, v->uv_dst_addr);
- if (n < min)
- min = n;
- }
- }
- if (min == 20000)
- min = 0; /* Neighborless router didn't send any routes */
-
- n = min;
- IF_DEBUG(DEBUG_ROUTE)
- log(LOG_INFO, 0, "update %d starting at %d of %d",
- n, (nroutes - start_rt), nroutes);
-
- start_rt = (start_rt + n) % nroutes;
- return (n);
-}
-
-
-/*
- * Print the contents of the routing table on file 'fp'.
- */
-void
-dump_routes(fp)
- FILE *fp;
-{
- register struct rtentry *r;
- register vifi_t i;
-
-
- fprintf(fp,
- "Multicast Routing Table (%u %s)\n%s\n",
- nroutes, (nroutes == 1) ? "entry" : "entries",
- " Origin-Subnet From-Gateway Metric Tmr Fl In-Vif Out-Vifs");
-
- for (r = routing_table; r != NULL; r = r->rt_next) {
-
- fprintf(fp, " %-18s %-15s ",
- inet_fmts(r->rt_origin, r->rt_originmask, s1),
- (r->rt_gateway == 0) ? "" : inet_fmt(r->rt_gateway, s2));
-
- fprintf(fp, (r->rt_metric == UNREACHABLE) ? " NR " : "%4u ",
- r->rt_metric);
-
- fprintf(fp, " %3u %c%c %3u ", r->rt_timer,
- (r->rt_flags & RTF_CHANGED) ? 'C' : '.',
- (r->rt_flags & RTF_HOLDDOWN) ? 'H' : '.',
- r->rt_parent);
-
- for (i = 0; i < numvifs; ++i) {
- struct listaddr *n;
- char l = '[';
-
- if (VIFM_ISSET(i, r->rt_children)) {
- if ((uvifs[i].uv_flags & VIFF_TUNNEL) &&
- !NBRM_ISSETMASK(uvifs[i].uv_nbrmap, r->rt_subordinates))
- /* Don't print out parenthood of a leaf tunnel. */
- continue;
- fprintf(fp, " %u", i);
- if (!NBRM_ISSETMASK(uvifs[i].uv_nbrmap, r->rt_subordinates))
- fprintf(fp, "*");
- for (n = uvifs[i].uv_neighbors; n; n = n->al_next) {
- if (NBRM_ISSET(n->al_index, r->rt_subordinates)) {
- fprintf(fp, "%c%d", l, n->al_index);
- l = ',';
- }
- }
- if (l == ',')
- fprintf(fp, "]");
- }
- }
- fprintf(fp, "\n");
- }
- fprintf(fp, "\n");
-}
-
-struct rtentry *
-determine_route(src)
- u_int32 src;
-{
- struct rtentry *rt;
-
- for (rt = routing_table; rt != NULL; rt = rt->rt_next) {
- if (rt->rt_origin == (src & rt->rt_originmask) &&
- rt->rt_metric != UNREACHABLE)
- break;
- }
- return rt;
-}
diff --git a/usr.sbin/mrouted/route.h b/usr.sbin/mrouted/route.h
deleted file mode 100644
index 300202b967dd..000000000000
--- a/usr.sbin/mrouted/route.h
+++ /dev/null
@@ -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)
diff --git a/usr.sbin/mrouted/rsrr.c b/usr.sbin/mrouted/rsrr.c
deleted file mode 100644
index 86d6e6eaf438..000000000000
--- a/usr.sbin/mrouted/rsrr.c
+++ /dev/null
@@ -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->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->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 */
diff --git a/usr.sbin/mrouted/rsrr.h b/usr.sbin/mrouted/rsrr.h
deleted file mode 100644
index c88f8ce78e8e..000000000000
--- a/usr.sbin/mrouted/rsrr.h
+++ /dev/null
@@ -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 */
-};
diff --git a/usr.sbin/mrouted/rsrr_var.h b/usr.sbin/mrouted/rsrr_var.h
deleted file mode 100644
index 9b1c09c1396e..000000000000
--- a/usr.sbin/mrouted/rsrr_var.h
+++ /dev/null
@@ -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 */
-};
-
diff --git a/usr.sbin/mrouted/testrsrr/Makefile b/usr.sbin/mrouted/testrsrr/Makefile
deleted file mode 100644
index 4f57dde7990b..000000000000
--- a/usr.sbin/mrouted/testrsrr/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $FreeBSD$
-
-S= ${.CURDIR}/..
-.PATH: $S
-
-PROG= testrsrr
-NO_MAN=
-
-CFLAGS+= -I$S
-
-install:
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/mrouted/testrsrr/testrsrr.c b/usr.sbin/mrouted/testrsrr/testrsrr.c
deleted file mode 100644
index 6dfe831b47ef..000000000000
--- a/usr.sbin/mrouted/testrsrr/testrsrr.c
+++ /dev/null
@@ -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);
-}
diff --git a/usr.sbin/mrouted/vif.c b/usr.sbin/mrouted/vif.c
deleted file mode 100644
index 423fa532225e..000000000000
--- a/usr.sbin/mrouted/vif.c
+++ /dev/null
@@ -1,1862 +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.
- *
- *
- * vif.c,v 3.8.4.56.2.1 1999/01/20 05:18:50 fenner Exp
- */
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include "defs.h"
-#include <fcntl.h>
-
-/*
- * Exported variables.
- */
-struct uvif uvifs[MAXVIFS]; /* array of virtual interfaces */
-vifi_t numvifs; /* number of vifs in use */
-int vifs_down; /* 1=>some interfaces are down */
-int phys_vif; /* An enabled vif */
-int udp_socket; /* Since the honkin' kernel doesn't support */
- /* ioctls on raw IP sockets, we need a UDP */
- /* socket as well as our IGMP (raw) socket. */
- /* How dumb. */
-int vifs_with_neighbors; /* == 1 if I am a leaf */
-
-/*
- * Private variables.
- */
-struct listaddr *nbrs[MAXNBRS]; /* array of neighbors */
-
-typedef struct {
- vifi_t vifi;
- struct listaddr *g;
- int q_time;
-} cbk_t;
-
-/*
- * Forward declarations.
- */
-static void start_vif __P((vifi_t vifi));
-static void start_vif2 __P((vifi_t vifi));
-static void stop_vif __P((vifi_t vifi));
-static void age_old_hosts __P((void));
-static void send_probe_on_vif __P((struct uvif *v));
-static void send_query __P((struct uvif *v));
-static int info_version __P((char *p, int plen));
-static void DelVif __P((void *arg));
-static int SetTimer __P((int vifi, struct listaddr *g));
-static int DeleteTimer __P((int id));
-static void SendQuery __P((void *arg));
-static int SetQueryTimer __P((struct listaddr *g, vifi_t vifi, int to_expire,
- int q_time));
-
-
-/*
- * Initialize the virtual interfaces, but do not install
- * them in the kernel. Start routing on all vifs that are
- * not down or disabled.
- */
-void
-init_vifs()
-{
- vifi_t vifi;
- struct uvif *v;
- int enabled_vifs, enabled_phyints;
- extern char *configfilename;
-
- numvifs = 0;
- vifs_with_neighbors = 0;
- vifs_down = FALSE;
-
- /*
- * Configure the vifs based on the interface configuration of the
- * the kernel and the contents of the configuration file.
- * (Open a UDP socket for ioctl use in the config procedures if
- * the kernel can't handle IOCTL's on the IGMP socket.)
- */
-#ifdef IOCTL_OK_ON_RAW_SOCKET
- udp_socket = igmp_socket;
-#else
- if ((udp_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- log(LOG_ERR, errno, "UDP socket");
-#endif
- log(LOG_INFO,0,"Getting vifs from kernel interfaces");
- config_vifs_from_kernel();
- log(LOG_INFO,0,"Getting vifs from %s",configfilename);
- config_vifs_from_file();
-
- /*
- * Quit if there are fewer than two enabled vifs.
- */
- enabled_vifs = 0;
- enabled_phyints = 0;
- phys_vif = -1;
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (!(v->uv_flags & VIFF_DISABLED)) {
- ++enabled_vifs;
- if (!(v->uv_flags & VIFF_TUNNEL)) {
- if (phys_vif == -1)
- phys_vif = vifi;
- ++enabled_phyints;
- }
- }
- }
- if (enabled_vifs < 2)
- log(LOG_ERR, 0, "can't forward: %s",
- enabled_vifs == 0 ? "no enabled vifs" : "only one enabled vif");
-
- if (enabled_phyints == 0)
- log(LOG_WARNING, 0,
- "no enabled interfaces, forwarding via tunnels only");
-
- log(LOG_INFO, 0, "Installing vifs in mrouted...");
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (!(v->uv_flags & VIFF_DISABLED)) {
- if (!(v->uv_flags & VIFF_DOWN)) {
- if (v->uv_flags & VIFF_TUNNEL)
- log(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi,
- inet_fmt(v->uv_lcl_addr, s1),
- inet_fmt(v->uv_rmt_addr, s2));
- else
- log(LOG_INFO, 0, "vif #%d, phyint %s", vifi,
- inet_fmt(v->uv_lcl_addr, s1));
- start_vif2(vifi);
- } else log(LOG_INFO, 0,
- "%s is not yet up; vif #%u not in service",
- v->uv_name, vifi);
- }
- }
-}
-
-/*
- * Initialize the passed vif with all appropriate default values.
- * "t" is true if a tunnel, or false if a phyint.
- */
-void
-zero_vif(v, t)
- struct uvif *v;
- int t;
-{
- v->uv_flags = 0;
- v->uv_metric = DEFAULT_METRIC;
- v->uv_admetric = 0;
- v->uv_threshold = DEFAULT_THRESHOLD;
- v->uv_rate_limit = t ? DEFAULT_TUN_RATE_LIMIT : DEFAULT_PHY_RATE_LIMIT;
- v->uv_lcl_addr = 0;
- v->uv_rmt_addr = 0;
- v->uv_dst_addr = t ? 0 : dvmrp_group;
- v->uv_subnet = 0;
- v->uv_subnetmask = 0;
- v->uv_subnetbcast = 0;
- v->uv_name[0] = '\0';
- v->uv_groups = NULL;
- v->uv_neighbors = NULL;
- NBRM_CLRALL(v->uv_nbrmap);
- v->uv_querier = NULL;
- v->uv_igmpv1_warn = 0;
- v->uv_prune_lifetime = 0;
- v->uv_leaf_timer = 0;
- v->uv_acl = NULL;
- v->uv_addrs = NULL;
- v->uv_filter = NULL;
- v->uv_blasterbuf = NULL;
- v->uv_blastercur = NULL;
- v->uv_blasterend = NULL;
- v->uv_blasterlen = 0;
- v->uv_blastertimer = 0;
- v->uv_nbrup = 0;
- v->uv_icmp_warn = 0;
- v->uv_nroutes = 0;
-}
-
-/*
- * Start routing on all virtual interfaces that are not down or
- * administratively disabled.
- */
-void
-init_installvifs()
-{
- vifi_t vifi;
- struct uvif *v;
-
- log(LOG_INFO, 0, "Installing vifs in kernel...");
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (!(v->uv_flags & VIFF_DISABLED)) {
- if (!(v->uv_flags & VIFF_DOWN)) {
- if (v->uv_flags & VIFF_TUNNEL)
- log(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi,
- inet_fmt(v->uv_lcl_addr, s1),
- inet_fmt(v->uv_rmt_addr, s2));
- else
- log(LOG_INFO, 0, "vif #%d, phyint %s", vifi,
- inet_fmt(v->uv_lcl_addr, s1));
- k_add_vif(vifi, &uvifs[vifi]);
- } else log(LOG_INFO, 0,
- "%s is not yet up; vif #%u not in service",
- v->uv_name, vifi);
- }
- }
-}
-
-/*
- * See if any interfaces have changed from up state to down, or vice versa,
- * including any non-multicast-capable interfaces that are in use as local
- * tunnel end-points. Ignore interfaces that have been administratively
- * disabled.
- */
-void
-check_vif_state()
-{
- register vifi_t vifi;
- register struct uvif *v;
- struct ifreq ifr;
- static int checking_vifs = 0;
-
- /*
- * If we get an error while checking, (e.g. two interfaces go down
- * at once, and we decide to send a prune out one of the failed ones)
- * then don't go into an infinite loop!
- */
- if (checking_vifs)
- return;
-
- vifs_down = FALSE;
- checking_vifs = 1;
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
-
- if (v->uv_flags & VIFF_DISABLED) continue;
-
- strncpy(ifr.ifr_name, v->uv_name, IFNAMSIZ);
- if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0)
- log(LOG_ERR, errno,
- "ioctl SIOCGIFFLAGS for %s", ifr.ifr_name);
-
- if (v->uv_flags & VIFF_DOWN) {
- if (ifr.ifr_flags & IFF_UP) {
- log(LOG_NOTICE, 0,
- "%s has come up; vif #%u now in service",
- v->uv_name, vifi);
- v->uv_flags &= ~VIFF_DOWN;
- start_vif(vifi);
- }
- else vifs_down = TRUE;
- }
- else {
- if (!(ifr.ifr_flags & IFF_UP)) {
- log(LOG_NOTICE, 0,
- "%s has gone down; vif #%u taken out of service",
- v->uv_name, vifi);
- stop_vif(vifi);
- v->uv_flags |= VIFF_DOWN;
- vifs_down = TRUE;
- }
- }
- }
- checking_vifs = 0;
-}
-
-/*
- * Send a DVMRP message on the specified vif. If DVMRP messages are
- * to be encapsulated and sent "inside" the tunnel, use the special
- * encapsulator. If it's not a tunnel or DVMRP messages are to be
- * sent "beside" the tunnel, as required by earlier versions of mrouted,
- * then just send the message.
- */
-void
-send_on_vif(v, dst, code, datalen)
- register struct uvif *v;
- u_int32 dst;
- int code;
- int datalen;
-{
- u_int32 group = htonl(MROUTED_LEVEL |
- ((v->uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS));
-
- /*
- * The UNIX kernel will not decapsulate unicasts.
- * Therefore, we don't send encapsulated unicasts.
- */
- if ((v->uv_flags & (VIFF_TUNNEL|VIFF_OTUNNEL)) == VIFF_TUNNEL &&
- ((dst == 0) || IN_MULTICAST(ntohl(dst))))
- send_ipip(v->uv_lcl_addr, dst ? dst : dvmrp_group, IGMP_DVMRP,
- code, group, datalen, v);
- else
- send_igmp(v->uv_lcl_addr, dst ? dst : v->uv_dst_addr, IGMP_DVMRP,
- code, group, datalen);
-}
-
-
-/*
- * Send a probe message on vif v
- */
-static void
-send_probe_on_vif(v)
- register struct uvif *v;
-{
- register char *p;
- register int datalen = 0;
- struct listaddr *nbr;
- int i;
-
- if ((v->uv_flags & VIFF_PASSIVE && v->uv_neighbors == NULL) ||
- (v->uv_flags & VIFF_FORCE_LEAF))
- return;
-
- p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
-
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&(dvmrp_genid))[i];
- datalen += 4;
-
- /*
- * add the neighbor list on the interface to the message
- */
- nbr = v->uv_neighbors;
-
- while (nbr) {
- for (i = 0; i < 4; i++)
- *p++ = ((char *)&nbr->al_addr)[i];
- datalen +=4;
- nbr = nbr->al_next;
- }
-
- send_on_vif(v, 0, DVMRP_PROBE, datalen);
-}
-
-static void
-send_query(v)
- register struct uvif *v;
-{
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0, "sending %squery on vif %d",
- (v->uv_flags & VIFF_IGMPV1) ? "v1 " : "",
- v - uvifs);
- send_igmp(v->uv_lcl_addr, allhosts_group,
- IGMP_MEMBERSHIP_QUERY,
- (v->uv_flags & VIFF_IGMPV1) ? 0 :
- IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0);
-}
-
-/*
- * Add a vifi to the kernel and start routing on it.
- */
-static void
-start_vif(vifi)
- vifi_t vifi;
-{
- /*
- * Install the interface in the kernel's vif structure.
- */
- k_add_vif(vifi, &uvifs[vifi]);
-
- start_vif2(vifi);
-}
-
-/*
- * Add a vifi to all the user-level data structures but don't add
- * it to the kernel yet.
- */
-static void
-start_vif2(vifi)
- vifi_t vifi;
-{
- struct uvif *v;
- u_int32 src;
- struct phaddr *p;
-
- v = &uvifs[vifi];
- src = v->uv_lcl_addr;
-
- /*
- * Update the existing route entries to take into account the new vif.
- */
- add_vif_to_routes(vifi);
-
- if (!(v->uv_flags & VIFF_TUNNEL)) {
- /*
- * Join the DVMRP multicast group on the interface.
- * (This is not strictly necessary, since the kernel promiscuously
- * receives IGMP packets addressed to ANY IP multicast group while
- * multicast routing is enabled. However, joining the group allows
- * this host to receive non-IGMP packets as well, such as 'pings'.)
- */
- k_join(dvmrp_group, src);
-
- /*
- * Join the ALL-ROUTERS multicast group on the interface.
- * This allows mtrace requests to loop back if they are run
- * on the multicast router.
- */
- k_join(allrtrs_group, src);
-
- /*
- * Install an entry in the routing table for the subnet to which
- * the interface is connected.
- */
- start_route_updates();
- update_route(v->uv_subnet, v->uv_subnetmask, 0, 0, vifi, NULL);
- for (p = v->uv_addrs; p; p = p->pa_next) {
- start_route_updates();
- update_route(p->pa_subnet, p->pa_subnetmask, 0, 0, vifi, NULL);
- }
-
- /*
- * Until neighbors are discovered, assume responsibility for sending
- * periodic group membership queries to the subnet. Send the first
- * query.
- */
- v->uv_flags |= VIFF_QUERIER;
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0, "assuming querier duties on vif %d", vifi);
- send_query(v);
- }
-
- v->uv_leaf_timer = LEAF_CONFIRMATION_TIME;
-
- /*
- * Send a probe via the new vif to look for neighbors.
- */
- send_probe_on_vif(v);
-}
-
-/*
- * Stop routing on the specified virtual interface.
- */
-static void
-stop_vif(vifi)
- vifi_t vifi;
-{
- struct uvif *v;
- struct listaddr *a;
- struct phaddr *p;
-
- v = &uvifs[vifi];
-
- if (!(v->uv_flags & VIFF_TUNNEL)) {
- /*
- * Depart from the DVMRP multicast group on the interface.
- */
- k_leave(dvmrp_group, v->uv_lcl_addr);
-
- /*
- * Depart from the ALL-ROUTERS multicast group on the interface.
- */
- k_leave(allrtrs_group, v->uv_lcl_addr);
-
- /*
- * Update the entry in the routing table for the subnet to which
- * the interface is connected, to take into account the interface
- * failure.
- */
- start_route_updates();
- update_route(v->uv_subnet, v->uv_subnetmask, UNREACHABLE, 0, vifi, NULL);
- for (p = v->uv_addrs; p; p = p->pa_next) {
- start_route_updates();
- update_route(p->pa_subnet, p->pa_subnetmask, UNREACHABLE, 0, vifi, NULL);
- }
-
- /*
- * Discard all group addresses. (No need to tell kernel;
- * the k_del_vif() call, below, will clean up kernel state.)
- */
- while (v->uv_groups != NULL) {
- a = v->uv_groups;
- v->uv_groups = a->al_next;
- free((char *)a);
- }
-
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0, "releasing querier duties on vif %d", vifi);
- v->uv_flags &= ~VIFF_QUERIER;
- }
-
- /*
- * Update the existing route entries to take into account the vif failure.
- */
- delete_vif_from_routes(vifi);
-
- /*
- * Delete the interface from the kernel's vif structure.
- */
- k_del_vif(vifi);
-
- /*
- * Discard all neighbor addresses.
- */
- if (!NBRM_ISEMPTY(v->uv_nbrmap))
- vifs_with_neighbors--;
-
- while (v->uv_neighbors != NULL) {
- a = v->uv_neighbors;
- v->uv_neighbors = a->al_next;
- nbrs[a->al_index] = NULL;
- free((char *)a);
- }
- NBRM_CLRALL(v->uv_nbrmap);
-}
-
-
-/*
- * stop routing on all vifs
- */
-void
-stop_all_vifs()
-{
- vifi_t vifi;
- struct uvif *v;
- struct listaddr *a;
- struct vif_acl *acl;
-
- for (vifi = 0; vifi < numvifs; vifi++) {
- v = &uvifs[vifi];
- while (v->uv_groups != NULL) {
- a = v->uv_groups;
- v->uv_groups = a->al_next;
- free((char *)a);
- }
- while (v->uv_neighbors != NULL) {
- a = v->uv_neighbors;
- v->uv_neighbors = a->al_next;
- nbrs[a->al_index] = NULL;
- free((char *)a);
- }
- while (v->uv_acl != NULL) {
- acl = v->uv_acl;
- v->uv_acl = acl->acl_next;
- free((char *)acl);
- }
- }
-}
-
-
-/*
- * Find the virtual interface from which an incoming packet arrived,
- * based on the packet's source and destination IP addresses.
- */
-vifi_t
-find_vif(src, dst)
- register u_int32 src;
- register u_int32 dst;
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct phaddr *p;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
- if (!(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) {
- if (v->uv_flags & VIFF_TUNNEL) {
- if (src == v->uv_rmt_addr && (dst == v->uv_lcl_addr ||
- dst == dvmrp_group))
- return(vifi);
- }
- else {
- if ((src & v->uv_subnetmask) == v->uv_subnet &&
- ((v->uv_subnetmask == 0xffffffff) ||
- (src != v->uv_subnetbcast)))
- return(vifi);
- for (p=v->uv_addrs; p; p=p->pa_next) {
- if ((src & p->pa_subnetmask) == p->pa_subnet &&
- ((p->pa_subnetmask == 0xffffffff) ||
- (src != p->pa_subnetbcast)))
- return(vifi);
- }
- }
- }
- }
- return (NO_VIF);
-}
-
-static void
-age_old_hosts()
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct listaddr *g;
-
- /*
- * Decrement the old-hosts-present timer for each
- * active group on each vif.
- */
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++)
- for (g = v->uv_groups; g != NULL; g = g->al_next)
- if (g->al_old)
- g->al_old--;
-}
-
-
-/*
- * Send group membership queries on each interface for which I am querier.
- * Note that technically, there should be a timer per interface, as the
- * dynamics of querier election can cause the "right" time to send a
- * query to be different on different interfaces. However, this simple
- * implementation only ever sends queries sooner than the "right" time,
- * so can not cause loss of membership (but can send more packets than
- * necessary)
- */
-void
-query_groups()
-{
- register vifi_t vifi;
- register struct uvif *v;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
- if (v->uv_flags & VIFF_QUERIER) {
- send_query(v);
- }
- }
- age_old_hosts();
-}
-
-/*
- * Process an incoming host membership query. Warn about
- * IGMP version mismatches, perform querier election, and
- * handle group-specific queries when we're not the querier.
- */
-void
-accept_membership_query(src, dst, group, tmo)
- u_int32 src, dst, group;
- int tmo;
-{
- register vifi_t vifi;
- register struct uvif *v;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF ||
- (uvifs[vifi].uv_flags & VIFF_TUNNEL)) {
- log(LOG_INFO, 0,
- "ignoring group membership query from non-adjacent host %s",
- inet_fmt(src, s1));
- return;
- }
-
- v = &uvifs[vifi];
-
- if ((tmo == 0 && !(v->uv_flags & VIFF_IGMPV1)) ||
- (tmo != 0 && (v->uv_flags & VIFF_IGMPV1))) {
- int i;
-
- /*
- * Exponentially back-off warning rate
- */
- i = ++v->uv_igmpv1_warn;
- while (i && !(i & 1))
- i >>= 1;
- if (i == 1)
- log(LOG_WARNING, 0, "%s %s on vif %d, %s",
- tmo == 0 ? "Received IGMPv1 report from"
- : "Received IGMPv2 report from",
- inet_fmt(src, s1),
- vifi,
- tmo == 0 ? "please configure vif for IGMPv1"
- : "but I am configured for IGMPv1");
- }
-
- if (v->uv_querier == NULL || v->uv_querier->al_addr != src) {
- /*
- * This might be:
- * - A query from a new querier, with a lower source address
- * than the current querier (who might be me)
- * - A query from a new router that just started up and doesn't
- * know who the querier is.
- */
- if (ntohl(src) < (v->uv_querier ? ntohl(v->uv_querier->al_addr)
- : ntohl(v->uv_lcl_addr))) {
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0, "new querier %s (was %s) on vif %d",
- inet_fmt(src, s1),
- v->uv_querier ? inet_fmt(v->uv_querier->al_addr, s2) :
- "me", vifi);
- if (!v->uv_querier) {
- v->uv_querier = (struct listaddr *)
- malloc(sizeof(struct listaddr));
- v->uv_flags &= ~VIFF_QUERIER;
- }
- time(&v->uv_querier->al_ctime);
- v->uv_querier->al_addr = src;
- } else {
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0, "ignoring query from %s; querier on vif %d is still %s",
- inet_fmt(src, s1), vifi,
- v->uv_querier ? inet_fmt(v->uv_querier->al_addr, s2) :
- "me");
-
- return;
- }
- }
-
- /*
- * Reset the timer since we've received a query.
- */
- if (v->uv_querier && src == v->uv_querier->al_addr)
- v->uv_querier->al_timer = 0;
-
- /*
- * If this is a Group-Specific query which we did not source,
- * we must set our membership timer to [Last Member Query Count] *
- * the [Max Response Time] in the packet.
- */
- if (!(v->uv_flags & (VIFF_IGMPV1|VIFF_QUERIER)) && group != 0 &&
- src != v->uv_lcl_addr) {
- register struct listaddr *g;
-
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0,
- "%s for %s from %s on vif %d, timer %d",
- "Group-specific membership query",
- inet_fmt(group, s2), inet_fmt(src, s1), vifi, tmo);
-
- for (g = v->uv_groups; g != NULL; g = g->al_next) {
- if (group == g->al_addr && g->al_query == 0) {
- /* setup a timeout to remove the group membership */
- if (g->al_timerid)
- g->al_timerid = DeleteTimer(g->al_timerid);
- g->al_timer = IGMP_LAST_MEMBER_QUERY_COUNT *
- tmo / IGMP_TIMER_SCALE;
- /* use al_query to record our presence in last-member state */
- g->al_query = -1;
- g->al_timerid = SetTimer(vifi, g);
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0,
- "timer for grp %s on vif %d set to %d",
- inet_fmt(group, s2), vifi, g->al_timer);
- break;
- }
- }
- }
-}
-
-/*
- * Process an incoming group membership report.
- */
-void
-accept_group_report(src, dst, group, r_type)
- u_int32 src, dst, group;
- int r_type;
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct listaddr *g;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF ||
- (uvifs[vifi].uv_flags & VIFF_TUNNEL)) {
- log(LOG_INFO, 0,
- "ignoring group membership report from non-adjacent host %s",
- inet_fmt(src, s1));
- return;
- }
-
- v = &uvifs[vifi];
-
- /*
- * Look for the group in our group list; if found, reset its timer.
- */
- for (g = v->uv_groups; g != NULL; g = g->al_next) {
- if (group == g->al_addr) {
- if (r_type == IGMP_V1_MEMBERSHIP_REPORT)
- g->al_old = OLD_AGE_THRESHOLD;
-
- g->al_reporter = src;
-
- /** delete old timers, set a timer for expiration **/
- g->al_timer = IGMP_GROUP_MEMBERSHIP_INTERVAL;
- if (g->al_query)
- g->al_query = DeleteTimer(g->al_query);
- if (g->al_timerid)
- g->al_timerid = DeleteTimer(g->al_timerid);
- g->al_timerid = SetTimer(vifi, g);
- break;
- }
- }
-
- /*
- * If not found, add it to the list and update kernel cache.
- */
- if (g == NULL) {
- g = (struct listaddr *)malloc(sizeof(struct listaddr));
- if (g == NULL)
- log(LOG_ERR, 0, "ran out of memory"); /* fatal */
-
- g->al_addr = group;
- if (r_type == IGMP_V1_MEMBERSHIP_REPORT)
- g->al_old = OLD_AGE_THRESHOLD;
- else
- g->al_old = 0;
-
- /** set a timer for expiration **/
- g->al_query = 0;
- g->al_timer = IGMP_GROUP_MEMBERSHIP_INTERVAL;
- g->al_reporter = src;
- g->al_timerid = SetTimer(vifi, g);
- g->al_next = v->uv_groups;
- v->uv_groups = g;
- time(&g->al_ctime);
-
- update_lclgrp(vifi, group);
- }
-
- /*
- * Check if a graft is necessary for this group
- */
- chkgrp_graft(vifi, group);
-}
-
-/*
- * Process an incoming IGMPv2 Leave Group message.
- */
-void
-accept_leave_message(src, dst, group)
- u_int32 src, dst, group;
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct listaddr *g;
-
- if ((vifi = find_vif(src, dst)) == NO_VIF ||
- (uvifs[vifi].uv_flags & VIFF_TUNNEL)) {
- log(LOG_INFO, 0,
- "ignoring group leave report from non-adjacent host %s",
- inet_fmt(src, s1));
- return;
- }
-
- v = &uvifs[vifi];
-
- if (!(v->uv_flags & VIFF_QUERIER) || (v->uv_flags & VIFF_IGMPV1))
- return;
-
- /*
- * Look for the group in our group list in order to set up a short-timeout
- * query.
- */
- for (g = v->uv_groups; g != NULL; g = g->al_next) {
- if (group == g->al_addr) {
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0,
- "[vif.c, _accept_leave_message] %d %d \n",
- g->al_old, g->al_query);
-
- /* Ignore the leave message if there are old hosts present */
- if (g->al_old)
- return;
-
- /* still waiting for a reply to a query, ignore the leave */
- if (g->al_query)
- return;
-
- /** delete old timer set a timer for expiration **/
- if (g->al_timerid)
- g->al_timerid = DeleteTimer(g->al_timerid);
-
-#if IGMP_LAST_MEMBER_QUERY_COUNT != 2
-This code needs to be updated to keep a counter of the number
-of queries remaining.
-#endif
- /** send a group specific querry **/
- g->al_timer = IGMP_LAST_MEMBER_QUERY_INTERVAL *
- (IGMP_LAST_MEMBER_QUERY_COUNT + 1);
- send_igmp(v->uv_lcl_addr, g->al_addr,
- IGMP_MEMBERSHIP_QUERY,
- IGMP_LAST_MEMBER_QUERY_INTERVAL * IGMP_TIMER_SCALE,
- g->al_addr, 0);
- g->al_query = SetQueryTimer(g, vifi,
- IGMP_LAST_MEMBER_QUERY_INTERVAL,
- IGMP_LAST_MEMBER_QUERY_INTERVAL * IGMP_TIMER_SCALE);
- g->al_timerid = SetTimer(vifi, g);
- break;
- }
- }
-}
-
-
-/*
- * Send a periodic probe on all vifs.
- * Useful to determine one-way interfaces.
- * Detect neighbor loss faster.
- */
-void
-probe_for_neighbors()
-{
- register vifi_t vifi;
- register struct uvif *v;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
- if (!(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) {
- send_probe_on_vif(v);
- }
- }
-}
-
-
-/*
- * Send a list of all of our neighbors to the requestor, `src'.
- */
-void
-accept_neighbor_request(src, dst)
- u_int32 src, dst;
-{
- vifi_t vifi;
- struct uvif *v;
- u_char *p, *ncount;
- struct listaddr *la;
- int datalen;
- u_int32 temp_addr, them = src;
-
-#define PUT_ADDR(a) temp_addr = ntohl(a); \
- *p++ = temp_addr >> 24; \
- *p++ = (temp_addr >> 16) & 0xFF; \
- *p++ = (temp_addr >> 8) & 0xFF; \
- *p++ = temp_addr & 0xFF;
-
- p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
- datalen = 0;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
- if (v->uv_flags & VIFF_DISABLED)
- continue;
-
- ncount = 0;
-
- for (la = v->uv_neighbors; la; la = la->al_next) {
-
- /* Make sure that there's room for this neighbor... */
- if (datalen + (ncount == 0 ? 4 + 3 + 4 : 4) > MAX_DVMRP_DATA_LEN) {
- send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS,
- htonl(MROUTED_LEVEL), datalen);
- p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
- datalen = 0;
- ncount = 0;
- }
-
- /* Put out the header for this neighbor list... */
- if (ncount == 0) {
- PUT_ADDR(v->uv_lcl_addr);
- *p++ = v->uv_metric;
- *p++ = v->uv_threshold;
- ncount = p;
- *p++ = 0;
- datalen += 4 + 3;
- }
-
- PUT_ADDR(la->al_addr);
- datalen += 4;
- (*ncount)++;
- }
- }
-
- if (datalen != 0)
- send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS,
- htonl(MROUTED_LEVEL), datalen);
-}
-
-/*
- * Send a list of all of our neighbors to the requestor, `src'.
- */
-void
-accept_neighbor_request2(src, dst)
- u_int32 src, dst;
-{
- vifi_t vifi;
- struct uvif *v;
- u_char *p, *ncount;
- struct listaddr *la;
- int datalen;
- u_int32 them = src;
-
- p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
- datalen = 0;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
- register u_short vflags = v->uv_flags;
- register u_char rflags = 0;
- if (vflags & VIFF_TUNNEL)
- rflags |= DVMRP_NF_TUNNEL;
- if (vflags & VIFF_SRCRT)
- rflags |= DVMRP_NF_SRCRT;
- if (vflags & VIFF_DOWN)
- rflags |= DVMRP_NF_DOWN;
- if (vflags & VIFF_DISABLED)
- rflags |= DVMRP_NF_DISABLED;
- if (vflags & VIFF_QUERIER)
- rflags |= DVMRP_NF_QUERIER;
- if (vflags & VIFF_LEAF)
- rflags |= DVMRP_NF_LEAF;
- ncount = 0;
- la = v->uv_neighbors;
- if (la == NULL) {
- /*
- * include down & disabled interfaces and interfaces on
- * leaf nets.
- */
- if (rflags & DVMRP_NF_TUNNEL)
- rflags |= DVMRP_NF_DOWN;
- if (datalen > MAX_DVMRP_DATA_LEN - 12) {
- send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
- htonl(MROUTED_LEVEL), datalen);
- p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
- datalen = 0;
- }
- *(u_int*)p = v->uv_lcl_addr;
- p += 4;
- *p++ = v->uv_metric;
- *p++ = v->uv_threshold;
- *p++ = rflags;
- *p++ = 1;
- *(u_int*)p = v->uv_rmt_addr;
- p += 4;
- datalen += 12;
- } else {
- for ( ; la; la = la->al_next) {
- /* Make sure that there's room for this neighbor... */
- if (datalen + (ncount == 0 ? 4+4+4 : 4) > MAX_DVMRP_DATA_LEN) {
- send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
- htonl(MROUTED_LEVEL), datalen);
- p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
- datalen = 0;
- ncount = 0;
- }
- /* Put out the header for this neighbor list... */
- if (ncount == 0) {
- /* If it's a one-way tunnel, mark it down. */
- if (rflags & DVMRP_NF_TUNNEL && la->al_flags & NBRF_ONEWAY)
- rflags |= DVMRP_NF_DOWN;
- *(u_int*)p = v->uv_lcl_addr;
- p += 4;
- *p++ = v->uv_metric;
- *p++ = v->uv_threshold;
- *p++ = rflags;
- ncount = p;
- *p++ = 0;
- datalen += 4 + 4;
- }
- /* Don't report one-way peering on phyint at all */
- if (!(rflags & DVMRP_NF_TUNNEL) && la->al_flags & NBRF_ONEWAY)
- continue;
- *(u_int*)p = la->al_addr;
- p += 4;
- datalen += 4;
- (*ncount)++;
- }
- if (*ncount == 0) {
- *(u_int*)p = v->uv_rmt_addr;
- p += 4;
- datalen += 4;
- (*ncount)++;
- }
- }
- }
- if (datalen != 0)
- send_igmp(INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS2,
- htonl(MROUTED_LEVEL), datalen);
-}
-
-void
-accept_info_request(src, dst, p, datalen)
- u_int32 src, dst;
- u_char *p;
- int datalen;
-{
- u_char *q;
- int len;
- int outlen = 0;
-
- q = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
-
- /* To be general, this must deal properly with breaking up over-sized
- * packets. That implies passing a length to each function, and
- * allowing each function to request to be called again. Right now,
- * we're only implementing the one thing we are positive will fit into
- * a single packet, so we wimp out.
- */
- while (datalen > 0) {
- len = 0;
- switch (*p) {
- case DVMRP_INFO_VERSION:
- len = info_version(q, RECV_BUF_SIZE-(q-(u_char *)send_buf));
- break;
-
- case DVMRP_INFO_NEIGHBORS:
- default:
- log(LOG_INFO, 0, "ignoring unknown info type %d", *p);
- break;
- }
- *(q+1) = len++;
- outlen += len * 4;
- q += len * 4;
- len = (*(p+1) + 1) * 4;
- p += len;
- datalen -= len;
- }
-
- if (outlen != 0)
- send_igmp(INADDR_ANY, src, IGMP_DVMRP, DVMRP_INFO_REPLY,
- htonl(MROUTED_LEVEL), outlen);
-}
-
-/*
- * Information response -- return version string
- */
-static int
-info_version(p, plen)
- char *p;
- int plen;
-{
- int len;
- extern char versionstring[];
-
- *p++ = DVMRP_INFO_VERSION;
- p++; /* skip over length */
- *p++ = 0; /* zero out */
- *p++ = 0; /* reserved fields */
- strncpy(p, versionstring, plen - 4);
- p[plen-5] = '\0';
-
- len = strlen(versionstring);
- return ((len + 3) / 4);
-}
-
-/*
- * Process an incoming neighbor-list message.
- */
-void
-accept_neighbors(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- u_char *p;
- int datalen;
-{
- log(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-
-/*
- * Process an incoming neighbor-list message.
- */
-void
-accept_neighbors2(src, dst, p, datalen, level)
- u_int32 src, dst, level;
- u_char *p;
- int datalen;
-{
- IF_DEBUG(DEBUG_PKT)
- log(LOG_DEBUG, 0, "ignoring spurious DVMRP neighbor list2 from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-/*
- * Process an incoming info reply message.
- */
-void
-accept_info_reply(src, dst, p, datalen)
- u_int32 src, dst;
- u_char *p;
- int datalen;
-{
- IF_DEBUG(DEBUG_PKT)
- log(LOG_DEBUG, 0, "ignoring spurious DVMRP info reply from %s to %s",
- inet_fmt(src, s1), inet_fmt(dst, s2));
-}
-
-
-/*
- * Update the neighbor entry for neighbor 'addr' on vif 'vifi'.
- * 'msgtype' is the type of DVMRP message received from the neighbor.
- * Return the neighbor entry if 'addr' is a valid neighbor, FALSE otherwise.
- */
-struct listaddr *
-update_neighbor(vifi, addr, msgtype, p, datalen, level)
- vifi_t vifi;
- u_int32 addr;
- int msgtype;
- char *p;
- int datalen;
- u_int32 level;
-{
- register struct uvif *v;
- register struct listaddr *n;
- int pv = level & 0xff;
- int mv = (level >> 8) & 0xff;
- int has_genid = 0;
- int in_router_list = 0;
- int dvmrpspec = 0;
- u_int32 genid;
- u_int32 send_tables = 0;
- int i;
- int do_reset = FALSE;
-
- v = &uvifs[vifi];
-
- /*
- * Confirm that 'addr' is a valid neighbor address on vif 'vifi'.
- * IT IS ASSUMED that this was preceded by a call to find_vif(), which
- * checks that 'addr' is either a valid remote tunnel endpoint or a
- * non-broadcast address belonging to a directly-connected subnet.
- * Therefore, here we check only that 'addr' is not our own address
- * (due to an impostor or erroneous loopback) or an address of the form
- * {subnet,0} ("the unknown host"). These checks are not performed in
- * find_vif() because those types of address are acceptable for some
- * types of IGMP message (such as group membership reports).
- */
- if (!(v->uv_flags & VIFF_TUNNEL) &&
- (addr == v->uv_lcl_addr ||
- addr == v->uv_subnet )) {
- log(LOG_WARNING, 0,
- "received DVMRP message from %s: %s",
- (addr == v->uv_lcl_addr) ? "self (check device loopback)" :
- "'the unknown host'",
- inet_fmt(addr, s1));
- return NULL;
- }
-
- /*
- * Ignore all neighbors on vifs forced into leaf mode
- */
- if (v->uv_flags & VIFF_FORCE_LEAF) {
- return NULL;
- }
-
- /*
- * mrouted's version 3.3 and later include the generation ID
- * and the list of neighbors on the vif in their probe messages.
- */
- if (msgtype == DVMRP_PROBE && ((pv == 3 && mv > 2) ||
- (pv > 3 && pv < 10))) {
- u_int32 router;
-
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "checking probe from %s (%d.%d) on vif %d",
- inet_fmt(addr, s1), pv, mv, vifi);
-
- if (datalen < 4) {
- log(LOG_WARNING, 0,
- "received truncated probe message from %s (len %d)",
- inet_fmt(addr, s1), datalen);
- return NULL;
- }
-
- has_genid = 1;
-
- for (i = 0; i < 4; i++)
- ((char *)&genid)[i] = *p++;
- datalen -= 4;
-
- while (datalen > 0) {
- if (datalen < 4) {
- log(LOG_WARNING, 0,
- "received truncated probe message from %s (len %d)",
- inet_fmt(addr, s1), datalen);
- return NULL;
- }
- for (i = 0; i < 4; i++)
- ((char *)&router)[i] = *p++;
- datalen -= 4;
-
- if (router == v->uv_lcl_addr) {
- in_router_list = 1;
- break;
- }
- }
- }
-
- if ((pv == 3 && mv == 255) || (pv > 3 && pv < 10))
- dvmrpspec = 1;
-
- /*
- * Look for addr in list of neighbors.
- */
- for (n = v->uv_neighbors; n != NULL; n = n->al_next) {
- if (addr == n->al_addr) {
- break;
- }
- }
-
- if (n == NULL) {
- /*
- * New neighbor.
- *
- * If this neighbor follows the DVMRP spec, start the probe
- * handshake. If not, then it doesn't require the probe
- * handshake, so establish the peering immediately.
- */
- if (dvmrpspec && (msgtype != DVMRP_PROBE))
- return NULL;
-
- for (i = 0; i < MAXNBRS; i++)
- if (nbrs[i] == NULL)
- break;
-
- if (i == MAXNBRS) {
- /* XXX This is a severe new restriction. */
- /* XXX want extensible bitmaps! */
- log(LOG_ERR, 0, "Can't handle %dth neighbor %s on vif %d!",
- MAXNBRS, inet_fmt(addr, s1), vifi);
- /*NOTREACHED*/
- }
-
- /*
- * Add it to our list of neighbors.
- */
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "New neighbor %s on vif %d v%d.%d nf 0x%02x idx %d",
- inet_fmt(addr, s1), vifi, level & 0xff, (level >> 8) & 0xff,
- (level >> 16) & 0xff, i);
-
- n = (struct listaddr *)malloc(sizeof(struct listaddr));
- if (n == NULL)
- log(LOG_ERR, 0, "ran out of memory"); /* fatal */
-
- n->al_addr = addr;
- n->al_pv = pv;
- n->al_mv = mv;
- n->al_genid = has_genid ? genid : 0;
- n->al_index = i;
- nbrs[i] = n;
-
- time(&n->al_ctime);
- n->al_timer = 0;
- n->al_flags = has_genid ? NBRF_GENID : 0;
- n->al_next = v->uv_neighbors;
- v->uv_neighbors = n;
-
- /*
- * If we are not configured to peer with non-pruning routers,
- * check the deprecated "I-know-how-to-prune" bit. This bit
- * was MBZ in early mrouted implementations (<3.5) and is required
- * to be set by the DVMRPv3 specification.
- */
- if (!(v->uv_flags & VIFF_ALLOW_NONPRUNERS) &&
- !((level & 0x020000) || (pv == 3 && mv < 5))) {
- n->al_flags |= NBRF_TOOOLD;
- }
-
- /*
- * If this router implements the DVMRPv3 spec, then don't peer
- * with him if we haven't yet established a bidirectional connection.
- */
- if (dvmrpspec) {
- if (!in_router_list) {
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "waiting for probe from %s with my addr",
- inet_fmt(addr, s1));
- n->al_flags |= NBRF_WAITING;
- return NULL;
- }
- }
-
- if (n->al_flags & NBRF_DONTPEER) {
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "not peering with %s on vif %d because %x",
- inet_fmt(addr, s1), vifi, n->al_flags & NBRF_DONTPEER);
- return NULL;
- }
-
- /*
- * If we thought that we had no neighbors on this vif, send a route
- * report to the vif. If this is just a new neighbor on the same
- * vif, send the route report just to the new neighbor.
- */
- if (NBRM_ISEMPTY(v->uv_nbrmap)) {
- send_tables = v->uv_dst_addr;
- vifs_with_neighbors++;
- } else {
- send_tables = addr;
- }
-
-
- NBRM_SET(i, v->uv_nbrmap);
- add_neighbor_to_routes(vifi, i);
- } else {
- /*
- * Found it. Reset its timer.
- */
- n->al_timer = 0;
-
- if (n->al_flags & NBRF_WAITING && msgtype == DVMRP_PROBE) {
- n->al_flags &= ~NBRF_WAITING;
- if (!in_router_list) {
- log(LOG_WARNING, 0, "possible one-way peering with %s on vif %d",
- inet_fmt(addr, s1), vifi);
- n->al_flags |= NBRF_ONEWAY;
- return NULL;
- } else {
- if (NBRM_ISEMPTY(v->uv_nbrmap)) {
- send_tables = v->uv_dst_addr;
- vifs_with_neighbors++;
- } else {
- send_tables = addr;
- }
- NBRM_SET(n->al_index, v->uv_nbrmap);
- add_neighbor_to_routes(vifi, n->al_index);
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "%s on vif %d exits WAITING",
- inet_fmt(addr, s1), vifi);
- }
- }
-
- if (n->al_flags & NBRF_ONEWAY && msgtype == DVMRP_PROBE) {
- if (in_router_list) {
- if (NBRM_ISEMPTY(v->uv_nbrmap))
- vifs_with_neighbors++;
- NBRM_SET(n->al_index, v->uv_nbrmap);
- add_neighbor_to_routes(vifi, n->al_index);
- log(LOG_NOTICE, 0, "peering with %s on vif %d is no longer one-way",
- inet_fmt(addr, s1), vifi);
- n->al_flags &= ~NBRF_ONEWAY;
- } else {
- /* XXX rate-limited warning message? */
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "%s on vif %d is still ONEWAY",
- inet_fmt(addr, s1), vifi);
- }
- }
-
- /*
- * When peering with a genid-capable but pre-DVMRP spec peer,
- * we might bring up the peering with a route report and not
- * remember his genid. Assume that he doesn't send a route
- * report and then reboot before sending a probe.
- */
- if (has_genid && !(n->al_flags & NBRF_GENID)) {
- n->al_flags |= NBRF_GENID;
- n->al_genid = genid;
- }
-
- /*
- * update the neighbors version and protocol number and genid
- * if changed => router went down and came up,
- * so take action immediately.
- */
- if ((n->al_pv != pv) ||
- (n->al_mv != mv) ||
- (has_genid && n->al_genid != genid)) {
-
- do_reset = TRUE;
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0,
- "version/genid change neighbor %s [old:%d.%d/%8x, new:%d.%d/%8x]",
- inet_fmt(addr, s1),
- n->al_pv, n->al_mv, n->al_genid, pv, mv, genid);
-
- n->al_pv = pv;
- n->al_mv = mv;
- n->al_genid = genid;
- time(&n->al_ctime);
- }
-
- if ((pv == 3 && mv > 2) || (pv > 3 && pv < 10)) {
- if (!(n->al_flags & VIFF_ONEWAY) && has_genid && !in_router_list &&
- (time(NULL) - n->al_ctime > 20)) {
- if (NBRM_ISSET(n->al_index, v->uv_nbrmap)) {
- NBRM_CLR(n->al_index, v->uv_nbrmap);
- if (NBRM_ISEMPTY(v->uv_nbrmap))
- vifs_with_neighbors--;
- }
- delete_neighbor_from_routes(addr, vifi, n->al_index);
- reset_neighbor_state(vifi, addr);
- log(LOG_WARNING, 0, "peering with %s on vif %d is one-way",
- inet_fmt(addr, s1), vifi);
- n->al_flags |= NBRF_ONEWAY;
- }
- }
-
- if (n->al_flags & NBRF_DONTPEER) {
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "not peering with %s on vif %d because %x",
- inet_fmt(addr, s1), vifi, n->al_flags & NBRF_DONTPEER);
- return NULL;
- }
-
- /* check "leaf" flag */
- }
- if (do_reset) {
- reset_neighbor_state(vifi, addr);
- if (!send_tables)
- send_tables = addr;
- }
- if (send_tables) {
- send_probe_on_vif(v);
- report(ALL_ROUTES, vifi, send_tables);
- }
- v->uv_leaf_timer = 0;
- v->uv_flags &= ~VIFF_LEAF;
-
- return n;
-}
-
-
-/*
- * On every timer interrupt, advance the timer in each neighbor and
- * group entry on every vif.
- */
-void
-age_vifs()
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct listaddr *a, *prev_a;
- register u_int32 addr;
-
- for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v ) {
- if (v->uv_leaf_timer && (v->uv_leaf_timer -= TIMER_INTERVAL == 0)) {
- v->uv_flags |= VIFF_LEAF;
- }
-
- for (prev_a = (struct listaddr *)&(v->uv_neighbors),
- a = v->uv_neighbors;
- a != NULL;
- prev_a = a, a = a->al_next) {
- int exp_time;
- int idx;
-
- if (((a->al_pv == 3) && (a->al_mv >= 3)) ||
- ((a->al_pv > 3) && (a->al_pv < 10)))
- exp_time = NEIGHBOR_EXPIRE_TIME;
- else
- exp_time = OLD_NEIGHBOR_EXPIRE_TIME;
-
- if ((a->al_timer += TIMER_INTERVAL) < exp_time)
- continue;
-
- IF_DEBUG(DEBUG_PEER)
- log(LOG_DEBUG, 0, "Neighbor %s (%d.%d) expired after %d seconds",
- inet_fmt(a->al_addr, s1), a->al_pv, a->al_mv, exp_time);
-
- /*
- * Neighbor has expired; delete it from the neighbor list,
- * delete it from the 'dominants' and 'subordinates arrays of
- * any route entries.
- */
- NBRM_CLR(a->al_index, v->uv_nbrmap);
- nbrs[a->al_index] = NULL; /* XXX is it a good idea to reuse indxs? */
- idx = a->al_index;
- addr = a->al_addr;
- prev_a->al_next = a->al_next;
- free((char *)a);
- a = prev_a;/*XXX use ** */
-
- delete_neighbor_from_routes(addr, vifi, idx);
- reset_neighbor_state(vifi, addr);
-
- if (NBRM_ISEMPTY(v->uv_nbrmap))
- vifs_with_neighbors--;
-
- v->uv_leaf_timer = LEAF_CONFIRMATION_TIME;
- }
-
- if (v->uv_querier &&
- (v->uv_querier->al_timer += TIMER_INTERVAL) >
- IGMP_OTHER_QUERIER_PRESENT_INTERVAL) {
- /*
- * The current querier has timed out. We must become the
- * querier.
- */
- IF_DEBUG(DEBUG_IGMP)
- log(LOG_DEBUG, 0, "querier %s timed out",
- inet_fmt(v->uv_querier->al_addr, s1));
- free(v->uv_querier);
- v->uv_querier = NULL;
- v->uv_flags |= VIFF_QUERIER;
- send_query(v);
- }
- }
-}
-
-/*
- * Returns the neighbor info struct for a given neighbor
- */
-struct listaddr *
-neighbor_info(vifi, addr)
- vifi_t vifi;
- u_int32 addr;
-{
- struct listaddr *u;
-
- for (u = uvifs[vifi].uv_neighbors; u; u = u->al_next)
- if (u->al_addr == addr)
- return u;
-
- return NULL;
-}
-
-static struct vnflags {
- int vn_flag;
- char *vn_name;
-} vifflags[] = {
- { VIFF_DOWN, "down" },
- { VIFF_DISABLED, "disabled" },
- { VIFF_QUERIER, "querier" },
- { VIFF_ONEWAY, "one-way" },
- { VIFF_LEAF, "leaf" },
- { VIFF_IGMPV1, "IGMPv1" },
- { VIFF_REXMIT_PRUNES, "rexmit_prunes" },
- { VIFF_PASSIVE, "passive" },
- { VIFF_ALLOW_NONPRUNERS,"allow_nonpruners" },
- { VIFF_NOFLOOD, "noflood" },
- { VIFF_NOTRANSIT, "notransit" },
- { VIFF_BLASTER, "blaster" },
- { VIFF_FORCE_LEAF, "force_leaf" },
- { VIFF_OTUNNEL, "old-tunnel" },
-};
-
-static struct vnflags nbrflags[] = {
- { NBRF_LEAF, "leaf" },
- { NBRF_GENID, "have-genid" },
- { NBRF_WAITING, "waiting" },
- { NBRF_ONEWAY, "one-way" },
- { NBRF_TOOOLD, "too old" },
- { NBRF_TOOMANYROUTES, "too many routes" },
- { NBRF_NOTPRUNING, "not pruning?" },
-};
-
-/*
- * Print the contents of the uvifs array on file 'fp'.
- */
-void
-dump_vifs(fp)
- FILE *fp;
-{
- register vifi_t vifi;
- register struct uvif *v;
- register struct listaddr *a;
- register struct phaddr *p;
- register struct vif_acl *acl;
- int i;
- struct sioc_vif_req v_req;
- time_t now;
- char *label;
-
- time(&now);
- fprintf(fp, "vifs_with_neighbors = %d\n", vifs_with_neighbors);
-
- if (vifs_with_neighbors == 1)
- fprintf(fp,"[This host is a leaf]\n\n");
-
- fprintf(fp,
- "\nVirtual Interface Table\n%s",
- "Vif Name Local-Address ");
- fprintf(fp,
- "M Thr Rate Flags\n");
-
- for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
-
- fprintf(fp, "%2u %6s %-15s %6s: %-18s %2u %3u %5u ",
- vifi,
- v->uv_name,
- inet_fmt(v->uv_lcl_addr, s1),
- (v->uv_flags & VIFF_TUNNEL) ?
- "tunnel":
- "subnet",
- (v->uv_flags & VIFF_TUNNEL) ?
- inet_fmt(v->uv_rmt_addr, s2) :
- inet_fmts(v->uv_subnet, v->uv_subnetmask, s3),
- v->uv_metric,
- v->uv_threshold,
- v->uv_rate_limit);
-
- for (i = 0; i < sizeof(vifflags) / sizeof(struct vnflags); i++)
- if (v->uv_flags & vifflags[i].vn_flag)
- fprintf(fp, " %s", vifflags[i].vn_name);
-
- fprintf(fp, "\n");
- /*
- fprintf(fp, " #routes: %d\n", v->uv_nroutes);
- */
- if (v->uv_admetric != 0)
- fprintf(fp, " advert-metric %2u\n",
- v->uv_admetric);
-
- label = "alternate subnets:";
- for (p = v->uv_addrs; p; p = p->pa_next) {
- fprintf(fp, " %18s %s\n", label,
- inet_fmts(p->pa_subnet, p->pa_subnetmask, s1));
- label = "";
- }
-
- label = "peers:";
- for (a = v->uv_neighbors; a != NULL; a = a->al_next) {
- fprintf(fp, " %6s %s (%d.%d) [%d]",
- label, inet_fmt(a->al_addr, s1), a->al_pv, a->al_mv,
- a->al_index);
- for (i = 0; i < sizeof(nbrflags) / sizeof(struct vnflags); i++)
- if (a->al_flags & nbrflags[i].vn_flag)
- fprintf(fp, " %s", nbrflags[i].vn_name);
- fprintf(fp, " up %s\n", scaletime(now - a->al_ctime));
- /*fprintf(fp, " #routes %d\n", a->al_nroutes);*/
- label = "";
- }
-
- label = "group host (time left):";
- for (a = v->uv_groups; a != NULL; a = a->al_next) {
- fprintf(fp, " %23s %-15s %-15s (%s)\n",
- label,
- inet_fmt(a->al_addr, s1),
- inet_fmt(a->al_reporter, s2),
- scaletime(timer_leftTimer(a->al_timerid)));
- label = "";
- }
- label = "boundaries:";
- for (acl = v->uv_acl; acl != NULL; acl = acl->acl_next) {
- fprintf(fp, " %11s %-18s\n", label,
- inet_fmts(acl->acl_addr, acl->acl_mask, s1));
- label = "";
- }
- if (v->uv_filter) {
- struct vf_element *vfe;
- char lbuf[100];
-
- sprintf(lbuf, "%5s %7s filter:",
- v->uv_filter->vf_flags & VFF_BIDIR ? "bidir"
- : " ",
- v->uv_filter->vf_type == VFT_ACCEPT ? "accept"
- : "deny");
- label = lbuf;
- for (vfe = v->uv_filter->vf_filter;
- vfe != NULL; vfe = vfe->vfe_next) {
- fprintf(fp, " %23s %-18s%s\n",
- label,
- inet_fmts(vfe->vfe_addr, vfe->vfe_mask, s1),
- vfe->vfe_flags & VFEF_EXACT ? " (exact)" : "");
- label = "";
- }
- }
- if (!(v->uv_flags & (VIFF_TUNNEL|VIFF_DOWN|VIFF_DISABLED))) {
- fprintf(fp, " IGMP querier: ");
- if (v->uv_querier == NULL)
- if (v->uv_flags & VIFF_QUERIER)
- fprintf(fp, "%-18s (this system)\n",
- inet_fmt(v->uv_lcl_addr, s1));
- else
- fprintf(fp, "NONE - querier election failure?\n");
- else
- fprintf(fp, "%-18s up %s last heard %s ago\n",
- inet_fmt(v->uv_querier->al_addr, s1),
- scaletime(now - v->uv_querier->al_ctime),
- scaletime(v->uv_querier->al_timer));
- }
- if (v->uv_flags & VIFF_BLASTER)
- fprintf(fp, " blasterbuf size: %dk\n",
- v->uv_blasterlen / 1024);
- fprintf(fp, " Nbr bitmaps: 0x%08lx%08lx\n",/*XXX*/
- v->uv_nbrmap.hi, v->uv_nbrmap.lo);
- if (v->uv_prune_lifetime != 0)
- fprintf(fp, " Prune Lifetime: %d seconds\n",
- v->uv_prune_lifetime);
-
- v_req.vifi = vifi;
- if (did_final_init)
- if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) < 0) {
- log(LOG_WARNING, errno,
- "SIOCGETVIFCNT fails on vif %d", vifi);
- } else {
- fprintf(fp, " pkts/bytes in : %lu/%lu\n",
- v_req.icount, v_req.ibytes);
- fprintf(fp, " pkts/bytes out: %lu/%lu\n",
- v_req.ocount, v_req.obytes);
- }
- fprintf(fp, "\n");
- }
- fprintf(fp, "\n");
-}
-
-/*
- * Time out record of a group membership on a vif
- */
-static void
-DelVif(arg)
- void *arg;
-{
- cbk_t *cbk = (cbk_t *)arg;
- vifi_t vifi = cbk->vifi;
- struct uvif *v = &uvifs[vifi];
- struct listaddr *a, **anp, *g = cbk->g;
-
- /*
- * Group has expired
- * delete all kernel cache entries with this group
- */
- if (g->al_query)
- DeleteTimer(g->al_query);
-
- delete_lclgrp(vifi, g->al_addr);
-
- anp = &(v->uv_groups);
- while ((a = *anp) != NULL) {
- if (a == g) {
- *anp = a->al_next;
- free((char *)a);
- } else {
- anp = &a->al_next;
- }
- }
-
- free(cbk);
-}
-
-/*
- * Set a timer to delete the record of a group membership on a vif.
- */
-static int
-SetTimer(vifi, g)
- vifi_t vifi;
- struct listaddr *g;
-{
- cbk_t *cbk;
-
- cbk = (cbk_t *) malloc(sizeof(cbk_t));
- cbk->g = g;
- cbk->vifi = vifi;
- return timer_setTimer(g->al_timer, DelVif, cbk);
-}
-
-/*
- * Delete a timer that was set above.
- */
-static int
-DeleteTimer(id)
- int id;
-{
- timer_clearTimer(id);
- return 0;
-}
-
-/*
- * Send a group-specific query.
- */
-static void
-SendQuery(arg)
- void *arg;
-{
- cbk_t *cbk = (cbk_t *)arg;
- register struct uvif *v = &uvifs[cbk->vifi];
-
- send_igmp(v->uv_lcl_addr, cbk->g->al_addr,
- IGMP_MEMBERSHIP_QUERY,
- cbk->q_time, cbk->g->al_addr, 0);
- cbk->g->al_query = 0;
- free(cbk);
-}
-
-/*
- * Set a timer to send a group-specific query.
- */
-static int
-SetQueryTimer(g, vifi, to_expire, q_time)
- struct listaddr *g;
- vifi_t vifi;
- int to_expire, q_time;
-{
- cbk_t *cbk;
-
- cbk = (cbk_t *) malloc(sizeof(cbk_t));
- cbk->g = g;
- cbk->q_time = q_time;
- cbk->vifi = vifi;
- return timer_setTimer(to_expire, SendQuery, cbk);
-}
diff --git a/usr.sbin/mrouted/vif.h b/usr.sbin/mrouted/vif.h
deleted file mode 100644
index 5be618dea308..000000000000
--- a/usr.sbin/mrouted/vif.h
+++ /dev/null
@@ -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 */