Remove mrouted from -CURRENT.

Discussed with:	fenner, net@
This commit is contained in:
Bruce M Simpson 2006-09-29 10:40:53 +00:00
parent 13b3ebf134
commit aa805a5eb7
43 changed files with 0 additions and 18634 deletions

View File

@ -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.

View File

@ -1,5 +0,0 @@
# $FreeBSD$
SUBDIR= common mrouted mrinfo map-mbone mtrace testrsrr
.include <bsd.subdir.mk>

View File

@ -1,7 +0,0 @@
# $FreeBSD$
CFLAGS+= -DRSRR -Dlog=logit
LIBMROUTED= ${.OBJDIR}/../common/libmrouted.a
.include "../Makefile.inc"

View File

@ -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.

View File

@ -1 +0,0 @@
3.9-beta3+IOS12

View File

@ -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 */

View File

@ -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);
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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 */

View File

@ -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*/

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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

View File

@ -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);
}

View File

@ -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));
}

View File

@ -1,344 +0,0 @@
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE". Use of the mrouted program represents acceptance of
* the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* kern.c,v 3.8.4.10 1998/01/06 02:00:51 fenner Exp
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
int curttl = 0;
void k_set_rcvbuf(bufsize, minsize)
int bufsize;
int minsize;
{
int delta = bufsize / 2;
int iter = 0;
/*
* Set the socket buffer. If we can't set it as large as we
* want, search around to try to find the highest acceptable
* value. The highest acceptable value being smaller than
* minsize is a fatal error.
*/
if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
(char *)&bufsize, sizeof(bufsize)) < 0) {
bufsize -= delta;
while (1) {
iter++;
if (delta > 1)
delta /= 2;
if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,
(char *)&bufsize, sizeof(bufsize)) < 0) {
bufsize -= delta;
} else {
if (delta < 1024)
break;
bufsize += delta;
}
}
if (bufsize < minsize) {
log(LOG_ERR, 0, "OS-allowed buffer size %u < app min %u",
bufsize, minsize);
/*NOTREACHED*/
}
}
IF_DEBUG(DEBUG_KERN)
log(LOG_DEBUG, 0, "Got %d byte buffer size in %d iterations",
bufsize, iter);
}
void k_hdr_include(bool)
int bool;
{
#ifdef IP_HDRINCL
if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL,
(char *)&bool, sizeof(bool)) < 0)
log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool);
#endif
}
void k_set_ttl(t)
int t;
{
#ifndef RAW_OUTPUT_IS_RAW
u_char ttl;
ttl = t;
if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL,
(char *)&ttl, sizeof(ttl)) < 0)
log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);
#endif
curttl = t;
}
void k_set_loop(l)
int l;
{
u_char loop;
loop = l;
if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&loop, sizeof(loop)) < 0)
log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);
}
void k_set_if(ifa)
u_int32 ifa;
{
struct in_addr adr;
adr.s_addr = ifa;
if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&adr, sizeof(adr)) < 0)
log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",
inet_fmt(ifa, s1));
}
void k_join(grp, ifa)
u_int32 grp;
u_int32 ifa;
{
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = grp;
mreq.imr_interface.s_addr = ifa;
if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&mreq, sizeof(mreq)) < 0)
log(LOG_WARNING, errno, "can't join group %s on interface %s",
inet_fmt(grp, s1), inet_fmt(ifa, s2));
}
void k_leave(grp, ifa)
u_int32 grp;
u_int32 ifa;
{
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = grp;
mreq.imr_interface.s_addr = ifa;
if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(char *)&mreq, sizeof(mreq)) < 0)
log(LOG_WARNING, errno, "can't leave group %s on interface %s",
inet_fmt(grp, s1), inet_fmt(ifa, s2));
}
void k_init_dvmrp()
{
#ifdef OLD_KERNEL
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
(char *)NULL, 0) < 0)
#else
int v=1;
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT,
(char *)&v, sizeof(int)) < 0)
#endif
log(LOG_ERR, errno, "can't enable Multicast routing in kernel");
}
void k_stop_dvmrp()
{
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE,
(char *)NULL, 0) < 0)
log(LOG_WARNING, errno, "can't disable Multicast routing in kernel");
}
void k_add_vif(vifi, v)
vifi_t vifi;
struct uvif *v;
{
struct vifctl vc;
vc.vifc_vifi = vifi;
vc.vifc_flags = v->uv_flags & VIFF_KERNEL_FLAGS;
vc.vifc_threshold = v->uv_threshold;
vc.vifc_rate_limit = v->uv_rate_limit;
vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr;
vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr;
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF,
(char *)&vc, sizeof(vc)) < 0)
log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF on vif %d", vifi);
}
void k_del_vif(vifi)
vifi_t vifi;
{
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF,
(char *)&vifi, sizeof(vifi)) < 0)
log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
}
/*
* Adds a (source, mcastgrp) entry to the kernel
*/
void k_add_rg(origin, g)
u_int32 origin;
struct gtable *g;
{
struct mfcctl mc;
vifi_t i;
#ifdef DEBUG_MFC
md_log(MD_ADD, origin, g->gt_mcastgrp);
#endif
/* copy table values so that setsockopt can process it */
mc.mfcc_origin.s_addr = origin;
#ifdef OLD_KERNEL
mc.mfcc_originmask.s_addr = 0xffffffff;
#endif
mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF;
for (i = 0; i < numvifs; i++)
mc.mfcc_ttls[i] = g->gt_ttls[i];
/* write to kernel space */
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC,
(char *)&mc, sizeof(mc)) < 0) {
#ifdef DEBUG_MFC
md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
#endif
log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC",
inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
}
}
/*
* Deletes a (source, mcastgrp) entry from the kernel
*/
int k_del_rg(origin, g)
u_int32 origin;
struct gtable *g;
{
struct mfcctl mc;
int retval;
#ifdef DEBUG_MFC
md_log(MD_DEL, origin, g->gt_mcastgrp);
#endif
/* copy table values so that setsockopt can process it */
mc.mfcc_origin.s_addr = origin;
#ifdef OLD_KERNEL
mc.mfcc_originmask.s_addr = 0xffffffff;
#endif
mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp;
/* write to kernel space */
if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC,
(char *)&mc, sizeof(mc))) < 0) {
#ifdef DEBUG_MFC
md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
#endif
log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC of (%s %s)",
inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
}
return retval;
}
/*
* Get the kernel's idea of what version of mrouted needs to run with it.
*/
int k_get_version()
{
#ifdef OLD_KERNEL
return -1;
#else
int vers;
int len = sizeof(vers);
if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION,
(char *)&vers, &len) < 0)
log(LOG_ERR, errno,
"getsockopt MRT_VERSION: perhaps your kernel is too old");
return vers;
#endif
}
#if 0
/*
* Get packet counters
*/
int
k_get_vif_count(vifi, icount, ocount, ibytes, obytes)
vifi_t vifi;
int *icount, *ocount, *ibytes, *obytes;
{
struct sioc_vif_req vreq;
int retval = 0;
vreq.vifi = vifi;
if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&vreq) < 0) {
log(LOG_WARNING, errno, "SIOCGETVIFCNT on vif %d", vifi);
vreq.icount = vreq.ocount = vreq.ibytes =
vreq.obytes = 0xffffffff;
retval = 1;
}
if (icount)
*icount = vreq.icount;
if (ocount)
*ocount = vreq.ocount;
if (ibytes)
*ibytes = vreq.ibytes;
if (obytes)
*obytes = vreq.obytes;
return retval;
}
/*
* Get counters for a desired source and group.
*/
int
k_get_sg_count(src, grp, pktcnt, bytecnt, wrong_if)
u_int32 src;
u_int32 grp;
struct sg_count *retval;
{
struct sioc_sg_req sgreq;
int retval = 0;
sgreq.src.s_addr = src;
sgreq.grp.s_addr = grp;
if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sgreq) < 0) {
log(LOG_WARNING, errno, "SIOCGETSGCNT on (%s %s)",
inet_fmt(src, s1), inet_fmt(grp, s2));
sgreq.pktcnt = sgreq.bytecnt = sgreq.wrong_if = 0xffffffff;
return 1;
}
if (pktcnt)
*pktcnt = sgreq.pktcnt;
if (bytecnt)
*bytecnt = sgreq.bytecnt;
if (wrong_if)
*wrong_if = sgreq.wrong_if;
return retval;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -1,15 +0,0 @@
# $FreeBSD$
S= ${.CURDIR}/..
.PATH: $S
PROG= map-mbone
MAN= map-mbone.8
SRCS= mapper.c
CFLAGS+= -I$S
DPADD= ${LIBMROUTED}
LDADD= ${LIBMROUTED}
.include <bsd.prog.mk>

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
{
}

View File

@ -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>

View File

@ -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 .

View File

@ -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"

View File

@ -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>

View File

@ -1,589 +0,0 @@
.\" Copyright (c) 1995 by the University of Southern California
.\" All rights reserved.
.\"
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation in source and binary forms for non-commercial purposes
.\" and without fee is hereby granted, provided that the above copyright
.\" notice appear in all copies and that both the copyright notice and
.\" this permission notice appear in supporting documentation, and that
.\" any documentation, advertising materials, and other materials related
.\" to such distribution and use acknowledge that the software was
.\" developed by the University of Southern California, Information
.\" Sciences Institute. The name of the University may not be used to
.\" endorse or promote products derived from this software without
.\" specific prior written permission.
.\"
.\" THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
.\" the suitability of this software for any purpose. THIS SOFTWARE IS
.\" PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" Other copyrights might apply to parts of this software and are so
.\" noted when applicable.
.\"
.\" This manual page (but not the software) was derived from the
.\" manual page for the traceroute program which bears the following
.\" copyright notice:
.\"
.\" Copyright (c) 1988 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" $FreeBSD$
.\"
.Dd May 8, 1995
.Dt MTRACE 8
.Os
.Sh NAME
.Nm mtrace
.Nd print multicast path from a source to a receiver
.Sh SYNOPSIS
.Nm
.Op Fl e Ar extrahops
.Op Fl g Ar gateway
.Op Fl i Ar if_addr
.Op Fl l
.Op Fl M
.Op Fl m Ar max_hops
.Op Fl n
.Op Fl O
.Op Fl p
.Op Fl P
.Op Fl q Ar nqueries
.Op Fl r Ar resp_dest
.Op Fl s
.Op Fl S Ar stat_int
.Op Fl t Ar ttl
.Op Fl T
.Op Fl U
.Op Fl v
.Op Fl w Ar waittime
.Ar source
.Op Ar receiver
.Op Ar group
.Sh DESCRIPTION
Assessing problems in the distribution of IP multicast traffic
can be difficult.
The
.Nm
utility utilizes a tracing feature implemented in multicast routers that is
accessed via an extension to the IGMP protocol.
A trace query is
passed hop-by-hop along the reverse path from the
.Ar receiver
to the
.Ar source ,
collecting hop addresses, packet counts, and routing error conditions
along the path, and then the response is returned to the requestor.
.Pp
The only required parameter is the
.Ar source
host name or address.
The default
.Ar receiver
is the host running mtrace, and the default
.Ar group
is 0.0.0.0, which is sufficient if packet loss
statistics for a particular multicast group are not needed.
These two
optional parameters may be specified to test the path to some other
receiver in a particular group, subject to some constraints as
detailed below.
The two parameters can be distinguished because the
.Ar receiver
is a unicast address and the
.Ar group
is a multicast address.
If the
.Fl g
flag is specified, the source address defaults to the host running
.Nm ,
and the receiver defaults to the router being addressed with
the
.Fl g
flag.
In this case, there are no required parameters.
.Pp
NOTE: For Solaris 2.4/2.5, if the multicast interface is not the default
interface, the
.Fl i
option must be used to set the local address.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl e Ar extrahops
Try tracing
.Ar extrahops
hops past a non-responding router.
.It Fl g Ar gwy
Send the trace query via unicast directly to the multicast router
.Ar gwy
rather than multicasting the query.
This must be the last-hop router on the path from the intended
.Ar source
to the
.Ar receiver .
.Pp
.Em CAUTION ! !
Versions 3.3 and 3.5 of
.Nm mrouted
will crash if a trace query is received via a
unicast packet and
.Nm mrouted
has no route for the
.Ar source
address.
Therefore, do not use the
.Fl g
option unless the target
.Nm mrouted
has been verified to be 3.4 or newer than 3.5.
.It Fl i Ar addr
Use
.Ar addr
as the local interface address (on a multi-homed host) for sending the
trace query and as the default for the
.Ar receiver
and the response destination.
.It Fl l
Loop indefinitely printing packet rate and loss statistics for the
multicast path every 10 seconds (see
.Fl S Ar stat_int ) .
.It Fl M
Always request the response using multicast rather than attempting
unicast for the last half of the tries.
.It Fl m Ar n
Set to
.Ar n
the maximum number of hops that will be traced from the
.Ar receiver
back toward the
.Ar source .
The default is 32 hops (infinity for the DVMRP routing protocol).
.It Fl n
Print hop addresses numerically rather than symbolically and numerically
(saves a nameserver address-to-name lookup for each router found on the
path).
.It Fl q Ar n
Set the maximum number of query attempts for any hop to
.Ar n .
The default is 3.
.It Fl O
Do not use the Router-Alert IP option on those requests which need it.
Some versions of Cisco's IOS cannot handle
multicast traceroutes with IP options, so it may be necessary to use the
.Fl O
flag if the last-hop router is a Cisco.
.It Fl p
Listen passively for multicast responses from traces initiated by
others.
This works best when run on a multicast router.
.It Fl P
Loop indefinitely collecting the path every 10 seconds (see
.Fl S Ar stat_int )
and printing it when it changes.
Do not print any statistics.
.It Fl r Ar host
Send the trace response to
.Ar host
rather than to the host on which
.Nm
is being run, or to a multicast address other than the one registered
for this purpose (224.0.1.32).
.It Fl s
Print a short form output including only the multicast path and not
the packet rate and loss statistics.
.It Fl S Ar n
Change the interval between statistics gathering traces to
.Ar n
seconds (default 10 seconds).
.It Fl t Ar ttl
Set the
.Ar ttl
(time-to-live, or number of hops) for multicast trace queries and
responses.
The default is 127, except for local queries to the "all
routers" multicast group which use ttl 1.
.It Fl T
"Tunnel statistics" mode; show loss rates for overall traffic.
These statistics can be extremely misleading.
.It Fl U
Always request the response using unicast rather than attempting
multicast first.
.It Fl v
Verbose mode; show hop times on the initial trace and statistics display.
Also show the route that was used to forward the initial trace.
.It Fl w Ar n
Set the time to wait for a trace response to
.Ar n
seconds (default 3 seconds).
.El
.Sh USAGE
.Ss "How It Works"
The technique used by the
.Nm traceroute
utility to trace unicast network paths will not work for IP multicast
because ICMP responses are specifically forbidden for multicast traffic.
Instead, a tracing feature has been built into the multicast routers.
This technique has the advantage that additional information about
packet rates and losses can be accumulated while the number of packets
sent is minimized.
.Pp
Since multicast uses
reverse path forwarding, the trace is run backwards from the
.Ar receiver
to the
.Ar source .
A trace query packet is sent to the last
hop multicast router (the leaf router for the desired
.Ar receiver
address).
The last hop router builds a trace response packet, fills in
a report for its hop, and forwards the trace packet using unicast to
the router it believes is the previous hop for packets originating
from the specified
.Ar source .
Each router along the path adds its report and forwards the packet.
When the trace response packet reaches the first hop router (the router
that is directly connected to the source's net), that router sends the
completed response to the response destination address specified in
the trace query.
.Pp
If some multicast router along the path does not implement the
multicast traceroute feature or if there is some outage, then no
response will be returned.
To solve this problem, the trace query
includes a maximum hop count field to limit the number of hops traced
before the response is returned.
That allows a partial path to be
traced.
.Pp
The reports inserted by each router contain not only the address of
the hop, but also the ttl required to forward and some flags to indicate
routing errors, plus counts of the total number of packets on the
incoming and outgoing interfaces and those forwarded for the specified
.Ar group .
Taking differences in these counts for two traces separated in time
and comparing the output packet counts from one hop with the input
packet counts of the next hop allows the calculation of packet rate
and packet loss statistics for each hop to isolate congestion
problems.
.Ss Finding the Last-Hop Router
The trace query must be sent to the multicast router which is the
last hop on the path from the
.Ar source
to the
.Ar receiver .
If the receiver is on the local subnet (as determined using the subnet
mask), then the default method is to multicast the trace query to
all-routers.mcast.net (224.0.0.2) with a ttl of 1.
Otherwise, the
trace query is multicast to the
.Ar group
address since the last hop router will be a member of that group if
the receiver is.
Therefore it is necessary to specify a group that
the intended receiver has joined.
This multicast is sent with a
default ttl of 127, which may not be sufficient for all cases (changed
with the
.Fl t
option).
If the last hop router is known, it may also be addressed directly
using the
.Fl g
option).
Alternatively, if it is desired to trace a group that the
receiver has not joined, but it is known that the last-hop router is a
member of another group, the
.Fl g
option may also be used to specify a different multicast address for the
trace query.
.Pp
When tracing from a multihomed host or router, the default receiver
address may not be the desired interface for the path from the source.
In that case, the desired interface should be specified explicitly as
the
.Ar receiver .
.Ss Directing the Response
By default,
.Nm
first attempts to trace the full reverse path, unless the number of
hops to trace is explicitly set with the
.Fl m
option.
If there is no response within a 3 second timeout interval
(changed with the
.Fl w
option), a "*" is printed and the probing switches to hop-by-hop mode.
Trace queries are issued starting with a maximum hop count of one and
increasing by one until the full path is traced or no response is
received.
At each hop, multiple probes are sent (default is three,
changed with
.Fl q
option).
The first half of the attempts (default is two) are made with
the reply address set to standard multicast address, mtrace.mcast.net
(224.0.1.32) with the ttl set to 32 more than what is needed to pass the
thresholds seen so far along the path to the receiver.
For each
additional attempt, the ttl is increased by another 32 each time up to
a maximum of 192.
Since the desired router may not be able to send a
multicast reply, the remainder of the attempts request that the
response be sent via unicast to the host running
.Nm .
Alternatively, the multicast ttl may be set explicitly with the
.Fl t
option, the initial multicast attempts can be forced to use unicast
instead with the
.Fl U
option, the final unicast attempts can be forced to use multicast
instead with the
.Fl M
option, or if you specify
.Fl UM ,
.Nm
will first attempt using unicast and then multicast.
For each attempt,
if no response is received within the timeout, a "*" is printed.
After
the specified number of attempts have failed,
.Nm
will try to query the next hop router with a DVMRP_ASK_NEIGHBORS2
request (as used by the
.Nm mrinfo
program) to see what kind of router it is.
The
.Nm
utility will try to query three (changed with the
.Fl e
option) hops past a non-responding router, in the hopes that even
though it is not capable of sending a response, it might be capable of
forwarding the request on.
.Sh EXAMPLES
The output of
.Nm
is in two sections.
The first section is a short listing of the hops
in the order they are queried, that is, in the reverse of the order
from the
.Ar source
to the
.Ar receiver .
For each hop, a line is printed showing the hop number (counted
negatively to indicate that this is the reverse path); the multicast
routing protocol (DVMRP, MOSPF, PIM, etc.); the threshold required to
forward data (to the previous hop in the listing as indicated by the
up-arrow character); and the cumulative delay for the query to reach
that hop (valid only if the clocks are synchronized).
This first
section ends with a line showing the round-trip time which measures
the interval from when the query is issued until the response is
received, both derived from the local system clock, and the total
ttl required for a packet to travel along this path.
A sample use and
output might be:
.Pp
.Bd -literal
oak.isi.edu 80# mtrace -l caraway.lcs.mit.edu 224.2.0.3
Mtrace from 18.26.0.170 to 128.9.160.100 via group 224.2.0.3
Querying full reverse path...
0 oak.isi.edu (128.9.160.100)
-1 cub.isi.edu (128.9.160.153) DVMRP thresh^ 1 3 ms
-2 la.dart.net (140.173.128.1) DVMRP thresh^ 1 14 ms
-3 dc.dart.net (140.173.64.1) DVMRP thresh^ 1 50 ms
-4 bbn.dart.net (140.173.32.1) DVMRP thresh^ 1 63 ms
-5 mit.dart.net (140.173.48.2) DVMRP thresh^ 1 71 ms
-6 caraway.lcs.mit.edu (18.26.0.170)
Round trip time 124 ms; total ttl of 6 required.
.Ed
.Pp
If a hop reports that it is using the default route to forward packets,
the word
.Em [default]
is printed after that hop.
If the
.Fl v
flag is supplied, the route being used to forward packets is printed
in the form
.Em [18.26.0/24] .
.Pp
The second section provides a pictorial view of the path in the
forward direction with data flow indicated by arrows pointing downward
and the query path indicated by arrows pointing upward.
For each hop,
both the entry and exit addresses of the router are shown if
different, along with the initial ttl required on the packet in order
to be forwarded at this hop and the propagation delay across the hop
assuming that the routers at both ends have synchronized clocks.
The right half of this section is composed of two sets of statistics.
The first column contains the average packet rate for all traffic at
each hop.
The remaining columns are the
number of packets lost, the number of packets sent, the percentage
lost, and the average packet rate at each hop.
These statistics are
calculated from differences between traces and from hop to hop as
explained above.
The first group shows the statistics for all traffic
flowing out the interface at one hop and in the interface at the next
hop.
The second group shows the statistics only for traffic forwarded
from the specified
.Ar source
to the specified
.Ar group .
The first group of statistics may be expanded to include loss rates
using the
.Fl T
option.
However, these numbers can be extremely misleading and require
detailed knowledge of the routers involved to be interpreted properly.
.Pp
These statistics are shown on one or two lines for each hop.
Without
any options, this second section of the output is printed only once,
approximately 10 seconds after the initial trace.
One line is shown
for each hop showing the statistics over that 10-second period.
If
the
.Fl l
option is given, the second section is repeated every 10 seconds and
two lines are shown for each hop.
The first line shows the statistics
for the last 10 seconds, and the second line shows the cumulative
statistics over the period since the initial trace, which is 101
seconds in the example below.
The second section of the output is
omitted if the
.Fl s
option is set or if no multicast group is specified.
.Pp
.Bd -literal
Waiting to accumulate statistics... Results after 101 seconds:
Source Response Dest Overall Packet Statistics For Traffic From
18.26.0.170 128.9.160.100 Packet 18.26.0.170 To 224.2.0.3
| __/ rtt 125 ms Rate Lost/Sent = Pct Rate
v / hop 65 ms ------- ---------------------
18.26.0.144
140.173.48.2 mit.dart.net
| ^ ttl 1 0 pps 0/2 = --% 0 pps
v | hop 8 ms 0 pps 0/18 = 0% 0 pps
140.173.48.1
140.173.32.1 bbn.dart.net
| ^ ttl 2 0 pps 0/2 = --% 0 pps
v | hop 12 ms 0 pps 0/18 = 0% 0 pps
140.173.32.2
140.173.64.1 dc.dart.net
| ^ ttl 3 27 pps 0/2 = --% 0 pps
v | hop 34 ms 26 pps 0/18 = 0% 0 pps
140.173.64.2
140.173.128.1 la.dart.net
| ^ ttl 4 83 pps 0/2 = --% 0 pps
v | hop 11 ms 79 pps 0/18 = 0% 0 pps
140.173.128.2
128.9.160.153 cub.isi.edu
| \\__ ttl 5 83 pps ?/2 0 pps
v \\ hop -8 ms 79 pps ?/18 0 pps
128.9.160.100 128.9.160.100
Receiver Query Source
.Ed
.Pp
Because the packet counts may be changing as the trace query is
propagating, there may be small errors (off by 1 or 2) in these
statistics.
However, those errors should not accumulate, so the
cumulative statistics line should increase in accuracy as a new trace
is run every 10 seconds.
There are two sources of larger errors, both
of which show up as negative losses:
.Pp
If the input to a node is from a multi-access network with more than
one other node attached, then the input count will be (close to) the
sum of the output counts from all the attached nodes, but the output
count from the previous hop on the traced path will be only part of
that.
Hence the output count minus the input count will be negative.
.Pp
In release 3.3 of the DVMRP multicast forwarding software for SunOS
and other systems, a multicast packet generated on a router will be
counted as having come in an interface even though it did not.
This
creates the negative loss that can be seen in the example above.
.Pp
Note that these negative losses may mask positive losses.
.Pp
In the example, there is also one negative hop time.
This simply
indicates a lack of synchronization between the system clocks across
that hop.
This example also illustrates how the percentage loss is
shown as two dashes when the number of packets sent is less than 10
because the percentage would not be statistically valid.
.Pp
A second example shows a trace to a receiver that is not local; the
query is sent to the last-hop router with the
.Fl g
option.
In this example, the trace of the full reverse path resulted
in no response because there was a node running an old version of
.Nm mrouted
that did not implement the multicast traceroute function, so
.Nm
switched to hop-by-hop mode.
The
.Dq Output pruned
error code
indicates that traffic for group 224.2.143.24 would not be forwarded.
.Pp
.Bd -literal
oak.isi.edu 108# mtrace -g 140.173.48.2 204.62.246.73 \\
butter.lcs.mit.edu 224.2.143.24
Mtrace from 204.62.246.73 to 18.26.0.151 via group 224.2.143.24
Querying full reverse path... * switching to hop-by-hop:
0 butter.lcs.mit.edu (18.26.0.151)
-1 jam.lcs.mit.edu (18.26.0.144) DVMRP thresh^ 1 33 ms Output pruned
-2 bbn.dart.net (140.173.48.1) DVMRP thresh^ 1 36 ms
-3 dc.dart.net (140.173.32.2) DVMRP thresh^ 1 44 ms
-4 darpa.dart.net (140.173.240.2) DVMRP thresh^ 16 47 ms
-5 * * * noc.hpc.org (192.187.8.2) [mrouted 2.2] didn't respond
Round trip time 95 ms
.Ed
.Sh SEE ALSO
.Xr map-mbone 8 ,
.Xr mrinfo 8 ,
.Xr mrouted 8 ,
.Xr traceroute 8
.Sh AUTHORS
.An -nosplit
Implemented by
.An Steve Casner
based on an initial prototype written by
.An Ajit Thyagarajan .
The multicast traceroute mechanism was designed by
.An Van Jacobson
with help from
.An Steve Casner ,
.An Steve Deering ,
.An Dino Farinacci ,
and
.An Deb Agrawal ;
it was implemented in
.Nm mrouted
by
.An Ajit Thyagarajan
and
.An Bill Fenner .
The option syntax and the output format of
.Nm
are modeled after the unicast
.Nm traceroute
program written by
.An Van Jacobson .
.Sh BUGS
Statistics collection in passive mode does not always produce the same output
as when actively collecting data.

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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>

View File

@ -1,26 +0,0 @@
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE". Use of the mrouted program represents acceptance of
* the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* $FreeBSD$
* pathnames.h,v 3.8 1995/11/29 22:36:57 fenner Rel
*/
#define _PATH_MROUTED_CONF "/etc/mrouted.conf"
#if (defined(BSD) && (BSD >= 199103))
#define _PATH_MROUTED_PID "/var/run/mrouted.pid"
#define _PATH_MROUTED_GENID "/var/run/mrouted.genid"
#define _PATH_MROUTED_DUMP "/var/tmp/mrouted.dump"
#define _PATH_MROUTED_CACHE "/var/tmp/mrouted.cache"
#else
#define _PATH_MROUTED_PID "/etc/mrouted.pid"
#define _PATH_MROUTED_GENID "/etc/mrouted.genid"
#define _PATH_MROUTED_DUMP "/usr/tmp/mrouted.dump"
#define _PATH_MROUTED_CACHE "/usr/tmp/mrouted.cache"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,152 +0,0 @@
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE". Use of the mrouted program represents acceptance of
* the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* $FreeBSD$
* prune.h,v 3.8.4.5 1998/02/27 22:45:43 fenner Exp
*/
/*
* Group table
*
* Each group entry is a member of two doubly-linked lists:
*
* a) A list hanging off of the routing table entry for this source (rt_groups)
* sorted by group address under the routing entry (gt_next, gt_prev)
* b) An independent list pointed to by kernel_table, which is a list of
* active source,group's (gt_gnext, gt_gprev).
*
*/
struct gtable {
struct gtable *gt_next; /* pointer to the next entry */
struct gtable *gt_prev; /* back pointer for linked list */
struct gtable *gt_gnext; /* fwd pointer for group list */
struct gtable *gt_gprev; /* rev pointer for group list */
u_int32 gt_mcastgrp; /* multicast group associated */
vifbitmap_t gt_scope; /* scoped interfaces */
u_char gt_ttls[MAXVIFS]; /* ttl vector for forwarding */
vifbitmap_t gt_grpmems; /* forw. vifs for src, grp */
int gt_prsent_timer; /* prune timer for this group */
int gt_timer; /* timer for this group entry */
time_t gt_ctime; /* time of entry creation */
u_char gt_grftsnt; /* graft sent/retransmit timer */
nbrbitmap_t gt_prunes; /* bitmap of neighbors who pruned */
struct stable *gt_srctbl; /* source table */
struct ptable *gt_pruntbl; /* prune table */
struct rtentry *gt_route; /* parent route */
int gt_rexmit_timer; /* timer for prune retransmission */
int gt_prune_rexmit; /* time til prune retransmission */
#ifdef RSRR
struct rsrr_cache *gt_rsrr_cache; /* RSRR cache */
#endif /* RSRR */
};
/*
* Source table
*
* When source-based prunes exist, there will be a struct ptable here as well.
*/
struct stable
{
struct stable *st_next; /* pointer to the next entry */
u_int32 st_origin; /* host origin of multicasts */
u_long st_pktcnt; /* packet count for src-grp entry */
u_long st_savpkt; /* saved pkt cnt when no krnl entry */
time_t st_ctime; /* kernel entry creation time */
};
/*
* structure to store incoming prunes. Can hang off of either group or source.
*/
struct ptable
{
struct ptable *pt_next; /* pointer to the next entry */
u_int32 pt_router; /* router that sent this prune */
vifi_t pt_vifi; /* vif prune received on */
int pt_index; /* neighbor index of router */
int pt_timer; /* timer for prune */
};
#define MIN_PRUNE_LIFE TIMER_INTERVAL /* min prune lifetime to bother with */
/*
* The packet format for a traceroute request.
*/
struct tr_query {
u_int32 tr_src; /* traceroute source */
u_int32 tr_dst; /* traceroute destination */
u_int32 tr_raddr; /* traceroute response address */
#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
struct {
u_int qid : 24; /* traceroute query id */
u_int ttl : 8; /* traceroute response ttl */
} q;
#else
struct {
u_int ttl : 8; /* traceroute response ttl */
u_int qid : 24; /* traceroute query id */
} q;
#endif /* BYTE_ORDER */
};
#define tr_rttl q.ttl
#define tr_qid q.qid
/*
* Traceroute response format. A traceroute response has a tr_query at the
* beginning, followed by one tr_resp for each hop taken.
*/
struct tr_resp {
u_int32 tr_qarr; /* query arrival time */
u_int32 tr_inaddr; /* incoming interface address */
u_int32 tr_outaddr; /* outgoing interface address */
u_int32 tr_rmtaddr; /* parent address in source tree */
u_int32 tr_vifin; /* input packet count on interface */
u_int32 tr_vifout; /* output packet count on interface */
u_int32 tr_pktcnt; /* total incoming packets for src-grp */
u_char tr_rproto; /* routing protocol deployed on router */
u_char tr_fttl; /* ttl required to forward on outvif */
u_char tr_smask; /* subnet mask for src addr */
u_char tr_rflags; /* forwarding error codes */
};
/* defs within mtrace */
#define QUERY 1
#define RESP 2
#define QLEN sizeof(struct tr_query)
#define RLEN sizeof(struct tr_resp)
/* fields for tr_rflags (forwarding error codes) */
#define TR_NO_ERR 0
#define TR_WRONG_IF 1
#define TR_PRUNED 2
#define TR_OPRUNED 3
#define TR_SCOPED 4
#define TR_NO_RTE 5
#define TR_NO_FWD 7
#define TR_NO_SPACE 0x81
#define TR_OLD_ROUTER 0x82
/* fields for tr_rproto (routing protocol) */
#define PROTO_DVMRP 1
#define PROTO_MOSPF 2
#define PROTO_PIM 3
#define PROTO_CBT 4
#define MASK_TO_VAL(x, i) { \
u_int32 _x = ntohl(x); \
(i) = 1; \
while ((_x) <<= 1) \
(i)++; \
};
#define VAL_TO_MASK(x, i) { \
x = i ? htonl(~((1 << (32 - (i))) - 1)) : 0; \
};
#define NBR_VERS(n) (((n)->al_pv << 8) + (n)->al_mv)

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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 */

View File

@ -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 */
};

View File

@ -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 */
};

View File

@ -1,13 +0,0 @@
# $FreeBSD$
S= ${.CURDIR}/..
.PATH: $S
PROG= testrsrr
NO_MAN=
CFLAGS+= -I$S
install:
.include <bsd.prog.mk>

View File

@ -1,125 +0,0 @@
/*
* Copyright 1995 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
* granted, provided that both the above copyright notice and this
* permission notice appear in all copies, that both the above
* copyright notice and this permission notice appear in all
* supporting documentation, and that the name of M.I.T. not be used
* in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. M.I.T. makes
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <sysexits.h>
#include <sys/param.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "rsrr.h"
char sunpath[MAXPATHLEN];
int s;
void exitfn(void) {
close(s);
unlink(sunpath);
}
int main(void) {
struct sockaddr_un sun;
char buf[RSRR_MAX_LEN];
struct rsrr_header *rh;
struct rsrr_vif *rvp;
int i;
s = socket(PF_LOCAL, SOCK_DGRAM, 0);
if (s < 0) {
err(EX_OSERR, "socket(PF_LOCAL, SOCK_DGRAM, 0)");
}
sun.sun_family = AF_LOCAL;
snprintf(sunpath, sizeof sun.sun_path, "/tmp/testrsrr.%lu",
(unsigned long)getpid());
strcpy(sun.sun_path, sunpath);
sun.sun_len = (offsetof(struct sockaddr_un, sun_path)
+ strlen(sunpath));
if (bind(s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
err(EX_OSERR, "bind: %s", sunpath);
}
atexit(exitfn); /* clean up if we exit on error */
strcpy(sun.sun_path, RSRR_SERV_PATH);
sun.sun_len = (offsetof(struct sockaddr_un, sun_path)
+ strlen(sunpath));
if (connect(s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
err(EX_OSERR, "connect: %s", RSRR_SERV_PATH);
}
rh = (struct rsrr_header *)buf;
rh->version = RSRR_MAX_VERSION;
rh->type = RSRR_INITIAL_QUERY;
rh->flags = 0;
rh->num = 0;
if (write(s, rh, sizeof *rh) == (ssize_t)-1) {
err(EX_OSERR, "write(initial query)");
}
if (read(s, buf, sizeof buf) == (ssize_t)-1) {
err(EX_OSERR, "read(initial reply)");
}
if (rh->version != RSRR_MAX_VERSION) {
errx(EX_PROTOCOL, "bad remote version %d", rh->version);
}
if (rh->type != RSRR_INITIAL_REPLY) {
errx(EX_PROTOCOL, "remote returned unexpected message type %d",
rh->type);
}
if (rh->flags) {
printf("confusing flags: %d\n", rh->flags);
}
printf("There are %d vifs configured:\n", rh->num);
printf(" Vif Thresh Status Local address\n");
for(i = 0, rvp = (struct rsrr_vif *)(rh + 1); i < rh->num; i++,rvp++) {
printf(" %3d %6d %6d %s\n", rvp->id, rvp->threshold,
rvp->status, inet_ntoa(rvp->local_addr));
}
exit(0);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 */