mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2025-01-01 00:18:15 +01:00
Import mrouted version 3.9-beta3+IOS12 . This is a version of 3.9-beta3
with minor changes to work around a bug in Cisco's IOS version 12.0 . 3.9-beta3 is much improved over 3.8, and is only labelled "beta" because of missing features, as opposed to instability or known bugs.
This commit is contained in:
parent
ce595def07
commit
1f25327484
@ -1,21 +1,188 @@
|
||||
$Id: README-3.8.mrouted,v 3.8 1995/11/29 22:23:02 fenner Rel $
|
||||
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.8
|
||||
November 29, 1995
|
||||
Release 3.9-beta3
|
||||
February 28, 1998
|
||||
|
||||
available from parcftp.xerox.com,
|
||||
file pub/net-research/ipmulti/mrouted3.8.tar.Z
|
||||
binaries pub/net-research/ipmulti/mrouted3.8-sparc-sunos41x.tar.Z
|
||||
pub/net-research/ipmulti/mrouted3.8-sparc-solaris2.tar.Z
|
||||
pub/net-research/ipmulti/mrouted3.8-i386-bsd.tar.Z
|
||||
pub/net-research/ipmulti/mrouted3.8-alpha-osf1.tar.Z
|
||||
pub/net-research/ipmulti/mrouted3.8-sgi-irix.tar.Z
|
||||
pub/net-research/ipmulti/mrouted3.8-hp-hpux.tar.Z
|
||||
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.8 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 or 3.7 .
|
||||
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:
|
||||
|
||||
|
1
usr.sbin/mrouted/VERSION
Normal file
1
usr.sbin/mrouted/VERSION
Normal file
@ -0,0 +1 @@
|
||||
3.9-beta3+IOS12
|
@ -7,22 +7,25 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: callout.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* callout.c,v 3.8.4.8 1998/01/06 01:58:45 fenner Exp
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
callout.c,v 3.8.4.8 1998/01/06 01:58:45 fenner Exp $";
|
||||
#endif
|
||||
|
||||
/* the code below implements a callout queue */
|
||||
static int id = 0;
|
||||
static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
|
||||
|
||||
static int in_callout = 0;
|
||||
|
||||
struct timeout_q {
|
||||
struct timeout_q *next; /* next event */
|
||||
int id;
|
||||
cfunc_t func; /* function to call */
|
||||
char *data; /* func's data */
|
||||
void *data; /* func's data */
|
||||
int time; /* time offset to next event*/
|
||||
};
|
||||
|
||||
@ -38,47 +41,64 @@ callout_init()
|
||||
Q = (struct timeout_q *) 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* signal handler for SIGALARM that is called once every second
|
||||
*/
|
||||
void
|
||||
age_callout_queue()
|
||||
free_all_callouts()
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
|
||||
if (in_callout)
|
||||
return;
|
||||
struct timeout_q *p;
|
||||
|
||||
in_callout = 1;
|
||||
ptr = Q;
|
||||
|
||||
while (ptr) {
|
||||
if (!ptr->time) {
|
||||
/* timeout has happened */
|
||||
Q = Q->next;
|
||||
|
||||
in_callout = 0;
|
||||
if (ptr->func)
|
||||
ptr->func(ptr->data);
|
||||
in_callout = 1;
|
||||
|
||||
free(ptr);
|
||||
ptr = Q;
|
||||
}
|
||||
else {
|
||||
ptr->time --;
|
||||
#ifdef IGMP_DEBUG
|
||||
log(LOG_DEBUG,0,"[callout, age_callout_queue] -- time (%d)", ptr->time);
|
||||
#endif /* IGMP_DEBUG */
|
||||
in_callout = 0; return;
|
||||
}
|
||||
while (Q) {
|
||||
p = Q;
|
||||
Q = Q->next;
|
||||
free(p);
|
||||
}
|
||||
in_callout = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
@ -86,20 +106,15 @@ int
|
||||
timer_setTimer(delay, action, data)
|
||||
int delay; /* number of units for timeout */
|
||||
cfunc_t action; /* function to be called on timeout */
|
||||
char *data; /* what to call the timeout function with */
|
||||
void *data; /* what to call the timeout function with */
|
||||
{
|
||||
struct timeout_q *ptr, *node, *prev;
|
||||
|
||||
if (in_callout)
|
||||
return -1;
|
||||
|
||||
in_callout = 1;
|
||||
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");
|
||||
in_callout = 0;
|
||||
return -1;
|
||||
}
|
||||
node->func = action;
|
||||
@ -129,7 +144,8 @@ timer_setTimer(delay, action, data)
|
||||
prev->next = node;
|
||||
ptr->time -= node->time;
|
||||
print_Q();
|
||||
in_callout = 0;
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
log(LOG_DEBUG, 0, "created timeout %d (#%d)", node->id, i);
|
||||
return node->id;
|
||||
} else {
|
||||
/* keep moving */
|
||||
@ -138,29 +154,46 @@ timer_setTimer(delay, action, data)
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
prev->next = node;
|
||||
}
|
||||
print_Q();
|
||||
in_callout = 0;
|
||||
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;
|
||||
|
||||
/* clears the associated timer */
|
||||
void
|
||||
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 (in_callout)
|
||||
return;
|
||||
if (!timer_id)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
in_callout = 1;
|
||||
|
||||
prev = ptr = Q;
|
||||
|
||||
/*
|
||||
@ -183,17 +216,22 @@ timer_clearTimer(timer_id)
|
||||
if (ptr->next != 0)
|
||||
(ptr->next)->time += ptr->time;
|
||||
|
||||
free(ptr->data);
|
||||
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();
|
||||
in_callout = 0;
|
||||
return;
|
||||
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();
|
||||
in_callout = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef IGMP_DEBUG
|
||||
@ -205,22 +243,8 @@ print_Q()
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
|
||||
for(ptr = Q; ptr; ptr = ptr->next)
|
||||
log(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time);
|
||||
IF_DEBUG(DEBUG_TIMEOUT)
|
||||
for (ptr = Q; ptr; ptr = ptr->next)
|
||||
log(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
|
||||
}
|
||||
#endif /* IGMP_DEBUG */
|
||||
int
|
||||
secs_remaining( timer_id)
|
||||
int timer_id;
|
||||
{
|
||||
struct timeout_q *ptr;
|
||||
int left=0;
|
||||
|
||||
for (ptr = Q; ptr && ptr->id != timer_id; ptr = ptr->next)
|
||||
left += ptr->time;
|
||||
|
||||
if (!ptr) /* not found */
|
||||
return 0;
|
||||
|
||||
return left + ptr->time;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Written by Bill Fenner, NRL, 1994
|
||||
*
|
||||
* $Id: cfparse.y,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* cfparse.y,v 3.8.4.30 1998/03/01 01:48:58 fenner Exp
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
@ -29,19 +29,23 @@ int yyparse __P((void));
|
||||
|
||||
static FILE *f;
|
||||
|
||||
extern int udp_socket;
|
||||
char *configfilename = _PATH_MROUTED_CONF;
|
||||
|
||||
extern int cache_lifetime;
|
||||
extern int max_prune_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 ifreq ifbuf[32];
|
||||
static struct ifconf ifc;
|
||||
|
||||
static struct uvif *v;
|
||||
|
||||
static int order;
|
||||
static int order, state;
|
||||
static int noflood = 0;
|
||||
static int rexmit = VIFF_REXMIT_PRUNES;
|
||||
|
||||
struct addrmask {
|
||||
u_int32 addr;
|
||||
@ -66,12 +70,17 @@ int numbounds = 0; /* Number of named boundaries */
|
||||
char *ptr;
|
||||
struct addrmask addrmask;
|
||||
u_int32 addr;
|
||||
struct vf_element *filterelem;
|
||||
};
|
||||
|
||||
%token CACHE_LIFETIME PRUNING
|
||||
%token CACHE_LIFETIME PRUNE_LIFETIME PRUNING BLACK_HOLE NOFLOOD
|
||||
%token PHYINT TUNNEL NAME
|
||||
%token DISABLE IGMPV1 SRCRT
|
||||
%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET
|
||||
%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
|
||||
@ -81,6 +90,7 @@ int numbounds = 0; /* Number of named boundaries */
|
||||
|
||||
%type <addr> interface addrname
|
||||
%type <addrmask> bound boundary addrmask
|
||||
%type <filterelem> filter filtlist filtelement filtelem
|
||||
|
||||
%start conf
|
||||
|
||||
@ -98,6 +108,8 @@ stmt : error
|
||||
|
||||
vifi_t vifi;
|
||||
|
||||
state++;
|
||||
|
||||
if (order)
|
||||
fatal("phyints must appear before tunnels");
|
||||
|
||||
@ -127,11 +139,9 @@ stmt : error
|
||||
fatal("Tunnel local address %s is not mine",
|
||||
inet_fmt($2, s1));
|
||||
|
||||
strncpy(ffr.ifr_name, ifr->ifr_name, IFNAMSIZ);
|
||||
if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
|
||||
fatal("ioctl SIOCGIFFLAGS on %s",ffr.ifr_name);
|
||||
if (ffr.ifr_flags & IFF_LOOPBACK)
|
||||
fatal("Tunnel local address %s is a loopback interface",
|
||||
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(&ifc, $3) != 0)
|
||||
@ -147,28 +157,25 @@ stmt : error
|
||||
inet_fmt($3, s1));
|
||||
} else if (!(v->uv_flags & VIFF_DISABLED)) {
|
||||
if (($3 & v->uv_subnetmask) == v->uv_subnet)
|
||||
fatal("Unnecessary tunnel to %s",
|
||||
inet_fmt($3,s1));
|
||||
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");
|
||||
|
||||
strncpy(ffr.ifr_name, ifr->ifr_name, IFNAMSIZ);
|
||||
if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
|
||||
fatal("ioctl SIOCGIFFLAGS on %s", ffr.ifr_name);
|
||||
|
||||
v = &uvifs[numvifs];
|
||||
v->uv_flags = VIFF_TUNNEL;
|
||||
v->uv_metric = DEFAULT_METRIC;
|
||||
v->uv_rate_limit= DEFAULT_TUN_RATE_LIMIT;
|
||||
v->uv_threshold = DEFAULT_THRESHOLD;
|
||||
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_subnet = 0;
|
||||
v->uv_subnetmask= 0;
|
||||
v->uv_subnetbcast= 0;
|
||||
v->uv_dst_addr = $3;
|
||||
strncpy(v->uv_name, ffr.ifr_name, IFNAMSIZ);
|
||||
v->uv_groups = NULL;
|
||||
v->uv_neighbors = NULL;
|
||||
v->uv_acl = NULL;
|
||||
v->uv_addrs = NULL;
|
||||
|
||||
if (!(ffr.ifr_flags & IFF_UP)) {
|
||||
v->uv_flags |= VIFF_DOWN;
|
||||
@ -177,17 +184,101 @@ stmt : error
|
||||
}
|
||||
tunnelmods
|
||||
{
|
||||
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;
|
||||
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;
|
||||
|
||||
}
|
||||
| PRUNING BOOLEAN { pruning = $2; }
|
||||
| CACHE_LIFETIME NUMBER { cache_lifetime = $2;
|
||||
max_prune_lifetime = cache_lifetime * 2;
|
||||
| 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);
|
||||
}
|
||||
@ -223,6 +314,16 @@ tunnelmods : /* empty */
|
||||
;
|
||||
|
||||
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"); }
|
||||
;
|
||||
|
||||
@ -273,6 +374,20 @@ ifmod : mod
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
@ -293,6 +408,15 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
|
||||
|
||||
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);
|
||||
@ -323,6 +447,122 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
@ -365,6 +605,9 @@ bound : boundary { $$ = $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);
|
||||
@ -377,6 +620,35 @@ boundary : ADDRMASK {
|
||||
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
|
||||
@ -442,7 +714,6 @@ next_word()
|
||||
{
|
||||
static char buf[1024];
|
||||
static char *p=NULL;
|
||||
extern FILE *f;
|
||||
char *q;
|
||||
|
||||
while (1) {
|
||||
@ -481,45 +752,75 @@ next_word()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
if (!strcmp(q,"cache_lifetime"))
|
||||
return CACHE_LIFETIME;
|
||||
if (!strcmp(q,"pruning"))
|
||||
return PRUNING;
|
||||
if (!strcmp(q,"phyint"))
|
||||
return PHYINT;
|
||||
if (!strcmp(q,"tunnel"))
|
||||
return TUNNEL;
|
||||
if (!strcmp(q,"disable"))
|
||||
return DISABLE;
|
||||
if (!strcmp(q,"metric"))
|
||||
return METRIC;
|
||||
if (!strcmp(q,"threshold"))
|
||||
return THRESHOLD;
|
||||
if (!strcmp(q,"rate_limit"))
|
||||
return RATE_LIMIT;
|
||||
if (!strcmp(q,"srcrt") || !strcmp(q,"sourceroute"))
|
||||
return SRCRT;
|
||||
if (!strcmp(q,"boundary"))
|
||||
return BOUNDARY;
|
||||
if (!strcmp(q,"netmask"))
|
||||
return NETMASK;
|
||||
if (!strcmp(q,"igmpv1"))
|
||||
return IGMPV1;
|
||||
if (!strcmp(q,"altnet"))
|
||||
return ALTNET;
|
||||
if (!strcmp(q,"name"))
|
||||
return NAME;
|
||||
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;
|
||||
@ -528,8 +829,13 @@ yylex()
|
||||
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)) != 0xffffffff) {
|
||||
if ((addr = inet_parse(s1,1)) != 0xffffffff) {
|
||||
yylval.addrmask.mask = n;
|
||||
yylval.addrmask.addr = addr;
|
||||
return ADDRMASK;
|
||||
@ -537,7 +843,7 @@ yylex()
|
||||
/* fall through to returning STRING */
|
||||
}
|
||||
if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) {
|
||||
if ((addr = inet_parse(s1)) != 0xffffffff &&
|
||||
if ((addr = inet_parse(s1,4)) != 0xffffffff &&
|
||||
inet_valid_host(addr)) {
|
||||
yylval.addr = addr;
|
||||
return ADDR;
|
||||
@ -552,14 +858,6 @@ yylex()
|
||||
return NUMBER;
|
||||
}
|
||||
#ifdef SNMP
|
||||
if (!strcmp(q,"sysName"))
|
||||
return SYSNAM;
|
||||
if (!strcmp(q,"sysContact"))
|
||||
return SYSCONTACT;
|
||||
if (!strcmp(q,"sysVersion"))
|
||||
return SYSVERSION;
|
||||
if (!strcmp(q,"sysLocation"))
|
||||
return SYSLOCATION;
|
||||
if (*q=='"') {
|
||||
if (q[ strlen(q)-1 ]=='"')
|
||||
q[ strlen(q)-1 ]='\0'; /* trash trailing quote */
|
||||
@ -574,9 +872,8 @@ yylex()
|
||||
void
|
||||
config_vifs_from_file()
|
||||
{
|
||||
extern FILE *f;
|
||||
|
||||
order = 0;
|
||||
state = 0;
|
||||
numbounds = 0;
|
||||
lineno = 0;
|
||||
|
||||
@ -586,11 +883,6 @@ config_vifs_from_file()
|
||||
return;
|
||||
}
|
||||
|
||||
ifc.ifc_buf = (char *)ifbuf;
|
||||
ifc.ifc_len = sizeof(ifbuf);
|
||||
if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
|
||||
log(LOG_ERR, errno, "ioctl SIOCGIFCONF");
|
||||
|
||||
yyparse();
|
||||
|
||||
fclose(f);
|
||||
@ -623,7 +915,7 @@ ifconfaddr(ifcp, a)
|
||||
if (ifrp->ifr_addr.sa_family == AF_INET &&
|
||||
((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr == a)
|
||||
return (ifrp);
|
||||
#if (defined(BSD) && (BSD >= 199006))
|
||||
#ifdef HAVE_SA_LEN
|
||||
n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
|
||||
if (n < sizeof(*ifrp))
|
||||
++ifrp;
|
||||
|
@ -7,12 +7,18 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: config.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* config.c,v 3.8.4.10 1998/01/06 01:57:41 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
config.c,v 3.8.4.10 1998/01/06 01:57:41 fenner Exp $";
|
||||
#endif
|
||||
|
||||
struct ifconf ifc;
|
||||
|
||||
/*
|
||||
* Query the kernel to find network interfaces that are multicast-capable
|
||||
@ -21,28 +27,48 @@
|
||||
void
|
||||
config_vifs_from_kernel()
|
||||
{
|
||||
struct ifreq ifbuf[32];
|
||||
struct ifreq *ifrp, *ifend;
|
||||
struct ifconf ifc;
|
||||
register struct uvif *v;
|
||||
register vifi_t vifi;
|
||||
int n;
|
||||
u_int32 addr, mask, subnet;
|
||||
short flags;
|
||||
int num_ifreq = 32;
|
||||
|
||||
ifc.ifc_buf = (char *)ifbuf;
|
||||
ifc.ifc_len = sizeof(ifbuf);
|
||||
if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
|
||||
log(LOG_ERR, errno, "ioctl SIOCGIFCONF");
|
||||
ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
|
||||
ifc.ifc_buf = malloc(ifc.ifc_len);
|
||||
while (ifc.ifc_buf) {
|
||||
if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
|
||||
log(LOG_ERR, errno, "ioctl SIOCGIFCONF");
|
||||
|
||||
ifrp = (struct ifreq *)ifbuf;
|
||||
ifend = (struct ifreq *)((char *)ifbuf + ifc.ifc_len);
|
||||
/*
|
||||
* If the buffer was large enough to hold all the addresses
|
||||
* then break out, otherwise increase the buffer size and
|
||||
* try again.
|
||||
*
|
||||
* The only way to know that we definitely had enough space
|
||||
* is to know that there was enough space for at least one
|
||||
* more struct ifreq. ???
|
||||
*/
|
||||
if ((num_ifreq * sizeof(struct ifreq)) >=
|
||||
ifc.ifc_len + sizeof(struct ifreq))
|
||||
break;
|
||||
|
||||
num_ifreq *= 2;
|
||||
ifc.ifc_len = num_ifreq * sizeof(struct ifreq);
|
||||
ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
|
||||
}
|
||||
if (ifc.ifc_buf == NULL)
|
||||
log(LOG_ERR, 0, "config_vifs_from_kernel: ran out of memory");
|
||||
|
||||
ifrp = (struct ifreq *)ifc.ifc_buf;
|
||||
ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len);
|
||||
/*
|
||||
* Loop through all of the interfaces.
|
||||
*/
|
||||
for (; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) {
|
||||
struct ifreq ifr;
|
||||
#if BSD >= 199006
|
||||
#ifdef HAVE_SA_LEN
|
||||
n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
|
||||
if (n < sizeof(*ifrp))
|
||||
n = sizeof(*ifrp);
|
||||
@ -97,6 +123,12 @@ config_vifs_from_kernel()
|
||||
* one already installed in the uvifs array.
|
||||
*/
|
||||
for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
|
||||
if (strcmp(v->uv_name, ifr.ifr_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",
|
||||
@ -114,20 +146,15 @@ config_vifs_from_kernel()
|
||||
continue;
|
||||
}
|
||||
v = &uvifs[numvifs];
|
||||
v->uv_flags = 0;
|
||||
v->uv_metric = DEFAULT_METRIC;
|
||||
v->uv_rate_limit = DEFAULT_PHY_RATE_LIMIT;
|
||||
v->uv_threshold = DEFAULT_THRESHOLD;
|
||||
zero_vif(v, 0);
|
||||
v->uv_lcl_addr = addr;
|
||||
v->uv_rmt_addr = 0;
|
||||
v->uv_subnet = subnet;
|
||||
v->uv_subnetmask = mask;
|
||||
v->uv_subnetbcast = subnet | ~mask;
|
||||
strncpy(v->uv_name, ifr.ifr_name, IFNAMSIZ);
|
||||
v->uv_groups = NULL;
|
||||
v->uv_neighbors = NULL;
|
||||
v->uv_acl = NULL;
|
||||
v->uv_addrs = NULL;
|
||||
|
||||
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),
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: defs.h,v 3.8 1995/11/29 22:36:34 fenner Rel $
|
||||
* defs.h,v 3.8.4.15 1998/03/01 02:51:42 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
@ -26,12 +26,25 @@
|
||||
#ifdef SYSV
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#ifdef _AIX
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/igmp.h>
|
||||
#ifdef __FreeBSD__ /* sigh */
|
||||
#include <osreldate.h>
|
||||
#if __FreeBSD_version >= 220000
|
||||
#define rtentry kernel_rtentry
|
||||
#include <net/route.h>
|
||||
#undef rtentry
|
||||
#endif
|
||||
#endif
|
||||
#include <netinet/ip_mroute.h>
|
||||
#ifdef RSRR
|
||||
#include <sys/un.h>
|
||||
@ -52,6 +65,7 @@ typedef void (*cfunc_t) __P((void *));
|
||||
typedef void (*ihfunc_t) __P((int, fd_set *));
|
||||
|
||||
#include "dvmrp.h"
|
||||
#include "igmpv2.h"
|
||||
#include "vif.h"
|
||||
#include "route.h"
|
||||
#include "prune.h"
|
||||
@ -71,21 +85,17 @@ typedef void (*ihfunc_t) __P((int, fd_set *));
|
||||
|
||||
#define TIMER_INTERVAL ROUTE_MAX_REPORT_DELAY
|
||||
|
||||
#define VENDOR_CODE 1 /* Get a new vendor code if you make significant
|
||||
* changes to mrouted. */
|
||||
|
||||
#define PROTOCOL_VERSION 3 /* increment when packet format/content changes */
|
||||
#define MROUTED_VERSION 9 /* not in DVMRP packets at all */
|
||||
|
||||
#define MROUTED_VERSION 8 /* increment on local changes or bug fixes, */
|
||||
/* reset to 0 whever PROTOCOL_VERSION increments */
|
||||
#define DVMRP_CONSTANT 0x000eff00 /* constant portion of 'group' field */
|
||||
|
||||
#define MROUTED_LEVEL ((MROUTED_VERSION << 8) | PROTOCOL_VERSION | \
|
||||
((NF_PRUNE | NF_GENID | NF_MTRACE) << 16) | \
|
||||
(VENDOR_CODE << 24))
|
||||
#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 */
|
||||
@ -109,7 +119,10 @@ typedef void (*ihfunc_t) __P((int, fd_set *));
|
||||
#define bcopy(a, b, c) memcpy(b, a, c)
|
||||
#define bzero(s, n) memset((s), 0, (n))
|
||||
#define setlinebuf(s) setvbuf(s, NULL, _IOLBF, 0)
|
||||
#define signal(s,f) sigset(s,f)
|
||||
#endif
|
||||
|
||||
#if defined(_AIX) || (defined(BSD) && (BSD >= 199103))
|
||||
#define HAVE_SA_LEN
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -127,10 +140,27 @@ extern u_int32 allrtrs_group;
|
||||
extern u_int32 dvmrp_group;
|
||||
extern u_int32 dvmrp_genid;
|
||||
|
||||
#define DEFAULT_DEBUG 2 /* default if "-d" given without value */
|
||||
#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 u_char pruning;
|
||||
extern int did_final_init;
|
||||
|
||||
extern int routes_changed;
|
||||
extern int delay_change_reports;
|
||||
@ -160,81 +190,134 @@ extern char * sys_errlist[];
|
||||
#define MRT_DEL_VIF DVMRP_DEL_VIF
|
||||
#define MRT_ADD_MFC DVMRP_ADD_MFC
|
||||
#define MRT_DEL_MFC DVMRP_DEL_MFC
|
||||
#endif
|
||||
|
||||
#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 *, ...));
|
||||
extern int register_input_handler __P((int fd, ihfunc_t func));
|
||||
extern int register_input_handler __P((int, ihfunc_t));
|
||||
|
||||
/* igmp.c */
|
||||
extern void init_igmp __P((void));
|
||||
extern void accept_igmp __P((int recvlen));
|
||||
extern void send_igmp __P((u_int32 src, u_int32 dst, int type,
|
||||
int code, u_int32 group,
|
||||
int datalen));
|
||||
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 age_callout_queue __P((void));
|
||||
extern int timer_setTimer __P((int delay, cfunc_t action,
|
||||
char *data));
|
||||
extern void timer_clearTimer __P((int timer_id));
|
||||
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 origin, u_int32 mask,
|
||||
u_int metric, u_int32 src,
|
||||
vifi_t vifi));
|
||||
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 src, u_int32 dst,
|
||||
char *p, int datalen,
|
||||
u_int32 level));
|
||||
extern void accept_report __P((u_int32 src, u_int32 dst,
|
||||
char *p, int datalen,
|
||||
u_int32 level));
|
||||
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 which_routes, vifi_t vifi,
|
||||
u_int32 dst));
|
||||
extern void report_to_all_neighbors __P((int which_routes));
|
||||
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 add_vif_to_routes __P((vifi_t vifi));
|
||||
extern void delete_vif_from_routes __P((vifi_t vifi));
|
||||
extern void delete_neighbor_from_routes __P((u_int32 addr,
|
||||
vifi_t vifi));
|
||||
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));
|
||||
extern void start_route_updates __P((void));
|
||||
|
||||
/* 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 vifi_t find_vif __P((u_int32 src, u_int32 dst));
|
||||
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 *fp));
|
||||
extern void dump_vifs __P((FILE *));
|
||||
extern void stop_all_vifs __P((void));
|
||||
extern struct listaddr *neighbor_info __P((vifi_t vifi, u_int32 addr));
|
||||
extern void accept_group_report __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group, int r_type));
|
||||
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 int update_neighbor __P((vifi_t vifi, u_int32 addr,
|
||||
int msgtype, char *p, int datalen,
|
||||
u_int32 level));
|
||||
extern void accept_neighbor_request __P((u_int32 src, u_int32 dst));
|
||||
extern void accept_neighbor_request2 __P((u_int32 src,
|
||||
u_int32 dst));
|
||||
extern void accept_neighbors __P((u_int32 src, u_int32 dst,
|
||||
u_char *p, int datalen, u_int32 level));
|
||||
extern void accept_neighbors2 __P((u_int32 src, u_int32 dst,
|
||||
u_char *p, int datalen, u_int32 level));
|
||||
extern void accept_leave_message __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group));
|
||||
extern void accept_membership_query __P((u_int32 src, u_int32 dst,
|
||||
u_int32 group, int tmo));
|
||||
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));
|
||||
@ -243,75 +326,84 @@ extern void config_vifs_from_kernel __P((void));
|
||||
extern void config_vifs_from_file __P((void));
|
||||
|
||||
/* inet.c */
|
||||
extern int inet_valid_host __P((u_int32 naddr));
|
||||
extern int inet_valid_subnet __P((u_int32 nsubnet, u_int32 nmask));
|
||||
extern char * inet_fmt __P((u_int32 addr, char *s));
|
||||
extern char * inet_fmts __P((u_int32 addr, u_int32 mask, char *s));
|
||||
extern u_int32 inet_parse __P((char *s));
|
||||
extern int inet_cksum __P((u_short *addr, u_int len));
|
||||
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 add_table_entry __P((u_int32 origin, u_int32 mcastgrp));
|
||||
extern void del_table_entry __P((struct rtentry *r,
|
||||
u_int32 mcastgrp, u_int del_flag));
|
||||
extern void update_table_entry __P((struct rtentry *r));
|
||||
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 accept_prune __P((u_int32 src, u_int32 dst, char *p,
|
||||
int datalen));
|
||||
extern void steal_sources __P((struct rtentry *rt));
|
||||
extern void reset_neighbor_state __P((vifi_t vifi, u_int32 addr));
|
||||
extern int grplst_mem __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern int scoped_addr __P((vifi_t vifi, u_int32 addr));
|
||||
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 *fp2));
|
||||
extern void update_lclgrp __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern void delete_lclgrp __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern void chkgrp_graft __P((vifi_t vifi, u_int32 mcastgrp));
|
||||
extern void accept_graft __P((u_int32 src, u_int32 dst, char *p,
|
||||
int datalen));
|
||||
extern void accept_g_ack __P((u_int32 src, u_int32 dst, char *p,
|
||||
int datalen));
|
||||
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 src, u_int32 dst,
|
||||
u_int32 group, char *data, u_int no,
|
||||
int datalen));
|
||||
extern void accept_mtrace __P((u_int32, u_int32,
|
||||
u_int32, char *, u_int, int));
|
||||
|
||||
/* kern.c */
|
||||
extern void k_set_rcvbuf __P((int bufsize));
|
||||
extern void k_hdr_include __P((int bool));
|
||||
extern void k_set_ttl __P((int t));
|
||||
extern void k_set_loop __P((int l));
|
||||
extern void k_set_if __P((u_int32 ifa));
|
||||
extern void k_join __P((u_int32 grp, u_int32 ifa));
|
||||
extern void k_leave __P((u_int32 grp, u_int32 ifa));
|
||||
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 vifi, struct uvif *v));
|
||||
extern void k_del_vif __P((vifi_t vifi));
|
||||
extern void k_add_rg __P((u_int32 origin, struct gtable *g));
|
||||
extern int k_del_rg __P((u_int32 origin, struct gtable *g));
|
||||
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 rtentry * snmp_find_route __P(());
|
||||
extern struct gtable * find_grp __P(());
|
||||
extern struct stable * find_grp_src __P(());
|
||||
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;
|
||||
extern int find_src_grp __P((u_int32 src, u_int32 mask,
|
||||
u_int32 grp));
|
||||
|
||||
/* rsrr.c */
|
||||
extern void rsrr_init __P((void));
|
||||
extern void rsrr_read __P((int f, fd_set *rfd));
|
||||
extern void rsrr_clean __P((void));
|
||||
extern void rsrr_cache_send __P((struct gtable *gt, int notify));
|
||||
extern void rsrr_cache_clean __P((struct gtable *gt));
|
||||
extern void rsrr_cache_send __P((struct gtable *, int));
|
||||
extern void rsrr_cache_clean __P((struct gtable *));
|
||||
#endif /* RSRR */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: dvmrp.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* dvmrp.h,v 3.8.4.5 1997/11/18 23:25:57 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -152,13 +152,8 @@
|
||||
#define LEAF_CONFIRMATION_TIME 200 /* time to consider subnet a leaf */
|
||||
|
||||
#define NEIGHBOR_PROBE_INTERVAL 10 /* periodic neighbor probe interval */
|
||||
#define NEIGHBOR_EXPIRE_TIME 140 /* time to consider neighbor gone */
|
||||
|
||||
#define GROUP_QUERY_INTERVAL 125 /* periodic group query interval */
|
||||
#define GROUP_EXPIRE_TIME 270 /* time to consider group gone */
|
||||
#define LEAVE_EXPIRE_TIME 3 /* " " after receiving a leave */
|
||||
/* Note: LEAVE_EXPIRE_TIME should ideally be shorter, but the resolution of
|
||||
* the timer in mrouted doesn't allow us to make it any shorter. */
|
||||
#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 */
|
||||
@ -166,9 +161,11 @@
|
||||
|
||||
#define MAX_RATE_LIMIT 100000 /* max rate limit */
|
||||
#define DEFAULT_PHY_RATE_LIMIT 0 /* default phyint rate limit */
|
||||
#define DEFAULT_TUN_RATE_LIMIT 500 /* default tunnel 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 OLD_AGE_THRESHOLD 2
|
||||
#define PRUNE_REXMIT_VAL 3 /* initial time for prune rexmission*/
|
||||
|
225
usr.sbin/mrouted/icmp.c
Normal file
225
usr.sbin/mrouted/icmp.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -7,12 +7,16 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: igmp.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* igmp.c,v 3.8.4.19 1998/01/06 01:57:43 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
igmp.c,v 3.8.4.19 1998/01/06 01:57:43 fenner Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
@ -29,7 +33,6 @@ u_int32 dvmrp_genid; /* IGMP generation id */
|
||||
* Local function definitions.
|
||||
*/
|
||||
/* u_char promoted to u_int */
|
||||
static char * packet_kind __P((u_int type, u_int code));
|
||||
static int igmp_log_level __P((u_int type, u_int code));
|
||||
|
||||
/*
|
||||
@ -48,17 +51,23 @@ init_igmp()
|
||||
log(LOG_ERR, errno, "IGMP socket");
|
||||
|
||||
k_hdr_include(TRUE); /* include IP header when sending */
|
||||
k_set_rcvbuf(48*1024); /* lots of input buffering */
|
||||
k_set_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;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
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_tos = 0;
|
||||
ip->ip_off = 0;
|
||||
ip->ip_p = IPPROTO_IGMP;
|
||||
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);
|
||||
@ -74,29 +83,33 @@ init_igmp()
|
||||
#define PIM_GRAFT 6
|
||||
#define PIM_GRAFT_ACK 7
|
||||
|
||||
static char *
|
||||
packet_kind(type, code)
|
||||
char *
|
||||
igmp_packet_kind(type, code)
|
||||
u_int type, code;
|
||||
{
|
||||
static char unknown[20];
|
||||
|
||||
switch (type) {
|
||||
case IGMP_HOST_MEMBERSHIP_QUERY: return "membership query ";
|
||||
case IGMP_HOST_MEMBERSHIP_REPORT: return "membership report ";
|
||||
case IGMP_HOST_NEW_MEMBERSHIP_REPORT: return "new member report ";
|
||||
case IGMP_HOST_LEAVE_MESSAGE: return "leave message ";
|
||||
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_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: return "unknown DVMRP msg ";
|
||||
default:
|
||||
sprintf(unknown, "unknown DVMRP %3d ", code);
|
||||
return unknown;
|
||||
}
|
||||
case IGMP_PIM:
|
||||
switch (code) {
|
||||
@ -108,11 +121,57 @@ packet_kind(type, code)
|
||||
case PIM_ASSERT: return "PIM Assert ";
|
||||
case PIM_GRAFT: return "PIM Graft ";
|
||||
case PIM_GRAFT_ACK: return "PIM Graft-Ack ";
|
||||
default: return "unknown PIM msg ";
|
||||
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: return "unknown IGMP msg ";
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +212,11 @@ accept_igmp(recvlen)
|
||||
}
|
||||
|
||||
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)",
|
||||
@ -171,22 +234,23 @@ accept_igmp(recvlen)
|
||||
return;
|
||||
}
|
||||
|
||||
IF_DEBUG(DEBUG_PKT|igmp_debug_kind(igmp->igmp_type, igmp->igmp_code))
|
||||
log(LOG_DEBUG, 0, "RECV %s from %-15s to %s",
|
||||
packet_kind(igmp->igmp_type, igmp->igmp_code),
|
||||
igmp_packet_kind(igmp->igmp_type, igmp->igmp_code),
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
|
||||
switch (igmp->igmp_type) {
|
||||
|
||||
case IGMP_HOST_MEMBERSHIP_QUERY:
|
||||
case IGMP_MEMBERSHIP_QUERY:
|
||||
accept_membership_query(src, dst, group, igmp->igmp_code);
|
||||
return;
|
||||
|
||||
case IGMP_HOST_MEMBERSHIP_REPORT:
|
||||
case IGMP_HOST_NEW_MEMBERSHIP_REPORT:
|
||||
case IGMP_V1_MEMBERSHIP_REPORT:
|
||||
case IGMP_V2_MEMBERSHIP_REPORT:
|
||||
accept_group_report(src, dst, group, igmp->igmp_type);
|
||||
return;
|
||||
|
||||
case IGMP_HOST_LEAVE_MESSAGE:
|
||||
case IGMP_V2_LEAVE_GROUP:
|
||||
accept_leave_message(src, dst, group);
|
||||
return;
|
||||
|
||||
@ -297,8 +361,45 @@ igmp_log_level(type, code)
|
||||
|
||||
/*
|
||||
* Construct an IGMP message in the output packet buffer. The caller may
|
||||
* have already placed data in that buffer, of length 'datalen'. Then send
|
||||
* the message from the interface with IP address 'src' to destination 'dst'.
|
||||
* 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)
|
||||
@ -308,26 +409,13 @@ send_igmp(src, dst, type, code, group, datalen)
|
||||
int datalen;
|
||||
{
|
||||
struct sockaddr_in sdst;
|
||||
struct ip *ip;
|
||||
struct igmp *igmp;
|
||||
int setloop;
|
||||
int setloop = 0;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
build_igmp(src, dst, type, code, group, datalen);
|
||||
|
||||
if (IN_MULTICAST(ntohl(dst))) {
|
||||
k_set_if(src);
|
||||
if (type != IGMP_DVMRP) {
|
||||
if (type != IGMP_DVMRP || dst == allhosts_group) {
|
||||
setloop = 1;
|
||||
k_set_loop(TRUE);
|
||||
}
|
||||
@ -335,11 +423,12 @@ send_igmp(src, dst, type, code, group, datalen)
|
||||
|
||||
bzero(&sdst, sizeof(sdst));
|
||||
sdst.sin_family = AF_INET;
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#ifdef HAVE_SA_LEN
|
||||
sdst.sin_len = sizeof(sdst);
|
||||
#endif
|
||||
sdst.sin_addr.s_addr = dst;
|
||||
if (sendto(igmp_socket, send_buf, ip->ip_len, 0,
|
||||
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();
|
||||
@ -352,6 +441,8 @@ send_igmp(src, dst, type, code, group, datalen)
|
||||
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",
|
||||
packet_kind(type, code), inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
igmp_packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" :
|
||||
inet_fmt(src, s1), inet_fmt(dst, s2));
|
||||
}
|
||||
|
42
usr.sbin/mrouted/igmpv2.h
Normal file
42
usr.sbin/mrouted/igmpv2.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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
|
@ -7,12 +7,16 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: inet.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* inet.c,v 3.8.4.2 1998/01/06 01:57:44 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
inet.c,v 3.8.4.2 1998/01/06 01:57:44 fenner Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
@ -155,15 +159,17 @@ inet_fmts(addr, mask, s)
|
||||
* with "255.255.255.255".)
|
||||
*/
|
||||
u_int32
|
||||
inet_parse(s)
|
||||
inet_parse(s,n)
|
||||
char *s;
|
||||
int n;
|
||||
{
|
||||
u_int32 a = 0;
|
||||
u_int a0, a1, a2, a3;
|
||||
u_int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
|
||||
int i;
|
||||
char c;
|
||||
|
||||
if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 ||
|
||||
a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
|
||||
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;
|
||||
|
145
usr.sbin/mrouted/ipip.c
Normal file
145
usr.sbin/mrouted/ipip.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
@ -7,19 +7,58 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: kern.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* kern.c,v 3.8.4.10 1998/01/06 02:00:51 fenner Exp
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
kern.c,v 3.8.4.10 1998/01/06 02:00:51 fenner Exp $";
|
||||
#endif
|
||||
|
||||
void k_set_rcvbuf(bufsize)
|
||||
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)
|
||||
log(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize);
|
||||
(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);
|
||||
}
|
||||
|
||||
|
||||
@ -37,12 +76,15 @@ void k_hdr_include(bool)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -141,7 +183,7 @@ void k_add_vif(vifi, v)
|
||||
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF,
|
||||
(char *)&vc, sizeof(vc)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF");
|
||||
log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF on vif %d", vifi);
|
||||
}
|
||||
|
||||
|
||||
@ -150,7 +192,7 @@ void k_del_vif(vifi)
|
||||
{
|
||||
if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF,
|
||||
(char *)&vifi, sizeof(vifi)) < 0)
|
||||
log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF");
|
||||
log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF on vif %d", vifi);
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +225,8 @@ void k_add_rg(origin, g)
|
||||
#ifdef DEBUG_MFC
|
||||
md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp);
|
||||
#endif
|
||||
log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC");
|
||||
log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC",
|
||||
inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +257,8 @@ int k_del_rg(origin, g)
|
||||
#ifdef DEBUG_MFC
|
||||
md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp);
|
||||
#endif
|
||||
log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC");
|
||||
log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC of (%s %s)",
|
||||
inet_fmt(origin, s1), inet_fmt(g->gt_mcastgrp, s2));
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -239,3 +283,63 @@ int k_get_version()
|
||||
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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $
|
||||
* main.c,v 3.8.4.29 1998/03/01 01:49:00 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -33,8 +33,8 @@
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $";
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
main.c,v 3.8.4.29 1998/03/01 01:49:00 fenner Exp $";
|
||||
#endif
|
||||
|
||||
extern char *configfilename;
|
||||
@ -45,11 +45,21 @@ static char dumpfilename[] = _PATH_MROUTED_DUMP;
|
||||
static char cachefilename[] = _PATH_MROUTED_CACHE;
|
||||
static char genidfilename[] = _PATH_MROUTED_GENID;
|
||||
|
||||
static int haveterminal = 1;
|
||||
int did_final_init = 0;
|
||||
|
||||
static int sighandled = 0;
|
||||
#define GOT_SIGINT 0x01
|
||||
#define GOT_SIGHUP 0x02
|
||||
#define GOT_SIGUSR1 0x04
|
||||
#define GOT_SIGUSR2 0x08
|
||||
|
||||
int cache_lifetime = DEFAULT_CACHE_LIFETIME;
|
||||
int max_prune_lifetime = DEFAULT_CACHE_LIFETIME * 2;
|
||||
int prune_lifetime = AVERAGE_PRUNE_LIFETIME;
|
||||
|
||||
int debug = 0;
|
||||
u_char pruning = 1; /* Enable pruning by default */
|
||||
char *progname;
|
||||
time_t mrouted_init_time;
|
||||
|
||||
#ifdef SNMP
|
||||
#define NHANDLERS 34
|
||||
@ -63,16 +73,48 @@ static struct ihandler {
|
||||
} ihandlers[NHANDLERS];
|
||||
static int nhandlers = 0;
|
||||
|
||||
static struct debugname {
|
||||
char *name;
|
||||
int level;
|
||||
int nchars;
|
||||
} debugnames[] = {
|
||||
{ "packet", DEBUG_PKT, 2 },
|
||||
{ "pkt", DEBUG_PKT, 3 },
|
||||
{ "pruning", DEBUG_PRUNE, 1 },
|
||||
{ "prunes", DEBUG_PRUNE, 1 },
|
||||
{ "routing", DEBUG_ROUTE, 1 },
|
||||
{ "routes", DEBUG_ROUTE, 1 },
|
||||
{ "route_detail", DEBUG_RTDETAIL, 6 },
|
||||
{ "rtdetail", DEBUG_RTDETAIL, 2 },
|
||||
{ "peers", DEBUG_PEER, 2 },
|
||||
{ "neighbors", DEBUG_PEER, 1 },
|
||||
{ "cache", DEBUG_CACHE, 1 },
|
||||
{ "timeout", DEBUG_TIMEOUT, 1 },
|
||||
{ "callout", DEBUG_TIMEOUT, 2 },
|
||||
{ "interface", DEBUG_IF, 2 },
|
||||
{ "vif", DEBUG_IF, 1 },
|
||||
{ "membership", DEBUG_MEMBER, 1 },
|
||||
{ "groups", DEBUG_MEMBER, 1 },
|
||||
{ "traceroute", DEBUG_TRACE, 2 },
|
||||
{ "mtrace", DEBUG_TRACE, 2 },
|
||||
{ "igmp", DEBUG_IGMP, 1 },
|
||||
{ "icmp", DEBUG_ICMP, 2 },
|
||||
{ "rsrr", DEBUG_RSRR, 2 },
|
||||
{ "3", 0xffffffff, 1 } /* compat. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
static void fasttimer __P((int));
|
||||
static void done __P((int));
|
||||
static void dump __P((int));
|
||||
static void fdump __P((int));
|
||||
static void cdump __P((int));
|
||||
static void restart __P((int));
|
||||
static void timer __P((void));
|
||||
static void final_init __P((void *));
|
||||
static void fasttimer __P((void *));
|
||||
static void timer __P((void *));
|
||||
static void dump __P((void));
|
||||
static void dump_version __P((FILE *));
|
||||
static void fdump __P((void));
|
||||
static void cdump __P((void));
|
||||
static void restart __P((void));
|
||||
static void handler __P((int));
|
||||
static void cleanup __P((void));
|
||||
static void resetlogging __P((void *));
|
||||
|
||||
@ -99,14 +141,15 @@ main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
register int recvlen;
|
||||
register int omask;
|
||||
int dummy;
|
||||
FILE *fp;
|
||||
struct timeval tv;
|
||||
struct timeval tv, difftime, curtime, lasttime, *timeout;
|
||||
u_int32 prev_genid;
|
||||
int vers;
|
||||
fd_set rfds, readers;
|
||||
int nfds, n, i;
|
||||
int nfds, n, i, secs;
|
||||
extern char todaysversion[];
|
||||
struct sigaction sa;
|
||||
#ifdef SNMP
|
||||
struct timeval timeout, *tvp = &timeout;
|
||||
struct timeval sched, *svp = &sched, now, *nvp = &now;
|
||||
@ -116,16 +159,57 @@ main(argc, argv)
|
||||
setlinebuf(stderr);
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "must be root\n");
|
||||
fprintf(stderr, "mrouted: must be root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname)
|
||||
progname++;
|
||||
else
|
||||
progname = argv[0];
|
||||
|
||||
argv++, argc--;
|
||||
while (argc > 0 && *argv[0] == '-') {
|
||||
if (strcmp(*argv, "-d") == 0) {
|
||||
if (argc > 1 && isdigit(*(argv + 1)[0])) {
|
||||
if (argc > 1 && *(argv + 1)[0] != '-') {
|
||||
char *p,*q;
|
||||
int i, len;
|
||||
struct debugname *d;
|
||||
|
||||
argv++, argc--;
|
||||
debug = atoi(*argv);
|
||||
debug = 0;
|
||||
p = *argv; q = NULL;
|
||||
while (p) {
|
||||
q = strchr(p, ',');
|
||||
if (q)
|
||||
*q++ = '\0';
|
||||
len = strlen(p);
|
||||
for (i = 0, d = debugnames;
|
||||
i < sizeof(debugnames) / sizeof(debugnames[0]);
|
||||
i++, d++)
|
||||
if (len >= d->nchars && strncmp(d->name, p, len) == 0)
|
||||
break;
|
||||
if (i == sizeof(debugnames) / sizeof(debugnames[0])) {
|
||||
int j = 0xffffffff;
|
||||
int k = 0;
|
||||
fprintf(stderr, "Valid debug levels: ");
|
||||
for (i = 0, d = debugnames;
|
||||
i < sizeof(debugnames) / sizeof(debugnames[0]);
|
||||
i++, d++) {
|
||||
if ((j & d->level) == d->level) {
|
||||
if (k++)
|
||||
putc(',', stderr);
|
||||
fputs(d->name, stderr);
|
||||
j &= ~d->level;
|
||||
}
|
||||
}
|
||||
putc('\n', stderr);
|
||||
goto usage;
|
||||
}
|
||||
debug |= d->level;
|
||||
p = q;
|
||||
}
|
||||
} else
|
||||
debug = DEFAULT_DEBUG;
|
||||
} else if (strcmp(*argv, "-c") == 0) {
|
||||
@ -135,7 +219,7 @@ main(argc, argv)
|
||||
} else
|
||||
goto usage;
|
||||
} else if (strcmp(*argv, "-p") == 0) {
|
||||
pruning = 0;
|
||||
log(LOG_WARNING, 0, "disabling pruning is no longer supported");
|
||||
#ifdef SNMP
|
||||
} else if (strcmp(*argv, "-P") == 0) {
|
||||
if (argc > 1 && isdigit(*(argv + 1)[0])) {
|
||||
@ -151,40 +235,27 @@ main(argc, argv)
|
||||
|
||||
if (argc > 0) {
|
||||
usage: fprintf(stderr,
|
||||
"usage: mrouted [-p] [-c configfile] [-d [debug_level]]\n");
|
||||
"usage: mrouted [-p] [-c configfile] [-d [debug_level][,debug_level...]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (debug == 0) {
|
||||
/*
|
||||
* Detach from the terminal
|
||||
*/
|
||||
int t;
|
||||
if (debug != 0) {
|
||||
struct debugname *d;
|
||||
char c;
|
||||
int tmpd = debug;
|
||||
|
||||
if (fork()) exit(0);
|
||||
(void)close(0);
|
||||
(void)close(1);
|
||||
(void)close(2);
|
||||
(void)open("/", 0);
|
||||
(void)dup2(0, 1);
|
||||
(void)dup2(0, 2);
|
||||
#ifdef SYSV
|
||||
(void)setpgrp();
|
||||
#else
|
||||
#ifdef TIOCNOTTY
|
||||
t = open("/dev/tty", 2);
|
||||
if (t >= 0) {
|
||||
(void)ioctl(t, TIOCNOTTY, (char *)0);
|
||||
(void)close(t);
|
||||
fprintf(stderr, "debug level 0x%x ", debug);
|
||||
c = '(';
|
||||
for (d = debugnames; d < debugnames +
|
||||
sizeof(debugnames) / sizeof(debugnames[0]); d++) {
|
||||
if ((tmpd & d->level) == d->level) {
|
||||
tmpd &= ~d->level;
|
||||
fprintf(stderr, "%c%s", c, d->name);
|
||||
c = ',';
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (setsid() < 0)
|
||||
perror("setsid");
|
||||
#endif
|
||||
#endif
|
||||
fprintf(stderr, ")\n");
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "debug level %u\n", debug);
|
||||
|
||||
#ifdef LOG_DAEMON
|
||||
(void)openlog("mrouted", LOG_PID, LOG_DAEMON);
|
||||
@ -192,10 +263,9 @@ usage: fprintf(stderr,
|
||||
#else
|
||||
(void)openlog("mrouted", LOG_PID);
|
||||
#endif
|
||||
sprintf(versionstring, "mrouted version %d.%d",
|
||||
PROTOCOL_VERSION, MROUTED_VERSION);
|
||||
sprintf(versionstring, "mrouted version %s", todaysversion);
|
||||
|
||||
log(LOG_NOTICE, 0, "%s", versionstring);
|
||||
log(LOG_DEBUG, 0, "%s starting", versionstring);
|
||||
|
||||
#ifdef SYSV
|
||||
srand48(time(NULL));
|
||||
@ -223,14 +293,27 @@ usage: fprintf(stderr,
|
||||
(void) fclose(fp);
|
||||
}
|
||||
|
||||
/* Start up the log rate-limiter */
|
||||
resetlogging(NULL);
|
||||
|
||||
callout_init();
|
||||
init_igmp();
|
||||
init_icmp();
|
||||
init_ipip();
|
||||
init_routes();
|
||||
init_ktable();
|
||||
k_init_dvmrp(); /* enable DVMRP routing in kernel */
|
||||
|
||||
#ifndef OLD_KERNEL
|
||||
/*
|
||||
* Unfortunately, you can't k_get_version() unless you've
|
||||
* k_init_dvmrp()'d. Now that we want to move the
|
||||
* k_init_dvmrp() to later in the initialization sequence,
|
||||
* we have to do the disgusting hack of initializing,
|
||||
* getting the version, then stopping the kernel multicast
|
||||
* forwarding.
|
||||
*/
|
||||
k_init_dvmrp();
|
||||
vers = k_get_version();
|
||||
k_stop_dvmrp();
|
||||
/*XXX
|
||||
* This function must change whenever the kernel version changes
|
||||
*/
|
||||
@ -261,33 +344,14 @@ usage: fprintf(stderr,
|
||||
rsrr_init();
|
||||
#endif /* RSRR */
|
||||
|
||||
#if defined(__STDC__) || defined(__GNUC__)
|
||||
/*
|
||||
* Allow cleanup if unexpected exit. Apparently some architectures
|
||||
* have a kernel bug where closing the socket doesn't do an
|
||||
* ip_mrouter_done(), so we attempt to do it on exit.
|
||||
*/
|
||||
atexit(cleanup);
|
||||
#endif
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "pruning %s\n", pruning ? "on" : "off");
|
||||
|
||||
fp = fopen(pidfilename, "w");
|
||||
if (fp != NULL) {
|
||||
fprintf(fp, "%d\n", (int)getpid());
|
||||
(void) fclose(fp);
|
||||
}
|
||||
|
||||
(void)signal(SIGALRM, fasttimer);
|
||||
|
||||
(void)signal(SIGHUP, restart);
|
||||
(void)signal(SIGTERM, done);
|
||||
(void)signal(SIGINT, done);
|
||||
(void)signal(SIGUSR1, fdump);
|
||||
(void)signal(SIGUSR2, cdump);
|
||||
if (debug != 0)
|
||||
(void)signal(SIGQUIT, dump);
|
||||
sa.sa_handler = handler;
|
||||
sa.sa_flags = 0; /* Interrupt system calls */
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGUSR1, &sa, NULL);
|
||||
sigaction(SIGUSR2, &sa, NULL);
|
||||
|
||||
FD_ZERO(&readers);
|
||||
FD_SET(igmp_socket, &readers);
|
||||
@ -298,30 +362,82 @@ usage: fprintf(stderr,
|
||||
nfds = ihandlers[i].fd + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install the vifs in the kernel as late as possible in the
|
||||
* initialization sequence.
|
||||
IF_DEBUG(DEBUG_IF)
|
||||
dump_vifs(stderr);
|
||||
IF_DEBUG(DEBUG_ROUTE)
|
||||
dump_routes(stderr);
|
||||
|
||||
/* schedule first timer interrupt */
|
||||
timer_setTimer(1, fasttimer, NULL);
|
||||
timer_setTimer(TIMER_INTERVAL, timer, NULL);
|
||||
|
||||
if (debug == 0) {
|
||||
/*
|
||||
* Detach from the terminal
|
||||
*/
|
||||
int t;
|
||||
|
||||
haveterminal = 0;
|
||||
if (fork()) exit(0);
|
||||
(void)close(0);
|
||||
(void)close(1);
|
||||
(void)close(2);
|
||||
(void)open("/", 0);
|
||||
(void)dup2(0, 1);
|
||||
(void)dup2(0, 2);
|
||||
#if defined(SYSV) || defined(linux)
|
||||
(void)setpgrp();
|
||||
#else
|
||||
#ifdef TIOCNOTTY
|
||||
t = open("/dev/tty", 2);
|
||||
if (t >= 0) {
|
||||
(void)ioctl(t, TIOCNOTTY, (char *)0);
|
||||
(void)close(t);
|
||||
}
|
||||
#else
|
||||
if (setsid() < 0)
|
||||
perror("setsid");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
fp = fopen(pidfilename, "w");
|
||||
if (fp != NULL) {
|
||||
fprintf(fp, "%d\n", (int)getpid());
|
||||
(void) fclose(fp);
|
||||
}
|
||||
|
||||
/* XXX HACK
|
||||
* This will cause black holes for the first few seconds after startup,
|
||||
* since we are exchanging routes but not actually forwarding.
|
||||
* However, it eliminates much of the startup transient.
|
||||
*
|
||||
* It's possible that we can set a flag which says not to report any
|
||||
* routes (just accept reports) until this timer fires, and then
|
||||
* do a report_to_all_neighbors(ALL_ROUTES) immediately before
|
||||
* turning on DVMRP.
|
||||
*/
|
||||
init_installvifs();
|
||||
|
||||
if (debug >= 2) dump(0);
|
||||
|
||||
/* Start up the log rate-limiter */
|
||||
resetlogging(NULL);
|
||||
|
||||
(void)alarm(1); /* schedule first timer interrupt */
|
||||
timer_setTimer(10, final_init, NULL);
|
||||
|
||||
/*
|
||||
* Main receive loop.
|
||||
*/
|
||||
dummy = 0;
|
||||
difftime.tv_usec = 0;
|
||||
gettimeofday(&curtime, NULL);
|
||||
lasttime = curtime;
|
||||
for(;;) {
|
||||
#ifdef SYSV
|
||||
sigset_t block, oblock;
|
||||
#endif
|
||||
bcopy((char *)&readers, (char *)&rfds, sizeof(rfds));
|
||||
secs = timer_nextTimer();
|
||||
if (secs == -1)
|
||||
timeout = NULL;
|
||||
else {
|
||||
timeout = &tv;
|
||||
timeout->tv_sec = secs;
|
||||
timeout->tv_usec = 0;
|
||||
}
|
||||
#ifdef SNMP
|
||||
gettimeofday(nvp, 0);
|
||||
THIS IS BROKEN
|
||||
if (nvp->tv_sec > svp->tv_sec
|
||||
|| (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
|
||||
alarmTimer(nvp);
|
||||
@ -344,51 +460,121 @@ usage: fprintf(stderr,
|
||||
if (block == 1)
|
||||
tvp = NULL; /* block without timeout */
|
||||
if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0)
|
||||
#else
|
||||
if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0)
|
||||
#endif
|
||||
{
|
||||
if (errno != EINTR) /* SIGALRM is expected */
|
||||
if (sighandled) {
|
||||
if (sighandled & GOT_SIGINT) {
|
||||
sighandled &= ~GOT_SIGINT;
|
||||
break;
|
||||
}
|
||||
if (sighandled & GOT_SIGHUP) {
|
||||
sighandled &= ~GOT_SIGHUP;
|
||||
restart();
|
||||
}
|
||||
if (sighandled & GOT_SIGUSR1) {
|
||||
sighandled &= ~GOT_SIGUSR1;
|
||||
fdump();
|
||||
}
|
||||
if (sighandled & GOT_SIGUSR2) {
|
||||
sighandled &= ~GOT_SIGUSR2;
|
||||
cdump();
|
||||
}
|
||||
}
|
||||
if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
|
||||
if (errno != EINTR)
|
||||
log(LOG_WARNING, errno, "select failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(igmp_socket, &rfds)) {
|
||||
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
|
||||
0, NULL, &dummy);
|
||||
if (recvlen < 0) {
|
||||
if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
|
||||
continue;
|
||||
if (n > 0) {
|
||||
if (FD_ISSET(igmp_socket, &rfds)) {
|
||||
recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
|
||||
0, NULL, &dummy);
|
||||
if (recvlen < 0) {
|
||||
if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
|
||||
continue;
|
||||
}
|
||||
accept_igmp(recvlen);
|
||||
}
|
||||
#ifdef SYSV
|
||||
(void)sigemptyset(&block);
|
||||
(void)sigaddset(&block, SIGALRM);
|
||||
if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
|
||||
log(LOG_ERR, errno, "sigprocmask");
|
||||
#else
|
||||
omask = sigblock(sigmask(SIGALRM));
|
||||
#endif
|
||||
accept_igmp(recvlen);
|
||||
#ifdef SYSV
|
||||
(void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
|
||||
#else
|
||||
(void)sigsetmask(omask);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < nhandlers; i++) {
|
||||
if (FD_ISSET(ihandlers[i].fd, &rfds)) {
|
||||
(*ihandlers[i].func)(ihandlers[i].fd, &rfds);
|
||||
for (i = 0; i < nhandlers; i++) {
|
||||
if (FD_ISSET(ihandlers[i].fd, &rfds)) {
|
||||
(*ihandlers[i].func)(ihandlers[i].fd, &rfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SNMP
|
||||
THIS IS BROKEN
|
||||
snmp_read(&rfds);
|
||||
snmp_timeout(); /* poll */
|
||||
#endif
|
||||
/*
|
||||
* Handle timeout queue.
|
||||
*
|
||||
* If select + packet processing took more than 1 second,
|
||||
* or if there is a timeout pending, age the timeout queue.
|
||||
*
|
||||
* If not, collect usec in difftime to make sure that the
|
||||
* time doesn't drift too badly.
|
||||
*
|
||||
* If the timeout handlers took more than 1 second,
|
||||
* age the timeout queue again. XXX This introduces the
|
||||
* potential for infinite loops!
|
||||
*/
|
||||
do {
|
||||
/*
|
||||
* If the select timed out, then there's no other
|
||||
* activity to account for and we don't need to
|
||||
* call gettimeofday.
|
||||
*/
|
||||
if (n == 0) {
|
||||
curtime.tv_sec = lasttime.tv_sec + secs;
|
||||
curtime.tv_usec = lasttime.tv_usec;
|
||||
n = -1; /* don't do this next time through the loop */
|
||||
} else
|
||||
gettimeofday(&curtime, NULL);
|
||||
difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
|
||||
difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
|
||||
while (difftime.tv_usec > 1000000) {
|
||||
difftime.tv_sec++;
|
||||
difftime.tv_usec -= 1000000;
|
||||
}
|
||||
if (difftime.tv_usec < 0) {
|
||||
difftime.tv_sec--;
|
||||
difftime.tv_usec += 1000000;
|
||||
}
|
||||
lasttime = curtime;
|
||||
if (secs == 0 || difftime.tv_sec > 0)
|
||||
age_callout_queue(difftime.tv_sec);
|
||||
secs = -1;
|
||||
} while (difftime.tv_sec > 0);
|
||||
}
|
||||
log(LOG_NOTICE, 0, "%s exiting", versionstring);
|
||||
cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
final_init(i)
|
||||
void *i;
|
||||
{
|
||||
char *s = (char *)i;
|
||||
|
||||
log(LOG_NOTICE, 0, "%s%s", versionstring, s ? s : "");
|
||||
if (s)
|
||||
free(s);
|
||||
|
||||
k_init_dvmrp(); /* enable DVMRP routing in kernel */
|
||||
|
||||
/*
|
||||
* Install the vifs in the kernel as late as possible in the
|
||||
* initialization sequence.
|
||||
*/
|
||||
init_installvifs();
|
||||
|
||||
time(&mrouted_init_time);
|
||||
did_final_init = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* routine invoked every second. Its main goal is to cycle through
|
||||
@ -399,7 +585,7 @@ usage: fprintf(stderr,
|
||||
*/
|
||||
static void
|
||||
fasttimer(i)
|
||||
int i;
|
||||
void *i;
|
||||
{
|
||||
static unsigned int tlast;
|
||||
static unsigned int nsent;
|
||||
@ -428,12 +614,8 @@ fasttimer(i)
|
||||
}
|
||||
tlast = t;
|
||||
}
|
||||
if ((t % TIMER_INTERVAL) == 0)
|
||||
timer();
|
||||
|
||||
age_callout_queue();/* Advance the timer for the callout queue
|
||||
for groups */
|
||||
alarm(1);
|
||||
timer_setTimer(1, fasttimer, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -453,7 +635,7 @@ fasttimer(i)
|
||||
* avoid unwanted synchronization with other routers.
|
||||
*/
|
||||
|
||||
static u_long virtual_time = 0;
|
||||
u_long virtual_time = 0;
|
||||
|
||||
|
||||
/*
|
||||
@ -462,13 +644,14 @@ static u_long virtual_time = 0;
|
||||
* virtual interface data structures.
|
||||
*/
|
||||
static void
|
||||
timer()
|
||||
timer(i)
|
||||
void *i;
|
||||
{
|
||||
age_routes(); /* Advance the timers in the route entries */
|
||||
age_vifs(); /* Advance the timers for neighbors */
|
||||
age_table_entry(); /* Advance the timers for the cache entries */
|
||||
|
||||
if (virtual_time % GROUP_QUERY_INTERVAL == 0) {
|
||||
if (virtual_time % IGMP_QUERY_INTERVAL == 0) {
|
||||
/*
|
||||
* Time to query the local group memberships on all subnets
|
||||
* for which this router is the elected querier.
|
||||
@ -507,21 +690,10 @@ timer()
|
||||
* Advance virtual time
|
||||
*/
|
||||
virtual_time += TIMER_INTERVAL;
|
||||
timer_setTimer(TIMER_INTERVAL, timer, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* On termination, let everyone know we're going away.
|
||||
*/
|
||||
static void
|
||||
done(i)
|
||||
int i;
|
||||
{
|
||||
log(LOG_NOTICE, 0, "%s exiting", versionstring);
|
||||
cleanup();
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup()
|
||||
{
|
||||
@ -534,7 +706,36 @@ cleanup()
|
||||
#endif /* RSRR */
|
||||
expire_all_routes();
|
||||
report_to_all_neighbors(ALL_ROUTES);
|
||||
k_stop_dvmrp();
|
||||
if (did_final_init)
|
||||
k_stop_dvmrp();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal handler. Take note of the fact that the signal arrived
|
||||
* so that the main loop can take care of it.
|
||||
*/
|
||||
static void
|
||||
handler(sig)
|
||||
int sig;
|
||||
{
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
sighandled |= GOT_SIGINT;
|
||||
break;
|
||||
|
||||
case SIGHUP:
|
||||
sighandled |= GOT_SIGHUP;
|
||||
break;
|
||||
|
||||
case SIGUSR1:
|
||||
sighandled |= GOT_SIGUSR1;
|
||||
break;
|
||||
|
||||
case SIGUSR2:
|
||||
sighandled |= GOT_SIGUSR2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,25 +744,39 @@ cleanup()
|
||||
* Dump internal data structures to stderr.
|
||||
*/
|
||||
static void
|
||||
dump(i)
|
||||
int i;
|
||||
dump()
|
||||
{
|
||||
dump_vifs(stderr);
|
||||
dump_routes(stderr);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_version(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
fprintf(fp, "%s ", versionstring);
|
||||
if (did_final_init)
|
||||
fprintf(fp, "up %s",
|
||||
scaletime(t - mrouted_init_time));
|
||||
else
|
||||
fprintf(fp, "(not yet initialized)");
|
||||
fprintf(fp, " %s\n", ctime(&t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump internal data structures to a file.
|
||||
*/
|
||||
static void
|
||||
fdump(i)
|
||||
int i;
|
||||
fdump()
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(dumpfilename, "w");
|
||||
if (fp != NULL) {
|
||||
dump_version(fp);
|
||||
dump_vifs(fp);
|
||||
dump_routes(fp);
|
||||
(void) fclose(fp);
|
||||
@ -573,13 +788,13 @@ fdump(i)
|
||||
* Dump local cache contents to a file.
|
||||
*/
|
||||
static void
|
||||
cdump(i)
|
||||
int i;
|
||||
cdump()
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(cachefilename, "w");
|
||||
if (fp != NULL) {
|
||||
dump_version(fp);
|
||||
dump_cache(fp);
|
||||
(void) fclose(fp);
|
||||
}
|
||||
@ -590,52 +805,42 @@ cdump(i)
|
||||
* Restart mrouted
|
||||
*/
|
||||
static void
|
||||
restart(i)
|
||||
int i;
|
||||
restart()
|
||||
{
|
||||
register int omask;
|
||||
#ifdef SYSV
|
||||
sigset_t block, oblock;
|
||||
#endif
|
||||
char *s;
|
||||
|
||||
log(LOG_NOTICE, 0, "%s restart", versionstring);
|
||||
s = (char *)malloc(sizeof(" restart"));
|
||||
if (s == NULL)
|
||||
log(LOG_ERR, 0, "out of memory");
|
||||
strcpy(s, " restart");
|
||||
|
||||
/*
|
||||
* reset all the entries
|
||||
*/
|
||||
#ifdef SYSV
|
||||
(void)sigemptyset(&block);
|
||||
(void)sigaddset(&block, SIGALRM);
|
||||
if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
|
||||
log(LOG_ERR, errno, "sigprocmask");
|
||||
#else
|
||||
omask = sigblock(sigmask(SIGALRM));
|
||||
#endif
|
||||
free_all_prunes();
|
||||
free_all_routes();
|
||||
free_all_callouts();
|
||||
stop_all_vifs();
|
||||
k_stop_dvmrp();
|
||||
close(igmp_socket);
|
||||
close(udp_socket);
|
||||
did_final_init = 0;
|
||||
|
||||
/*
|
||||
* start processing again
|
||||
*/
|
||||
dvmrp_genid++;
|
||||
pruning = 1;
|
||||
|
||||
init_igmp();
|
||||
init_routes();
|
||||
init_ktable();
|
||||
init_vifs();
|
||||
k_init_dvmrp(); /* enable DVMRP routing in kernel */
|
||||
init_installvifs();
|
||||
/*XXX Schedule final_init() as main does? */
|
||||
final_init(s);
|
||||
|
||||
#ifdef SYSV
|
||||
(void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
|
||||
#else
|
||||
(void)sigsetmask(omask);
|
||||
#endif
|
||||
/* schedule timer interrupts */
|
||||
timer_setTimer(1, fasttimer, NULL);
|
||||
timer_setTimer(TIMER_INTERVAL, timer, NULL);
|
||||
}
|
||||
|
||||
#define LOG_MAX_MSGS 20 /* if > 20/minute then shut up for a while */
|
||||
@ -661,6 +866,61 @@ resetlogging(arg)
|
||||
timer_setTimer(nxttime, resetlogging, narg);
|
||||
}
|
||||
|
||||
char *
|
||||
scaletime(t)
|
||||
u_long t;
|
||||
{
|
||||
#define SCALETIMEBUFLEN 20
|
||||
static char buf1[20];
|
||||
static char buf2[20];
|
||||
static char *buf = buf1;
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
if (buf == buf1)
|
||||
buf = buf2;
|
||||
else
|
||||
buf = buf1;
|
||||
|
||||
/* XXX snprintf */
|
||||
sprintf(p, "%2ld:%02ld:%02ld", t / 3600, (t % 3600) / 60, t % 60);
|
||||
p[SCALETIMEBUFLEN - 1] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef RINGBUFFER
|
||||
#define NLOGMSGS 10000
|
||||
#define LOGMSGSIZE 200
|
||||
char *logmsg[NLOGMSGS];
|
||||
static int logmsgno = 0;
|
||||
|
||||
void
|
||||
printringbuf()
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
f = fopen("/var/tmp/mrouted.log", "a");
|
||||
if (f == NULL) {
|
||||
log(LOG_ERR, errno, "can't open /var/tmp/mrouted.log");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
fprintf(f, "--------------------------------------------\n");
|
||||
|
||||
i = (logmsgno + 1) % NLOGMSGS;
|
||||
|
||||
while (i != logmsgno) {
|
||||
if (*logmsg[i]) {
|
||||
fprintf(f, "%s\n", logmsg[i]);
|
||||
*logmsg[i] = '\0';
|
||||
}
|
||||
i = (i + 1) % NLOGMSGS;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Log errors and other messages to the system log daemon and to stderr,
|
||||
* according to the severity of the message and the current debug level.
|
||||
@ -673,9 +933,11 @@ log(int severity, int syserr, char *format, ...)
|
||||
va_list ap;
|
||||
static char fmt[211] = "warning - ";
|
||||
char *msg;
|
||||
char tbuf[20];
|
||||
struct timeval now;
|
||||
struct tm *thyme;
|
||||
#ifdef RINGBUFFER
|
||||
static int ringbufinit = 0;
|
||||
#endif
|
||||
|
||||
va_start(ap, format);
|
||||
#else
|
||||
@ -687,11 +949,14 @@ log(severity, syserr, format, va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
static char fmt[211] = "warning - ";
|
||||
static char fmt[311] = "warning - ";
|
||||
char *msg;
|
||||
char tbuf[20];
|
||||
struct timeval now;
|
||||
struct tm *thyme;
|
||||
#ifdef RINGBUFFER
|
||||
static int ringbufinit = 0;
|
||||
#endif
|
||||
|
||||
va_start(ap);
|
||||
#endif
|
||||
@ -699,35 +964,66 @@ log(severity, syserr, format, va_alist)
|
||||
va_end(ap);
|
||||
msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
|
||||
|
||||
switch (debug) {
|
||||
case 0: break;
|
||||
case 1: if (severity > LOG_NOTICE) break;
|
||||
case 2: if (severity > LOG_INFO ) break;
|
||||
default:
|
||||
gettimeofday(&now,NULL);
|
||||
thyme = localtime(&now.tv_sec);
|
||||
strftime(tbuf, sizeof(tbuf), "%X.%%03d ", thyme);
|
||||
fprintf(stderr, tbuf, now.tv_usec / 1000);
|
||||
fprintf(stderr, "%s", msg);
|
||||
if (syserr == 0)
|
||||
fprintf(stderr, "\n");
|
||||
else if (syserr < sys_nerr)
|
||||
fprintf(stderr, ": %s\n", sys_errlist[syserr]);
|
||||
else
|
||||
fprintf(stderr, ": errno %d\n", syserr);
|
||||
}
|
||||
#ifdef RINGBUFFER
|
||||
if (!ringbufinit) {
|
||||
int i;
|
||||
|
||||
if (severity <= LOG_NOTICE) {
|
||||
if (log_nmsgs++ < LOG_MAX_MSGS) {
|
||||
if (syserr != 0) {
|
||||
errno = syserr;
|
||||
syslog(severity, "%s: %m", msg);
|
||||
} else
|
||||
syslog(severity, "%s", msg);
|
||||
for (i = 0; i < NLOGMSGS; i++) {
|
||||
logmsg[i] = malloc(LOGMSGSIZE);
|
||||
if (logmsg[i] == 0) {
|
||||
syslog(LOG_ERR, "out of memory");
|
||||
exit(-1);
|
||||
}
|
||||
*logmsg[i] = 0;
|
||||
}
|
||||
|
||||
if (severity <= LOG_ERR) exit(-1);
|
||||
ringbufinit = 1;
|
||||
}
|
||||
gettimeofday(&now,NULL);
|
||||
thyme = localtime(&now.tv_sec);
|
||||
sprintf(logmsg[logmsgno++], "%02d:%02d:%02d.%03ld %s err %d",
|
||||
thyme->tm_hour, thyme->tm_min, thyme->tm_sec,
|
||||
now.tv_usec / 1000, msg, syserr);
|
||||
logmsgno %= NLOGMSGS;
|
||||
if (severity <= LOG_NOTICE)
|
||||
#endif
|
||||
/*
|
||||
* Log to stderr if we haven't forked yet and it's a warning or worse,
|
||||
* or if we're debugging.
|
||||
*/
|
||||
if (haveterminal && (debug || severity <= LOG_WARNING)) {
|
||||
gettimeofday(&now,NULL);
|
||||
thyme = localtime(&now.tv_sec);
|
||||
if (!debug)
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour,
|
||||
thyme->tm_min, thyme->tm_sec, now.tv_usec / 1000, msg);
|
||||
if (syserr == 0)
|
||||
fprintf(stderr, "\n");
|
||||
else if (syserr < sys_nerr)
|
||||
fprintf(stderr, ": %s\n", sys_errlist[syserr]);
|
||||
else
|
||||
fprintf(stderr, ": errno %d\n", syserr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Always log things that are worse than warnings, no matter what
|
||||
* the log_nmsgs rate limiter says.
|
||||
* Only count things worse than debugging in the rate limiter
|
||||
* (since if you put daemon.debug in syslog.conf you probably
|
||||
* actually want to log the debugging messages so they shouldn't
|
||||
* be rate-limited)
|
||||
*/
|
||||
if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
|
||||
if (severity < LOG_DEBUG)
|
||||
log_nmsgs++;
|
||||
if (syserr != 0) {
|
||||
errno = syserr;
|
||||
syslog(severity, "%s: %m", msg);
|
||||
} else
|
||||
syslog(severity, "%s", msg);
|
||||
}
|
||||
|
||||
if (severity <= LOG_ERR) exit(-1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MFC
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Mapper for connections between MRouteD multicast routers.
|
||||
* Written by Pavel Curtis <Pavel@PARC.Xerox.Com>
|
||||
*
|
||||
* $Id: mapper.c,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* mapper.c,v 3.8.4.3 1998/01/06 01:57:47 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -32,6 +32,11 @@
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
mapper.c,v 3.8.4.3 1998/01/06 01:57:47 fenner Exp $";
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEOUT 2 /* How long to wait before retrying requests */
|
||||
#define DEFAULT_RETRIES 1 /* How many times to ask each router */
|
||||
|
||||
@ -844,13 +849,16 @@ int main(argc, argv)
|
||||
{
|
||||
int flood = FALSE, graph = FALSE;
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "must be root\n");
|
||||
fprintf(stderr, "map-mbone: must be root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init_igmp();
|
||||
setuid(getuid());
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
argv++, argc--;
|
||||
while (argc > 0 && argv[0][0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
@ -899,15 +907,13 @@ int main(argc, argv)
|
||||
if (debug)
|
||||
fprintf(stderr, "Debug level %u\n", debug);
|
||||
|
||||
init_igmp();
|
||||
|
||||
{ /* Find a good local address for us. */
|
||||
int udp;
|
||||
struct sockaddr_in addr;
|
||||
int addrlen = sizeof(addr);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#ifdef HAVE_SA_LEN
|
||||
addr.sin_len = sizeof addr;
|
||||
#endif
|
||||
addr.sin_addr.s_addr = dvmrp_group;
|
||||
|
@ -60,11 +60,8 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"@(#) $Id: mrinfo.c,v 3.8 1995/11/29 22:36:34 fenner Rel $";
|
||||
/* original rcsid:
|
||||
"@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)";
|
||||
*/
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
mrinfo.c,v 3.8.4.7 1998/03/01 03:05:20 fenner Exp $";
|
||||
#endif
|
||||
|
||||
#include <netdb.h>
|
||||
@ -236,13 +233,14 @@ accept_neighbors2(src, dst, p, datalen, level)
|
||||
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) [version %d.%d", inet_fmt(src, s1), inet_name(src),
|
||||
level & 0xff, (level >> 8) & 0xff);
|
||||
if ((level >> 16) & NF_LEAF) { printf (",leaf"); }
|
||||
if ((level >> 16) & NF_PRUNE) { printf (",prune"); }
|
||||
if ((level >> 16) & NF_GENID) { printf (",genid"); }
|
||||
if ((level >> 16) & NF_MTRACE) { printf (",mtrace"); }
|
||||
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) {
|
||||
@ -333,12 +331,16 @@ main(argc, argv)
|
||||
char *host;
|
||||
int curaddr;
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "mrinfo: must be root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init_igmp();
|
||||
setuid(getuid());
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
argv++, argc--;
|
||||
while (argc > 0 && argv[0][0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
@ -386,8 +388,6 @@ main(argc, argv)
|
||||
if (debug)
|
||||
fprintf(stderr, "Debug level %u\n", debug);
|
||||
|
||||
init_igmp();
|
||||
|
||||
/* 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);
|
||||
@ -397,7 +397,7 @@ main(argc, argv)
|
||||
int addrlen = sizeof(addr);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#ifdef HAVE_SA_LEN
|
||||
addr.sin_len = sizeof addr;
|
||||
#endif
|
||||
addr.sin_addr.s_addr = target_addr;
|
||||
@ -492,7 +492,11 @@ main(argc, argv)
|
||||
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)",
|
||||
|
@ -1,14 +1,12 @@
|
||||
'\"COPYRIGHT 1989 by The Board of Trustees of Leland Stanford Junior University.
|
||||
'\"$Id: mrouted.8,v 3.8 1995/11/29 22:37:21 fenner Rel $
|
||||
'\"mrouted.8,v 3.8.4.5 1998/03/01 01:50:28 fenner Exp
|
||||
.TH MROUTED 8
|
||||
.UC 5
|
||||
.SH NAME
|
||||
mrouted \- IP multicast routing daemon
|
||||
.SH SYNOPSIS
|
||||
.B /etc/mrouted
|
||||
.B /usr/sbin/mrouted
|
||||
[
|
||||
.B \-p
|
||||
] [
|
||||
.B \-c
|
||||
.I config_file
|
||||
] [
|
||||
@ -39,17 +37,17 @@ routers that do not support IP multicasting,
|
||||
.I mrouted
|
||||
includes support for
|
||||
"tunnels", which are virtual point-to-point links between pairs of
|
||||
.IR mrouted s
|
||||
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.
|
||||
By default, the packets are encapsulated using the IP-in-IP protocol
|
||||
The packets are encapsulated using the IP-in-IP protocol
|
||||
(IP protocol number 4).
|
||||
Older versions of
|
||||
.I mrouted
|
||||
tunnel using IP source routing, which puts a heavy load on some
|
||||
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
|
||||
@ -75,136 +73,323 @@ to have access to more than one physical subnet
|
||||
in order to perform multicast forwarding.
|
||||
.br
|
||||
.ne 5
|
||||
.SH OPTIONS
|
||||
.TP 10
|
||||
.BI \-c " config_file"
|
||||
Specifies an alternate configuration file to read (normally /etc/mrouted.conf)
|
||||
.TP
|
||||
.BI \-d " debug_level"
|
||||
Turn on debugging;
|
||||
.I debug_level
|
||||
is a comma-seperated list of subsections to debug.
|
||||
.SH INVOCATION
|
||||
.PP
|
||||
If no "\-d" option is given, or if the debug level is specified as 0,
|
||||
If no "\-d" option is given,
|
||||
.I mrouted
|
||||
detaches from the invoking terminal. Otherwise, it remains attached to the
|
||||
invoking terminal and responsive to signals from that terminal. If "\-d" is
|
||||
given with no argument, the debug level defaults to 2. Regardless of the
|
||||
debug level,
|
||||
invoking terminal and responsive to signals from that terminal.
|
||||
Regardless of the debug level,
|
||||
.I mrouted
|
||||
always writes warning and error messages to the system
|
||||
log demon. Non-zero debug levels have the following effects:
|
||||
.IP "level 1"
|
||||
all syslog'ed messages are also printed to stderr.
|
||||
.IP "level 2"
|
||||
all level 1 messages plus notifications of "significant"
|
||||
events are printed to stderr.
|
||||
.IP "level 3"
|
||||
all level 2 messages plus notifications of all packet
|
||||
arrivals and departures are printed to stderr.
|
||||
log demon. The
|
||||
.I debug-level
|
||||
argument is a comma-seperated list of any of the following:
|
||||
.TP 13
|
||||
packet
|
||||
Display the type, source and destination of all packets sent or received.
|
||||
.TP
|
||||
pruning
|
||||
Display more information about prunes sent or received.
|
||||
.TP
|
||||
routing
|
||||
Display more information about routing update packets sent or received.
|
||||
.TP
|
||||
route_detail
|
||||
Display routing updates in excruciating detail. This is generally way too
|
||||
much information.
|
||||
.TP
|
||||
neighbors
|
||||
Display information about neighbor discovery.
|
||||
.TP
|
||||
cache
|
||||
Display insertions, deletions and refreshes of entries in
|
||||
the kernel forwarding cache.
|
||||
.TP
|
||||
timeout
|
||||
Debug timeouts and periodic processes.
|
||||
.TP
|
||||
interface
|
||||
Display information about interfaces and their configuration.
|
||||
.TP
|
||||
membership
|
||||
Display information about group memberships on physical interfaces.
|
||||
.TP
|
||||
traceroute
|
||||
Display information about multicast traceroute requests
|
||||
passing through this router.
|
||||
.TP
|
||||
igmp
|
||||
Display IGMP operation including group membership and querier election.
|
||||
.TP
|
||||
icmp
|
||||
Monitor ICMP handling.
|
||||
.TP
|
||||
rsrr
|
||||
Monitor RSRR operation.
|
||||
.PP
|
||||
Upon startup, mrouted writes its pid to the file /etc/mrouted.pid .
|
||||
Upon startup, mrouted writes its pid to the file /var/run/mrouted.pid .
|
||||
.SH CONFIGURATION
|
||||
.PP
|
||||
.I Mrouted
|
||||
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
|
||||
.IR mrouted s
|
||||
directly reachable
|
||||
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
|
||||
.IR mrouted s,
|
||||
tunnel links to other multicast routers,
|
||||
configuration commands may be placed in
|
||||
/etc/mrouted.conf (or an alternative file, specified by the "\-c" option).
|
||||
There are four types of configuration commands:
|
||||
.nf
|
||||
|
||||
phyint <local-addr> [disable] [metric <m>]
|
||||
[threshold <t>] [rate_limit <b>]
|
||||
[boundary (<boundary-name>|<scoped-addr>/<mask-len>)]
|
||||
[altnet <network>/<mask-len>]
|
||||
|
||||
tunnel <local-addr> <remote-addr> [metric <m>]
|
||||
[threshold <t>] [rate_limit <b>]
|
||||
[boundary (<boundary-name>|<scoped-addr>/<mask-len>)]
|
||||
|
||||
cache_lifetime <ct>
|
||||
|
||||
pruning <off/on>
|
||||
|
||||
name <boundary-name> <scoped-addr>/<mask-len>
|
||||
|
||||
.fi
|
||||
.PP
|
||||
The file format is free-form; whitespace (including newlines) is not
|
||||
significant.
|
||||
The
|
||||
.I boundary
|
||||
and
|
||||
.I altnet
|
||||
options may be specified as many times as necessary.
|
||||
The file begins with commands that apply to
|
||||
.IR mrouted 's
|
||||
overall operation or set defaults.
|
||||
.TP 15
|
||||
.BI cache_lifetime " 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
|
||||
.I 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).
|
||||
.TP
|
||||
.BI prune_lifetime " secs"
|
||||
Sepcifies, 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. mrouted <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.
|
||||
.TP
|
||||
.B noflood
|
||||
.I Mrouted
|
||||
uses a DVMRP optimization to prevent having to keep individual routing tables
|
||||
for each neighbor; part of this optimization is that
|
||||
.I mrouted
|
||||
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;
|
||||
.I mrouted
|
||||
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.
|
||||
.TP
|
||||
.BI rexmit_prunes " [on|off]"
|
||||
.IR Mrouted 's
|
||||
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.
|
||||
.TP
|
||||
.BI name " boundary-name scoped-addr/mask-len"
|
||||
Associates
|
||||
.I boundary-name
|
||||
with the boundary described by
|
||||
.IR scoped-addr/mask-len ,
|
||||
to help make interface configurations
|
||||
more readable and reduce repetition in the configuration file.
|
||||
.PP
|
||||
The phyint command can be used to disable multicast routing on the physical
|
||||
interface identified by local IP address <local-addr>, or to associate a
|
||||
non-default metric or threshold with the specified physical interface.
|
||||
The local IP address <local-addr> may be replaced by the
|
||||
interface name (e.g le0).
|
||||
The second section of the configuration file, which may optionally
|
||||
be empty, describes options that apply to physical interfaces.
|
||||
.TP 15
|
||||
.BI phyint " 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.
|
||||
.TP
|
||||
.B disable
|
||||
Disables multicast forwarding on this interface. By default,
|
||||
.I mrouted
|
||||
discovers all locally attached multicast capable interfaces and forwards
|
||||
on all of them.
|
||||
.TP
|
||||
.BI netmask " netmask"
|
||||
If the kernel's netmask does not accurately reflect
|
||||
the subnet (e.g. you're using proxy-ARP in lieu of IP subnetting), use the
|
||||
netmask command to describe the real netmask.
|
||||
.TP
|
||||
.BI altnet " network/mask-len"
|
||||
If a phyint is attached to multiple IP subnets, describe each additional subnet
|
||||
with the altnet keyword.
|
||||
Phyint commands must precede tunnel commands.
|
||||
with the altnet keyword. This command may be specified multiple times
|
||||
to describe multiple subnets.
|
||||
.TP
|
||||
.B igmpv1
|
||||
If there are any IGMPv1 routers on the phyint, use the \fBigmpv1\fP
|
||||
keyword to force \fImrouted\fP into IGMPv1 mode. All routers on the phyint
|
||||
must use the same version of IGMP.
|
||||
.TP
|
||||
.B force_leaf
|
||||
Force \fImrouted\fP to ignore other routers on this interface.
|
||||
mrouted will never send or accept neighbor probes or
|
||||
route reports on this interface.
|
||||
.PP
|
||||
The tunnel command can be used to establish a tunnel link between local
|
||||
IP address <local-addr> and remote IP address <remote-addr>, and to associate
|
||||
a non-default metric or threshold with that tunnel.
|
||||
The local IP address <local-addr> may be replaced by the
|
||||
interface name (e.g. le0). The remote IP address <remote-addr> may
|
||||
be replaced by a host name, if and only if the host name has a single
|
||||
IP address associated with it.
|
||||
The tunnel must be set
|
||||
up in the mrouted.conf files of both routers before it can be used.
|
||||
'\"For backwards compatibility with older
|
||||
'\".IR mrouted s,
|
||||
'\"the srcrt keyword specifies
|
||||
'\"encapsulation using IP source routing.
|
||||
In addition, the common vif commands described later may all be used on
|
||||
a phyint.
|
||||
.PP
|
||||
The cache_lifetime is a value that determines the amount of time that a
|
||||
cached multicast route stays in kernel before timing out. The value of this
|
||||
entry should lie between 300 (5 min) and 86400 (1 day). It defaults to 300.
|
||||
The third section of the configuration file, also optional, describes
|
||||
the configuration of any DVMRP tunnels this router might have.
|
||||
.TP 15
|
||||
.BI tunnel " local-addr|ifname remote-addr|remote-hostname"
|
||||
This command establishes a DVMRP tunnel between this host (on the interface
|
||||
described by
|
||||
.I local-addr
|
||||
or
|
||||
.IR ifname )
|
||||
and a remote host (identified by
|
||||
.I remote-addr
|
||||
or
|
||||
.IR 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.
|
||||
|
||||
Be careful that the unicast route to the remote address goes out the
|
||||
interface specified by the
|
||||
.I local-addr|ifname
|
||||
argument. Some UNIX
|
||||
kernels rewrite the source address of
|
||||
.IR mrouted 's
|
||||
packets on their way out to contain the address of the transmission
|
||||
interface. This is best assured via a static host route.
|
||||
.PP
|
||||
The pruning <off/on> option is provided for
|
||||
.IR mrouted
|
||||
to act as a non-pruning router. It is also possible to start
|
||||
.IR mrouted
|
||||
in a non-pruning mode using the "-p" option on the command line. It is
|
||||
expected that a router would be configured in this manner for test
|
||||
purposes only. The default mode is pruning enabled.
|
||||
.PP
|
||||
You may assign names to boundaries to make configuration easier with
|
||||
the name keyword. The boundary option on phyint or tunnel commands
|
||||
can accept either a name or a boundary.
|
||||
.PP
|
||||
The metric is the "cost" associated with sending a datagram on the given
|
||||
The common vif commands described below
|
||||
may all be used on tunnels or phyints.
|
||||
.TP 15
|
||||
.BI metric " 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
|
||||
.I mrouted
|
||||
cannot route along paths with a sum of metrics greater
|
||||
because DVMRP cannot route along paths with a sum of metrics greater
|
||||
than 31.
|
||||
.LP
|
||||
.TP
|
||||
.BI advert_metric " 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.
|
||||
.TP
|
||||
.BI threshold " 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 1.) The default threshold is 1.
|
||||
router decrements the TTL by exactly 1.) The default threshold is 1.
|
||||
.LP
|
||||
In general, all
|
||||
.IR mrouted s
|
||||
In general, all multicast routers
|
||||
connected to a particular subnet or tunnel should
|
||||
use the same metric and threshold for that subnet or tunnel.
|
||||
.PP
|
||||
.TP 15
|
||||
.BI rate_limit " 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 to 500Kbps on tunnels, and 0 (unlimited) on physical
|
||||
interfaces.
|
||||
.PP
|
||||
traffic. It defaults 0 (unlimited).
|
||||
.TP
|
||||
.BI boundary " 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.
|
||||
a name or a boundary spec. This command may be specified several times
|
||||
on an interface in order to describe multiple boundaries.
|
||||
.TP
|
||||
.B 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.
|
||||
.TP
|
||||
.B noflood
|
||||
As described above, but only applicable to this interface/tunnel.
|
||||
.TP
|
||||
.BI prune_lifetime " secs"
|
||||
As described above, but only applicable to this interface/tunnel.
|
||||
.TP
|
||||
.BI rexmit_prunes " [on|off]"
|
||||
As described above, but only applicable to this interface/tunnel.
|
||||
Recall that prune retransmission
|
||||
defaults to on on point-to-point links and tunnels, and off on
|
||||
multi-access links.
|
||||
.TP
|
||||
.B allow_nonpruners
|
||||
By default, \fImrouted\fP refuses to peer with DVMRP neighbors that
|
||||
do not claim to support pruning. This option allows such peerings
|
||||
on this interface.
|
||||
.TP
|
||||
.B 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.
|
||||
.TP
|
||||
.BI accept|deny " (route/mask-len [exact])+ [bidir]"
|
||||
The
|
||||
.B accept
|
||||
and
|
||||
.B deny
|
||||
commands allow rudimentary route filtering. The
|
||||
.B accept
|
||||
command causes
|
||||
.I mrouted
|
||||
to accept only the listed routes on the configured interface; the
|
||||
.B deny
|
||||
command causes
|
||||
.I mrouted
|
||||
to accept all but the listed routes.
|
||||
Only one of
|
||||
.B accept
|
||||
or
|
||||
.B deny
|
||||
commands may be used on a given interface.
|
||||
|
||||
The list of routes follows the
|
||||
.B accept
|
||||
or
|
||||
.B deny
|
||||
keyword. If the keyword
|
||||
.I exact
|
||||
follows a route, then only that route is matched; otherwise, that route
|
||||
and any more specific route is matched. For example,
|
||||
.B deny 0/0
|
||||
denys all routes, while
|
||||
.B deny 0/0 exact
|
||||
denys only the default route. The default route may also be specified
|
||||
with the
|
||||
.B default
|
||||
keyword.
|
||||
|
||||
The
|
||||
.B bidir
|
||||
keyword enables bidirectional route filtering; the filter will be applied
|
||||
to routes on both output and input. Without the
|
||||
.B bidir
|
||||
keyword,
|
||||
.B accept
|
||||
and
|
||||
.B deny
|
||||
filters are only applied on input. Poison reverse routes are never
|
||||
filtered out.
|
||||
.PP
|
||||
.I Mrouted
|
||||
will not initiate execution if it has fewer than two enabled vifs,
|
||||
@ -213,7 +398,7 @@ interface or a tunnel. It will log a warning if all of its vifs are
|
||||
tunnels; such an
|
||||
.I mrouted
|
||||
configuration would be better replaced by more
|
||||
direct tunnels (i.e., eliminate the middle man).
|
||||
direct tunnels (i.e. eliminate the middle man).
|
||||
.SH "EXAMPLE CONFIGURATION"
|
||||
.PP
|
||||
This is an example configuration for a mythical multicast router at a big
|
||||
@ -267,9 +452,9 @@ good-bye messages to all neighboring routers).
|
||||
.IP TERM
|
||||
same as INT
|
||||
.IP USR1
|
||||
dumps the internal routing tables to /usr/tmp/mrouted.dump.
|
||||
dumps the internal routing tables to /var/tmp/mrouted.dump.
|
||||
.IP USR2
|
||||
dumps the internal cache tables to /usr/tmp/mrouted.cache.
|
||||
dumps the internal cache tables to /var/tmp/mrouted.cache.
|
||||
.IP QUIT
|
||||
dumps the internal routing tables to stderr (only if
|
||||
.I mrouted
|
||||
@ -277,22 +462,23 @@ was invoked with a non-zero debug level).
|
||||
.PP
|
||||
For convenience in sending signals,
|
||||
.I mrouted
|
||||
writes its pid to /etc/mrouted.pid upon startup.
|
||||
writes its pid to /var/run/mrouted.pid upon startup.
|
||||
.bp
|
||||
.SH EXAMPLE
|
||||
.PP
|
||||
The routing tables look like this:
|
||||
The routing tables dumped in /var/tmp/mrouted.dump look like this:
|
||||
.nf
|
||||
.ft C
|
||||
|
||||
Virtual Interface Table
|
||||
Vif Local-Address Metric Thresh Flags
|
||||
0 36.2.0.8 subnet: 36.2 1 1 querier
|
||||
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 1 1 querier
|
||||
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
|
||||
@ -300,9 +486,9 @@ Virtual Interface Table
|
||||
pkts out: 3456
|
||||
|
||||
2 36.2.0.8 tunnel: 36.8.0.77 3 1
|
||||
peers: 36.8.0.77 (2.2)
|
||||
boundaries: 239.0.1
|
||||
: 239.1.2
|
||||
peers: 36.8.0.77 (3.255)
|
||||
boundaries: 239.0.1/24
|
||||
: 239.1.2/24
|
||||
pkts in: 34545433
|
||||
pkts out: 234342
|
||||
|
||||
@ -318,6 +504,7 @@ Multicast Routing Table (1136 entries)
|
||||
.
|
||||
|
||||
.fi
|
||||
.LP
|
||||
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
|
||||
@ -344,8 +531,9 @@ also maintains a copy of the kernel forwarding cache table. Entries
|
||||
are created and deleted by
|
||||
.I mrouted.
|
||||
.PP
|
||||
The cache tables look like this:
|
||||
The cache tables dumped in /var/tmp/mrouted.cache look like this:
|
||||
.nf
|
||||
.ft C
|
||||
|
||||
Multicast Routing Cache Table (147 entries)
|
||||
Origin Mcast-group CTmr Age Ptmr IVif Forwvifs
|
||||
@ -360,9 +548,11 @@ Multicast Routing Cache Table (147 entries)
|
||||
>198.106.194.22
|
||||
|
||||
.fi
|
||||
.LP
|
||||
Each entry is characterized by the origin subnet number and mask and the
|
||||
destination multicast group. 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.
|
||||
@ -377,21 +567,55 @@ subnet, a prune message is sent to the upstream router. They are
|
||||
indicated by a "P" after the vif number. 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 are no
|
||||
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.
|
||||
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 FILES
|
||||
/etc/mrouted.conf
|
||||
.br
|
||||
/etc/mrouted.pid
|
||||
.br
|
||||
/usr/tmp/mrouted.dump
|
||||
.br
|
||||
/usr/tmp/mrouted.cache
|
||||
.TP 25
|
||||
.B /etc/mrouted.conf
|
||||
.IR mrouted 's
|
||||
configuration file.
|
||||
.TP
|
||||
.B /var/run/mrouted.pid
|
||||
.IR mrouted 's
|
||||
PID file.
|
||||
.TP
|
||||
.B /var/tmp/mrouted.dump
|
||||
Where
|
||||
.I mrouted
|
||||
dumps its routing table when sent a SIGUSR1.
|
||||
.TP
|
||||
.B /var/tmp/mrouted.cache
|
||||
Where
|
||||
.I mrouted
|
||||
dumps its forwarding cache when sent a SIGUSR2.
|
||||
.PP
|
||||
Note that these files are located in the following places on pre-4.4BSD systems:
|
||||
.TP 25
|
||||
.B /etc/mrouted.conf
|
||||
.IR mrouted 's
|
||||
configuration file.
|
||||
.TP
|
||||
.B /etc/mrouted.pid
|
||||
.IR mrouted 's
|
||||
PID file.
|
||||
.TP
|
||||
.B /usr/tmp/mrouted.dump
|
||||
Where
|
||||
.I mrouted
|
||||
dumps its routing table when sent a SIGUSR1.
|
||||
.TP
|
||||
.B /usr/tmp/mrouted.cache
|
||||
Where
|
||||
.I mrouted
|
||||
dumps its forwarding cache when sent a SIGUSR2.
|
||||
.SH SEE ALSO
|
||||
.BR mrinfo (8) ,
|
||||
.BR mtrace (8) ,
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: mrouted.conf,v 3.8 1995/11/29 22:40:47 fenner Rel $
|
||||
# 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".
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: pathnames.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* pathnames.h,v 3.8 1995/11/29 22:36:57 fenner Rel
|
||||
*/
|
||||
|
||||
#define _PATH_MROUTED_CONF "/etc/mrouted.conf"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: prune.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* prune.h,v 3.8.4.5 1998/02/27 22:45:43 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -32,11 +32,14 @@ struct gtable {
|
||||
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 */
|
||||
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 */
|
||||
@ -52,6 +55,8 @@ 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 */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -62,9 +67,12 @@ 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.
|
||||
*/
|
||||
@ -137,7 +145,7 @@ struct tr_resp {
|
||||
};
|
||||
|
||||
#define VAL_TO_MASK(x, i) { \
|
||||
x = htonl(~((1 << (32 - (i))) - 1)); \
|
||||
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
@ -7,7 +7,7 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: route.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* route.h,v 3.8.4.6 1997/07/01 23:02:35 fenner Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -35,17 +35,18 @@ struct rtentry {
|
||||
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 */
|
||||
vifbitmap_t rt_leaves; /* subset of outgoing children vifs */
|
||||
u_int32 *rt_dominants; /* per vif dominant gateways */
|
||||
u_int32 *rt_subordinates; /* per vif subordinate gateways */
|
||||
u_int *rt_leaf_timers; /* per vif leaf confirmation timers */
|
||||
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_LEAF_TIMING 0x02 /* some leaf timers are running */
|
||||
#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)
|
||||
|
@ -34,21 +34,14 @@
|
||||
|
||||
#include "defs.h"
|
||||
#include <sys/param.h>
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_SA_LEN
|
||||
#include <stddef.h> /* for offsetof */
|
||||
#endif
|
||||
|
||||
/* Taken from prune.c */
|
||||
/*
|
||||
* checks for scoped multicast addresses
|
||||
*/
|
||||
#define GET_SCOPE(gt) { \
|
||||
register int _i; \
|
||||
if (((gt)->gt_mcastgrp & 0xff000000) == 0xef000000) \
|
||||
for (_i = 0; _i < numvifs; _i++) \
|
||||
if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
|
||||
VIFM_SET(_i, (gt)->gt_scope); \
|
||||
}
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#) $Id: \
|
||||
rsrr.c,v 3.8.4.8 1998/01/06 01:57:58 fenner Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exported variables.
|
||||
@ -72,6 +65,7 @@ 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));
|
||||
@ -90,7 +84,7 @@ rsrr_init()
|
||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
serv_addr.sun_family = AF_UNIX;
|
||||
strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
|
||||
#if (defined(BSD) && (BSD >= 199103))
|
||||
#ifdef HAVE_SA_LEN
|
||||
servlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
strlen(serv_addr.sun_path);
|
||||
serv_addr.sun_len = servlen;
|
||||
@ -101,18 +95,17 @@ rsrr_init()
|
||||
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)
|
||||
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 */
|
||||
void
|
||||
static void
|
||||
rsrr_read(f, rfd)
|
||||
int f;
|
||||
fd_set *rfd;
|
||||
{
|
||||
register int rsrr_recvlen;
|
||||
register int omask;
|
||||
|
||||
bzero((char *) &client_addr, sizeof(client_addr));
|
||||
rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
|
||||
@ -122,10 +115,7 @@ rsrr_read(f, rfd)
|
||||
log(LOG_ERR, errno, "RSRR recvfrom");
|
||||
return;
|
||||
}
|
||||
/* Use of omask taken from main() */
|
||||
omask = sigblock(sigmask(SIGALRM));
|
||||
rsrr_accept(rsrr_recvlen);
|
||||
(void)sigsetmask(omask);
|
||||
}
|
||||
|
||||
/* Accept a message from the reservation protocol and take
|
||||
@ -159,7 +149,8 @@ rsrr_accept(recvlen)
|
||||
switch (rsrr->type) {
|
||||
case RSRR_INITIAL_QUERY:
|
||||
/* Send Initial Reply to client */
|
||||
log(LOG_INFO, 0, "Received Initial Query\n");
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Received Initial Query\n");
|
||||
rsrr_accept_iq();
|
||||
break;
|
||||
case RSRR_ROUTE_QUERY:
|
||||
@ -172,7 +163,8 @@ rsrr_accept(recvlen)
|
||||
}
|
||||
/* Get the query */
|
||||
route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
|
||||
log(LOG_INFO, 0,
|
||||
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),
|
||||
@ -238,7 +230,8 @@ rsrr_accept_iq()
|
||||
sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
|
||||
|
||||
/* Send it. */
|
||||
log(LOG_INFO, 0, "Send RSRR Initial Reply");
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Send RSRR Initial Reply");
|
||||
rsrr_send(sendlen);
|
||||
}
|
||||
|
||||
@ -259,7 +252,7 @@ rsrr_accept_rq(route_query,flags,gt_notify)
|
||||
struct rsrr_rr *route_reply;
|
||||
struct gtable *gt,local_g;
|
||||
struct rtentry *r;
|
||||
int sendlen,i;
|
||||
int sendlen;
|
||||
u_long mcastgrp;
|
||||
|
||||
/* Set up message */
|
||||
@ -291,8 +284,10 @@ rsrr_accept_rq(route_query,flags,gt_notify)
|
||||
rsrr->flags = flags;
|
||||
/* Include the routing entry. */
|
||||
route_reply->in_vif = gt_notify->gt_route->rt_parent;
|
||||
route_reply->out_vif_bm = gt_notify->gt_grpmems;
|
||||
|
||||
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)) {
|
||||
|
||||
@ -331,17 +326,7 @@ rsrr_accept_rq(route_query,flags,gt_notify)
|
||||
gt->gt_route = r;
|
||||
|
||||
/* obtain the multicast group membership list */
|
||||
for (i = 0; i < numvifs; i++) {
|
||||
if (VIFM_ISSET(i, r->rt_children) &&
|
||||
!(VIFM_ISSET(i, r->rt_leaves)))
|
||||
VIFM_SET(i, gt->gt_grpmems);
|
||||
|
||||
if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
|
||||
VIFM_SET(i, gt->gt_grpmems);
|
||||
}
|
||||
|
||||
GET_SCOPE(gt);
|
||||
gt->gt_grpmems &= ~gt->gt_scope;
|
||||
determine_forwvifs(gt);
|
||||
|
||||
/* Include the routing entry. */
|
||||
route_reply->in_vif = gt->gt_route->rt_parent;
|
||||
@ -353,13 +338,9 @@ rsrr_accept_rq(route_query,flags,gt_notify)
|
||||
}
|
||||
}
|
||||
|
||||
if (gt_notify)
|
||||
log(LOG_INFO, 0, "Route Change: Send RSRR Route Reply");
|
||||
|
||||
else
|
||||
log(LOG_INFO, 0, "Send RSRR Route Reply");
|
||||
|
||||
log(LOG_INFO, 0, "for src %s dst %s in vif %d out vif %d\n",
|
||||
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);
|
||||
@ -419,6 +400,7 @@ rsrr_cache(gt,route_query)
|
||||
} 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);
|
||||
@ -441,6 +423,7 @@ rsrr_cache(gt,route_query)
|
||||
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);
|
||||
}
|
||||
@ -462,6 +445,7 @@ rsrr_cache_send(gt,notify)
|
||||
rcnp = >->gt_rsrr_cache;
|
||||
while ((rc = *rcnp) != NULL) {
|
||||
if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) {
|
||||
IF_DEBUG(DEBUG_RSRR)
|
||||
log(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
|
||||
rc->route_query.query_id,rc->client_addr.sun_path);
|
||||
/* Delete cache entry. */
|
||||
@ -480,7 +464,9 @@ rsrr_cache_clean(gt)
|
||||
{
|
||||
struct rsrr_cache *rc,*rc_next;
|
||||
|
||||
printf("cleaning cache for group %s\n",inet_fmt(gt->gt_mcastgrp, s1));
|
||||
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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,9 +7,91 @@
|
||||
* Leland Stanford Junior University.
|
||||
*
|
||||
*
|
||||
* $Id: vif.h,v 3.8 1995/11/29 22:36:57 fenner Rel $
|
||||
* 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
|
||||
*
|
||||
@ -18,30 +100,62 @@
|
||||
* (Note: all addresses, subnet numbers and masks are kept in NETWORK order.)
|
||||
*/
|
||||
struct uvif {
|
||||
u_short uv_flags; /* VIFF_ flags defined below */
|
||||
u_int uv_flags; /* VIFF_ flags defined below */
|
||||
u_char uv_metric; /* cost of this vif */
|
||||
u_int uv_rate_limit; /* rate limit on 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 0x0100 /* kernel state of interface */
|
||||
#define VIFF_DISABLED 0x0200 /* administratively disabled */
|
||||
#define VIFF_QUERIER 0x0400 /* I am the subnet's querier */
|
||||
#define VIFF_ONEWAY 0x0800 /* Maybe one way interface */
|
||||
#define VIFF_LEAF 0x1000 /* all neighbors are leaves */
|
||||
#define VIFF_IGMPV1 0x2000 /* Act as an IGMPv1 Router */
|
||||
#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;
|
||||
@ -56,23 +170,67 @@ struct vif_acl {
|
||||
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; /* neighbor creation time */
|
||||
u_int32 al_genid; /* generation id for neighbor */
|
||||
u_char al_pv; /* router protocol version */
|
||||
u_char al_mv; /* router mrouted version */
|
||||
u_long al_timerid; /* returned by set timer */
|
||||
u_long al_query; /* second query in case of leave */
|
||||
u_short al_old; /* time since heard old report */
|
||||
u_char al_flags; /* flags related to this 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 NF_LEAF 0x01 /* This neighbor is a leaf */
|
||||
#define NF_PRUNE 0x02 /* This neighbor understands prunes */
|
||||
#define NF_GENID 0x04 /* I supply genid & rtrlist in probe*/
|
||||
#define NF_MTRACE 0x08 /* I can understand mtrace requests */
|
||||
#define NBRF_LEAF 0x0001 /* This neighbor is a leaf */
|
||||
#define NBRF_GENID 0x0100 /* I know this neighbor's genid */
|
||||
#define NBRF_WAITING 0x0200 /* Waiting for peering to come up */
|
||||
#define NBRF_ONEWAY 0x0400 /* One-way peering */
|
||||
#define NBRF_TOOOLD 0x0800 /* Too old (policy decision) */
|
||||
#define NBRF_TOOMANYROUTES 0x1000 /* Neighbor is spouting routes */
|
||||
#define NBRF_NOTPRUNING 0x2000 /* Neighbor doesn't appear to prune */
|
||||
|
||||
/*
|
||||
* Don't peer with neighbors with any of these flags set
|
||||
*/
|
||||
#define NBRF_DONTPEER (NBRF_WAITING|NBRF_ONEWAY|NBRF_TOOOLD| \
|
||||
NBRF_TOOMANYROUTES|NBRF_NOTPRUNING)
|
||||
|
||||
#define NO_VIF ((vifi_t)MAXVIFS) /* An invalid vif index */
|
||||
|
Loading…
Reference in New Issue
Block a user