diff options
author | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-20 05:11:49 +0000 |
---|---|---|
committer | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-20 05:11:49 +0000 |
commit | 2f85fff773f8dc2ad537319fcbe4352f2d241d7a (patch) | |
tree | b813176c0af72f8e0a63a099aad4dba6b72630c9 | |
parent | ce595def0708b60ce4dde9002ac206fae20be240 (diff) |
This commit was manufactured by cvs2svn to create tag 'mtrace_5_2'.vendor/mrouted/mtrace-5.2
Notes
Notes:
svn path=/cvs2svn/branches/XEROX/; revision=42881
svn path=/cvs2svn/tags/mtrace_5_2/; revision=42883; tag=vendor/mrouted/mtrace-5.2
27 files changed, 0 insertions, 11668 deletions
diff --git a/usr.sbin/mrouted/LICENSE b/usr.sbin/mrouted/LICENSE deleted file mode 100644 index ef7da470b117..000000000000 --- a/usr.sbin/mrouted/LICENSE +++ /dev/null @@ -1,48 +0,0 @@ - -The mrouted program is covered by the following license. Use of the -mrouted program represents acceptance of these terms and conditions. - -1. STANFORD grants to LICENSEE a nonexclusive and nontransferable license -to use, copy and modify the computer software ``mrouted'' (hereinafter -called the ``Program''), upon the terms and conditions hereinafter set -out and until Licensee discontinues use of the Licensed Program. - -2. LICENSEE acknowledges that the Program is a research tool still in -the development state, that it is being supplied ``as is,'' without any -accompanying services from STANFORD, and that this license is entered -into in order to encourage scientific collaboration aimed at further -development and application of the Program. - -3. LICENSEE may copy the Program and may sublicense others to use object -code copies of the Program or any derivative version of the Program. -All copies must contain all copyright and other proprietary notices found -in the Program as provided by STANFORD. Title to copyright to the -Program remains with STANFORD. - -4. LICENSEE may create derivative versions of the Program. LICENSEE -hereby grants STANFORD a royalty-free license to use, copy, modify, -distribute and sublicense any such derivative works. At the time -LICENSEE provides a copy of a derivative version of the Program to a -third party, LICENSEE shall provide STANFORD with one copy of the source -code of the derivative version at no charge to STANFORD. - -5. STANFORD MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. -By way of example, but not limitation, STANFORD MAKES NO REPRESENTATION -OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR -THAT THE USE OF THE LICENSED PROGRAM WILL NOT INFRINGE ANY PATENTS, -COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. STANFORD shall not be held liable -for any liability nor for any direct, indirect or consequential damages -with respect to any claim by LICENSEE or any third party on account of or -arising from this Agreement or use of the Program. - -6. This agreement shall be construed, interpreted and applied in -accordance with the State of California and any legal action arising -out of this Agreement or use of the Program shall be filed in a court -in the State of California. - -7. Nothing in this Agreement shall be construed as conferring rights to -use in advertising, publicity or otherwise any trademark or the name -of ``Stanford''. - -The mrouted program is COPYRIGHT 1989 by The Board of Trustees of -Leland Stanford Junior University. diff --git a/usr.sbin/mrouted/RELEASE b/usr.sbin/mrouted/RELEASE deleted file mode 100644 index 50127513aa00..000000000000 --- a/usr.sbin/mrouted/RELEASE +++ /dev/null @@ -1,326 +0,0 @@ -$Id: README-3.8.mrouted,v 3.8 1995/11/29 22:23:02 fenner Rel $ - - IP Multicast Extensions for BSD-Derived Unix Systems - - Release 3.8 - November 29, 1995 - - 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 - -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 . - -The 3.8 release fixes the following bugs: - - o mrouted would fail to forget prunes when a neighbor went away, - thus potentially sending traffic down a tunnel after the tunnel - endpoint has gone down. This was due to some research code making - it into the "emergency" 3.7 release, sigh. - - o mrouted could send prunes with negative lifetimes. This causes - slightly higher prune traffic but shouldn't be any major problem. - -=========== -Release 3.7 -November 28, 1995 - -The 3.7 release fixes the following bugs: - - o mrouted now ignores route reports that include bogus netmasks. - There was a bug in 3.5 that would mangle default routes into - tens of bogus routes; this should prevent that bug from killing - the MBONE. - - This solution can cause route flaps and black holes until the - 3.5's are gone or all of the 3.5's neighbors are 3.7 . - - o mrouted now ignores duplicate routes. Ciscos and the above 3.5 - bug could cause two copies of the same route to appear in a single - routing update; mrouted would insert two copies of the same route - into its routing table and wreak all sorts of havoc. - - o mrouted now sends a group-specific query for both retransmissions - of a g-s query; previous versions sent a general query the second - time. - - o mrouted now loops back multicasted mtrace responses and - group-specific membership queries - - o mrouted now performs deterministic tiebreaking between two - neighbors on the same vif. - - o mrouted now only does duplicate suppression on traceroute requests, - not all traceroute packets, so that a loop can be nicely detected - via a duplicate router instead of just a timeout. - - o the buffer size that mrouted uses has been increased to allow - more than 16 hops in mtrace messages. - - o mtrace's hop-by-hop termination is now more likely to be correct. - - o mrinfo now waits for the responses to its retransmitted queries. - -The 3.7 release has the following new features: - - o The configuration file can accept a hostname as the other end - of a tunnel. There must be a single name->ip mapping for the - given name, however, or mrouted will fail to start up. - - o mrinfo now sends requests to all interfaces of a multihomed host. - - o mtrace's passive mode has been implemented. - - o The first screen of mtrace statistics is shorter and more likely - to fit on one screen. - -=========== -Release 3.6 -June 26, 1995 - -The 3.6 release fixes the following bugs: - - o mrouted would dump core when attempting to report no routes (i.e. upon - startup, if you have no enabled phyint's) - - o mrouted would dump core if requested to traceroute a source for which it - had no route - - o neighbor flags were not always properly updated on probe or report - - o mrouted would sometimes reply to a multicast traceroute on a disabled - phyint; now it uses the first configured phyint to reply to traceroutes. - - o host routes (i.e. netmask 0xffffffff) works now; it was discarding - IGMP from the host because it was coming from the "broadcast address" - of the subnet. - - o send_igmp() now treats the failure to send an mtrace or a neighbor - reply as informational, as opposed to warning. - - o mrouted would go into an infinite loop trying to respond to a traceroute - for a source with a netmask of 0xffffffff. - - o vifs_with_neighbors was not being reset if the mrouted was restarted - with SIGHUP - - o the default route was not being properly advertised to neighbors (although - it was accepted if it was advertised to it) - - o ANSI-fication for those who it helps, still-K&R-ish for those it doesn't. - - o mtrace now attempts to trace three hops past a non-responding router, - in the hopes that it does support traceroute but just couldn't respond - (i.e. unicast didn't work and it can't source multicast because all its - phyints are disabled). - - o mrinfo now times out even on a multicast router. - - -=========== -Release 3.5 -May 8, 1995 - -The 3.5 release has the following new features: - - o The kernel and mrouted make sure that each is the correct version, to - prevent problems with mismatched kernel/mrouted versions. A too-old - mrouted will die with the error: - - can't enable DVMRP routing in kernel: Option not supported by protocol - - o mrouted can accept and propogate a default route (essential for - heirarchical multicast routing) - - o Kernel route cache keeps source-specific routes instead of subnet routes, - eliminating hashing and longest-match problems. - (allows classless routing, longest-match and default routing) - - o Cached kernel routes only get deleted if no traffic is flowing, to - facilitate multicast traceroute - - o mrouted has a new configuration file parser, which provides better error - messages than before, and allows named boundaries (see man page) - - o added "netmask" to phyint configuration, at the suggestion of - Anders Klemets - - o System V and FreeBSD compatibility from John Brezak <brezak@ch.hp.com> - - o phyint's can have additional subnets configured, for people with - multiple subnets on one physical network. mrouted.conf syntax is - altnet 1.2.3.0, or altnet 1.2.3.0/24 if you need to specify - a different netmask. There can be as many altnet statements - as you need. - - o both mrouted and the kernel now support classless addresses. - - o the kernel supports PIM assert processing by notifying the router - when a packet arrives on the wrong interface - - o the kernel keeps additional counters, and mrouted can be compiled to - support SNMP and the Multicast MIB - - o the packet classifier in the kernel now uses the following udp port - ranges: - [0, 16384) - lowest priority, unclassified - [16384, 32768) - highest priority, i.e. audio - [32768, 49152) - medium priority, i.e. whiteboard - [49152, 65536) - low priority, i.e. video - A future release of a session directory will allocate ports in these - ranges. - - o the configuration code has been modified to default tunnels' rate_limit - parameters to 500kbps. This is easily modified with a rate_limit keyword - in mrouted.conf, but should be a good default for the MBONE in general. - - o The tunnel sending code now caches a route for ip_output(), this should - help performance on machines with lots of tunnels. - - o Dispatching for de-capsulating packets is now via protosw[], making - reception of other raw protocols more efficient - - o Neighbor capabilities are discovered via a bitmask as opposed to - version number. - - o Multicast traceroute code improved - - o mrouted can be compiled with Routing Support for Resource Reservation - (RSRR), required for RSVP. - - -The 3.5 release fixes the following bugs: - - o The IGMPv2 query timeout field was interpreted as being in units of - 200ms as opposed to 100ms, thus the maximum timeout was set to twice - the expected value. This is not fatal, as mrouted always queries - twice in the expectation that a packet could get loss, but it does - make it less robust in the face of packet loss. - - o IGMP could report membership in local-only groups (i.e. 224.0.0.X) - - o IGMP could get confused by hearing its own new membership reports, thus - a router would never perform fast leave. - - o IGMP could reset timers for the wrong interface. - - o mrouted put a bogus value in the maximum timeout field of IGMPv2 query - packets. - - o Non-querier mrouters would respond to IGMP leave messages - - o mrouted was not performing fast leave properly - - o If the last member goes away on a transit network, the upstream router - would stop forwarding even if there are downstream members. - - o Kernel hash function improved - - o Eliminated possibility of panic(): timeout in cache maintenance - - o Reordered resource allocation when sending upcall to handle failure properly - - o some endian-ness bugs squashed in mrouted, probably more to go. - - o Multicast traceroute could send a reply on a disabled interface. - - -This release consists of the following files: - - - README-3.8.mrouted - this file - - mrouted/* - version 3.8 of mrouted, - mrinfo, map-mbone and - mtrace. - - ifconfig/* - Changes to ifconfig to - show multicast interfaces - - netstat/* - Diffs to netstat - - ping/* - sources for ping - which support - multicasting - - mtest/* - utility for testing - multicast group - membership - - -MROUTED 3.8 - -Mrouted 3.8 has two optional features: SNMP and RSRR. RSRR support -is required for running RSVP; the SNMP code, with the help of the -ISODE snmpd, implements both the Multicast MIB and the DVMRP MIB. - -RSRR ----- -Routing Support for Resource Reservations (RSRR) was contributed by -Daniel Zappala <daniel@isi.edu>. - -To enable RSRR support, uncomment the three lines starting with -RSRR near the top of the Makefile and "make clean; make". Or use -the prebuilt binary, mrouted.rsrr . - -RSRR allows RSVP to query mrouted for its routing entry for a particular -source-group pair. Using the routing entry and the IP_MULTICAST_VIF -socket call, RSVP can forward distinct control messages out each -outgoing interface. This version of mrouted supports RSRR messages -using a Unix datagram socket. - -RSRR currently includes two pairs of query-reply messages. RSVP sends -an Initial Query when it starts. Mrouted responds with an Initial Reply -that includes the set of vifs it is using, flagging those that are -administratively disabled. When RSVP needs the routing entry for a -source-group pair, it sends a Route Query. Mrouted responds with a -Route Reply that includes the incoming vif and outgoing vifs for the -source-group pair. - -RSVP may request route change notification by setting the notification -bit in the Route Query. If mrouted can provide route change -notification for the source-group pair, it sets the notification bit in -its Route Reply. When the routing entry for the source-group pair -changes, mrouted sends an unsolicited Route Reply containing the new -routing information. The initial release of mrouted 3.5 did not support -route change notification and always returned a Route Reply with the -notification bit cleared. This release of mrouted provides route change -notification when possible. - -SNMP ----- -SNMP support was contributed by David Thaler <thalerd@eecs.umich.edu>. - -To enable SNMP support, uncomment the six lines near the top of -the Makefile below the description of SNMP support, or use the -prebuilt binary, mrouted.snmp or mrouted.rsrr.snmp . - -To link the SNMP-capable mrouted, you need the CMU libraries. -See http://nic.merit.edu/~mbone/ for a full mrouted-snmp distribution. - -Make sure to add the "sysName", "sysContact", "sysVersion" and -"sysLocation" variables to your /etc/mrouted.conf if you want them -to provide anything other than default values. - -Example: - -sysName "tibia" -sysContact "Bill Fenner <fenner@parc.xerox.com> +1 415 812-4816" -sysVersion "SunOS 4.1.3 and mrouted 3.8" -sysLocation "MAXC room, PARC building 35" - -The SNMP version of mrouted has an additional command line flag: - - -P snmp_port - - Specifies a port for SNMP communication (default 161). This option - should be used when another SNMP daemon already exists. The - preferred alternate port in this case is port 9161. - -The mstat(8) program allows querying of statistics using SNMP. diff --git a/usr.sbin/mrouted/callout.c b/usr.sbin/mrouted/callout.c deleted file mode 100644 index 358c7ae86a21..000000000000 --- a/usr.sbin/mrouted/callout.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: callout.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - -#include "defs.h" - -/* the code below implements a callout queue */ -static int id = 0; -static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */ - -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 */ - int time; /* time offset to next event*/ -}; - -#ifdef IGMP_DEBUG -static void print_Q __P((void)); -#else -#define print_Q() -#endif - -void -callout_init() -{ - Q = (struct timeout_q *) 0; -} - - -/* - * signal handler for SIGALARM that is called once every second - */ -void -age_callout_queue() -{ - struct timeout_q *ptr; - - if (in_callout) - return; - - 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; - } - } - in_callout = 0; - return; -} - - -/* - * sets the timer - */ -int -timer_setTimer(delay, action, data) - int delay; /* number of units for timeout */ - cfunc_t action; /* function to be called on timeout */ - char *data; /* what to call the timeout function with */ -{ - struct timeout_q *ptr, *node, *prev; - - if (in_callout) - return -1; - - in_callout = 1; - - /* 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; - node->data = data; - node->time = delay; - node->next = 0; - node->id = ++id; - - prev = ptr = Q; - - /* insert node in the queue */ - - /* if the queue is empty, insert the node and return */ - if (!Q) - Q = node; - else { - /* chase the pointer looking for the right place */ - while (ptr) { - - if (delay < ptr->time) { - /* right place */ - - node->next = ptr; - if (ptr == Q) - Q = node; - else - prev->next = node; - ptr->time -= node->time; - print_Q(); - in_callout = 0; - return node->id; - } else { - /* keep moving */ - - delay -= ptr->time; node->time = delay; - prev = ptr; - ptr = ptr->next; - } - } - prev->next = node; - } - print_Q(); - in_callout = 0; - return node->id; -} - - -/* clears the associated timer */ -void -timer_clearTimer(timer_id) - int timer_id; -{ - struct timeout_q *ptr, *prev; - - if (in_callout) - return; - if (!timer_id) - return; - - in_callout = 1; - - prev = ptr = Q; - - /* - * find the right node, delete it. the subsequent node's time - * gets bumped up - */ - - print_Q(); - while (ptr) { - if (ptr->id == timer_id) { - /* got the right node */ - - /* unlink it from the queue */ - if (ptr == Q) - Q = Q->next; - else - prev->next = ptr->next; - - /* increment next node if any */ - if (ptr->next != 0) - (ptr->next)->time += ptr->time; - - free(ptr->data); - free(ptr); - print_Q(); - in_callout = 0; - return; - } - prev = ptr; - ptr = ptr->next; - } - print_Q(); - in_callout = 0; -} - -#ifdef IGMP_DEBUG -/* - * debugging utility - */ -static void -print_Q() -{ - struct timeout_q *ptr; - - 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; -} diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y deleted file mode 100644 index ab5b89f30ea8..000000000000 --- a/usr.sbin/mrouted/cfparse.y +++ /dev/null @@ -1,637 +0,0 @@ -%{ -/* - * Configuration file parser for mrouted. - * - * Written by Bill Fenner, NRL, 1994 - * - * $Id: cfparse.y,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ -#include <stdio.h> -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif -#include "defs.h" -#include <netdb.h> - -/* - * Local function declarations - */ -static void fatal __P((char *fmt, ...)); -static void warn __P((char *fmt, ...)); -static void yyerror __P((char *s)); -static char * next_word __P((void)); -static int yylex __P((void)); -static u_int32 valid_if __P((char *s)); -static struct ifreq * ifconfaddr __P((struct ifconf *ifcp, u_int32 a)); -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; - -static int lineno; -static struct ifreq ifbuf[32]; -static struct ifconf ifc; - -static struct uvif *v; - -static int order; - -struct addrmask { - u_int32 addr; - int mask; -}; - -struct boundnam { - char *name; - struct addrmask bound; -}; - -#define MAXBOUNDS 20 - -struct boundnam boundlist[MAXBOUNDS]; /* Max. of 20 named boundaries */ -int numbounds = 0; /* Number of named boundaries */ - -%} - -%union -{ - int num; - char *ptr; - struct addrmask addrmask; - u_int32 addr; -}; - -%token CACHE_LIFETIME PRUNING -%token PHYINT TUNNEL NAME -%token DISABLE IGMPV1 SRCRT -%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET -%token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION -%token <num> BOOLEAN -%token <num> NUMBER -%token <ptr> STRING -%token <addrmask> ADDRMASK -%token <addr> ADDR - -%type <addr> interface addrname -%type <addrmask> bound boundary addrmask - -%start conf - -%% - -conf : stmts - ; - -stmts : /* Empty */ - | stmts stmt - ; - -stmt : error - | PHYINT interface { - - vifi_t vifi; - - if (order) - fatal("phyints must appear before tunnels"); - - for (vifi = 0, v = uvifs; - vifi < numvifs; - ++vifi, ++v) - if (!(v->uv_flags & VIFF_TUNNEL) && - $2 == v->uv_lcl_addr) - break; - - if (vifi == numvifs) - fatal("%s is not a configured interface", - inet_fmt($2,s1)); - - } - ifmods - | TUNNEL interface addrname { - - struct ifreq *ifr; - struct ifreq ffr; - vifi_t vifi; - - order++; - - ifr = ifconfaddr(&ifc, $2); - if (ifr == 0) - 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", - inet_fmt($2, s1)); - - if (ifconfaddr(&ifc, $3) != 0) - fatal("Tunnel remote address %s is one of mine", - inet_fmt($3, s1)); - - for (vifi = 0, v = uvifs; - vifi < numvifs; - ++vifi, ++v) - if (v->uv_flags & VIFF_TUNNEL) { - if ($3 == v->uv_rmt_addr) - fatal("Duplicate tunnel to %s", - inet_fmt($3, s1)); - } else if (!(v->uv_flags & VIFF_DISABLED)) { - if (($3 & v->uv_subnetmask) == v->uv_subnet) - fatal("Unnecessary tunnel to %s", - inet_fmt($3,s1)); - } - - if (numvifs == MAXVIFS) - fatal("too many vifs"); - - 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; - v->uv_lcl_addr = $2; - v->uv_rmt_addr = $3; - v->uv_subnet = 0; - v->uv_subnetmask= 0; - v->uv_subnetbcast= 0; - 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; - vifs_down = TRUE; - } - } - 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; - } - | PRUNING BOOLEAN { pruning = $2; } - | CACHE_LIFETIME NUMBER { cache_lifetime = $2; - max_prune_lifetime = cache_lifetime * 2; - } - | NAME STRING boundary { if (numbounds >= MAXBOUNDS) { - fatal("Too many named boundaries (max %d)", MAXBOUNDS); - } - - boundlist[numbounds].name = malloc(strlen($2) + 1); - strcpy(boundlist[numbounds].name, $2); - boundlist[numbounds++].bound = $3; - } - | SYSNAM STRING { -#ifdef SNMP - set_sysName($2); -#endif /* SNMP */ - } - | SYSCONTACT STRING { -#ifdef SNMP - set_sysContact($2); -#endif /* SNMP */ - } - | SYSVERSION STRING { -#ifdef SNMP - set_sysVersion($2); -#endif /* SNMP */ - } - | SYSLOCATION STRING { -#ifdef SNMP - set_sysLocation($2); -#endif /* SNMP */ - } - ; - -tunnelmods : /* empty */ - | tunnelmods tunnelmod - ; - -tunnelmod : mod - | SRCRT { fatal("Source-route tunnels not supported"); } - ; - -ifmods : /* empty */ - | ifmods ifmod - ; - -ifmod : mod - | DISABLE { v->uv_flags |= VIFF_DISABLED; } - | IGMPV1 { v->uv_flags |= VIFF_IGMPV1; } - | NETMASK addrname { - u_int32 subnet, mask; - - mask = $2; - subnet = v->uv_lcl_addr & mask; - if (!inet_valid_subnet(subnet, mask)) - fatal("Invalid netmask"); - v->uv_subnet = subnet; - v->uv_subnetmask = mask; - v->uv_subnetbcast = subnet | ~mask; - } - | NETMASK { - - warn("Expected address after netmask keyword, ignored"); - - } - | ALTNET addrmask { - - struct phaddr *ph; - - ph = (struct phaddr *)malloc(sizeof(struct phaddr)); - if (ph == NULL) - fatal("out of memory"); - if ($2.mask) { - VAL_TO_MASK(ph->pa_subnetmask, $2.mask); - } else - ph->pa_subnetmask = v->uv_subnetmask; - ph->pa_subnet = $2.addr & ph->pa_subnetmask; - ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask; - if ($2.addr & ~ph->pa_subnetmask) - warn("Extra subnet %s/%d has host bits set", - inet_fmt($2.addr,s1), $2.mask); - ph->pa_next = v->uv_addrs; - v->uv_addrs = ph; - - } - | ALTNET { - - warn("Expected address after altnet keyword, ignored"); - - } - ; - -mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255) - fatal("Invalid threshold %d",$2); - v->uv_threshold = $2; - } - | THRESHOLD { - - warn("Expected number after threshold keyword, ignored"); - - } - | METRIC NUMBER { if ($2 < 1 || $2 > UNREACHABLE) - fatal("Invalid metric %d",$2); - v->uv_metric = $2; - } - | METRIC { - - warn("Expected number after metric keyword, ignored"); - - } - | RATE_LIMIT NUMBER { if ($2 > MAX_RATE_LIMIT) - fatal("Invalid rate_limit %d",$2); - v->uv_rate_limit = $2; - } - | RATE_LIMIT { - - warn("Expected number after rate_limit keyword, ignored"); - - } - | BOUNDARY bound { - - struct vif_acl *v_acl; - - v_acl = (struct vif_acl *)malloc(sizeof(struct vif_acl)); - if (v_acl == NULL) - fatal("out of memory"); - VAL_TO_MASK(v_acl->acl_mask, $2.mask); - v_acl->acl_addr = $2.addr & v_acl->acl_mask; - if ($2.addr & ~v_acl->acl_mask) - warn("Boundary spec %s/%d has host bits set", - inet_fmt($2.addr,s1),$2.mask); - v_acl->acl_next = v->uv_acl; - v->uv_acl = v_acl; - - } - | BOUNDARY { - - warn("Expected boundary spec after boundary keyword, ignored"); - - } - ; - -interface : ADDR { $$ = $1; } - | STRING { - $$ = valid_if($1); - if ($$ == 0) - fatal("Invalid interface name %s",$1); - } - ; - -addrname : ADDR { $$ = $1; } - | STRING { struct hostent *hp; - - if ((hp = gethostbyname($1)) == NULL) - fatal("No such host %s", $1); - - if (hp->h_addr_list[1]) - fatal("Hostname %s does not %s", - $1, "map to a unique address"); - - bcopy(hp->h_addr_list[0], &$$, - hp->h_length); - } - -bound : boundary { $$ = $1; } - | STRING { int i; - - for (i=0; i < numbounds; i++) { - if (!strcmp(boundlist[i].name, $1)) { - $$ = boundlist[i].bound; - break; - } - } - if (i == numbounds) { - fatal("Invalid boundary name %s",$1); - } - } - ; - -boundary : ADDRMASK { - - if ((ntohl($1.addr) & 0xff000000) != 0xef000000) { - fatal("Boundaries must be 239.x.x.x, not %s/%d", - inet_fmt($1.addr, s1), $1.mask); - } - $$ = $1; - - } - ; - -addrmask : ADDRMASK { $$ = $1; } - | ADDR { $$.addr = $1; $$.mask = 0; } - ; -%% -#ifdef __STDC__ -static void -fatal(char *fmt, ...) -{ - va_list ap; - char buf[200]; - - va_start(ap, fmt); -#else -/*VARARGS1*/ -static void -fatal(fmt, va_alist) -char *fmt; -va_dcl -{ - va_list ap; - char buf[200]; - - va_start(ap); -#endif - vsprintf(buf, fmt, ap); - va_end(ap); - - log(LOG_ERR,0,"%s: %s near line %d", configfilename, buf, lineno); -} - -#ifdef __STDC__ -static void -warn(char *fmt, ...) -{ - va_list ap; - char buf[200]; - - va_start(ap, fmt); -#else -/*VARARGS1*/ -static void -warn(fmt, va_alist) -char *fmt; -va_dcl -{ - va_list ap; - char buf[200]; - - va_start(ap); -#endif - vsprintf(buf, fmt, ap); - va_end(ap); - - log(LOG_WARNING,0,"%s: %s near line %d", configfilename, buf, lineno); -} - -static void -yyerror(s) -char *s; -{ - log(LOG_ERR, 0, "%s: %s near line %d", configfilename, s, lineno); -} - -static char * -next_word() -{ - static char buf[1024]; - static char *p=NULL; - extern FILE *f; - char *q; - - while (1) { - if (!p || !*p) { - lineno++; - if (fgets(buf, sizeof(buf), f) == NULL) - return NULL; - p = buf; - } - while (*p && (*p == ' ' || *p == '\t')) /* skip whitespace */ - p++; - if (*p == '#') { - p = NULL; /* skip comments */ - continue; - } - q = p; -#ifdef SNMP - if (*p == '"') { - p++; - while (*p && *p != '"' && *p != '\n') - p++; /* find next whitespace */ - if (*p == '"') - p++; - } else -#endif - while (*p && *p != ' ' && *p != '\t' && *p != '\n') - p++; /* find next whitespace */ - *p++ = '\0'; /* null-terminate string */ - - if (!*q) { - p = NULL; - continue; /* if 0-length string, read another line */ - } - - return q; - } -} - -static int -yylex() -{ - int n; - u_int32 addr; - char *q; - - 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; - if (!strcmp(q,"on") || !strcmp(q,"yes")) { - yylval.num = 1; - return BOOLEAN; - } - if (!strcmp(q,"off") || !strcmp(q,"no")) { - yylval.num = 0; - return BOOLEAN; - } - if (sscanf(q,"%[.0-9]/%d%c",s1,&n,s2) == 2) { - if ((addr = inet_parse(s1)) != 0xffffffff) { - yylval.addrmask.mask = n; - yylval.addrmask.addr = addr; - return ADDRMASK; - } - /* fall through to returning STRING */ - } - if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) { - if ((addr = inet_parse(s1)) != 0xffffffff && - inet_valid_host(addr)) { - yylval.addr = addr; - return ADDR; - } - } - if (sscanf(q,"0x%8x%c",&n,s1) == 1) { - yylval.addr = n; - return ADDR; - } - if (sscanf(q,"%d%c",&n,s1) == 1) { - yylval.num = n; - return NUMBER; - } -#ifdef SNMP - if (!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 */ - yylval.ptr = q+1; - return STRING; - } -#endif - yylval.ptr = q; - return STRING; -} - -void -config_vifs_from_file() -{ - extern FILE *f; - - order = 0; - numbounds = 0; - lineno = 0; - - if ((f = fopen(configfilename, "r")) == NULL) { - if (errno != ENOENT) - log(LOG_ERR, errno, "can't open %s", configfilename); - 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); -} - -static u_int32 -valid_if(s) -char *s; -{ - register vifi_t vifi; - register struct uvif *v; - - for (vifi=0, v=uvifs; vifi<numvifs; vifi++, v++) - if (!strcmp(v->uv_name, s)) - return v->uv_lcl_addr; - - return 0; -} - -static struct ifreq * -ifconfaddr(ifcp, a) - struct ifconf *ifcp; - u_int32 a; -{ - int n; - struct ifreq *ifrp = (struct ifreq *)ifcp->ifc_buf; - struct ifreq *ifend = (struct ifreq *)((char *)ifrp + ifcp->ifc_len); - - while (ifrp < ifend) { - 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)) - n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - ++ifrp; - else - ifrp = (struct ifreq *)((char *)ifrp + n); -#else - ++ifrp; -#endif - } - return (0); -} diff --git a/usr.sbin/mrouted/config.c b/usr.sbin/mrouted/config.c deleted file mode 100644 index 1147412b904e..000000000000 --- a/usr.sbin/mrouted/config.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: config.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - - -#include "defs.h" - - -/* - * Query the kernel to find network interfaces that are multicast-capable - * and install them in the uvifs array. - */ -void -config_vifs_from_kernel() -{ - struct 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; - - ifc.ifc_buf = (char *)ifbuf; - ifc.ifc_len = sizeof(ifbuf); - 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); - /* - * Loop through all of the interfaces. - */ - for (; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) { - struct ifreq ifr; -#if BSD >= 199006 - n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - n = sizeof(*ifrp); -#else - n = sizeof(*ifrp); -#endif - /* - * Ignore any interface for an address family other than IP. - */ - if (ifrp->ifr_addr.sa_family != AF_INET) - continue; - - addr = ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr; - - /* - * Need a template to preserve address info that is - * used below to locate the next entry. (Otherwise, - * SIOCGIFFLAGS stomps over it because the requests - * are returned in a union.) - */ - bcopy(ifrp->ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); - - /* - * Ignore loopback interfaces and interfaces that do not support - * multicast. - */ - if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0) - log(LOG_ERR, errno, "ioctl SIOCGIFFLAGS for %s", ifr.ifr_name); - flags = ifr.ifr_flags; - if ((flags & (IFF_LOOPBACK|IFF_MULTICAST)) != IFF_MULTICAST) continue; - - /* - * Ignore any interface whose address and mask do not define a - * valid subnet number, or whose address is of the form {subnet,0} - * or {subnet,-1}. - */ - if (ioctl(udp_socket, SIOCGIFNETMASK, (char *)&ifr) < 0) - log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", ifr.ifr_name); - mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; - subnet = addr & mask; - if (!inet_valid_subnet(subnet, mask) || - addr == subnet || - addr == (subnet | ~mask)) { - log(LOG_WARNING, 0, - "ignoring %s, has invalid address (%s) and/or mask (%s)", - ifr.ifr_name, inet_fmt(addr, s1), inet_fmt(mask, s2)); - continue; - } - - /* - * Ignore any interface that is connected to the same subnet as - * one already installed in the uvifs array. - */ - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if ((addr & v->uv_subnetmask) == v->uv_subnet || - (v->uv_subnet & mask) == subnet) { - log(LOG_WARNING, 0, "ignoring %s, same subnet as %s", - ifr.ifr_name, v->uv_name); - break; - } - } - if (vifi != numvifs) continue; - - /* - * If there is room in the uvifs array, install this interface. - */ - if (numvifs == MAXVIFS) { - log(LOG_WARNING, 0, "too many vifs, ignoring %s", ifr.ifr_name); - 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; - 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; - - log(LOG_INFO,0,"installing %s (%s on subnet %s) as vif #%u - rate=%d", - v->uv_name, inet_fmt(addr, s1), inet_fmts(subnet, mask, s2), - numvifs, v->uv_rate_limit); - - ++numvifs; - - /* - * If the interface is not yet up, set the vifs_down flag to - * remind us to check again later. - */ - if (!(flags & IFF_UP)) { - v->uv_flags |= VIFF_DOWN; - vifs_down = TRUE; - } - } -} diff --git a/usr.sbin/mrouted/defs.h b/usr.sbin/mrouted/defs.h deleted file mode 100644 index 63aef773e77c..000000000000 --- a/usr.sbin/mrouted/defs.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: defs.h,v 3.8 1995/11/29 22:36:34 fenner Rel $ - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <syslog.h> -#include <signal.h> -#include <string.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#ifdef SYSV -#include <sys/sockio.h> -#endif -#include <sys/time.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/igmp.h> -#include <netinet/ip_mroute.h> -#ifdef RSRR -#include <sys/un.h> -#endif /* RSRR */ - -/*XXX*/ -typedef u_int u_int32; - -#ifndef __P -#ifdef __STDC__ -#define __P(x) x -#else -#define __P(x) () -#endif -#endif - -typedef void (*cfunc_t) __P((void *)); -typedef void (*ihfunc_t) __P((int, fd_set *)); - -#include "dvmrp.h" -#include "vif.h" -#include "route.h" -#include "prune.h" -#include "pathnames.h" -#ifdef RSRR -#include "rsrr.h" -#include "rsrr_var.h" -#endif /* RSRR */ - -/* - * Miscellaneous constants and macros. - */ -#define FALSE 0 -#define TRUE 1 - -#define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0) - -#define TIMER_INTERVAL ROUTE_MAX_REPORT_DELAY - -#define 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 8 /* increment on local changes or bug fixes, */ - /* reset to 0 whever PROTOCOL_VERSION increments */ - -#define MROUTED_LEVEL ((MROUTED_VERSION << 8) | PROTOCOL_VERSION | \ - ((NF_PRUNE | NF_GENID | NF_MTRACE) << 16) | \ - (VENDOR_CODE << 24)) - /* 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 */ - -/* obnoxious gcc gives an extraneous warning about this constant... */ -#if defined(__STDC__) || defined(__GNUC__) -#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ -#else -#define JAN_1970 2208988800L /* 1970 - 1900 in seconds */ -#define const /**/ -#endif - -#ifdef RSRR -#define BIT_ZERO(X) ((X) = 0) -#define BIT_SET(X,n) ((X) |= 1 << (n)) -#define BIT_CLR(X,n) ((X) &= ~(1 << (n))) -#define BIT_TST(X,n) ((X) & 1 << (n)) -#endif /* RSRR */ - -#ifdef SYSV -#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 - -/* - * External declarations for global variables and functions. - */ -#define RECV_BUF_SIZE 8192 -extern char *recv_buf; -extern char *send_buf; -extern int igmp_socket; -#ifdef RSRR -extern int rsrr_socket; -#endif /* RSRR */ -extern u_int32 allhosts_group; -extern u_int32 allrtrs_group; -extern u_int32 dvmrp_group; -extern u_int32 dvmrp_genid; - -#define DEFAULT_DEBUG 2 /* default if "-d" given without value */ - -extern int debug; -extern u_char pruning; - -extern int routes_changed; -extern int delay_change_reports; -extern unsigned nroutes; - -extern struct uvif uvifs[MAXVIFS]; -extern vifi_t numvifs; -extern int vifs_down; -extern int udp_socket; -extern int vifs_with_neighbors; - -extern char s1[]; -extern char s2[]; -extern char s3[]; -extern char s4[]; - -#if !(defined(BSD) && (BSD >= 199103)) -extern int errno; -extern int sys_nerr; -extern char * sys_errlist[]; -#endif - -#ifdef OLD_KERNEL -#define MRT_INIT DVMRP_INIT -#define MRT_DONE DVMRP_DONE -#define MRT_ADD_VIF DVMRP_ADD_VIF -#define MRT_DEL_VIF DVMRP_DEL_VIF -#define MRT_ADD_MFC DVMRP_ADD_MFC -#define MRT_DEL_MFC DVMRP_DEL_MFC - -#define IGMP_PIM 0x14 -#endif - -/* main.c */ -extern void log __P((int, int, char *, ...)); -extern int register_input_handler __P((int fd, ihfunc_t func)); - -/* 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)); - -/* 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)); - -/* 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 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 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 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 dump_routes __P((FILE *fp)); -extern void start_route_updates __P((void)); - -/* vif.c */ -extern void init_vifs __P((void)); -extern void check_vif_state __P((void)); -extern vifi_t find_vif __P((u_int32 src, u_int32 dst)); -extern void age_vifs __P((void)); -extern void dump_vifs __P((FILE *fp)); -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 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)); - -/* config.c */ -extern void config_vifs_from_kernel __P((void)); - -/* cfparse.y */ -extern void config_vifs_from_file __P((void)); - -/* inet.c */ -extern int inet_valid_host __P((u_int32 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)); - -/* 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 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 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)); -/* 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)); - -/* 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_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 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(()); -#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)); -#endif /* RSRR */ diff --git a/usr.sbin/mrouted/dvmrp.h b/usr.sbin/mrouted/dvmrp.h deleted file mode 100644 index e471800588dc..000000000000 --- a/usr.sbin/mrouted/dvmrp.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: dvmrp.h,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - -/* - * A DVMRP message consists of an IP header + an IGMP header + (for some types) - * zero or more bytes of data. - * - * For REPORT messages, the data is route information; the route information - * consists of one or more lists of the following form: - * - * (mask, (origin, metric), (origin, metric), ...) - * - * where: - * - * "mask" is the subnet mask for all the origins in the list. - * It is always THREE bytes long, containing the low-order - * three bytes of the mask (the high-order byte is always - * 0xff and therefore need not be transmitted). - * - * "origin" is the number of a subnet from which multicast datagrams - * may originate. It is from one to four bytes long, - * depending on the value of "mask": - * if all bytes of the mask are zero - * the subnet number is one byte long - * else if the low-order two bytes of the mask are zero - * the subnet number is two bytes long - * else if the lowest-order byte of the mask is zero - * the subnet number is three bytes long, - * else - * the subnet number is four bytes long. - * - * "metric" is a one-byte value consisting of two subfields: - * - the high-order bit is a flag which, when set, indicates - * the last (origin, metric) pair of a list. - * - the low-order seven bits contain the routing metric for - * the corresponding origin, relative to the sender of the - * DVMRP report. The metric may have the value of UNREACHABLE - * added to it as a "split horizon" indication (so called - * "poisoned reverse"). - * - * Within a list, the origin subnet numbers must be in ascending order, and - * the lists themselves are in order of increasing mask value. A message may - * not exceed 576 bytes, the default maximum IP reassembly size, including - * the IP and IGMP headers; the route information may be split across more - * than one message if necessary, by terminating a list in one message and - * starting a new list in the next message (repeating the same mask value, - * if necessary). - * - * For NEIGHBORS messages, the data is neighboring-router information - * consisting of one or more lists of the following form: - * - * (local-addr, metric, threshold, ncount, neighbor, neighbor, ...) - * - * where: - * - * "local-addr" is the sending router's address as seen by the neighbors - * in this list; it is always four bytes long. - * "metric" is a one-byte unsigned value, the TTL `cost' of forwarding - * packets to any of the neighbors on this list. - * "threshold" is a one-byte unsigned value, a lower bound on the TTL a - * packet must have to be forwarded to any of the neighbors on - * this list. - * "ncount" is the number of neighbors in this list. - * "neighbor" is the address of a neighboring router, four bytes long. - * - * As with REPORT messages, NEIGHBORS messages should not exceed 576 bytes, - * including the IP and IGMP headers; split longer messages by terminating the - * list in one and continuing in another, repeating the local-addr, etc., if - * necessary. - * - * For NEIGHBORS2 messages, the data is identical to NEIGHBORS except - * there is a flags byte before the neighbor count: - * - * (local-addr, metric, threshold, flags, ncount, neighbor, neighbor, ...) - */ - -/* - * DVMRP message types (carried in the "code" field of an IGMP header) - */ -#define DVMRP_PROBE 1 /* for finding neighbors */ -#define DVMRP_REPORT 2 /* for reporting some or all routes */ -#define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ - /* of this router's neighbors. */ -#define DVMRP_NEIGHBORS 4 /* response to such a request */ -#define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ -#define DVMRP_NEIGHBORS2 6 -#define DVMRP_PRUNE 7 /* prune message */ -#define DVMRP_GRAFT 8 /* graft message */ -#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ -#define DVMRP_INFO_REQUEST 10 /* information request */ -#define DVMRP_INFO_REPLY 11 /* information reply */ - -/* - * 'flags' byte values in DVMRP_NEIGHBORS2 reply. - */ -#define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ -#define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ -#define DVMRP_NF_PIM 0x04 /* neighbor is a PIM neighbor */ -#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ -#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ -#define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ -#define DVMRP_NF_LEAF 0x80 /* Neighbor reports that it is a leaf */ - -/* - * Request/reply types for info queries/replies - */ -#define DVMRP_INFO_VERSION 1 /* version string */ -#define DVMRP_INFO_NEIGHBORS 2 /* neighbors2 data */ - -/* - * Limit on length of route data - */ -#define MAX_IP_PACKET_LEN 576 -#define MIN_IP_HEADER_LEN 20 -#define MAX_IP_HEADER_LEN 60 -#define MAX_DVMRP_DATA_LEN \ - ( MAX_IP_PACKET_LEN - MAX_IP_HEADER_LEN - IGMP_MINLEN ) - -/* - * Various protocol constants (all times in seconds) - */ - /* address for multicast DVMRP msgs */ -#define INADDR_DVMRP_GROUP (u_int32)0xe0000004 /* 224.0.0.4 */ -/* - * The IGMPv2 <netinet/in.h> defines INADDR_ALLRTRS_GROUP, but earlier - * ones don't, so we define it conditionally here. - */ -#ifndef INADDR_ALLRTRS_GROUP - /* address for multicast mtrace msg */ -#define INADDR_ALLRTRS_GROUP (u_int32)0xe0000002 /* 224.0.0.2 */ -#endif - -#define ROUTE_MAX_REPORT_DELAY 5 /* max delay for reporting changes */ - /* (This is the timer interrupt */ - /* interval; all times must be */ - /* multiples of this value.) */ - -#define ROUTE_REPORT_INTERVAL 60 /* periodic route report interval */ -#define ROUTE_SWITCH_TIME 140 /* time to switch to equivalent gw */ -#define ROUTE_EXPIRE_TIME 200 /* time to mark route invalid */ -#define ROUTE_DISCARD_TIME 340 /* time to garbage collect route */ - -#define LEAF_CONFIRMATION_TIME 200 /* time to consider subnet a leaf */ - -#define NEIGHBOR_PROBE_INTERVAL 10 /* periodic neighbor probe interval */ -#define NEIGHBOR_EXPIRE_TIME 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 UNREACHABLE 32 /* "infinity" metric, must be <= 64 */ -#define DEFAULT_METRIC 1 /* default subnet/tunnel metric */ -#define DEFAULT_THRESHOLD 1 /* default subnet/tunnel threshold */ - -#define MAX_RATE_LIMIT 100000 /* max rate limit */ -#define DEFAULT_PHY_RATE_LIMIT 0 /* default phyint rate limit */ -#define DEFAULT_TUN_RATE_LIMIT 500 /* default tunnel rate limit */ - -#define DEFAULT_CACHE_LIFETIME 300 /* kernel route entry discard time */ -#define GRAFT_TIMEOUT_VAL 5 /* retransmission time for grafts */ - -#define OLD_AGE_THRESHOLD 2 diff --git a/usr.sbin/mrouted/igmp.c b/usr.sbin/mrouted/igmp.c deleted file mode 100644 index 3c27e6d38d26..000000000000 --- a/usr.sbin/mrouted/igmp.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: igmp.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - - -#include "defs.h" - - -/* - * Exported variables. - */ -char *recv_buf; /* input packet buffer */ -char *send_buf; /* output packet buffer */ -int igmp_socket; /* socket for all network I/O */ -u_int32 allhosts_group; /* All hosts addr in net order */ -u_int32 allrtrs_group; /* All-Routers " in net order */ -u_int32 dvmrp_group; /* DVMRP grp addr in net order */ -u_int32 dvmrp_genid; /* IGMP generation id */ - -/* - * Local function definitions. - */ -/* u_char promoted to u_int */ -static char * packet_kind __P((u_int type, u_int code)); -static int igmp_log_level __P((u_int type, u_int code)); - -/* - * Open and initialize the igmp socket, and fill in the non-changing - * IP header fields in the output packet buffer. - */ -void -init_igmp() -{ - struct ip *ip; - - recv_buf = malloc(RECV_BUF_SIZE); - send_buf = malloc(RECV_BUF_SIZE); - - if ((igmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0) - log(LOG_ERR, errno, "IGMP socket"); - - k_hdr_include(TRUE); /* include IP header when sending */ - k_set_rcvbuf(48*1024); /* lots of input buffering */ - k_set_ttl(1); /* restrict multicasts to one hop */ - k_set_loop(FALSE); /* disable multicast loopback */ - - ip = (struct ip *)send_buf; - ip->ip_hl = sizeof(struct ip) >> 2; - ip->ip_v = IPVERSION; - ip->ip_tos = 0; - ip->ip_off = 0; - ip->ip_p = IPPROTO_IGMP; - ip->ip_ttl = MAXTTL; /* applies to unicasts only */ - - allhosts_group = htonl(INADDR_ALLHOSTS_GROUP); - dvmrp_group = htonl(INADDR_DVMRP_GROUP); - allrtrs_group = htonl(INADDR_ALLRTRS_GROUP); -} - -#define PIM_QUERY 0 -#define PIM_REGISTER 1 -#define PIM_REGISTER_STOP 2 -#define PIM_JOIN_PRUNE 3 -#define PIM_RP_REACHABLE 4 -#define PIM_ASSERT 5 -#define PIM_GRAFT 6 -#define PIM_GRAFT_ACK 7 - -static char * -packet_kind(type, code) - u_int type, code; -{ - 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_DVMRP: - switch (code) { - case DVMRP_PROBE: return "neighbor probe "; - case DVMRP_REPORT: return "route report "; - case DVMRP_ASK_NEIGHBORS: return "neighbor request "; - case DVMRP_NEIGHBORS: return "neighbor list "; - case DVMRP_ASK_NEIGHBORS2: return "neighbor request 2"; - case DVMRP_NEIGHBORS2: return "neighbor list 2 "; - case DVMRP_PRUNE: return "prune message "; - case DVMRP_GRAFT: return "graft message "; - case DVMRP_GRAFT_ACK: return "graft message ack "; - case DVMRP_INFO_REQUEST: return "info request "; - case DVMRP_INFO_REPLY: return "info reply "; - default: return "unknown DVMRP msg "; - } - case IGMP_PIM: - switch (code) { - case PIM_QUERY: return "PIM Router-Query "; - case PIM_REGISTER: return "PIM Register "; - case PIM_REGISTER_STOP: return "PIM Register-Stop "; - case PIM_JOIN_PRUNE: return "PIM Join/Prune "; - case PIM_RP_REACHABLE: return "PIM RP-Reachable "; - case PIM_ASSERT: return "PIM Assert "; - case PIM_GRAFT: return "PIM Graft "; - case PIM_GRAFT_ACK: return "PIM Graft-Ack "; - default: return "unknown PIM msg "; - } - case IGMP_MTRACE: return "IGMP trace query "; - case IGMP_MTRACE_RESP: return "IGMP trace reply "; - default: return "unknown IGMP msg "; - } -} - -/* - * Process a newly received IGMP packet that is sitting in the input - * packet buffer. - */ -void -accept_igmp(recvlen) - int recvlen; -{ - register u_int32 src, dst, group; - struct ip *ip; - struct igmp *igmp; - int ipdatalen, iphdrlen, igmpdatalen; - - if (recvlen < sizeof(struct ip)) { - log(LOG_WARNING, 0, - "received packet too short (%u bytes) for IP header", recvlen); - return; - } - - ip = (struct ip *)recv_buf; - src = ip->ip_src.s_addr; - dst = ip->ip_dst.s_addr; - - /* - * this is most likely a message from the kernel indicating that - * a new src grp pair message has arrived and so, it would be - * necessary to install a route into the kernel for this. - */ - if (ip->ip_p == 0) { - if (src == 0 || dst == 0) - log(LOG_WARNING, 0, "kernel request not accurate"); - else - add_table_entry(src, dst); - return; - } - - iphdrlen = ip->ip_hl << 2; - ipdatalen = ip->ip_len; - if (iphdrlen + ipdatalen != recvlen) { - log(LOG_WARNING, 0, - "received packet from %s shorter (%u bytes) than hdr+data length (%u+%u)", - inet_fmt(src, s1), recvlen, iphdrlen, ipdatalen); - return; - } - - igmp = (struct igmp *)(recv_buf + iphdrlen); - group = igmp->igmp_group.s_addr; - igmpdatalen = ipdatalen - IGMP_MINLEN; - if (igmpdatalen < 0) { - log(LOG_WARNING, 0, - "received IP data field too short (%u bytes) for IGMP, from %s", - ipdatalen, inet_fmt(src, s1)); - return; - } - - log(LOG_DEBUG, 0, "RECV %s from %-15s to %s", - 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: - accept_membership_query(src, dst, group, igmp->igmp_code); - return; - - case IGMP_HOST_MEMBERSHIP_REPORT: - case IGMP_HOST_NEW_MEMBERSHIP_REPORT: - accept_group_report(src, dst, group, igmp->igmp_type); - return; - - case IGMP_HOST_LEAVE_MESSAGE: - accept_leave_message(src, dst, group); - return; - - case IGMP_DVMRP: - group = ntohl(group); - - switch (igmp->igmp_code) { - case DVMRP_PROBE: - accept_probe(src, dst, - (char *)(igmp+1), igmpdatalen, group); - return; - - case DVMRP_REPORT: - accept_report(src, dst, - (char *)(igmp+1), igmpdatalen, group); - return; - - case DVMRP_ASK_NEIGHBORS: - accept_neighbor_request(src, dst); - return; - - case DVMRP_ASK_NEIGHBORS2: - accept_neighbor_request2(src, dst); - return; - - case DVMRP_NEIGHBORS: - accept_neighbors(src, dst, (u_char *)(igmp+1), igmpdatalen, - group); - return; - - case DVMRP_NEIGHBORS2: - accept_neighbors2(src, dst, (u_char *)(igmp+1), igmpdatalen, - group); - return; - - case DVMRP_PRUNE: - accept_prune(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - case DVMRP_GRAFT: - accept_graft(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - case DVMRP_GRAFT_ACK: - accept_g_ack(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - case DVMRP_INFO_REQUEST: - accept_info_request(src, dst, (char *)(igmp+1), - igmpdatalen); - return; - - case DVMRP_INFO_REPLY: - accept_info_reply(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - default: - log(LOG_INFO, 0, - "ignoring unknown DVMRP message code %u from %s to %s", - igmp->igmp_code, inet_fmt(src, s1), - inet_fmt(dst, s2)); - return; - } - - case IGMP_PIM: - return; - - case IGMP_MTRACE_RESP: - return; - - case IGMP_MTRACE: - accept_mtrace(src, dst, group, (char *)(igmp+1), - igmp->igmp_code, igmpdatalen); - return; - - default: - log(LOG_INFO, 0, - "ignoring unknown IGMP message type %x from %s to %s", - igmp->igmp_type, inet_fmt(src, s1), - inet_fmt(dst, s2)); - return; - } -} - -/* - * Some IGMP messages are more important than others. This routine - * determines the logging level at which to log a send error (often - * "No route to host"). This is important when there is asymmetric - * reachability and someone is trying to, i.e., mrinfo me periodically. - */ -static int -igmp_log_level(type, code) - u_int type, code; -{ - switch (type) { - case IGMP_MTRACE_RESP: - return LOG_INFO; - - case IGMP_DVMRP: - switch (code) { - case DVMRP_NEIGHBORS: - case DVMRP_NEIGHBORS2: - return LOG_INFO; - } - } - return LOG_WARNING; -} - -/* - * Construct an IGMP message in the output packet buffer. The caller may - * have already placed data in that buffer, of length 'datalen'. Then send - * the message from the interface with IP address 'src' to destination 'dst'. - */ -void -send_igmp(src, dst, type, code, group, datalen) - u_int32 src, dst; - int type, code; - u_int32 group; - int datalen; -{ - struct sockaddr_in sdst; - struct ip *ip; - struct igmp *igmp; - int setloop; - - 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); - - if (IN_MULTICAST(ntohl(dst))) { - k_set_if(src); - if (type != IGMP_DVMRP) { - setloop = 1; - k_set_loop(TRUE); - } - } - - bzero(&sdst, sizeof(sdst)); - sdst.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - sdst.sin_len = sizeof(sdst); -#endif - sdst.sin_addr.s_addr = dst; - if (sendto(igmp_socket, send_buf, ip->ip_len, 0, - (struct sockaddr *)&sdst, sizeof(sdst)) < 0) { - if (errno == ENETDOWN) - check_vif_state(); - else - log(igmp_log_level(type, code), errno, - "sendto to %s on %s", - inet_fmt(dst, s1), inet_fmt(src, s2)); - } - - if (setloop) - k_set_loop(FALSE); - - log(LOG_DEBUG, 0, "SENT %s from %-15s to %s", - packet_kind(type, code), inet_fmt(src, s1), inet_fmt(dst, s2)); -} diff --git a/usr.sbin/mrouted/inet.c b/usr.sbin/mrouted/inet.c deleted file mode 100644 index b60e3854da35..000000000000 --- a/usr.sbin/mrouted/inet.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: inet.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - - -#include "defs.h" - - -/* - * Exported variables. - */ -char s1[19]; /* buffers to hold the string representations */ -char s2[19]; /* of IP addresses, to be passed to inet_fmt() */ -char s3[19]; /* or inet_fmts(). */ -char s4[19]; - - -/* - * Verify that a given IP address is credible as a host address. - * (Without a mask, cannot detect addresses of the form {subnet,0} or - * {subnet,-1}.) - */ -int -inet_valid_host(naddr) - u_int32 naddr; -{ - register u_int32 addr; - - addr = ntohl(naddr); - - return (!(IN_MULTICAST(addr) || - IN_BADCLASS (addr) || - (addr & 0xff000000) == 0)); -} - -/* - * Verify that a given netmask is plausible; - * make sure that it is a series of 1's followed by - * a series of 0's with no discontiguous 1's. - */ -int -inet_valid_mask(mask) - u_int32 mask; -{ - if (~(((mask & -mask) - 1) | mask) != 0) { - /* Mask is not contiguous */ - return (FALSE); - } - - return (TRUE); -} - -/* - * Verify that a given subnet number and mask pair are credible. - * - * With CIDR, almost any subnet and mask are credible. mrouted still - * can't handle aggregated class A's, so we still check that, but - * otherwise the only requirements are that the subnet address is - * within the [ABC] range and that the host bits of the subnet - * are all 0. - */ -int -inet_valid_subnet(nsubnet, nmask) - u_int32 nsubnet, nmask; -{ - register u_int32 subnet, mask; - - subnet = ntohl(nsubnet); - mask = ntohl(nmask); - - if ((subnet & mask) != subnet) return (FALSE); - - if (subnet == 0) - return (mask == 0); - - if (IN_CLASSA(subnet)) { - if (mask < 0xff000000 || - (subnet & 0xff000000) == 0x7f000000 || - (subnet & 0xff000000) == 0x00000000) return (FALSE); - } - else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) { - /* Above Class C address space */ - return (FALSE); - } - if (subnet & ~mask) { - /* Host bits are set in the subnet */ - return (FALSE); - } - if (!inet_valid_mask(mask)) { - /* Netmask is not contiguous */ - return (FALSE); - } - - return (TRUE); -} - - -/* - * Convert an IP address in u_long (network) format into a printable string. - */ -char * -inet_fmt(addr, s) - u_int32 addr; - char *s; -{ - register u_char *a; - - a = (u_char *)&addr; - sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); - return (s); -} - - -/* - * Convert an IP subnet number in u_long (network) format into a printable - * string including the netmask as a number of bits. - */ -char * -inet_fmts(addr, mask, s) - u_int32 addr, mask; - char *s; -{ - register u_char *a, *m; - int bits; - - if ((addr == 0) && (mask == 0)) { - sprintf(s, "default"); - return (s); - } - a = (u_char *)&addr; - m = (u_char *)&mask; - bits = 33 - ffs(ntohl(mask)); - - if (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3], - bits); - else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d", a[0], a[1], a[2], bits); - else if (m[1] != 0) sprintf(s, "%u.%u/%d", a[0], a[1], bits); - else sprintf(s, "%u/%d", a[0], bits); - - return (s); -} - -/* - * Convert the printable string representation of an IP address into the - * u_long (network) format. Return 0xffffffff on error. (To detect the - * legal address with that value, you must explicitly compare the string - * with "255.255.255.255".) - */ -u_int32 -inet_parse(s) - char *s; -{ - u_int32 a = 0; - u_int a0, a1, a2, a3; - char c; - - if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 || - a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255) - return (0xffffffff); - - ((u_char *)&a)[0] = a0; - ((u_char *)&a)[1] = a1; - ((u_char *)&a)[2] = a2; - ((u_char *)&a)[3] = a3; - - return (a); -} - - -/* - * inet_cksum extracted from: - * P I N G . C - * - * Author - - * Mike Muuss - * U. S. Army Ballistic Research Laboratory - * December, 1983 - * Modified at Uc Berkeley - * - * (ping.c) Status - - * Public Domain. Distribution Unlimited. - * - * I N _ C K S U M - * - * Checksum routine for Internet Protocol family headers (C Version) - * - */ -int -inet_cksum(addr, len) - u_short *addr; - u_int len; -{ - register int nleft = (int)len; - register u_short *w = addr; - u_short answer = 0; - register int sum = 0; - - /* - * Our algorithm is simple, using a 32 bit accumulator (sum), - * we add sequential 16 bit words to it, and at the end, fold - * back all the carry bits from the top 16 bits into the lower - * 16 bits. - */ - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nleft == 1) { - *(u_char *) (&answer) = *(u_char *)w ; - sum += answer; - } - - /* - * add back carry outs from top 16 bits to low 16 bits - */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return (answer); -} diff --git a/usr.sbin/mrouted/kern.c b/usr.sbin/mrouted/kern.c deleted file mode 100644 index 2a64e5c13916..000000000000 --- a/usr.sbin/mrouted/kern.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: kern.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - - -#include "defs.h" - - -void k_set_rcvbuf(bufsize) - int bufsize; -{ - if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF, - (char *)&bufsize, sizeof(bufsize)) < 0) - log(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize); -} - - -void k_hdr_include(bool) - int bool; -{ -#ifdef IP_HDRINCL - if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL, - (char *)&bool, sizeof(bool)) < 0) - log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool); -#endif -} - - -void k_set_ttl(t) - int t; -{ - u_char ttl; - - ttl = t; - if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL, - (char *)&ttl, sizeof(ttl)) < 0) - log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl); -} - - -void k_set_loop(l) - int l; -{ - u_char loop; - - loop = l; - if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP, - (char *)&loop, sizeof(loop)) < 0) - log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop); -} - - -void k_set_if(ifa) - u_int32 ifa; -{ - struct in_addr adr; - - adr.s_addr = ifa; - if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&adr, sizeof(adr)) < 0) - log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s", - inet_fmt(ifa, s1)); -} - - -void k_join(grp, ifa) - u_int32 grp; - u_int32 ifa; -{ - struct ip_mreq mreq; - - mreq.imr_multiaddr.s_addr = grp; - mreq.imr_interface.s_addr = ifa; - - if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *)&mreq, sizeof(mreq)) < 0) - log(LOG_WARNING, errno, "can't join group %s on interface %s", - inet_fmt(grp, s1), inet_fmt(ifa, s2)); -} - - -void k_leave(grp, ifa) - u_int32 grp; - u_int32 ifa; -{ - struct ip_mreq mreq; - - mreq.imr_multiaddr.s_addr = grp; - mreq.imr_interface.s_addr = ifa; - - if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (char *)&mreq, sizeof(mreq)) < 0) - log(LOG_WARNING, errno, "can't leave group %s on interface %s", - inet_fmt(grp, s1), inet_fmt(ifa, s2)); -} - - -void k_init_dvmrp() -{ -#ifdef OLD_KERNEL - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT, - (char *)NULL, 0) < 0) -#else - int v=1; - - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT, - (char *)&v, sizeof(int)) < 0) -#endif - log(LOG_ERR, errno, "can't enable Multicast routing in kernel"); -} - - -void k_stop_dvmrp() -{ - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE, - (char *)NULL, 0) < 0) - log(LOG_WARNING, errno, "can't disable Multicast routing in kernel"); -} - - -void k_add_vif(vifi, v) - vifi_t vifi; - struct uvif *v; -{ - struct vifctl vc; - - vc.vifc_vifi = vifi; - vc.vifc_flags = v->uv_flags & VIFF_KERNEL_FLAGS; - vc.vifc_threshold = v->uv_threshold; - vc.vifc_rate_limit = v->uv_rate_limit; - vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr; - vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr; - - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF, - (char *)&vc, sizeof(vc)) < 0) - log(LOG_ERR, errno, "setsockopt MRT_ADD_VIF"); -} - - -void k_del_vif(vifi) - vifi_t vifi; -{ - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF, - (char *)&vifi, sizeof(vifi)) < 0) - log(LOG_ERR, errno, "setsockopt MRT_DEL_VIF"); -} - - -/* - * Adds a (source, mcastgrp) entry to the kernel - */ -void k_add_rg(origin, g) - u_int32 origin; - struct gtable *g; -{ - struct mfcctl mc; - vifi_t i; - -#ifdef DEBUG_MFC - md_log(MD_ADD, origin, g->gt_mcastgrp); -#endif - /* copy table values so that setsockopt can process it */ - mc.mfcc_origin.s_addr = origin; -#ifdef OLD_KERNEL - mc.mfcc_originmask.s_addr = 0xffffffff; -#endif - mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp; - mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF; - for (i = 0; i < numvifs; i++) - mc.mfcc_ttls[i] = g->gt_ttls[i]; - - /* write to kernel space */ - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC, - (char *)&mc, sizeof(mc)) < 0) { -#ifdef DEBUG_MFC - md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp); -#endif - log(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC"); - } -} - - -/* - * Deletes a (source, mcastgrp) entry from the kernel - */ -int k_del_rg(origin, g) - u_int32 origin; - struct gtable *g; -{ - struct mfcctl mc; - int retval; - -#ifdef DEBUG_MFC - md_log(MD_DEL, origin, g->gt_mcastgrp); -#endif - /* copy table values so that setsockopt can process it */ - mc.mfcc_origin.s_addr = origin; -#ifdef OLD_KERNEL - mc.mfcc_originmask.s_addr = 0xffffffff; -#endif - mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp; - - /* write to kernel space */ - if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC, - (char *)&mc, sizeof(mc))) < 0) { -#ifdef DEBUG_MFC - md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp); -#endif - log(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC"); - } - - return retval; -} - -/* - * Get the kernel's idea of what version of mrouted needs to run with it. - */ -int k_get_version() -{ -#ifdef OLD_KERNEL - return -1; -#else - int vers; - int len = sizeof(vers); - - if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION, - (char *)&vers, &len) < 0) - log(LOG_ERR, errno, - "getsockopt MRT_VERSION: perhaps your kernel is too old"); - - return vers; -#endif -} diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c deleted file mode 100644 index b5ef723bcb73..000000000000 --- a/usr.sbin/mrouted/main.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $ - */ - -/* - * Written by Steve Deering, Stanford University, February 1989. - * - * (An earlier version of DVMRP was implemented by David Waitzman of - * BBN STC by extending Berkeley's routed program. Some of Waitzman's - * extensions have been incorporated into mrouted, but none of the - * original routed code has been adopted.) - */ - - -#include "defs.h" -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif -#include <fcntl.h> - -#ifdef SNMP -#include "snmp.h" -#endif - -#ifndef lint -static char rcsid[] = - "@(#) $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $"; -#endif - -extern char *configfilename; -char versionstring[100]; - -static char pidfilename[] = _PATH_MROUTED_PID; -static char dumpfilename[] = _PATH_MROUTED_DUMP; -static char cachefilename[] = _PATH_MROUTED_CACHE; -static char genidfilename[] = _PATH_MROUTED_GENID; - -int cache_lifetime = DEFAULT_CACHE_LIFETIME; -int max_prune_lifetime = DEFAULT_CACHE_LIFETIME * 2; - -int debug = 0; -u_char pruning = 1; /* Enable pruning by default */ - -#ifdef SNMP -#define NHANDLERS 34 -#else -#define NHANDLERS 2 -#endif - -static struct ihandler { - int fd; /* File descriptor */ - ihfunc_t func; /* Function to call with &fd_set */ -} ihandlers[NHANDLERS]; -static int nhandlers = 0; - -/* - * 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 cleanup __P((void)); -static void resetlogging __P((void *)); - -/* To shut up gcc -Wstrict-prototypes */ -int main __P((int argc, char **argv)); - -int -register_input_handler(fd, func) - int fd; - ihfunc_t func; -{ - if (nhandlers >= NHANDLERS) - return -1; - - ihandlers[nhandlers].fd = fd; - ihandlers[nhandlers++].func = func; - - return 0; -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - register int recvlen; - register int omask; - int dummy; - FILE *fp; - struct timeval tv; - u_int32 prev_genid; - int vers; - fd_set rfds, readers; - int nfds, n, i; -#ifdef SNMP - struct timeval timeout, *tvp = &timeout; - struct timeval sched, *svp = &sched, now, *nvp = &now; - int index, block; -#endif - - setlinebuf(stderr); - - if (geteuid() != 0) { - fprintf(stderr, "must be root\n"); - exit(1); - } - - argv++, argc--; - while (argc > 0 && *argv[0] == '-') { - if (strcmp(*argv, "-d") == 0) { - if (argc > 1 && isdigit(*(argv + 1)[0])) { - argv++, argc--; - debug = atoi(*argv); - } else - debug = DEFAULT_DEBUG; - } else if (strcmp(*argv, "-c") == 0) { - if (argc > 1) { - argv++, argc--; - configfilename = *argv; - } else - goto usage; - } else if (strcmp(*argv, "-p") == 0) { - pruning = 0; -#ifdef SNMP - } else if (strcmp(*argv, "-P") == 0) { - if (argc > 1 && isdigit(*(argv + 1)[0])) { - argv++, argc--; - dest_port = atoi(*argv); - } else - dest_port = DEFAULT_PORT; -#endif - } else - goto usage; - argv++, argc--; - } - - if (argc > 0) { -usage: fprintf(stderr, - "usage: mrouted [-p] [-c configfile] [-d [debug_level]]\n"); - exit(1); - } - - if (debug == 0) { - /* - * Detach from the terminal - */ - int t; - - 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); - } -#else - if (setsid() < 0) - perror("setsid"); -#endif -#endif - } - else - fprintf(stderr, "debug level %u\n", debug); - -#ifdef LOG_DAEMON - (void)openlog("mrouted", LOG_PID, LOG_DAEMON); - (void)setlogmask(LOG_UPTO(LOG_NOTICE)); -#else - (void)openlog("mrouted", LOG_PID); -#endif - sprintf(versionstring, "mrouted version %d.%d", - PROTOCOL_VERSION, MROUTED_VERSION); - - log(LOG_NOTICE, 0, "%s", versionstring); - -#ifdef SYSV - srand48(time(NULL)); -#else - srandom(gethostid()); -#endif - - /* - * Get generation id - */ - gettimeofday(&tv, 0); - dvmrp_genid = tv.tv_sec; - - fp = fopen(genidfilename, "r"); - if (fp != NULL) { - fscanf(fp, "%d", &prev_genid); - if (prev_genid == dvmrp_genid) - dvmrp_genid++; - (void) fclose(fp); - } - - fp = fopen(genidfilename, "w"); - if (fp != NULL) { - fprintf(fp, "%d", dvmrp_genid); - (void) fclose(fp); - } - - callout_init(); - init_igmp(); - init_routes(); - init_ktable(); - k_init_dvmrp(); /* enable DVMRP routing in kernel */ - -#ifndef OLD_KERNEL - vers = k_get_version(); - /*XXX - * This function must change whenever the kernel version changes - */ - if ((((vers >> 8) & 0xff) != 3) || - ((vers & 0xff) != 5)) - log(LOG_ERR, 0, "kernel (v%d.%d)/mrouted (v%d.%d) version mismatch", - (vers >> 8) & 0xff, vers & 0xff, - PROTOCOL_VERSION, MROUTED_VERSION); -#endif - -#ifdef SNMP - if (i = snmp_init()) - return i; - - gettimeofday(nvp, 0); - if (nvp->tv_usec < 500000L){ - svp->tv_usec = nvp->tv_usec + 500000L; - svp->tv_sec = nvp->tv_sec; - } else { - svp->tv_usec = nvp->tv_usec - 500000L; - svp->tv_sec = nvp->tv_sec + 1; - } -#endif /* SNMP */ - - init_vifs(); - -#ifdef RSRR - rsrr_init(); -#endif /* RSRR */ - -#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); - - FD_ZERO(&readers); - FD_SET(igmp_socket, &readers); - nfds = igmp_socket + 1; - for (i = 0; i < nhandlers; i++) { - FD_SET(ihandlers[i].fd, &readers); - if (ihandlers[i].fd >= nfds) - nfds = ihandlers[i].fd + 1; - } - - /* - * Install the vifs in the kernel as late as possible in the - * initialization sequence. - */ - init_installvifs(); - - if (debug >= 2) dump(0); - - /* Start up the log rate-limiter */ - resetlogging(NULL); - - (void)alarm(1); /* schedule first timer interrupt */ - - /* - * Main receive loop. - */ - dummy = 0; - for(;;) { -#ifdef SYSV - sigset_t block, oblock; -#endif - bcopy((char *)&readers, (char *)&rfds, sizeof(rfds)); -#ifdef SNMP - gettimeofday(nvp, 0); - if (nvp->tv_sec > svp->tv_sec - || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){ - alarmTimer(nvp); - eventTimer(nvp); - if (nvp->tv_usec < 500000L){ - svp->tv_usec = nvp->tv_usec + 500000L; - svp->tv_sec = nvp->tv_sec; - } else { - svp->tv_usec = nvp->tv_usec - 500000L; - svp->tv_sec = nvp->tv_sec + 1; - } - } - - tvp = &timeout; - tvp->tv_sec = 0; - tvp->tv_usec = 500000L; - - block = 0; - snmp_select_info(&nfds, &rfds, tvp, &block); - if (block == 1) - tvp = NULL; /* block without timeout */ - if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0) -#else - if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0) -#endif - { - if (errno != EINTR) /* SIGALRM is expected */ - 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; - } -#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); - } - } - -#ifdef SNMP - snmp_read(&rfds); - snmp_timeout(); /* poll */ -#endif - } -} - - -/* - * routine invoked every second. Its main goal is to cycle through - * the routing table and send partial updates to all neighbors at a - * rate that will cause the entire table to be sent in ROUTE_REPORT_INTERVAL - * seconds. Also, every TIMER_INTERVAL seconds it calls timer() to - * do all the other time-based processing. - */ -static void -fasttimer(i) - int i; -{ - static unsigned int tlast; - static unsigned int nsent; - register unsigned int t = tlast + 1; - register int n; - - /* - * if we're in the last second, send everything that's left. - * otherwise send at least the fraction we should have sent by now. - */ - if (t >= ROUTE_REPORT_INTERVAL) { - register int nleft = nroutes - nsent; - while (nleft > 0) { - if ((n = report_next_chunk()) <= 0) - break; - nleft -= n; - } - tlast = 0; - nsent = 0; - } else { - register unsigned int ncum = nroutes * t / ROUTE_REPORT_INTERVAL; - while (nsent < ncum) { - if ((n = report_next_chunk()) <= 0) - break; - nsent += n; - } - tlast = t; - } - if ((t % TIMER_INTERVAL) == 0) - timer(); - - age_callout_queue();/* Advance the timer for the callout queue - for groups */ - alarm(1); -} - -/* - * The 'virtual_time' variable is initialized to a value that will cause the - * first invocation of timer() to send a probe or route report to all vifs - * and send group membership queries to all subnets for which this router is - * querier. This first invocation occurs approximately TIMER_INTERVAL seconds - * after the router starts up. Note that probes for neighbors and queries - * for group memberships are also sent at start-up time, as part of initial- - * ization. This repetition after a short interval is desirable for quickly - * building up topology and membership information in the presence of possible - * packet loss. - * - * 'virtual_time' advances at a rate that is only a crude approximation of - * real time, because it does not take into account any time spent processing, - * and because the timer intervals are sometimes shrunk by a random amount to - * avoid unwanted synchronization with other routers. - */ - -static u_long virtual_time = 0; - - -/* - * Timer routine. Performs periodic neighbor probing, route reporting, and - * group querying duties, and drives various timers in routing entries and - * virtual interface data structures. - */ -static void -timer() -{ - 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) { - /* - * Time to query the local group memberships on all subnets - * for which this router is the elected querier. - */ - query_groups(); - } - - if (virtual_time % NEIGHBOR_PROBE_INTERVAL == 0) { - /* - * Time to send a probe on all vifs from which no neighbors have - * been heard. Also, check if any inoperative interfaces have now - * come up. (If they have, they will also be probed as part of - * their initialization.) - */ - probe_for_neighbors(); - - if (vifs_down) - check_vif_state(); - } - - delay_change_reports = FALSE; - if (routes_changed) { - /* - * Some routes have changed since the last timer interrupt, but - * have not been reported yet. Report the changed routes to all - * neighbors. - */ - report_to_all_neighbors(CHANGED_ROUTES); - } - -#ifdef SNMP - sync_timer(); -#endif - - /* - * Advance virtual time - */ - virtual_time += TIMER_INTERVAL; -} - - -/* - * 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() -{ - static in_cleanup = 0; - - if (!in_cleanup) { - in_cleanup++; -#ifdef RSRR - rsrr_clean(); -#endif /* RSRR */ - expire_all_routes(); - report_to_all_neighbors(ALL_ROUTES); - k_stop_dvmrp(); - } -} - - -/* - * Dump internal data structures to stderr. - */ -static void -dump(i) - int i; -{ - dump_vifs(stderr); - dump_routes(stderr); -} - - -/* - * Dump internal data structures to a file. - */ -static void -fdump(i) - int i; -{ - FILE *fp; - - fp = fopen(dumpfilename, "w"); - if (fp != NULL) { - dump_vifs(fp); - dump_routes(fp); - (void) fclose(fp); - } -} - - -/* - * Dump local cache contents to a file. - */ -static void -cdump(i) - int i; -{ - FILE *fp; - - fp = fopen(cachefilename, "w"); - if (fp != NULL) { - dump_cache(fp); - (void) fclose(fp); - } -} - - -/* - * Restart mrouted - */ -static void -restart(i) - int i; -{ - register int omask; -#ifdef SYSV - sigset_t block, oblock; -#endif - - log(LOG_NOTICE, 0, "%s restart", versionstring); - - /* - * 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(); - stop_all_vifs(); - k_stop_dvmrp(); - close(igmp_socket); - close(udp_socket); - - /* - * 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(); - -#ifdef SYSV - (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL); -#else - (void)sigsetmask(omask); -#endif -} - -#define LOG_MAX_MSGS 20 /* if > 20/minute then shut up for a while */ -#define LOG_SHUT_UP 600 /* shut up for 10 minutes */ -static int log_nmsgs = 0; - -static void -resetlogging(arg) - void *arg; -{ - int nxttime = 60; - void *narg = NULL; - - if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) { - nxttime = LOG_SHUT_UP; - narg = (void *)&log_nmsgs; /* just need some valid void * */ - syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes", - LOG_SHUT_UP / 60); - } else { - log_nmsgs = 0; - } - - timer_setTimer(nxttime, resetlogging, narg); -} - -/* - * Log errors and other messages to the system log daemon and to stderr, - * according to the severity of the message and the current debug level. - * For errors of severity LOG_ERR or worse, terminate the program. - */ -#ifdef __STDC__ -void -log(int severity, int syserr, char *format, ...) -{ - va_list ap; - static char fmt[211] = "warning - "; - char *msg; - char tbuf[20]; - struct timeval now; - struct tm *thyme; - - va_start(ap, format); -#else -/*VARARGS3*/ -void -log(severity, syserr, format, va_alist) - int severity, syserr; - char *format; - va_dcl -{ - va_list ap; - static char fmt[211] = "warning - "; - char *msg; - char tbuf[20]; - struct timeval now; - struct tm *thyme; - - va_start(ap); -#endif - vsprintf(&fmt[10], format, ap); - 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); - } - - 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); - } - - if (severity <= LOG_ERR) exit(-1); - } -} - -#ifdef DEBUG_MFC -void -md_log(what, origin, mcastgrp) - int what; - u_int32 origin, mcastgrp; -{ - static FILE *f = NULL; - struct timeval tv; - u_int32 buf[4]; - - if (!f) { - if ((f = fopen("/tmp/mrouted.clog", "w")) == NULL) { - log(LOG_ERR, errno, "open /tmp/mrouted.clog"); - } - } - - gettimeofday(&tv, NULL); - buf[0] = tv.tv_sec; - buf[1] = what; - buf[2] = origin; - buf[3] = mcastgrp; - - fwrite(buf, sizeof(u_int32), 4, f); -} -#endif diff --git a/usr.sbin/mrouted/map-mbone.8 b/usr.sbin/mrouted/map-mbone.8 deleted file mode 100644 index ba850d234395..000000000000 --- a/usr.sbin/mrouted/map-mbone.8 +++ /dev/null @@ -1,89 +0,0 @@ -.TH MAP-MBONE 8 -.UC 5 -.SH NAME -map-mbone \- Multicast connection mapper -.SH SYNOPSIS -.B /usr/sbin/map-mbone -[ -.B \-d -.I debug_level -] [ -.B \-f -] [ -.B \-g -] [ -.B \-n -] [ -.B \-r -.I retry_count -] [ -.B \-t -.I timeout_count -] [ -.B starting_router -] -.SH DESCRIPTION -.I map-mbone -attempts to display all multicast routers that are reachable from the multicast -.I starting_router. -If not specified on the command line, the default multicast -.I starting_router -is the localhost. -.PP -.I map-mbone -traverses neighboring multicast routers by sending the ASK_NEIGHBORS IGMP -message to the multicast starting_router. If this multicast router responds, -the version number and a list of their neighboring multicast router addresses is -part of that response. If the responding router has recent multicast version -number, then -.I map-mbone -requests additional information such as metrics, thresholds, and flags from the -multicast router. For each new occurrence of neighboring multicast router in -the reply and provided the flooding option has been selected, then -.I map-mbone -asks each of this multicast router for a list of neighbors. This search -for unique routers will continue until no new neighboring multicast routers -are reported. -.br -.ne 5 -.SH INVOCATION -.PP -"\-d" option sets the debug level. When the debug level is greater than the -default value of 0, addition debugging messages are printed. Regardless of -the debug level, an error condition, will always write an error message and will -cause -.I map-mbone -to terminate. -Non-zero debug levels have the following effects: -.IP "level 1" -packet warnings are printed to stderr. -.IP "level 2" -all level 1 messages plus notifications down networks are printed to stderr. -.IP "level 3" -all level 2 messages plus notifications of all packet -timeouts are printed to stderr. -.PP -"\-f" option sets flooding option. Flooding allows the recursive search -of neighboring multicast routers and is enable by default when starting_router -is not used. -.PP -"\-g" option sets graphing in GraphEd format. -.PP -"\-n" option disables the DNS lookup for the multicast routers names. -.PP -"\-r retry_count" sets the neighbor query retry limit. Default is 1 retry. -.PP -"\-t timeout_count" sets the number of seconds to wait for a neighbor query -reply before retrying. Default timeout is 2 seconds. -.PP -.SH IMPORTANT NOTE -.I map-mbone -must be run as root. -.PP -.SH SEE ALSO -.BR mrouted (8) , -.BR mrinfo (8) , -.BR mtrace (8) -.PP -.SH AUTHOR -Pavel Curtis diff --git a/usr.sbin/mrouted/mapper.c b/usr.sbin/mrouted/mapper.c deleted file mode 100644 index 1eacd04bb61d..000000000000 --- a/usr.sbin/mrouted/mapper.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* 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 $ - */ - -/* - * Copyright (c) Xerox Corporation 1992. All rights reserved. - * - * License is granted to copy, to use, and to make and to use derivative - * works for research and evaluation purposes, provided that Xerox is - * acknowledged in all documentation pertaining to any such copy or derivative - * work. Xerox grants no other licenses expressed or implied. The Xerox trade - * name should not be used in any advertising without its written permission. - * - * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE - * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE - * FOR ANY PARTICULAR PURPOSE. The software is provided "as is" without - * express or implied warranty of any kind. - * - * These notices must be retained in any copies of any part of this software. - */ - -#include <string.h> -#include <netdb.h> -#include <sys/time.h> -#include "defs.h" -#include <arpa/inet.h> -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -#define DEFAULT_TIMEOUT 2 /* How long to wait before retrying requests */ -#define DEFAULT_RETRIES 1 /* How many times to ask each router */ - - -/* All IP addresses are stored in the data structure in NET order. */ - -typedef struct neighbor { - struct neighbor *next; - u_int32 addr; /* IP address in NET order */ - u_char metric; /* TTL cost of forwarding */ - u_char threshold; /* TTL threshold to forward */ - u_short flags; /* flags on connection */ -#define NF_PRESENT 0x8000 /* True if flags are meaningful */ -} Neighbor; - -typedef struct interface { - struct interface *next; - u_int32 addr; /* IP address of the interface in NET order */ - Neighbor *neighbors; /* List of neighbors' IP addresses */ -} Interface; - -typedef struct node { - u_int32 addr; /* IP address of this entry in NET order */ - u_int32 version; /* which mrouted version is running */ - int tries; /* How many requests sent? -1 for aliases */ - union { - struct node *alias; /* If alias, to what? */ - struct interface *interfaces; /* Else, neighbor data */ - } u; - struct node *left, *right; -} Node; - - -Node *routers = 0; -u_int32 our_addr, target_addr = 0; /* in NET order */ -int debug = 0; -int retries = DEFAULT_RETRIES; -int timeout = DEFAULT_TIMEOUT; -int show_names = TRUE; -vifi_t numvifs; /* to keep loader happy */ - /* (see COPY_TABLES macro called in kern.c) */ - -Node * find_node __P((u_int32 addr, Node **ptr)); -Interface * find_interface __P((u_int32 addr, Node *node)); -Neighbor * find_neighbor __P((u_int32 addr, Node *node)); -int main __P((int argc, char *argv[])); -void ask __P((u_int32 dst)); -void ask2 __P((u_int32 dst)); -int retry_requests __P((Node *node)); -char * inet_name __P((u_int32 addr)); -void print_map __P((Node *node)); -char * graph_name __P((u_int32 addr, char *buf)); -void graph_edges __P((Node *node)); -void elide_aliases __P((Node *node)); -void graph_map __P((void)); -int get_number __P((int *var, int deflt, char ***pargv, - int *pargc)); -u_int32 host_addr __P((char *name)); - - -Node *find_node(addr, ptr) - u_int32 addr; - Node **ptr; -{ - Node *n = *ptr; - - if (!n) { - *ptr = n = (Node *) malloc(sizeof(Node)); - n->addr = addr; - n->version = 0; - n->tries = 0; - n->u.interfaces = 0; - n->left = n->right = 0; - return n; - } else if (addr == n->addr) - return n; - else if (addr < n->addr) - return find_node(addr, &(n->left)); - else - return find_node(addr, &(n->right)); -} - - -Interface *find_interface(addr, node) - u_int32 addr; - Node *node; -{ - Interface *ifc; - - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) - if (ifc->addr == addr) - return ifc; - - ifc = (Interface *) malloc(sizeof(Interface)); - ifc->addr = addr; - ifc->next = node->u.interfaces; - node->u.interfaces = ifc; - ifc->neighbors = 0; - - return ifc; -} - - -Neighbor *find_neighbor(addr, node) - u_int32 addr; - Node *node; -{ - Interface *ifc; - - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) { - Neighbor *nb; - - for (nb = ifc->neighbors; nb; nb = nb->next) - if (nb->addr == addr) - return nb; - } - - return 0; -} - - -/* - * Log errors and other messages to stderr, according to the severity of the - * message and the current debug level. For errors of severity LOG_ERR or - * worse, terminate the program. - */ -#ifdef __STDC__ -void -log(int severity, int syserr, char *format, ...) -{ - va_list ap; - char fmt[100]; - - va_start(ap, format); -#else -/*VARARGS3*/ -void -log(severity, syserr, format, va_alist) - int severity, syserr; - char *format; - va_dcl -{ - va_list ap; - char fmt[100]; - - va_start(ap); -#endif - - switch (debug) { - case 0: if (severity > LOG_WARNING) return; - case 1: if (severity > LOG_NOTICE ) return; - case 2: if (severity > LOG_INFO ) return; - default: - fmt[0] = '\0'; - if (severity == LOG_WARNING) - strcat(fmt, "warning - "); - strncat(fmt, format, 80); - vfprintf(stderr, fmt, ap); - if (syserr == 0) - fprintf(stderr, "\n"); - else if (syserr < sys_nerr) - fprintf(stderr, ": %s\n", sys_errlist[syserr]); - else - fprintf(stderr, ": errno %d\n", syserr); - } - - if (severity <= LOG_ERR) - exit(-1); -} - - -/* - * Send a neighbors-list request. - */ -void ask(dst) - u_int32 dst; -{ - send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS, - htonl(MROUTED_LEVEL), 0); -} - -void ask2(dst) - u_int32 dst; -{ - send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, - htonl(MROUTED_LEVEL), 0); -} - - -/* - * Process an incoming group membership report. - */ -void accept_group_report(src, dst, group, r_type) - u_int32 src, dst, group; - int r_type; -{ - log(LOG_INFO, 0, "ignoring IGMP group membership report from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Process an incoming neighbor probe message. - */ -void accept_probe(src, dst, p, datalen, level) - u_int32 src, dst, level; - char *p; - int datalen; -{ - log(LOG_INFO, 0, "ignoring DVMRP probe from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Process an incoming route report message. - */ -void accept_report(src, dst, p, datalen, level) - u_int32 src, dst, level; - char *p; - int datalen; -{ - log(LOG_INFO, 0, "ignoring DVMRP routing report from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Process an incoming neighbor-list request message. - */ -void accept_neighbor_request(src, dst) - u_int32 src, dst; -{ - if (src != our_addr) - log(LOG_INFO, 0, - "ignoring spurious DVMRP neighbor request from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - -void accept_neighbor_request2(src, dst) - u_int32 src, dst; -{ - if (src != our_addr) - log(LOG_INFO, 0, - "ignoring spurious DVMRP neighbor request2 from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Process an incoming neighbor-list message. - */ -void accept_neighbors(src, dst, p, datalen, level) - u_int32 src, dst, level; - u_char *p; - int datalen; -{ - Node *node = find_node(src, &routers); - - if (node->tries == 0) /* Never heard of 'em; must have hit them at */ - node->tries = 1; /* least once, though...*/ - else if (node->tries == -1) /* follow alias link */ - node = node->u.alias; - -#define GET_ADDR(a) (a = ((u_int32)*p++ << 24), a += ((u_int32)*p++ << 16),\ - a += ((u_int32)*p++ << 8), a += *p++) - - /* if node is running a recent mrouted, ask for additional info */ - if (level != 0) { - node->version = level; - node->tries = 1; - ask2(src); - return; - } - - if (debug > 3) { - int i; - - fprintf(stderr, " datalen = %d\n", datalen); - for (i = 0; i < datalen; i++) { - if ((i & 0xF) == 0) - fprintf(stderr, " "); - fprintf(stderr, " %02x", p[i]); - if ((i & 0xF) == 0xF) - fprintf(stderr, "\n"); - } - if ((datalen & 0xF) != 0xF) - fprintf(stderr, "\n"); - } - - while (datalen > 0) { /* loop through interfaces */ - u_int32 ifc_addr; - u_char metric, threshold, ncount; - Node *ifc_node; - Interface *ifc; - Neighbor *old_neighbors; - - if (datalen < 4 + 3) { - log(LOG_WARNING, 0, "received truncated interface record from %s", - inet_fmt(src, s1)); - return; - } - - GET_ADDR(ifc_addr); - ifc_addr = htonl(ifc_addr); - metric = *p++; - threshold = *p++; - ncount = *p++; - datalen -= 4 + 3; - - /* Fix up any alias information */ - ifc_node = find_node(ifc_addr, &routers); - if (ifc_node->tries == 0) { /* new node */ - ifc_node->tries = -1; - ifc_node->u.alias = node; - } else if (ifc_node != node - && (ifc_node->tries > 0 || ifc_node->u.alias != node)) { - /* must merge two hosts' nodes */ - Interface *ifc_i, *next_ifc_i; - - if (ifc_node->tries == -1) { - Node *tmp = ifc_node->u.alias; - - ifc_node->u.alias = node; - ifc_node = tmp; - } - - /* Merge ifc_node (foo_i) into node (foo_n) */ - - if (ifc_node->tries > node->tries) - node->tries = ifc_node->tries; - - for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) { - Neighbor *nb_i, *next_nb_i, *nb_n; - Interface *ifc_n = find_interface(ifc_i->addr, node); - - old_neighbors = ifc_n->neighbors; - for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) { - next_nb_i = nb_i->next; - for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next) - if (nb_i->addr == nb_n->addr) { - if (nb_i->metric != nb_n->metric - || nb_i->threshold != nb_n->threshold) - log(LOG_WARNING, 0, - "inconsistent %s for neighbor %s of %s", - "metric/threshold", - inet_fmt(nb_i->addr, s1), - inet_fmt(node->addr, s2)); - free(nb_i); - break; - } - if (!nb_n) { /* no match for this neighbor yet */ - nb_i->next = ifc_n->neighbors; - ifc_n->neighbors = nb_i; - } - } - - next_ifc_i = ifc_i->next; - free(ifc_i); - } - - ifc_node->tries = -1; - ifc_node->u.alias = node; - } - - ifc = find_interface(ifc_addr, node); - old_neighbors = ifc->neighbors; - - /* Add the neighbors for this interface */ - while (ncount--) { - u_int32 neighbor; - Neighbor *nb; - Node *n_node; - - if (datalen < 4) { - log(LOG_WARNING, 0, "received truncated neighbor list from %s", - inet_fmt(src, s1)); - return; - } - - GET_ADDR(neighbor); - neighbor = htonl(neighbor); - datalen -= 4; - - for (nb = old_neighbors; nb; nb = nb->next) - if (nb->addr == neighbor) { - if (metric != nb->metric || threshold != nb->threshold) - log(LOG_WARNING, 0, - "inconsistent %s for neighbor %s of %s", - "metric/threshold", - inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2)); - goto next_neighbor; - } - - nb = (Neighbor *) malloc(sizeof(Neighbor)); - nb->next = ifc->neighbors; - ifc->neighbors = nb; - nb->addr = neighbor; - nb->metric = metric; - nb->threshold = threshold; - nb->flags = 0; - - n_node = find_node(neighbor, &routers); - if (n_node->tries == 0 && !target_addr) { /* it's a new router */ - ask(neighbor); - n_node->tries = 1; - } - - next_neighbor: ; - } - } -} - -void accept_neighbors2(src, dst, p, datalen, level) - u_int32 src, dst, level; - u_char *p; - int datalen; -{ - Node *node = find_node(src, &routers); - u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */ - /* well, only possibly_broken_cisco, but that's too long to type. */ - - if (node->tries == 0) /* Never heard of 'em; must have hit them at */ - node->tries = 1; /* least once, though...*/ - else if (node->tries == -1) /* follow alias link */ - node = node->u.alias; - - while (datalen > 0) { /* loop through interfaces */ - u_int32 ifc_addr; - u_char metric, threshold, ncount, flags; - Node *ifc_node; - Interface *ifc; - Neighbor *old_neighbors; - - if (datalen < 4 + 4) { - log(LOG_WARNING, 0, "received truncated interface record from %s", - inet_fmt(src, s1)); - return; - } - - ifc_addr = *(u_int32*)p; - p += 4; - metric = *p++; - threshold = *p++; - flags = *p++; - ncount = *p++; - datalen -= 4 + 4; - - if (broken_cisco && ncount == 0) /* dumb Ciscos */ - ncount = 1; - if (broken_cisco && ncount > 15) /* dumb Ciscos */ - ncount = ncount & 0xf; - - /* Fix up any alias information */ - ifc_node = find_node(ifc_addr, &routers); - if (ifc_node->tries == 0) { /* new node */ - ifc_node->tries = -1; - ifc_node->u.alias = node; - } else if (ifc_node != node - && (ifc_node->tries > 0 || ifc_node->u.alias != node)) { - /* must merge two hosts' nodes */ - Interface *ifc_i, *next_ifc_i; - - if (ifc_node->tries == -1) { - Node *tmp = ifc_node->u.alias; - - ifc_node->u.alias = node; - ifc_node = tmp; - } - - /* Merge ifc_node (foo_i) into node (foo_n) */ - - if (ifc_node->tries > node->tries) - node->tries = ifc_node->tries; - - for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) { - Neighbor *nb_i, *next_nb_i, *nb_n; - Interface *ifc_n = find_interface(ifc_i->addr, node); - - old_neighbors = ifc_n->neighbors; - for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) { - next_nb_i = nb_i->next; - for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next) - if (nb_i->addr == nb_n->addr) { - if (nb_i->metric != nb_n->metric - || nb_i->threshold != nb_i->threshold) - log(LOG_WARNING, 0, - "inconsistent %s for neighbor %s of %s", - "metric/threshold", - inet_fmt(nb_i->addr, s1), - inet_fmt(node->addr, s2)); - free(nb_i); - break; - } - if (!nb_n) { /* no match for this neighbor yet */ - nb_i->next = ifc_n->neighbors; - ifc_n->neighbors = nb_i; - } - } - - next_ifc_i = ifc_i->next; - free(ifc_i); - } - - ifc_node->tries = -1; - ifc_node->u.alias = node; - } - - ifc = find_interface(ifc_addr, node); - old_neighbors = ifc->neighbors; - - /* Add the neighbors for this interface */ - while (ncount-- && datalen > 0) { - u_int32 neighbor; - Neighbor *nb; - Node *n_node; - - if (datalen < 4) { - log(LOG_WARNING, 0, "received truncated neighbor list from %s", - inet_fmt(src, s1)); - return; - } - - neighbor = *(u_int32*)p; - p += 4; - datalen -= 4; - if (neighbor == 0) - /* make leaf nets point to themselves */ - neighbor = ifc_addr; - - for (nb = old_neighbors; nb; nb = nb->next) - if (nb->addr == neighbor) { - if (metric != nb->metric || threshold != nb->threshold) - log(LOG_WARNING, 0, - "inconsistent %s for neighbor %s of %s", - "metric/threshold", - inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2)); - goto next_neighbor; - } - - nb = (Neighbor *) malloc(sizeof(Neighbor)); - nb->next = ifc->neighbors; - ifc->neighbors = nb; - nb->addr = neighbor; - nb->metric = metric; - nb->threshold = threshold; - nb->flags = flags | NF_PRESENT; - - n_node = find_node(neighbor, &routers); - if (n_node->tries == 0 && !target_addr) { /* it's a new router */ - ask(neighbor); - n_node->tries = 1; - } - - next_neighbor: ; - } - } -} - - -void check_vif_state() -{ - log(LOG_NOTICE, 0, "network marked down..."); -} - - -int retry_requests(node) - Node *node; -{ - int result; - - if (node) { - result = retry_requests(node->left); - if (node->tries > 0 && node->tries < retries) { - if (node->version) - ask2(node->addr); - else - ask(node->addr); - node->tries++; - result = 1; - } - return retry_requests(node->right) || result; - } else - return 0; -} - - -char *inet_name(addr) - u_int32 addr; -{ - struct hostent *e; - - e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); - - return e ? e->h_name : 0; -} - - -void print_map(node) - Node *node; -{ - if (node) { - char *name, *addr; - - print_map(node->left); - - addr = inet_fmt(node->addr, s1); - if (!target_addr - || (node->tries >= 0 && node->u.interfaces) - || (node->tries == -1 - && node->u.alias->tries >= 0 - && node->u.alias->u.interfaces)) { - if (show_names && (name = inet_name(node->addr))) - printf("%s (%s):", addr, name); - else - printf("%s:", addr); - if (node->tries < 0) - printf(" alias for %s\n\n", inet_fmt(node->u.alias->addr, s1)); - else if (!node->u.interfaces) - printf(" no response to query\n\n"); - else { - Interface *ifc; - - if (node->version) - printf(" <v%d.%d>", node->version & 0xff, - (node->version >> 8) & 0xff); - printf("\n"); - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) { - Neighbor *nb; - char *ifc_name = inet_fmt(ifc->addr, s1); - int ifc_len = strlen(ifc_name); - int count = 0; - - printf(" %s:", ifc_name); - for (nb = ifc->neighbors; nb; nb = nb->next) { - if (count > 0) - printf("%*s", ifc_len + 5, ""); - printf(" %s", inet_fmt(nb->addr, s1)); - if (show_names && (name = inet_name(nb->addr))) - printf(" (%s)", name); - printf(" [%d/%d", nb->metric, nb->threshold); - if (nb->flags) { - u_short flags = nb->flags; - if (flags & DVMRP_NF_TUNNEL) - printf("/tunnel"); - if (flags & DVMRP_NF_SRCRT) - printf("/srcrt"); - if (flags & DVMRP_NF_QUERIER) - printf("/querier"); - if (flags & DVMRP_NF_DISABLED) - printf("/disabled"); - if (flags & DVMRP_NF_DOWN) - printf("/down"); - } - printf("]\n"); - count++; - } - } - printf("\n"); - } - } - print_map(node->right); - } -} - - -char *graph_name(addr, buf) - u_int32 addr; - char *buf; -{ - char *name; - - if (show_names && (name = inet_name(addr))) - strcpy(buf, name); - else - inet_fmt(addr, buf); - - return buf; -} - - -void graph_edges(node) - Node *node; -{ - Interface *ifc; - Neighbor *nb; - char name[100]; - - if (node) { - graph_edges(node->left); - if (node->tries >= 0) { - printf(" %d {$ NP %d0 %d0 $} \"%s%s\" \n", - (int) node->addr, - node->addr & 0xFF, (node->addr >> 8) & 0xFF, - graph_name(node->addr, name), - node->u.interfaces ? "" : "*"); - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) - for (nb = ifc->neighbors; nb; nb = nb->next) { - Node *nb_node = find_node(nb->addr, &routers); - Neighbor *nb2; - - if (nb_node->tries < 0) - nb_node = nb_node->u.alias; - - if (node != nb_node && - (!(nb2 = find_neighbor(node->addr, nb_node)) - || node->addr < nb_node->addr)) { - printf(" %d \"%d/%d", - nb_node->addr, nb->metric, nb->threshold); - if (nb2 && (nb2->metric != nb->metric - || nb2->threshold != nb->threshold)) - printf(",%d/%d", nb2->metric, nb2->threshold); - if (nb->flags & NF_PRESENT) - printf("%s%s", - nb->flags & DVMRP_NF_SRCRT ? "" : - nb->flags & DVMRP_NF_TUNNEL ? "E" : "P", - nb->flags & DVMRP_NF_DOWN ? "D" : ""); - printf("\"\n"); - } - } - printf(" ;\n"); - } - graph_edges(node->right); - } -} - -void elide_aliases(node) - Node *node; -{ - if (node) { - elide_aliases(node->left); - if (node->tries >= 0) { - Interface *ifc; - - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) { - Neighbor *nb; - - for (nb = ifc->neighbors; nb; nb = nb->next) { - Node *nb_node = find_node(nb->addr, &routers); - - if (nb_node->tries < 0) - nb->addr = nb_node->u.alias->addr; - } - } - } - elide_aliases(node->right); - } -} - -void graph_map() -{ - time_t now = time(0); - char *nowstr = ctime(&now); - - nowstr[24] = '\0'; /* Kill the newline at the end */ - elide_aliases(routers); - printf("GRAPH \"Multicast Router Connectivity: %s\" = UNDIRECTED\n", - nowstr); - graph_edges(routers); - printf("END\n"); -} - - -int get_number(var, deflt, pargv, pargc) - int *var, *pargc, deflt; - char ***pargv; -{ - if ((*pargv)[0][2] == '\0') { /* Get the value from the next argument */ - if (*pargc > 1 && isdigit((*pargv)[1][0])) { - (*pargv)++, (*pargc)--; - *var = atoi((*pargv)[0]); - return 1; - } else if (deflt >= 0) { - *var = deflt; - return 1; - } else - return 0; - } else { /* Get value from the rest of this argument */ - if (isdigit((*pargv)[0][2])) { - *var = atoi((*pargv)[0] + 2); - return 1; - } else { - return 0; - } - } -} - - -u_int32 host_addr(name) - char *name; -{ - struct hostent *e = gethostbyname(name); - int addr; - - if (e) - memcpy(&addr, e->h_addr_list[0], e->h_length); - else { - addr = inet_addr(name); - if (addr == -1) - addr = 0; - } - - return addr; -} - - -int main(argc, argv) - int argc; - char *argv[]; -{ - int flood = FALSE, graph = FALSE; - - setlinebuf(stderr); - - if (geteuid() != 0) { - fprintf(stderr, "must be root\n"); - exit(1); - } - - argv++, argc--; - while (argc > 0 && argv[0][0] == '-') { - switch (argv[0][1]) { - case 'd': - if (!get_number(&debug, DEFAULT_DEBUG, &argv, &argc)) - goto usage; - break; - case 'f': - flood = TRUE; - break; - case 'g': - graph = TRUE; - break; - case 'n': - show_names = FALSE; - break; - case 'r': - if (!get_number(&retries, -1, &argv, &argc)) - goto usage; - break; - case 't': - if (!get_number(&timeout, -1, &argv, &argc)) - goto usage; - break; - default: - goto usage; - } - argv++, argc--; - } - - if (argc > 1) { - usage: - fprintf(stderr, - "Usage: map-mbone [-f] [-g] [-n] [-t timeout] %s\n\n", - "[-r retries] [-d [debug-level]] [router]"); - fprintf(stderr, "\t-f Flood the routing graph with queries\n"); - fprintf(stderr, "\t (True by default unless `router' is given)\n"); - fprintf(stderr, "\t-g Generate output in GraphEd format\n"); - fprintf(stderr, "\t-n Don't look up DNS names for routers\n"); - exit(1); - } else if (argc == 1 && !(target_addr = host_addr(argv[0]))) { - fprintf(stderr, "Unknown host: %s\n", argv[0]); - exit(2); - } - - 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)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = dvmrp_group; - addr.sin_port = htons(2000); /* any port over 1024 will do... */ - if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0 - || connect(udp, (struct sockaddr *) &addr, sizeof(addr)) < 0 - || getsockname(udp, (struct sockaddr *) &addr, &addrlen) < 0) { - perror("Determining local address"); - exit(-1); - } - close(udp); - our_addr = addr.sin_addr.s_addr; - } - - /* Send initial seed message to all local routers */ - ask(target_addr ? target_addr : allhosts_group); - - if (target_addr) { - Node *n = find_node(target_addr, &routers); - - n->tries = 1; - - if (flood) - target_addr = 0; - } - - /* Main receive loop */ - for(;;) { - fd_set fds; - struct timeval tv; - int count, recvlen, dummy = 0; - - FD_ZERO(&fds); - FD_SET(igmp_socket, &fds); - - tv.tv_sec = timeout; - tv.tv_usec = 0; - - count = select(igmp_socket + 1, &fds, 0, 0, &tv); - - if (count < 0) { - if (errno != EINTR) - perror("select"); - continue; - } else if (count == 0) { - log(LOG_DEBUG, 0, "Timed out receiving neighbor lists"); - if (retry_requests(routers)) - continue; - else - break; - } - - recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, - 0, NULL, &dummy); - if (recvlen >= 0) - accept_igmp(recvlen); - else if (errno != EINTR) - perror("recvfrom"); - } - - printf("\n"); - - if (graph) - graph_map(); - else { - if (!target_addr) - printf("Multicast Router Connectivity:\n\n"); - print_map(routers); - } - - exit(0); -} - -/* dummies */ -void accept_prune(src, dst, p, datalen) - u_int32 src, dst; - char *p; - int datalen; -{ -} -void accept_graft(src, dst, p, datalen) - u_int32 src, dst; - char *p; - int datalen; -{ -} -void accept_g_ack(src, dst, p, datalen) - u_int32 src, dst; - char *p; - int datalen; -{ -} -void add_table_entry(origin, mcastgrp) - u_int32 origin, mcastgrp; -{ -} -void accept_leave_message(src, dst, group) - u_int32 src, dst, group; -{ -} -void accept_mtrace(src, dst, group, data, no, datalen) - u_int32 src, dst, group; - char *data; - u_int no; - int datalen; -{ -} -void accept_membership_query(src, dst, group, tmo) - u_int32 src, dst, group; - int tmo; -{ -} -void accept_info_request(src, dst, p, datalen) - u_int32 src, dst; - u_char *p; - int datalen; -{ -} -void accept_info_reply(src, dst, p, datalen) - u_int32 src, dst; - u_char *p; - int datalen; -{ -} diff --git a/usr.sbin/mrouted/mrinfo.8 b/usr.sbin/mrouted/mrinfo.8 deleted file mode 100644 index 1e7f9a91159a..000000000000 --- a/usr.sbin/mrouted/mrinfo.8 +++ /dev/null @@ -1,83 +0,0 @@ -.TH MRINFO 8 -.UC 5 -.SH NAME -mrinfo \- Displays configuration info from a multicast router -.SH SYNOPSIS -.B /usr/sbin/mrinfo -[ -.B \-d -.I debug_level -] [ -.B \-r -.I retry_count -] [ -.B \-t -.I timeout_count -] -.B multicast_router - -.SH DESCRIPTION -.I mrinfo -attempts to display the configuration information from the multicast router -.I multicast_router. -.PP -.I mrinfo -uses the ASK_NEIGHBORS IGMP message to the specified multicast router. If this -multicast router responds, the version number and a list of their neighboring -multicast router addresses is part of that response. If the responding router -has a recent multicast version number, then -.I mrinfo -requests additional information such as metrics, thresholds, and flags from the -multicast router. Once the specified multicast router responds, the -configuration is displayed to the standard output. -.br -.ne 5 -.SH INVOCATION -.PP -"\-d" option sets the debug level. When the debug level is greater than the -default value of 0, addition debugging messages are printed. Regardless of -the debug level, an error condition, will always write an error message and will -cause -.I mrinfo -to terminate. -Non-zero debug levels have the following effects: -.IP "level 1" -packet warnings are printed to stderr. -.IP "level 2" -all level 1 messages plus notifications down networks are printed to stderr. -.IP "level 3" -all level 2 messages plus notifications of all packet -timeouts are printed to stderr. -.PP -"\-r retry_count" sets the neighbor query retry limit. Default is 3 retry. -.PP -"\-t timeout_count" sets the number of seconds to wait for a neighbor query -reply. Default timeout is 4 seconds. -.PP -.SH SAMPLE OUTPUT -.nf -.I mrinfo mbone.phony.dom.net -127.148.176.10 (mbone.phony.dom.net) [version 3.3]: - 127.148.176.10 -> 0.0.0.0 (?) [1/1/querier] - 127.148.176.10 -> 127.0.8.4 (mbone2.phony.dom.net) [1/45/tunnel] - 127.148.176.10 -> 105.1.41.9 (momoney.com) [1/32/tunnel/down] - 127.148.176.10 -> 143.192.152.119 (mbone.dipu.edu) [1/32/tunnel] -.fi -.PP -For each neighbor of the queried multicast router, the IP of the queried router -is displayed, followed by the IP and name of the neighbor. In square brackets -the metric (cost of connection), the treashold (multicast ttl) is displayed. If -the queried multicast router has a newer version number, the type (tunnel, -srcrt) and status (disabled, down) of the connection is displayed. -.PP -.SH IMPORTANT NOTE -.I mrinfo -must be run as root. -.PP -.SH SEE ALSO -.BR mrouted (8) , -.BR map-mbone (8) , -.BR mtrace (8) -.PP -.SH AUTHOR -Van Jacobson diff --git a/usr.sbin/mrouted/mrinfo.c b/usr.sbin/mrouted/mrinfo.c deleted file mode 100644 index 7335aba95cf9..000000000000 --- a/usr.sbin/mrouted/mrinfo.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * This tool requests configuration info from a multicast router - * and prints the reply (if any). Invoke it as: - * - * mrinfo router-name-or-address - * - * Written Wed Mar 24 1993 by Van Jacobson (adapted from the - * multicast mapper written by Pavel Curtis). - * - * The lawyers insist we include the following UC copyright notice. - * The mapper from which this is derived contained a Xerox copyright - * notice which follows the UC one. Try not to get depressed noting - * that the legal gibberish is larger than the program. - * - * Copyright (c) 1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * --------------------------------- - * Copyright (c) Xerox Corporation 1992. All rights reserved. - * - * License is granted to copy, to use, and to make and to use derivative works - * for research and evaluation purposes, provided that Xerox is acknowledged - * in all documentation pertaining to any such copy or derivative work. Xerox - * grants no other licenses expressed or implied. The Xerox trade name should - * not be used in any advertising without its written permission. - * - * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE - * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE FOR - * ANY PARTICULAR PURPOSE. The software is provided "as is" without express - * or implied warranty of any kind. - * - * These notices must be retained in any copies of any part of this software. - */ - -#ifndef lint -static 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)"; -*/ -#endif - -#include <netdb.h> -#include <sys/time.h> -#include "defs.h" -#include <arpa/inet.h> -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -#define DEFAULT_TIMEOUT 4 /* How long to wait before retrying requests */ -#define DEFAULT_RETRIES 3 /* How many times to ask each router */ - -u_int32 our_addr, target_addr = 0; /* in NET order */ -int debug = 0; -int nflag = 0; -int retries = DEFAULT_RETRIES; -int timeout = DEFAULT_TIMEOUT; -int target_level = 0; -vifi_t numvifs; /* to keep loader happy */ - /* (see COPY_TABLES macro called in kern.c) */ - -char * inet_name __P((u_int32 addr)); -void ask __P((u_int32 dst)); -void ask2 __P((u_int32 dst)); -int get_number __P((int *var, int deflt, char ***pargv, - int *pargc)); -u_int32 host_addr __P((char *name)); -void usage __P((void)); - -/* to shut up -Wstrict-prototypes */ -int main __P((int argc, char *argv[])); - - -char * -inet_name(addr) - u_int32 addr; -{ - struct hostent *e; - struct in_addr in; - - if (addr == 0) - return "local"; - - if (nflag || - (e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == NULL) { - in.s_addr = addr; - return (inet_ntoa(in)); - } - return (e->h_name); -} - -/* - * Log errors and other messages to stderr, according to the severity of the - * message and the current debug level. For errors of severity LOG_ERR or - * worse, terminate the program. - */ -#ifdef __STDC__ -void -log(int severity, int syserr, char *format, ...) -{ - va_list ap; - char fmt[100]; - - va_start(ap, format); -#else -void -log(severity, syserr, format, va_alist) - int severity, syserr; - char *format; - va_dcl -{ - va_list ap; - char fmt[100]; - - va_start(ap); -#endif - switch (debug) { - case 0: - if (severity > LOG_WARNING) - return; - case 1: - if (severity > LOG_NOTICE) - return; - case 2: - if (severity > LOG_INFO) - return; - default: - fmt[0] = '\0'; - if (severity == LOG_WARNING) - strcat(fmt, "warning - "); - strncat(fmt, format, 80); - vfprintf(stderr, fmt, ap); - if (syserr == 0) - fprintf(stderr, "\n"); - else if (syserr < sys_nerr) - fprintf(stderr, ": %s\n", sys_errlist[syserr]); - else - fprintf(stderr, ": errno %d\n", syserr); - } - - if (severity <= LOG_ERR) - exit(-1); -} - -/* - * Send a neighbors-list request. - */ -void -ask(dst) - u_int32 dst; -{ - send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS, - htonl(MROUTED_LEVEL), 0); -} - -void -ask2(dst) - u_int32 dst; -{ - send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, - htonl(MROUTED_LEVEL), 0); -} - -/* - * Process an incoming neighbor-list message. - */ -void -accept_neighbors(src, dst, p, datalen, level) - u_int32 src, dst, level; - u_char *p; - int datalen; -{ - u_char *ep = p + datalen; -#define GET_ADDR(a) (a = ((u_int32)*p++ << 24), a += ((u_int32)*p++ << 16),\ - a += ((u_int32)*p++ << 8), a += *p++) - - printf("%s (%s):\n", inet_fmt(src, s1), inet_name(src)); - while (p < ep) { - register u_int32 laddr; - register u_char metric; - register u_char thresh; - register int ncount; - - GET_ADDR(laddr); - laddr = htonl(laddr); - metric = *p++; - thresh = *p++; - ncount = *p++; - while (--ncount >= 0) { - register u_int32 neighbor; - GET_ADDR(neighbor); - neighbor = htonl(neighbor); - printf(" %s -> ", inet_fmt(laddr, s1)); - printf("%s (%s) [%d/%d]\n", inet_fmt(neighbor, s1), - inet_name(neighbor), metric, thresh); - } - } -} - -void -accept_neighbors2(src, dst, p, datalen, level) - u_int32 src, dst, level; - u_char *p; - int datalen; -{ - u_char *ep = p + datalen; - u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */ - /* well, only possibly_broken_cisco, but that's too long to type. */ - - 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 ("]:\n"); - - while (p < ep) { - register u_char metric; - register u_char thresh; - register u_char flags; - register int ncount; - register u_int32 laddr = *(u_int32*)p; - - p += 4; - metric = *p++; - thresh = *p++; - flags = *p++; - ncount = *p++; - if (broken_cisco && ncount == 0) /* dumb Ciscos */ - ncount = 1; - if (broken_cisco && ncount > 15) /* dumb Ciscos */ - ncount = ncount & 0xf; - while (--ncount >= 0 && p < ep) { - register u_int32 neighbor = *(u_int32*)p; - p += 4; - printf(" %s -> ", inet_fmt(laddr, s1)); - printf("%s (%s) [%d/%d", inet_fmt(neighbor, s1), - inet_name(neighbor), metric, thresh); - if (flags & DVMRP_NF_TUNNEL) - printf("/tunnel"); - if (flags & DVMRP_NF_SRCRT) - printf("/srcrt"); - if (flags & DVMRP_NF_PIM) - printf("/pim"); - if (flags & DVMRP_NF_QUERIER) - printf("/querier"); - if (flags & DVMRP_NF_DISABLED) - printf("/disabled"); - if (flags & DVMRP_NF_DOWN) - printf("/down"); - if (flags & DVMRP_NF_LEAF) - printf("/leaf"); - printf("]\n"); - } - } -} - -int -get_number(var, deflt, pargv, pargc) - int *var, *pargc, deflt; - char ***pargv; -{ - if ((*pargv)[0][2] == '\0') { /* Get the value from the next - * argument */ - if (*pargc > 1 && isdigit((*pargv)[1][0])) { - (*pargv)++, (*pargc)--; - *var = atoi((*pargv)[0]); - return 1; - } else if (deflt >= 0) { - *var = deflt; - return 1; - } else - return 0; - } else { /* Get value from the rest of this argument */ - if (isdigit((*pargv)[0][2])) { - *var = atoi((*pargv)[0] + 2); - return 1; - } else { - return 0; - } - } -} - -void -usage() -{ - fprintf(stderr, - "Usage: mrinfo [-n] [-t timeout] [-r retries] [router]\n"); - exit(1); -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - int tries; - int trynew; - struct timeval et; - struct hostent *hp; - struct hostent bogus; - char *host; - int curaddr; - - setlinebuf(stderr); - - if (geteuid() != 0) { - fprintf(stderr, "mrinfo: must be root\n"); - exit(1); - } - argv++, argc--; - while (argc > 0 && argv[0][0] == '-') { - switch (argv[0][1]) { - case 'd': - if (!get_number(&debug, DEFAULT_DEBUG, &argv, &argc)) - usage(); - break; - case 'n': - ++nflag; - break; - case 'r': - if (!get_number(&retries, -1, &argv, &argc)) - usage(); - break; - case 't': - if (!get_number(&timeout, -1, &argv, &argc)) - usage(); - break; - default: - usage(); - } - argv++, argc--; - } - if (argc > 1) - usage(); - if (argc == 1) - host = argv[0]; - else - host = "127.0.0.1"; - - if ((target_addr = inet_addr(host)) != -1) { - hp = &bogus; - hp->h_length = sizeof(target_addr); - hp->h_addr_list = (char **)malloc(2 * sizeof(char *)); - hp->h_addr_list[0] = malloc(hp->h_length); - memcpy(hp->h_addr_list[0], &target_addr, hp->h_length); - hp->h_addr_list[1] = 0; - } else - hp = gethostbyname(host); - - if (hp == NULL) { - fprintf(stderr, "mrinfo: %s: no such host\n", argv[0]); - exit(1); - } - 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); - { /* 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)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = target_addr; - addr.sin_port = htons(2000); /* any port over 1024 will - * do... */ - if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0 - || connect(udp, (struct sockaddr *) & addr, sizeof(addr)) < 0 - || getsockname(udp, (struct sockaddr *) & addr, &addrlen) < 0) { - perror("Determining local address"); - exit(-1); - } - close(udp); - our_addr = addr.sin_addr.s_addr; - } - - tries = 0; - trynew = 1; - /* - * New strategy: send 'ask2' for two timeouts, then fall back - * to 'ask', since it's not very likely that we are going to - * find someone who only responds to 'ask' these days - */ - ask2(target_addr); - - gettimeofday(&et, 0); - et.tv_sec += timeout; - - /* Main receive loop */ - for (;;) { - fd_set fds; - struct timeval tv, now; - int count, recvlen, dummy = 0; - register u_int32 src, dst, group; - struct ip *ip; - struct igmp *igmp; - int ipdatalen, iphdrlen, igmpdatalen; - - FD_ZERO(&fds); - FD_SET(igmp_socket, &fds); - - gettimeofday(&now, 0); - tv.tv_sec = et.tv_sec - now.tv_sec; - tv.tv_usec = et.tv_usec - now.tv_usec; - - if (tv.tv_usec < 0) { - tv.tv_usec += 1000000L; - --tv.tv_sec; - } - if (tv.tv_sec < 0) - tv.tv_sec = tv.tv_usec = 0; - - count = select(igmp_socket + 1, &fds, 0, 0, &tv); - - if (count < 0) { - if (errno != EINTR) - perror("select"); - continue; - } else if (count == 0) { - log(LOG_DEBUG, 0, "Timed out receiving neighbor lists"); - if (++tries > retries) - break; - /* If we've tried ASK_NEIGHBORS2 twice with - * no response, fall back to ASK_NEIGHBORS - */ - if (tries == 2 && target_level == 0) - trynew = 0; - if (target_level == 0 && trynew == 0) - ask(target_addr); - else - ask2(target_addr); - gettimeofday(&et, 0); - et.tv_sec += timeout; - continue; - } - recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, - 0, NULL, &dummy); - if (recvlen <= 0) { - if (recvlen && errno != EINTR) - perror("recvfrom"); - continue; - } - - if (recvlen < sizeof(struct ip)) { - log(LOG_WARNING, 0, - "packet too short (%u bytes) for IP header", - recvlen); - continue; - } - ip = (struct ip *) recv_buf; - if (ip->ip_p == 0) - continue; /* Request to install cache entry */ - src = ip->ip_src.s_addr; - dst = ip->ip_dst.s_addr; - iphdrlen = ip->ip_hl << 2; - ipdatalen = ip->ip_len; - if (iphdrlen + ipdatalen != recvlen) { - log(LOG_WARNING, 0, - "packet shorter (%u bytes) than hdr+data length (%u+%u)", - recvlen, iphdrlen, ipdatalen); - continue; - } - igmp = (struct igmp *) (recv_buf + iphdrlen); - group = igmp->igmp_group.s_addr; - igmpdatalen = ipdatalen - IGMP_MINLEN; - if (igmpdatalen < 0) { - log(LOG_WARNING, 0, - "IP data field too short (%u bytes) for IGMP, from %s", - ipdatalen, inet_fmt(src, s1)); - continue; - } - if (igmp->igmp_type != IGMP_DVMRP) - continue; - - switch (igmp->igmp_code) { - case DVMRP_NEIGHBORS: - case DVMRP_NEIGHBORS2: - if (src != target_addr) { - fprintf(stderr, "mrinfo: got reply from %s", - inet_fmt(src, s1)); - fprintf(stderr, " instead of %s\n", - inet_fmt(target_addr, s1)); - /*continue;*/ - } - break; - default: - continue; /* ignore all other DVMRP messages */ - } - - switch (igmp->igmp_code) { - - case DVMRP_NEIGHBORS: - if (group) { - /* knows about DVMRP_NEIGHBORS2 msg */ - if (target_level == 0) { - target_level = ntohl(group); - ask2(target_addr); - } - } else { - accept_neighbors(src, dst, (u_char *)(igmp + 1), - igmpdatalen, ntohl(group)); - exit(0); - } - break; - - case DVMRP_NEIGHBORS2: - accept_neighbors2(src, dst, (u_char *)(igmp + 1), - igmpdatalen, ntohl(group)); - exit(0); - } - } - } - exit(1); -} - -/* dummies */ -void accept_probe(src, dst, p, datalen, level) - u_int32 src, dst, level; - char *p; - int datalen; -{ -} -void accept_group_report(src, dst, group, r_type) - u_int32 src, dst, group; - int r_type; -{ -} -void accept_neighbor_request2(src, dst) - u_int32 src, dst; -{ -} -void accept_report(src, dst, p, datalen, level) - u_int32 src, dst, level; - char *p; - int datalen; -{ -} -void accept_neighbor_request(src, dst) - u_int32 src, dst; -{ -} -void accept_prune(src, dst, p, datalen) - u_int32 src, dst; - char *p; - int datalen; -{ -} -void accept_graft(src, dst, p, datalen) - u_int32 src, dst; - char *p; - int datalen; -{ -} -void accept_g_ack(src, dst, p, datalen) - u_int32 src, dst; - char *p; - int datalen; -{ -} -void add_table_entry(origin, mcastgrp) - u_int32 origin, mcastgrp; -{ -} -void check_vif_state() -{ -} -void accept_leave_message(src, dst, group) - u_int32 src, dst, group; -{ -} -void accept_mtrace(src, dst, group, data, no, datalen) - u_int32 src, dst, group; - char *data; - u_int no; - int datalen; -{ -} -void accept_membership_query(src, dst, group, tmo) - u_int32 src, dst, group; - int tmo; -{ -} -void accept_info_request(src, dst, p, datalen) - u_int32 src, dst; - u_char *p; - int datalen; -{ -} -void accept_info_reply(src, dst, p, datalen) - u_int32 src, dst; - u_char *p; - int datalen; -{ -} diff --git a/usr.sbin/mrouted/mrouted.8 b/usr.sbin/mrouted/mrouted.8 deleted file mode 100644 index 6c4c7bd98616..000000000000 --- a/usr.sbin/mrouted/mrouted.8 +++ /dev/null @@ -1,404 +0,0 @@ -'\"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 $ -.TH MROUTED 8 -.UC 5 -.SH NAME -mrouted \- IP multicast routing daemon -.SH SYNOPSIS -.B /etc/mrouted -[ -.B \-p -] [ -.B \-c -.I config_file -] [ -.B \-d -[ -.I debug_level -]] -.SH DESCRIPTION -.I Mrouted -is an implementation of the Distance-Vector Multicast Routing -Protocol (DVMRP), an earlier version of which is specified in RFC-1075. -It maintains topological knowledge via a distance-vector routing protocol -(like RIP, described in RFC-1058), upon which it implements a multicast -datagram forwarding algorithm called Reverse Path Multicasting. -.PP -.I Mrouted -forwards a multicast datagram along a shortest (reverse) path tree -rooted at the subnet on which the datagram originates. The multicast -delivery tree may be thought of as a broadcast delivery tree that has -been pruned back so that it does not extend beyond those subnetworks -that have members of the destination group. Hence, datagrams -are not forwarded along those branches which have no listeners of the -multicast group. The IP time-to-live of a multicast datagram can be -used to limit the range of multicast datagrams. -.PP -In order to support multicasting among subnets that are separated by (unicast) -routers that do not support IP multicasting, -.I mrouted -includes support for -"tunnels", which are virtual point-to-point links between pairs of -.IR mrouted s -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 -(IP protocol number 4). -Older versions of -.I mrouted -tunnel using IP source routing, which puts a heavy load on some -types of routers. -This version does not support IP source route tunnelling. -.PP -The tunnelling mechanism allows -.I mrouted -to establish a virtual internet, for -the purpose of multicasting only, which is independent of the physical -internet, and which may span multiple Autonomous Systems. This capability -is intended for experimental support of internet multicasting only, pending -widespread support for multicast routing by the regular (unicast) routers. -.I Mrouted -suffers from the well-known scaling problems of any distance-vector -routing protocol, and does not (yet) support hierarchical multicast routing. -.PP -.I Mrouted -handles multicast routing only; there may or may not be unicast routing -software running on the same machine as -.IR mrouted . -With the use of tunnels, it -is not necessary for -.I mrouted -to have access to more than one physical subnet -in order to perform multicast forwarding. -.br -.ne 5 -.SH INVOCATION -.PP -If no "\-d" option is given, or if the debug level is specified as 0, -.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, -.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. -.PP -Upon startup, mrouted writes its pid to the file /etc/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 -via those interfaces. To override the default configuration, or to add -tunnel links to other -.IR mrouted s, -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. -.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). -If a phyint is attached to multiple IP subnets, describe each additional subnet -with the altnet keyword. -Phyint commands must precede tunnel commands. -.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. -.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. -.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 -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 -than 31. -.LP -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. -.LP -In general, all -.IR mrouted s -connected to a particular subnet or tunnel should -use the same metric and threshold for that subnet or tunnel. -.PP -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 -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. -.PP -.I Mrouted -will not initiate execution if it has fewer than two enabled vifs, -where a vif (virtual interface) is either a physical multicast-capable -interface or a tunnel. It will log a warning if all of its vifs are -tunnels; such an -.I mrouted -configuration would be better replaced by more -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 -school. -.sp -.nf -# -# mrouted.conf example -# -# Name our boundaries to make it easier -name LOCAL 239.255.0.0/16 -name EE 239.254.0.0/16 -# -# le1 is our gateway to compsci, don't forward our -# local groups to them -phyint le1 boundary EE -# -# le2 is our interface on the classroom net, it has four -# different length subnets on it. -# note that you can use either an ip address or an -# interface name -phyint 172.16.12.38 boundary EE altnet 172.16.15.0/26 - altnet 172.16.15.128/26 altnet 172.16.48.0/24 -# -# atm0 is our ATM interface, which doesn't properly -# support multicasting. -phyint atm0 disable -# -# This is an internal tunnel to another EE subnet -# Remove the default tunnel rate limit, since this -# tunnel is over ethernets -tunnel 192.168.5.4 192.168.55.101 metric 1 threshold 1 - rate_limit 0 -# -# This is our tunnel to the outside world. -# Careful with those boundaries, Eugene. -tunnel 192.168.5.4 10.11.12.13 metric 1 threshold 32 - boundary LOCAL boundary EE -.fi -.SH SIGNALS -.PP -.I Mrouted -responds to the following signals: -.IP HUP -restarts -.I mrouted . -The configuration file is reread every time this signal is evoked. -.IP INT -terminates execution gracefully (i.e., by sending -good-bye messages to all neighboring routers). -.IP TERM -same as INT -.IP USR1 -dumps the internal routing tables to /usr/tmp/mrouted.dump. -.IP USR2 -dumps the internal cache tables to /usr/tmp/mrouted.cache. -.IP QUIT -dumps the internal routing tables to stderr (only if -.I mrouted -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. -.bp -.SH EXAMPLE -.PP -The routing tables look like this: -.nf - -Virtual Interface Table - Vif Local-Address Metric Thresh Flags - 0 36.2.0.8 subnet: 36.2 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 - groups: 224.0.2.1 - 224.0.1.0 - 224.0.0.4 - pkts in: 345 - pkts out: 3456 - - 2 36.2.0.8 tunnel: 36.8.0.77 3 1 - peers: 36.8.0.77 (2.2) - boundaries: 239.0.1 - : 239.1.2 - pkts in: 34545433 - pkts out: 234342 - - 3 36.2.0.8 tunnel: 36.6.8.23 3 16 - -Multicast Routing Table (1136 entries) - Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs - 36.2 1 45 0 1* 2 3* - 36.8 36.8.0.77 4 15 2 0* 1* 3* - 36.11 1 20 1 0* 2 3* - . - . - . - -.fi -In this example, there are four vifs connecting to two subnets and two -tunnels. The vif 3 tunnel is not in use (no peer address). The vif 0 and -vif 1 subnets have some groups present; tunnels never have any groups. This -instance of -.I mrouted -is the one responsible for sending periodic group -membership queries on the vif 0 and vif 1 subnets, as indicated by the -"querier" flags. The list of boundaries indicate the scoped addresses on that -interface. A count of the no. of incoming and outgoing packets is also -shown at each interface. -.PP -Associated with each subnet from which a multicast datagram can originate -is the address of the previous hop router (unless the subnet is directly- -connected), the metric of the path back to the origin, the amount of time -since we last received an update for this subnet, the incoming vif for -multicasts from that origin, and a list of outgoing vifs. "*" means that -the outgoing vif is connected to a leaf of the broadcast tree rooted at the -origin, and a multicast datagram from that origin will be forwarded on that -outgoing vif only if there are members of the destination group on that leaf. -.bp -.PP -.I Mrouted -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: -.nf - -Multicast Routing Cache Table (147 entries) - Origin Mcast-group CTmr Age Ptmr IVif Forwvifs - 13.2.116/22 224.2.127.255 3m 2m - 0 1 ->13.2.116.19 ->13.2.116.196 - 138.96.48/21 224.2.127.255 5m 2m - 0 1 ->138.96.48.108 - 128.9.160/20 224.2.127.255 3m 2m - 0 1 ->128.9.160.45 - 198.106.194/24 224.2.135.190 9m 28s 9m 0P ->198.106.194.22 - -.fi -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 -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. -The 'Ptmr' field is simply a dash if no prune was sent upstream, or the -amount of time until the upstream prune will time out. -The 'Ivif' field indicates the -incoming vif for multicast packets from that origin. Each router also -maintains a record of the number of prunes received from neighboring -routers for a particular source and group. If there are no members of -a multicast group on any downward link of the multicast tree for a -subnet, a prune message is sent to the upstream router. They are -indicated by a "P" after the vif number. 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 -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. -.SH FILES -/etc/mrouted.conf -.br -/etc/mrouted.pid -.br -/usr/tmp/mrouted.dump -.br -/usr/tmp/mrouted.cache -.SH SEE ALSO -.BR mrinfo (8) , -.BR mtrace (8) , -.BR map-mbone (8) -.sp -DVMRP is described, along with other multicast routing algorithms, in the -paper "Multicast Routing in Internetworks and Extended LANs" by S. Deering, -in the Proceedings of the ACM SIGCOMM '88 Conference. -.SH AUTHORS -Steve Deering, Ajit Thyagarajan, Bill Fenner diff --git a/usr.sbin/mrouted/mrouted.conf b/usr.sbin/mrouted/mrouted.conf deleted file mode 100644 index eb3bad3f4995..000000000000 --- a/usr.sbin/mrouted/mrouted.conf +++ /dev/null @@ -1,43 +0,0 @@ -# $Id: mrouted.conf,v 3.8 1995/11/29 22:40:47 fenner Rel $ -# -# This is the configuration file for "mrouted", an IP multicast router. -# mrouted looks for it in "/etc/mrouted.conf". -# -# Command formats: -# -# name <boundname> <scoped-addr>/<mask-len> -# cache_lifetime 3600 # seconds -# pruning on -# -# phyint <local-addr> [disable] [metric <m>] [threshold <t>] [rate_limit <b>] -# [boundary (<boundname>|<scoped-addr>/<mask-len>)] -# [altnet (<subnet>/<mask-len>|<subnet>)] -# tunnel <local-addr> <remote-addr> [srcrt] [metric <m>] -# [threshold <t>] [rate_limit <b>] -# [boundary (<boundname>|<scoped-addr>/<mask-len>)] -# -# NOTE: any phyint commands MUST precede any tunnel commands -# NOTE: the mask-len is the no. of leading 1's in the mask -# NOTE: rate_limit is in kilobits, and defaults to 500 for tunnels -# -# Example of named bounary: -#name LOCAL 239.255.0.0/16 -#name EE 239.254.0.0/16 # i.e. the EE dept wants local groups -# -# Example of use of named boundary -#phyint le1 boundary EE # le1 is our interface to comp sci, -# # keep them away from our local groups -# -# -# Template tunnel for mcast_install -tunnel 128.4.0.77 128.4.0.8 metric 1 threshold 64 rate_limit 500 # <-- REPLACE -# boundary LOCAL -# -# You might want to specify a boundary on your tunnel to the outside world, -# as above. -# -# NOTE: ONLY uncomment the following if you are running mrouted.snmp! -#sysName "mymrouter" -#sysContact "Me <me@me.com> +x.yyy.zzz-zzzz" -#sysVersion "MyOS 4.1.3 and mrouted" -#sysLocation "The MBONE" diff --git a/usr.sbin/mrouted/pathnames.h b/usr.sbin/mrouted/pathnames.h deleted file mode 100644 index b3e3c88f8988..000000000000 --- a/usr.sbin/mrouted/pathnames.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: pathnames.h,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - -#define _PATH_MROUTED_CONF "/etc/mrouted.conf" - -#if (defined(BSD) && (BSD >= 199103)) -#define _PATH_MROUTED_PID "/var/run/mrouted.pid" -#define _PATH_MROUTED_GENID "/var/run/mrouted.genid" -#define _PATH_MROUTED_DUMP "/var/tmp/mrouted.dump" -#define _PATH_MROUTED_CACHE "/var/tmp/mrouted.cache" -#else -#define _PATH_MROUTED_PID "/etc/mrouted.pid" -#define _PATH_MROUTED_GENID "/etc/mrouted.genid" -#define _PATH_MROUTED_DUMP "/usr/tmp/mrouted.dump" -#define _PATH_MROUTED_CACHE "/usr/tmp/mrouted.cache" -#endif diff --git a/usr.sbin/mrouted/prune.c b/usr.sbin/mrouted/prune.c deleted file mode 100644 index fe3cdd5b4e14..000000000000 --- a/usr.sbin/mrouted/prune.c +++ /dev/null @@ -1,2303 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: prune.c,v 3.8 1995/11/29 22:36:34 fenner Rel $ - */ - - -#include "defs.h" - -extern int cache_lifetime; -extern int max_prune_lifetime; -extern struct rtentry *routing_table; - -extern int phys_vif; - -/* - * dither cache lifetime to obtain a value between x and 2*x - */ -#ifdef SYSV -#define CACHE_LIFETIME(x) ((x) + (lrand48() % (x))) -#else -#define CACHE_LIFETIME(x) ((x) + (random() % (x))) -#endif - -#define CHK_GS(x, y) { \ - switch(x) { \ - case 2: \ - case 4: \ - case 8: \ - case 16: \ - case 32: \ - case 64: \ - case 128: \ - case 256: y = 1; \ - break; \ - default: y = 0; \ - } \ - } - -struct gtable *kernel_table; /* ptr to list of kernel grp entries*/ -static struct gtable *kernel_no_route; /* list of grp entries w/o routes */ -struct gtable *gtp; /* pointer for kernel rt entries */ -unsigned int kroutes; /* current number of cache entries */ - -/**************************************************************************** - Functions that are local to prune.c -****************************************************************************/ -static void prun_add_ttls __P((struct gtable *gt)); -static int pruning_neighbor __P((vifi_t vifi, u_int32 addr)); -static int can_mtrace __P((vifi_t vifi, u_int32 addr)); -static struct ptable * find_prune_entry __P((u_int32 vr, struct ptable *pt)); -static void expire_prune __P((vifi_t vifi, struct gtable *gt)); -static void send_prune __P((struct gtable *gt)); -static void send_graft __P((struct gtable *gt)); -static void send_graft_ack __P((u_int32 src, u_int32 dst, - u_int32 origin, u_int32 grp)); -static void update_kernel __P((struct gtable *g)); -static char * scaletime __P((u_long t)); - -/* - * Updates the ttl values for each vif. - */ -static void -prun_add_ttls(gt) - struct gtable *gt; -{ - struct uvif *v; - vifi_t vifi; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (VIFM_ISSET(vifi, gt->gt_grpmems)) - gt->gt_ttls[vifi] = v->uv_threshold; - else - gt->gt_ttls[vifi] = 0; - } -} - -/* - * checks for scoped multicast addresses - */ -#define GET_SCOPE(gt) { \ - register vifi_t _i; \ - if ((ntohl((gt)->gt_mcastgrp) & 0xff000000) == 0xef000000) \ - for (_i = 0; _i < numvifs; _i++) \ - if (scoped_addr(_i, (gt)->gt_mcastgrp)) \ - VIFM_SET(_i, (gt)->gt_scope); \ - } - -int -scoped_addr(vifi, addr) - vifi_t vifi; - u_int32 addr; -{ - struct vif_acl *acl; - - for (acl = uvifs[vifi].uv_acl; acl; acl = acl->acl_next) - if ((addr & acl->acl_mask) == acl->acl_addr) - return 1; - - return 0; -} - -/* - * Determine if mcastgrp has a listener on vifi - */ -int -grplst_mem(vifi, mcastgrp) - vifi_t vifi; - u_int32 mcastgrp; -{ - register struct listaddr *g; - register struct uvif *v; - - v = &uvifs[vifi]; - - for (g = v->uv_groups; g != NULL; g = g->al_next) - if (mcastgrp == g->al_addr) - return 1; - - return 0; -} - -/* - * Finds the group entry with the specified source and netmask. - * If netmask is 0, it uses the route's netmask. - * - * Returns TRUE if found a match, and the global variable gtp is left - * pointing to entry before the found entry. - * Returns FALSE if no exact match found, gtp is left pointing to before - * the entry in question belongs, or is NULL if the it belongs at the - * head of the list. - */ -int -find_src_grp(src, mask, grp) - u_int32 src; - u_int32 mask; - u_int32 grp; -{ - struct gtable *gt; - - gtp = NULL; - gt = kernel_table; - while (gt != NULL) { - if (grp == gt->gt_mcastgrp && - (mask ? (gt->gt_route->rt_origin == src && - gt->gt_route->rt_originmask == mask) : - ((src & gt->gt_route->rt_originmask) == - gt->gt_route->rt_origin))) - return TRUE; - if (ntohl(grp) > ntohl(gt->gt_mcastgrp) || - (grp == gt->gt_mcastgrp && - (ntohl(mask) < ntohl(gt->gt_route->rt_originmask) || - (mask == gt->gt_route->rt_originmask && - (ntohl(src) > ntohl(gt->gt_route->rt_origin)))))) { - gtp = gt; - gt = gt->gt_gnext; - } - else break; - } - return FALSE; -} - -/* - * Check if the neighbor supports pruning - */ -static int -pruning_neighbor(vifi, addr) - vifi_t vifi; - u_int32 addr; -{ - struct listaddr *n = neighbor_info(vifi, addr); - int vers; - - if (n == NULL) - return 0; - - if (n->al_flags & NF_PRUNE) - return 1; - - /* - * Versions from 3.0 to 3.4 relied on the version number to identify - * that they could handle pruning. - */ - vers = NBR_VERS(n); - return (vers >= 0x0300 && vers <= 0x0304); -} - -/* - * Can the neighbor in question handle multicast traceroute? - */ -static int -can_mtrace(vifi, addr) - vifi_t vifi; - u_int32 addr; -{ - struct listaddr *n = neighbor_info(vifi, addr); - int vers; - - if (n == NULL) - return 0; - - if (n->al_flags & NF_MTRACE) - return 1; - - /* - * Versions 3.3 and 3.4 relied on the version number to identify - * that they could handle traceroute. - */ - vers = NBR_VERS(n); - return (vers >= 0x0303 && vers <= 0x0304); -} - -/* - * Returns the prune entry of the router, or NULL if none exists - */ -static struct ptable * -find_prune_entry(vr, pt) - u_int32 vr; - struct ptable *pt; -{ - while (pt) { - if (pt->pt_router == vr) - return pt; - pt = pt->pt_next; - } - - return NULL; -} - -/* - * Send a prune message to the dominant router for - * this source. - * - * Record an entry that a prune was sent for this group - */ -static void -send_prune(gt) - struct gtable *gt; -{ - struct ptable *pt; - char *p; - int i; - int datalen; - u_int32 src; - u_int32 dst; - u_int32 tmp; - - /* Don't process any prunes if router is not pruning */ - if (pruning == 0) - return; - - /* Can't process a prune if we don't have an associated route */ - if (gt->gt_route == NULL) - return; - - /* Don't send a prune to a non-pruning router */ - if (!pruning_neighbor(gt->gt_route->rt_parent, gt->gt_route->rt_gateway)) - return; - - /* - * sends a prune message to the router upstream. - */ - src = uvifs[gt->gt_route->rt_parent].uv_lcl_addr; - dst = gt->gt_route->rt_gateway; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - - /* - * determine prune lifetime - */ - gt->gt_prsent_timer = gt->gt_timer; - for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) - if (pt->pt_timer < gt->gt_prsent_timer) - gt->gt_prsent_timer = pt->pt_timer; - - /* - * If we have a graft pending, cancel graft retransmission - */ - gt->gt_grftsnt = 0; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_route->rt_origin))[i]; - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_mcastgrp))[i]; - tmp = htonl(gt->gt_prsent_timer); - for (i = 0; i < 4; i++) - *p++ = ((char *)&(tmp))[i]; - datalen += 12; - - send_igmp(src, dst, IGMP_DVMRP, DVMRP_PRUNE, - htonl(MROUTED_LEVEL), datalen); - - log(LOG_DEBUG, 0, "sent prune for (%s %s)/%d on vif %d to %s", - inet_fmts(gt->gt_route->rt_origin, gt->gt_route->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), - gt->gt_prsent_timer, gt->gt_route->rt_parent, - inet_fmt(gt->gt_route->rt_gateway, s3)); -} - -/* - * a prune was sent upstream - * so, a graft has to be sent to annul the prune - * set up a graft timer so that if an ack is not - * heard within that time, another graft request - * is sent out. - */ -static void -send_graft(gt) - struct gtable *gt; -{ - register char *p; - register int i; - int datalen; - u_int32 src; - u_int32 dst; - - /* Can't send a graft without an associated route */ - if (gt->gt_route == NULL) - return; - - src = uvifs[gt->gt_route->rt_parent].uv_lcl_addr; - dst = gt->gt_route->rt_gateway; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_route->rt_origin))[i]; - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_mcastgrp))[i]; - datalen += 8; - - if (datalen != 0) { - send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT, - htonl(MROUTED_LEVEL), datalen); - } - log(LOG_DEBUG, 0, "sent graft for (%s %s) to %s on vif %d", - inet_fmts(gt->gt_route->rt_origin, gt->gt_route->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), - inet_fmt(gt->gt_route->rt_gateway, s3), gt->gt_route->rt_parent); -} - -/* - * Send an ack that a graft was received - */ -static void -send_graft_ack(src, dst, origin, grp) - u_int32 src; - u_int32 dst; - u_int32 origin; - u_int32 grp; -{ - register char *p; - register int i; - int datalen; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(origin))[i]; - for (i = 0; i < 4; i++) - *p++ = ((char *)&(grp))[i]; - datalen += 8; - - send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT_ACK, - htonl(MROUTED_LEVEL), datalen); - - log(LOG_DEBUG, 0, "sent graft ack for (%s, %s) to %s", - inet_fmt(origin, s1), inet_fmt(grp, s2), inet_fmt(dst, s3)); -} - -/* - * Update the kernel cache with all the routes hanging off the group entry - */ -static void -update_kernel(g) - struct gtable *g; -{ - struct stable *st; - - for (st = g->gt_srctbl; st; st = st->st_next) - k_add_rg(st->st_origin, g); -} - -/**************************************************************************** - Functions that are used externally -****************************************************************************/ - -#ifdef SNMP -#include <sys/types.h> -#include "snmp.h" - -/* - * Find a specific group entry in the group table - */ -struct gtable * -find_grp(grp) - u_long grp; -{ - struct gtable *gt; - - for (gt = kernel_table; gt; gt = gt->gt_gnext) { - if (ntohl(grp) < ntohl(gt->gt_mcastgrp)) - break; - if (gt->gt_mcastgrp == grp) - return gt; - } - return NULL; -} - -/* - * Given a group entry and source, find the corresponding source table - * entry - */ -struct stable * -find_grp_src(gt, src) - struct gtable *gt; - u_long src; -{ - struct stable *st; - u_long grp = gt->gt_mcastgrp; - struct gtable *gtcurr; - - for (gtcurr = gt; gtcurr->gt_mcastgrp == grp; gtcurr = gtcurr->gt_gnext) { - for (st = gtcurr->gt_srctbl; st; st = st->st_next) - if (st->st_origin == src) - return st; - } - return NULL; -} - -/* - * Find next entry > specification - */ -int -next_grp_src_mask(gtpp, stpp, grp, src, mask) - struct gtable **gtpp; /* ordered by group */ - struct stable **stpp; /* ordered by source */ - u_long grp; - u_long src; - u_long mask; -{ - struct gtable *gt, *gbest = NULL; - struct stable *st, *sbest = NULL; - - /* Find first group entry >= grp spec */ - (*gtpp) = kernel_table; - while ((*gtpp) && ntohl((*gtpp)->gt_mcastgrp) < ntohl(grp)) - (*gtpp)=(*gtpp)->gt_gnext; - if (!(*gtpp)) - return 0; /* no more groups */ - - for (gt = kernel_table; gt; gt=gt->gt_gnext) { - /* Since grps are ordered, we can stop when group changes from gbest */ - if (gbest && gbest->gt_mcastgrp != gt->gt_mcastgrp) - break; - for (st = gt->gt_srctbl; st; st=st->st_next) { - - /* Among those entries > spec, find "lowest" one */ - if (((ntohl(gt->gt_mcastgrp)> ntohl(grp)) - || (ntohl(gt->gt_mcastgrp)==ntohl(grp) - && ntohl(st->st_origin)> ntohl(src)) - || (ntohl(gt->gt_mcastgrp)==ntohl(grp) - && ntohl(st->st_origin)==src && 0xFFFFFFFF>ntohl(mask))) - && (!gbest - || (ntohl(gt->gt_mcastgrp)< ntohl(gbest->gt_mcastgrp)) - || (ntohl(gt->gt_mcastgrp)==ntohl(gbest->gt_mcastgrp) - && ntohl(st->st_origin)< ntohl(sbest->st_origin)))) { - gbest = gt; - sbest = st; - } - } - } - (*gtpp) = gbest; - (*stpp) = sbest; - return (*gtpp)!=0; -} - -/* - * Ensure that sg contains current information for the given group,source. - * This is fetched from the kernel as a unit so that counts for the entry - * are consistent, i.e. packet and byte counts for the same entry are - * read at the same time. - */ -void -refresh_sg(sg, gt, st) - struct sioc_sg_req *sg; - struct gtable *gt; - struct stable *st; -{ - static int lastq = -1; - - if (quantum != lastq || sg->src.s_addr!=st->st_origin - || sg->grp.s_addr!=gt->gt_mcastgrp) { - lastq = quantum; - sg->src.s_addr = st->st_origin; - sg->grp.s_addr = gt->gt_mcastgrp; - ioctl(udp_socket, SIOCGETSGCNT, (char *)sg); - } -} - -/* - * Return pointer to a specific route entry. This must be a separate - * function from find_route() which modifies rtp. - */ -struct rtentry * -snmp_find_route(src, mask) - register u_long src, mask; -{ - register struct rtentry *rt; - - for (rt = routing_table; rt; rt = rt->rt_next) { - if (src == rt->rt_origin && mask == rt->rt_originmask) - return rt; - } - return NULL; -} - -/* - * Find next route entry > specification - */ -int -next_route(rtpp, src, mask) - struct rtentry **rtpp; - u_long src; - u_long mask; -{ - struct rtentry *rt, *rbest = NULL; - - /* Among all entries > spec, find "lowest" one in order */ - for (rt = routing_table; rt; rt=rt->rt_next) { - if ((ntohl(rt->rt_origin) > ntohl(src) - || (ntohl(rt->rt_origin) == ntohl(src) - && ntohl(rt->rt_originmask) > ntohl(mask))) - && (!rbest || (ntohl(rt->rt_origin) < ntohl(rbest->rt_origin)) - || (ntohl(rt->rt_origin) == ntohl(rbest->rt_origin) - && ntohl(rt->rt_originmask) < ntohl(rbest->rt_originmask)))) - rbest = rt; - } - (*rtpp) = rbest; - return (*rtpp)!=0; -} - -/* - * Given a routing table entry, and a vifi, find the next vifi/entry - */ -int -next_route_child(rtpp, src, mask, vifi) - struct rtentry **rtpp; - u_long src; - u_long mask; - vifi_t *vifi; /* vif at which to start looking */ -{ - struct rtentry *rt; - - /* Get (S,M) entry */ - if (!((*rtpp) = snmp_find_route(src,mask))) - if (!next_route(rtpp, src, mask)) - return 0; - - /* Continue until we get one with a valid next vif */ - do { - for (; (*rtpp)->rt_children && *vifi<numvifs; (*vifi)++) - if (VIFM_ISSET(*vifi, (*rtpp)->rt_children)) - return 1; - *vifi = 0; - } while( next_route(rtpp, (*rtpp)->rt_origin, (*rtpp)->rt_originmask) ); - - return 0; -} - -/* - * Given a routing table entry, and a vifi, find the next entry - * equal to or greater than those - */ -int -next_child(gtpp, stpp, grp, src, mask, vifi) - struct gtable **gtpp; - struct stable **stpp; - u_long grp; - u_long src; - u_long mask; - vifi_t *vifi; /* vif at which to start looking */ -{ - struct stable *st; - - /* Get (G,S,M) entry */ - if (mask!=0xFFFFFFFF - || !((*gtpp) = find_grp(grp)) - || !((*stpp) = find_grp_src((*gtpp),src))) - if (!next_grp_src_mask(gtpp, stpp, grp, src, mask)) - return 0; - - /* Continue until we get one with a valid next vif */ - do { - for (; (*gtpp)->gt_route->rt_children && *vifi<numvifs; (*vifi)++) - if (VIFM_ISSET(*vifi, (*gtpp)->gt_route->rt_children)) - return 1; - *vifi = 0; - } while (next_grp_src_mask(gtpp, stpp, (*gtpp)->gt_mcastgrp, - (*stpp)->st_origin, 0xFFFFFFFF) ); - - return 0; -} -#endif /* SNMP */ - -/* - * Initialize the kernel table structure - */ -void -init_ktable() -{ - kernel_table = NULL; - kernel_no_route = NULL; - kroutes = 0; -} - -/* - * Add a new table entry for (origin, mcastgrp) - */ -void -add_table_entry(origin, mcastgrp) - u_int32 origin; - u_int32 mcastgrp; -{ - struct rtentry *r; - struct gtable *gt,**gtnp,*prev_gt; - struct stable *st,**stnp; - vifi_t i; - -#ifdef DEBUG_MFC - md_log(MD_MISS, origin, mcastgrp); -#endif - - r = determine_route(origin); - prev_gt = NULL; - if (r == NULL) { - /* - * Look for it on the no_route table; if it is found then - * it will be detected as a duplicate below. - */ - for (gt = kernel_no_route; gt; gt = gt->gt_next) - if (mcastgrp == gt->gt_mcastgrp && - gt->gt_srctbl && gt->gt_srctbl->st_origin == origin) - break; - gtnp = &kernel_no_route; - } else { - gtnp = &r->rt_groups; - while ((gt = *gtnp) != NULL) { - if (gt->gt_mcastgrp >= mcastgrp) - break; - gtnp = >->gt_next; - prev_gt = gt; - } - } - - if (gt == NULL || gt->gt_mcastgrp != mcastgrp) { - gt = (struct gtable *)malloc(sizeof(struct gtable)); - if (gt == NULL) - log(LOG_ERR, 0, "ran out of memory"); - - gt->gt_mcastgrp = mcastgrp; - gt->gt_timer = CACHE_LIFETIME(cache_lifetime); - time(>->gt_ctime); - gt->gt_grpmems = 0; - gt->gt_scope = 0; - gt->gt_prsent_timer = 0; - gt->gt_grftsnt = 0; - gt->gt_srctbl = NULL; - gt->gt_pruntbl = NULL; - gt->gt_route = r; -#ifdef RSRR - gt->gt_rsrr_cache = NULL; -#endif - - if (r != NULL) { - /* 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); - if (VIFM_ISSET(r->rt_parent, gt->gt_scope)) - gt->gt_scope = -1; - gt->gt_grpmems &= ~gt->gt_scope; - } else { - gt->gt_scope = -1; - gt->gt_grpmems = 0; - } - - /* update ttls */ - prun_add_ttls(gt); - - gt->gt_next = *gtnp; - *gtnp = gt; - if (gt->gt_next) - gt->gt_next->gt_prev = gt; - gt->gt_prev = prev_gt; - - if (r) { - if (find_src_grp(r->rt_origin, r->rt_originmask, gt->gt_mcastgrp)) { - struct gtable *g; - - g = gtp ? gtp->gt_gnext : kernel_table; - log(LOG_WARNING, 0, "Entry for (%s %s) (rt:%x) exists (rt:%x)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), - r, g->gt_route); - } else { - if (gtp) { - gt->gt_gnext = gtp->gt_gnext; - gt->gt_gprev = gtp; - gtp->gt_gnext = gt; - } else { - gt->gt_gnext = kernel_table; - gt->gt_gprev = NULL; - kernel_table = gt; - } - if (gt->gt_gnext) - gt->gt_gnext->gt_gprev = gt; - } - } else { - gt->gt_gnext = gt->gt_gprev = NULL; - } - } - - stnp = >->gt_srctbl; - while ((st = *stnp) != NULL) { - if (ntohl(st->st_origin) >= ntohl(origin)) - break; - stnp = &st->st_next; - } - - if (st == NULL || st->st_origin != origin) { - st = (struct stable *)malloc(sizeof(struct stable)); - if (st == NULL) - log(LOG_ERR, 0, "ran out of memory"); - - st->st_origin = origin; - st->st_pktcnt = 0; - st->st_next = *stnp; - *stnp = st; - } else { -#ifdef DEBUG_MFC - md_log(MD_DUPE, origin, mcastgrp); -#endif - log(LOG_WARNING, 0, "kernel entry already exists for (%s %s)", - inet_fmt(origin, s1), inet_fmt(mcastgrp, s2)); - /* XXX Doing this should cause no harm, and may ensure - * kernel<>mrouted synchronization */ - k_add_rg(origin, gt); - return; - } - - kroutes++; - k_add_rg(origin, gt); - - log(LOG_DEBUG, 0, "add cache entry (%s %s) gm:%x, parent-vif:%d", - inet_fmt(origin, s1), - inet_fmt(mcastgrp, s2), - gt->gt_grpmems, r ? r->rt_parent : -1); - - /* If there are no leaf vifs - * which have this group, then - * mark this src-grp as a prune candidate. - */ - if (!gt->gt_prsent_timer && !gt->gt_grpmems && r && r->rt_gateway) - send_prune(gt); -} - -/* - * An mrouter has gone down and come up on an interface - * Forward on that interface immediately - */ -void -reset_neighbor_state(vifi, addr) - vifi_t vifi; - u_int32 addr; -{ - struct rtentry *r; - struct gtable *g; - struct ptable *pt, **ptnp; - struct stable *st; - - for (g = kernel_table; g; g = g->gt_gnext) { - r = g->gt_route; - - /* - * If neighbor was the parent, remove the prune sent state - * and all of the source cache info so that prunes get - * regenerated. - */ - if (vifi == r->rt_parent) { - if (addr == r->rt_gateway) { - log(LOG_DEBUG, 0, "reset_neighbor_state parent reset (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2)); - - g->gt_prsent_timer = 0; - g->gt_grftsnt = 0; - while (st = g->gt_srctbl) { - g->gt_srctbl = st->st_next; - k_del_rg(st->st_origin, g); - kroutes--; - free(st); - } - } - } else { - /* - * Neighbor was not the parent, send grafts to join the groups - */ - if (g->gt_prsent_timer) { - g->gt_grftsnt = 1; - send_graft(g); - g->gt_prsent_timer = 0; - } - - /* - * Remove any prunes that this router has sent us. - */ - ptnp = &g->gt_pruntbl; - while ((pt = *ptnp) != NULL) { - if (pt->pt_vifi == vifi && pt->pt_router == addr) { - *ptnp = pt->pt_next; - free(pt); - } else - ptnp = &pt->pt_next; - } - - /* - * And see if we want to forward again. - */ - if (!VIFM_ISSET(vifi, g->gt_grpmems)) { - if (VIFM_ISSET(vifi, r->rt_children) && - !(VIFM_ISSET(vifi, r->rt_leaves))) - VIFM_SET(vifi, g->gt_grpmems); - - if (VIFM_ISSET(vifi, r->rt_leaves) && - grplst_mem(vifi, g->gt_mcastgrp)) - VIFM_SET(vifi, g->gt_grpmems); - - g->gt_grpmems &= ~g->gt_scope; - prun_add_ttls(g); - - /* Update kernel state */ - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - - log(LOG_DEBUG, 0, "reset member state (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - } - } - } -} - -/* - * Delete table entry from the kernel - * del_flag determines how many entries to delete - */ -void -del_table_entry(r, mcastgrp, del_flag) - struct rtentry *r; - u_int32 mcastgrp; - u_int del_flag; -{ - struct gtable *g, *prev_g; - struct stable *st, *prev_st; - struct ptable *pt, *prev_pt; - - if (del_flag == DEL_ALL_ROUTES) { - g = r->rt_groups; - while (g) { - log(LOG_DEBUG, 0, "del_table_entry deleting (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2)); - st = g->gt_srctbl; - while (st) { - if (k_del_rg(st->st_origin, g) < 0) { - log(LOG_WARNING, errno, - "del_table_entry trying to delete (%s, %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(g->gt_mcastgrp, s2)); - } - kroutes--; - prev_st = st; - st = st->st_next; - free(prev_st); - } - g->gt_srctbl = NULL; - - pt = g->gt_pruntbl; - while (pt) { - prev_pt = pt; - pt = pt->pt_next; - free(prev_pt); - } - g->gt_pruntbl = NULL; - - if (g->gt_gnext) - g->gt_gnext->gt_gprev = g->gt_gprev; - if (g->gt_gprev) - g->gt_gprev->gt_gnext = g->gt_gnext; - else - kernel_table = g->gt_gnext; - -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,0); - rsrr_cache_clean(g); -#endif /* RSRR */ - prev_g = g; - g = g->gt_next; - free(prev_g); - } - r->rt_groups = NULL; - } - - /* - * Dummy routine - someday this may be needed, so it is just there - */ - if (del_flag == DEL_RTE_GROUP) { - prev_g = (struct gtable *)&r->rt_groups; - for (g = r->rt_groups; g; g = g->gt_next) { - if (g->gt_mcastgrp == mcastgrp) { - log(LOG_DEBUG, 0, "del_table_entry deleting (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2)); - st = g->gt_srctbl; - while (st) { - if (k_del_rg(st->st_origin, g) < 0) { - log(LOG_WARNING, errno, - "del_table_entry trying to delete (%s, %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(g->gt_mcastgrp, s2)); - } - kroutes--; - prev_st = st; - st = st->st_next; - free(prev_st); - } - g->gt_srctbl = NULL; - - pt = g->gt_pruntbl; - while (pt) { - prev_pt = pt; - pt = pt->pt_next; - free(prev_pt); - } - g->gt_pruntbl = NULL; - - if (g->gt_gnext) - g->gt_gnext->gt_gprev = g->gt_gprev; - if (g->gt_gprev) - g->gt_gprev->gt_gnext = g->gt_gnext; - else - kernel_table = g->gt_gnext; - - if (prev_g != (struct gtable *)&r->rt_groups) - g->gt_next->gt_prev = prev_g; - else - g->gt_next->gt_prev = NULL; - prev_g->gt_next = g->gt_next; - -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,0); - rsrr_cache_clean(g); -#endif /* RSRR */ - free(g); - g = prev_g; - } else { - prev_g = g; - } - } - } -} - -/* - * update kernel table entry when a route entry changes - */ -void -update_table_entry(r) - struct rtentry *r; -{ - struct gtable *g; - struct ptable *pt, *prev_pt; - vifi_t i; - - for (g = r->rt_groups; g; g = g->gt_next) { - pt = g->gt_pruntbl; - while (pt) { - prev_pt = pt->pt_next; - free(pt); - pt = prev_pt; - } - g->gt_pruntbl = NULL; - - g->gt_grpmems = 0; - - /* 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, g->gt_grpmems); - - if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, g->gt_mcastgrp)) - VIFM_SET(i, g->gt_grpmems); - } - if (VIFM_ISSET(r->rt_parent, g->gt_scope)) - g->gt_scope = -1; - g->gt_grpmems &= ~g->gt_scope; - - log(LOG_DEBUG, 0, "updating cache entries (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), - g->gt_grpmems); - - if (g->gt_grpmems && g->gt_prsent_timer) { - g->gt_grftsnt = 1; - send_graft(g); - g->gt_prsent_timer = 0; - } - - /* update ttls and add entry into kernel */ - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - - /* Check if we want to prune this group */ - if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) { - g->gt_timer = CACHE_LIFETIME(cache_lifetime); - send_prune(g); - } - } -} - -/* - * set the forwarding flag for all mcastgrps on this vifi - */ -void -update_lclgrp(vifi, mcastgrp) - vifi_t vifi; - u_int32 mcastgrp; -{ - struct rtentry *r; - struct gtable *g; - - log(LOG_DEBUG, 0, "group %s joined on vif %d", - inet_fmt(mcastgrp, s1), vifi); - - for (g = kernel_table; g; g = g->gt_gnext) { - if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp)) - break; - - r = g->gt_route; - if (g->gt_mcastgrp == mcastgrp && - VIFM_ISSET(vifi, r->rt_children)) { - - VIFM_SET(vifi, g->gt_grpmems); - g->gt_grpmems &= ~g->gt_scope; - if (g->gt_grpmems == 0) - continue; - - prun_add_ttls(g); - log(LOG_DEBUG, 0, "update lclgrp (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - } - } -} - -/* - * reset forwarding flag for all mcastgrps on this vifi - */ -void -delete_lclgrp(vifi, mcastgrp) - vifi_t vifi; - u_int32 mcastgrp; -{ - struct rtentry *r; - struct gtable *g; - - log(LOG_DEBUG, 0, "group %s left on vif %d", - inet_fmt(mcastgrp, s1), vifi); - - for (g = kernel_table; g; g = g->gt_gnext) { - if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp)) - break; - - if (g->gt_mcastgrp == mcastgrp) { - int stop_sending = 1; - - r = g->gt_route; - /* - * If this is not a leaf, then we have router neighbors on this - * vif. Only turn off forwarding if they have all pruned. - */ - if (!VIFM_ISSET(vifi, r->rt_leaves)) { - struct listaddr *vr; - - for (vr = uvifs[vifi].uv_neighbors; vr; vr = vr->al_next) - if (find_prune_entry(vr->al_addr, g->gt_pruntbl) == NULL) { - stop_sending = 0; - break; - } - } - - if (stop_sending) { - VIFM_CLR(vifi, g->gt_grpmems); - log(LOG_DEBUG, 0, "delete lclgrp (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - - /* - * If there are no more members of this particular group, - * send prune upstream - */ - if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) - send_prune(g); - } - } - } -} - -/* - * Takes the prune message received and then strips it to - * determine the (src, grp) pair to be pruned. - * - * Adds the router to the (src, grp) entry then. - * - * Determines if further packets have to be sent down that vif - * - * Determines if a corresponding prune message has to be generated - */ -void -accept_prune(src, dst, p, datalen) - u_int32 src; - u_int32 dst; - char *p; - int datalen; -{ - u_int32 prun_src; - u_int32 prun_grp; - u_int32 prun_tmr; - vifi_t vifi; - int i; - int stop_sending; - struct rtentry *r; - struct gtable *g; - struct ptable *pt; - struct listaddr *vr; - - /* Don't process any prunes if router is not pruning */ - if (pruning == 0) - return; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - log(LOG_INFO, 0, - "ignoring prune report from non-neighbor %s", - inet_fmt(src, s1)); - return; - } - - /* Check if enough data is present */ - if (datalen < 12) - { - log(LOG_WARNING, 0, - "non-decipherable prune from %s", - inet_fmt(src, s1)); - return; - } - - for (i = 0; i< 4; i++) - ((char *)&prun_src)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&prun_grp)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&prun_tmr)[i] = *p++; - prun_tmr = ntohl(prun_tmr); - - log(LOG_DEBUG, 0, "%s on vif %d prunes (%s %s)/%d", - inet_fmt(src, s1), vifi, - inet_fmt(prun_src, s2), inet_fmt(prun_grp, s3), prun_tmr); - - /* - * Find the subnet for the prune - */ - if (find_src_grp(prun_src, 0, prun_grp)) { - g = gtp ? gtp->gt_gnext : kernel_table; - r = g->gt_route; - - if (!VIFM_ISSET(vifi, r->rt_children)) { - log(LOG_WARNING, 0, "prune received from non-child %s for (%s %s)", - inet_fmt(src, s1), inet_fmt(prun_src, s2), - inet_fmt(prun_grp, s3)); - return; - } - if (VIFM_ISSET(vifi, g->gt_scope)) { - log(LOG_WARNING, 0, "prune received from %s on scoped grp (%s %s)", - inet_fmt(src, s1), inet_fmt(prun_src, s2), - inet_fmt(prun_grp, s3)); - return; - } - if ((pt = find_prune_entry(src, g->gt_pruntbl)) != NULL) { - /* - * If it's about to expire, then it's only still around because - * of timer granularity, so don't warn about it. - */ - if (pt->pt_timer > 10) { - log(LOG_WARNING, 0, "%s %d from %s for (%s %s)/%d %s %d %s %x", - "duplicate prune received on vif", - vifi, inet_fmt(src, s1), inet_fmt(prun_src, s2), - inet_fmt(prun_grp, s3), prun_tmr, - "old timer:", pt->pt_timer, "cur gm:", g->gt_grpmems); - } - pt->pt_timer = prun_tmr; - } else { - /* allocate space for the prune structure */ - pt = (struct ptable *)(malloc(sizeof(struct ptable))); - if (pt == NULL) - log(LOG_ERR, 0, "pt: ran out of memory"); - - pt->pt_vifi = vifi; - pt->pt_router = src; - pt->pt_timer = prun_tmr; - - pt->pt_next = g->gt_pruntbl; - g->gt_pruntbl = pt; - } - - /* Refresh the group's lifetime */ - g->gt_timer = CACHE_LIFETIME(cache_lifetime); - if (g->gt_timer < prun_tmr) - g->gt_timer = prun_tmr; - - /* - * check if any more packets need to be sent on the - * vif which sent this message - */ - stop_sending = 1; - for (vr = uvifs[vifi].uv_neighbors; vr; vr = vr->al_next) - if (find_prune_entry(vr->al_addr, g->gt_pruntbl) == NULL) { - stop_sending = 0; - break; - } - - if (stop_sending && !grplst_mem(vifi, prun_grp)) { - VIFM_CLR(vifi, g->gt_grpmems); - log(LOG_DEBUG, 0, "prune (%s %s), stop sending on vif %d, gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), vifi, g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - } - - /* - * check if all the child routers have expressed no interest - * in this group and if this group does not exist in the - * interface - * Send a prune message then upstream - */ - if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) { - send_prune(g); - } - } else { - /* - * There is no kernel entry for this group. Therefore, we can - * simply ignore the prune, as we are not forwarding this traffic - * downstream. - */ - log(LOG_DEBUG, 0, "%s (%s %s)/%d from %s", - "prune message received with no kernel entry for", - inet_fmt(prun_src, s1), inet_fmt(prun_grp, s2), - prun_tmr, inet_fmt(src, s3)); - return; - } -} - -/* - * Checks if this mcastgrp is present in the kernel table - * If so and if a prune was sent, it sends a graft upwards - */ -void -chkgrp_graft(vifi, mcastgrp) - vifi_t vifi; - u_int32 mcastgrp; -{ - struct rtentry *r; - struct gtable *g; - - for (g = kernel_table; g; g = g->gt_gnext) { - if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp)) - break; - - r = g->gt_route; - if (g->gt_mcastgrp == mcastgrp && VIFM_ISSET(vifi, r->rt_children)) - if (g->gt_prsent_timer) { - VIFM_SET(vifi, g->gt_grpmems); - - /* - * If the vif that was joined was a scoped vif, - * ignore it ; don't graft back - */ - g->gt_grpmems &= ~g->gt_scope; - if (g->gt_grpmems == 0) - continue; - - /* set the flag for graft retransmission */ - g->gt_grftsnt = 1; - - /* send graft upwards */ - send_graft(g); - - /* reset the prune timer and update cache timer*/ - g->gt_prsent_timer = 0; - g->gt_timer = max_prune_lifetime; - - log(LOG_DEBUG, 0, "chkgrp graft (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - } - } -} - -/* determine the multicast group and src - * - * if it does, then determine if a prune was sent - * upstream. - * if prune sent upstream, send graft upstream and send - * ack downstream. - * - * if no prune sent upstream, change the forwarding bit - * for this interface and send ack downstream. - * - * if no entry exists for this group send ack downstream. - */ -void -accept_graft(src, dst, p, datalen) - u_int32 src; - u_int32 dst; - char *p; - int datalen; -{ - vifi_t vifi; - u_int32 graft_src; - u_int32 graft_grp; - int i; - struct rtentry *r; - struct gtable *g; - struct ptable *pt, **ptnp; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - log(LOG_INFO, 0, - "ignoring graft from non-neighbor %s", - inet_fmt(src, s1)); - return; - } - - if (datalen < 8) { - log(LOG_WARNING, 0, - "received non-decipherable graft from %s", - inet_fmt(src, s1)); - return; - } - - for (i = 0; i< 4; i++) - ((char *)&graft_src)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&graft_grp)[i] = *p++; - - log(LOG_DEBUG, 0, "%s on vif %d grafts (%s %s)", - inet_fmt(src, s1), vifi, - inet_fmt(graft_src, s2), inet_fmt(graft_grp, s3)); - - /* - * Find the subnet for the graft - */ - if (find_src_grp(graft_src, 0, graft_grp)) { - g = gtp ? gtp->gt_gnext : kernel_table; - r = g->gt_route; - - if (VIFM_ISSET(vifi, g->gt_scope)) { - log(LOG_WARNING, 0, "graft received from %s on scoped grp (%s %s)", - inet_fmt(src, s1), inet_fmt(graft_src, s2), - inet_fmt(graft_grp, s3)); - return; - } - - ptnp = &g->gt_pruntbl; - while ((pt = *ptnp) != NULL) { - if ((pt->pt_vifi == vifi) && (pt->pt_router == src)) { - *ptnp = pt->pt_next; - free(pt); - - VIFM_SET(vifi, g->gt_grpmems); - log(LOG_DEBUG, 0, "accept graft (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - break; - } else { - ptnp = &pt->pt_next; - } - } - - /* send ack downstream */ - send_graft_ack(dst, src, graft_src, graft_grp); - g->gt_timer = max_prune_lifetime; - - if (g->gt_prsent_timer) { - /* set the flag for graft retransmission */ - g->gt_grftsnt = 1; - - /* send graft upwards */ - send_graft(g); - - /* reset the prune sent timer */ - g->gt_prsent_timer = 0; - } - } else { - /* - * We have no state for the source and group in question. - * We can simply acknowledge the graft, since we know - * that we have no prune state, and grafts are requests - * to remove prune state. - */ - send_graft_ack(dst, src, graft_src, graft_grp); - log(LOG_DEBUG, 0, "%s (%s %s) from %s", - "graft received with no kernel entry for", - inet_fmt(graft_src, s1), inet_fmt(graft_grp, s2), - inet_fmt(src, s3)); - return; - } -} - -/* - * find out which group is involved first of all - * then determine if a graft was sent. - * if no graft sent, ignore the message - * if graft was sent and the ack is from the right - * source, remove the graft timer so that we don't - * have send a graft again - */ -void -accept_g_ack(src, dst, p, datalen) - u_int32 src; - u_int32 dst; - char *p; - int datalen; -{ - struct gtable *g; - vifi_t vifi; - u_int32 grft_src; - u_int32 grft_grp; - int i; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - log(LOG_INFO, 0, - "ignoring graft ack from non-neighbor %s", - inet_fmt(src, s1)); - return; - } - - if (datalen < 0 || datalen > 8) { - log(LOG_WARNING, 0, - "received non-decipherable graft ack from %s", - inet_fmt(src, s1)); - return; - } - - for (i = 0; i< 4; i++) - ((char *)&grft_src)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&grft_grp)[i] = *p++; - - log(LOG_DEBUG, 0, "%s on vif %d acks graft (%s, %s)", - inet_fmt(src, s1), vifi, - inet_fmt(grft_src, s2), inet_fmt(grft_grp, s3)); - - /* - * Find the subnet for the graft ack - */ - if (find_src_grp(grft_src, 0, grft_grp)) { - g = gtp ? gtp->gt_gnext : kernel_table; - g->gt_grftsnt = 0; - } else { - log(LOG_WARNING, 0, "%s (%s, %s) from %s", - "rcvd graft ack with no kernel entry for", - inet_fmt(grft_src, s1), inet_fmt(grft_grp, s2), - inet_fmt(src, s3)); - return; - } -} - - -/* - * free all prune entries and kernel routes - * normally, this should inform the kernel that all of its routes - * are going away, but this is only called by restart(), which is - * about to call MRT_DONE which does that anyway. - */ -void -free_all_prunes() -{ - register struct rtentry *r; - register struct gtable *g, *prev_g; - register struct stable *s, *prev_s; - register struct ptable *p, *prev_p; - - for (r = routing_table; r; r = r->rt_next) { - g = r->rt_groups; - while (g) { - s = g->gt_srctbl; - while (s) { - prev_s = s; - s = s->st_next; - free(prev_s); - } - - p = g->gt_pruntbl; - while (p) { - prev_p = p; - p = p->pt_next; - free(prev_p); - } - - prev_g = g; - g = g->gt_next; - free(prev_g); - } - r->rt_groups = NULL; - } - kernel_table = NULL; - - g = kernel_no_route; - while (g) { - if (g->gt_srctbl) - free(g->gt_srctbl); - - prev_g = g; - g = g->gt_next; - free(prev_g); - } - kernel_no_route = NULL; -} - -/* - * When a new route is created, search - * a) The less-specific part of the routing table - * b) The route-less kernel table - * for sources that the new route might want to handle. - * - * "Inheriting" these sources might be cleanest, but simply deleting - * them is easier, and letting the kernel re-request them. - */ -void -steal_sources(rt) - struct rtentry *rt; -{ - register struct rtentry *rp; - register struct gtable *gt, **gtnp; - register struct stable *st, **stnp; - - for (rp = rt->rt_next; rp; rp = rp->rt_next) { - if ((rt->rt_origin & rp->rt_originmask) == rp->rt_origin) { - log(LOG_DEBUG, 0, "Route for %s stealing sources from %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmts(rp->rt_origin, rp->rt_originmask, s2)); - for (gt = rp->rt_groups; gt; gt = gt->gt_next) { - stnp = >->gt_srctbl; - while ((st = *stnp) != NULL) { - if ((st->st_origin & rt->rt_originmask) == rt->rt_origin) { - log(LOG_DEBUG, 0, "%s stealing (%s %s) from %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmt(st->st_origin, s3), - inet_fmt(gt->gt_mcastgrp, s4), - inet_fmts(rp->rt_origin, rp->rt_originmask, s2)); - if (k_del_rg(st->st_origin, gt) < 0) { - log(LOG_WARNING, errno, "%s (%s, %s)", - "steal_sources trying to delete", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - *stnp = st->st_next; - kroutes--; - free(st); - } else { - stnp = &st->st_next; - } - } - } - } - } - - gtnp = &kernel_no_route; - while ((gt = *gtnp) != NULL) { - if (gt->gt_srctbl && ((gt->gt_srctbl->st_origin & rt->rt_originmask) - == rt->rt_origin)) { - log(LOG_DEBUG, 0, "%s stealing (%s %s) from %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmt(gt->gt_srctbl->st_origin, s3), - inet_fmt(gt->gt_mcastgrp, s4), - "no_route table"); - if (k_del_rg(gt->gt_srctbl->st_origin, gt) < 0) { - log(LOG_WARNING, errno, "%s (%s %s)", - "steal_sources trying to delete", - inet_fmt(gt->gt_srctbl->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - kroutes--; - free(gt->gt_srctbl); - *gtnp = gt->gt_next; - if (gt->gt_next) - gt->gt_next->gt_prev = gt->gt_prev; - free(gt); - } else { - gtnp = >->gt_next; - } - } -} - -/* - * Advance the timers on all the cache entries. - * If there are any entries whose timers have expired, - * remove these entries from the kernel cache. - */ -void -age_table_entry() -{ - struct rtentry *r; - struct gtable *gt, **gtnptr; - struct stable *st, **stnp; - struct ptable *pt, **ptnp; - struct sioc_sg_req sg_req; - - log(LOG_DEBUG, 0, "ageing entries"); - - gtnptr = &kernel_table; - while ((gt = *gtnptr) != NULL) { - r = gt->gt_route; - - /* advance the timer for the kernel entry */ - gt->gt_timer -= ROUTE_MAX_REPORT_DELAY; - - /* decrement prune timer if need be */ - if (gt->gt_prsent_timer > 0) { - gt->gt_prsent_timer -= ROUTE_MAX_REPORT_DELAY; - if (gt->gt_prsent_timer <= 0) { - log(LOG_DEBUG, 0, "upstream prune tmo (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - gt->gt_prsent_timer = -1; - } - } - - /* retransmit graft if graft sent flag is still set */ - if (gt->gt_grftsnt) { - register int y; - CHK_GS(gt->gt_grftsnt++, y); - if (y) - send_graft(gt); - } - - /* - * Age prunes - * - * If a prune expires, forward again on that vif. - */ - ptnp = >->gt_pruntbl; - while ((pt = *ptnp) != NULL) { - if ((pt->pt_timer -= ROUTE_MAX_REPORT_DELAY) <= 0) { - log(LOG_DEBUG, 0, "expire prune (%s %s) from %s on vif %d", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), - inet_fmt(pt->pt_router, s3), - pt->pt_vifi); - - expire_prune(pt->pt_vifi, gt); - - /* remove the router's prune entry and await new one */ - *ptnp = pt->pt_next; - free(pt); - } else { - ptnp = &pt->pt_next; - } - } - - /* - * If the cache entry has expired, delete source table entries for - * silent sources. If there are no source entries left, and there - * are no downstream prunes, then the entry is deleted. - * Otherwise, the cache entry's timer is refreshed. - */ - if (gt->gt_timer <= 0) { - /* Check for traffic before deleting source entries */ - sg_req.grp.s_addr = gt->gt_mcastgrp; - stnp = >->gt_srctbl; - while ((st = *stnp) != NULL) { - sg_req.src.s_addr = st->st_origin; - if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) < 0) { - log(LOG_WARNING, errno, "%s (%s %s)", - "age_table_entry: SIOCGETSGCNT failing for", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - /* Make sure it gets deleted below */ - sg_req.pktcnt = st->st_pktcnt; - } - if (sg_req.pktcnt == st->st_pktcnt) { - *stnp = st->st_next; - log(LOG_DEBUG, 0, "age_table_entry deleting (%s %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - if (k_del_rg(st->st_origin, gt) < 0) { - log(LOG_WARNING, errno, - "age_table_entry trying to delete (%s %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - kroutes--; - free(st); - } else { - st->st_pktcnt = sg_req.pktcnt; - stnp = &st->st_next; - } - } - - /* - * Retain the group entry if we have downstream prunes or if - * there is at least one source in the list that still has - * traffic, or if our upstream prune timer is running. - */ - if (gt->gt_pruntbl != NULL || gt->gt_srctbl != NULL || - gt->gt_prsent_timer > 0) { - gt->gt_timer = CACHE_LIFETIME(cache_lifetime); - if (gt->gt_prsent_timer == -1) - if (gt->gt_grpmems == 0) - send_prune(gt); - else - gt->gt_prsent_timer = 0; - gtnptr = >->gt_gnext; - continue; - } - - log(LOG_DEBUG, 0, "timeout cache entry (%s, %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - - if (gt->gt_prev) - gt->gt_prev->gt_next = gt->gt_next; - else - gt->gt_route->rt_groups = gt->gt_next; - if (gt->gt_next) - gt->gt_next->gt_prev = gt->gt_prev; - - if (gt->gt_gprev) { - gt->gt_gprev->gt_gnext = gt->gt_gnext; - gtnptr = >->gt_gprev->gt_gnext; - } else { - kernel_table = gt->gt_gnext; - gtnptr = &kernel_table; - } - if (gt->gt_gnext) - gt->gt_gnext->gt_gprev = gt->gt_gprev; - -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(gt,0); - rsrr_cache_clean(gt); -#endif /* RSRR */ - free((char *)gt); - } else { - if (gt->gt_prsent_timer == -1) - if (gt->gt_grpmems == 0) - send_prune(gt); - else - gt->gt_prsent_timer = 0; - gtnptr = >->gt_gnext; - } - } - - /* - * When traversing the no_route table, the decision is much easier. - * Just delete it if it has timed out. - */ - gtnptr = &kernel_no_route; - while ((gt = *gtnptr) != NULL) { - /* advance the timer for the kernel entry */ - gt->gt_timer -= ROUTE_MAX_REPORT_DELAY; - - if (gt->gt_timer < 0) { - if (gt->gt_srctbl) { - if (k_del_rg(gt->gt_srctbl->st_origin, gt) < 0) { - log(LOG_WARNING, errno, "%s (%s %s)", - "age_table_entry trying to delete no-route", - inet_fmt(gt->gt_srctbl->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - free(gt->gt_srctbl); - } - *gtnptr = gt->gt_next; - if (gt->gt_next) - gt->gt_next->gt_prev = gt->gt_prev; - - free((char *)gt); - } else { - gtnptr = >->gt_next; - } - } -} - -/* - * Modify the kernel to forward packets when one or multiple prunes that - * were received on the vif given by vifi, for the group given by gt, - * have expired. - */ -static void -expire_prune(vifi, gt) - vifi_t vifi; - struct gtable *gt; -{ - /* - * No need to send a graft, any prunes that we sent - * will expire before any prunes that we have received. - */ - if (gt->gt_prsent_timer > 0) { - log(LOG_DEBUG, 0, "prune expired with %d left on %s", - gt->gt_prsent_timer, "prsent_timer"); - gt->gt_prsent_timer = 0; - } - - /* modify the kernel entry to forward packets */ - if (!VIFM_ISSET(vifi, gt->gt_grpmems)) { - struct rtentry *rt = gt->gt_route; - VIFM_SET(vifi, gt->gt_grpmems); - log(LOG_DEBUG, 0, "forw again (%s %s) gm:%x vif:%d", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems, vifi); - - prun_add_ttls(gt); - update_kernel(gt); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(gt,1); -#endif /* RSRR */ - } -} - - -static char * -scaletime(t) - u_long t; -{ - static char buf1[5]; - static char buf2[5]; - static char *buf=buf1; - char s; - char *p; - - p = buf; - if (buf == buf1) - buf = buf2; - else - buf = buf1; - - if (t < 120) { - s = 's'; - } else if (t < 3600) { - t /= 60; - s = 'm'; - } else if (t < 86400) { - t /= 3600; - s = 'h'; - } else if (t < 864000) { - t /= 86400; - s = 'd'; - } else { - t /= 604800; - s = 'w'; - } - if (t > 999) - return "*** "; - - sprintf(p,"%3d%c", (int)t, s); - - return p; -} - -/* - * Print the contents of the cache table on file 'fp2'. - */ -void -dump_cache(fp2) - FILE *fp2; -{ - register struct rtentry *r; - register struct gtable *gt; - register struct stable *st; - register struct ptable *pt; - register vifi_t i; - register time_t thyme = time(0); - - fprintf(fp2, - "Multicast Routing Cache Table (%d entries)\n%s", kroutes, - " Origin Mcast-group CTmr Age Ptmr IVif Forwvifs\n"); - - for (gt = kernel_no_route; gt; gt = gt->gt_next) { - if (gt->gt_srctbl) { - fprintf(fp2, " %-18s %-15s %-4s %-4s - -1\n", - inet_fmts(gt->gt_srctbl->st_origin, 0xffffffff, s1), - inet_fmt(gt->gt_mcastgrp, s2), scaletime(gt->gt_timer), - scaletime(thyme - gt->gt_ctime)); - fprintf(fp2, ">%s\n", inet_fmt(gt->gt_srctbl->st_origin, s1)); - } - } - - for (gt = kernel_table; gt; gt = gt->gt_gnext) { - r = gt->gt_route; - fprintf(fp2, " %-18s %-15s", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - - fprintf(fp2, " %-4s", scaletime(gt->gt_timer)); - - fprintf(fp2, " %-4s %-4s ", scaletime(thyme - gt->gt_ctime), - gt->gt_prsent_timer ? scaletime(gt->gt_prsent_timer) : - " -"); - - fprintf(fp2, "%2u%c%c ", r->rt_parent, - gt->gt_prsent_timer ? 'P' : ' ', - VIFM_ISSET(r->rt_parent, gt->gt_scope) ? 'B' : ' '); - - for (i = 0; i < numvifs; ++i) { - if (VIFM_ISSET(i, gt->gt_grpmems)) - fprintf(fp2, " %u ", i); - else if (VIFM_ISSET(i, r->rt_children) && - !VIFM_ISSET(i, r->rt_leaves)) - fprintf(fp2, " %u%c", i, - VIFM_ISSET(i, gt->gt_scope) ? 'b' : 'p'); - } - fprintf(fp2, "\n"); - for (st = gt->gt_srctbl; st; st = st->st_next) { - fprintf(fp2, ">%s\n", inet_fmt(st->st_origin, s1)); - } -#ifdef DEBUG_PRUNES - for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) { - fprintf(fp2, "<r:%s v:%d t:%d\n", inet_fmt(pt->pt_router, s1), - pt->pt_vifi, pt->pt_timer); - } -#endif - } -} - -/* - * Traceroute function which returns traceroute replies to the requesting - * router. Also forwards the request to downstream routers. - */ -void -accept_mtrace(src, dst, group, data, no, datalen) - u_int32 src; - u_int32 dst; - u_int32 group; - char *data; - u_int no; /* promoted u_char */ - int datalen; -{ - u_char type; - struct rtentry *rt; - struct gtable *gt; - struct tr_query *qry; - struct tr_resp *resp; - int vifi; - char *p; - int rcount; - int errcode = TR_NO_ERR; - int resptype; - struct timeval tp; - struct sioc_vif_req v_req; - struct sioc_sg_req sg_req; - - /* Remember qid across invocations */ - static u_int32 oqid = 0; - - /* timestamp the request/response */ - gettimeofday(&tp, 0); - - /* - * Check if it is a query or a response - */ - if (datalen == QLEN) { - type = QUERY; - log(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); - } - else if ((datalen - QLEN) % RLEN == 0) { - type = RESP; - log(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); - if (IN_MULTICAST(ntohl(dst))) { - log(LOG_DEBUG, 0, "Dropping multicast response"); - return; - } - } - else { - log(LOG_WARNING, 0, "%s from %s to %s", - "Non decipherable traceroute request recieved", - inet_fmt(src, s1), inet_fmt(dst, s2)); - return; - } - - qry = (struct tr_query *)data; - - /* - * if it is a packet with all reports filled, drop it - */ - if ((rcount = (datalen - QLEN)/RLEN) == no) { - log(LOG_DEBUG, 0, "packet with all reports filled in"); - return; - } - - log(LOG_DEBUG, 0, "s: %s g: %s d: %s ", inet_fmt(qry->tr_src, s1), - inet_fmt(group, s2), inet_fmt(qry->tr_dst, s3)); - log(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl, - inet_fmt(qry->tr_raddr, s1)); - log(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid); - - /* determine the routing table entry for this traceroute */ - rt = determine_route(qry->tr_src); - if (rt) { - log(LOG_DEBUG, 0, "rt parent vif: %d rtr: %s metric: %d", - rt->rt_parent, inet_fmt(rt->rt_gateway, s1), rt->rt_metric); - log(LOG_DEBUG, 0, "rt origin %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1)); - } else - log(LOG_DEBUG, 0, "...no route"); - - /* - * Query type packet - check if rte exists - * Check if the query destination is a vif connected to me. - * and if so, whether I should start response back - */ - if (type == QUERY) { - if (oqid == qry->tr_qid) { - /* - * If the multicast router is a member of the group being - * queried, and the query is multicasted, then the router can - * recieve multiple copies of the same query. If we have already - * replied to this traceroute, just ignore it this time. - * - * This is not a total solution, but since if this fails you - * only get N copies, N <= the number of interfaces on the router, - * it is not fatal. - */ - log(LOG_DEBUG, 0, "ignoring duplicate traceroute packet"); - return; - } - - if (rt == NULL) { - log(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s", - inet_fmt(qry->tr_src, s1)); - if (IN_MULTICAST(ntohl(dst))) - return; - } - vifi = find_vif(qry->tr_dst, 0); - - if (vifi == NO_VIF) { - /* The traceroute destination is not on one of my subnet vifs. */ - log(LOG_DEBUG, 0, "Destination %s not an interface", - inet_fmt(qry->tr_dst, s1)); - if (IN_MULTICAST(ntohl(dst))) - return; - errcode = TR_WRONG_IF; - } else if (rt != NULL && !VIFM_ISSET(vifi, rt->rt_children)) { - log(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s", - inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2)); - if (IN_MULTICAST(ntohl(dst))) - return; - errcode = TR_WRONG_IF; - } - } - else { - /* - * determine which interface the packet came in on - * RESP packets travel hop-by-hop so this either traversed - * a tunnel or came from a directly attached mrouter. - */ - if ((vifi = find_vif(src, dst)) == NO_VIF) { - log(LOG_DEBUG, 0, "Wrong interface for packet"); - errcode = TR_WRONG_IF; - } - } - - /* Now that we've decided to send a response, save the qid */ - oqid = qry->tr_qid; - - log(LOG_DEBUG, 0, "Sending traceroute response"); - - /* copy the packet to the sending buffer */ - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - - bcopy(data, p, datalen); - - p += datalen; - - /* - * If there is no room to insert our reply, coopt the previous hop - * error indication to relay this fact. - */ - if (p + sizeof(struct tr_resp) > send_buf + RECV_BUF_SIZE) { - resp = (struct tr_resp *)p - 1; - resp->tr_rflags = TR_NO_SPACE; - rt = NULL; - goto sendit; - } - - /* - * fill in initial response fields - */ - resp = (struct tr_resp *)p; - bzero(resp, sizeof(struct tr_resp)); - datalen += RLEN; - - resp->tr_qarr = htonl((tp.tv_sec + JAN_1970) << 16) + - ((tp.tv_usec >> 4) & 0xffff); - - resp->tr_rproto = PROTO_DVMRP; - if (errcode != TR_NO_ERR) { - resp->tr_rflags = errcode; - rt = NULL; /* hack to enforce send straight to requestor */ - goto sendit; - } - resp->tr_outaddr = uvifs[vifi].uv_lcl_addr; - resp->tr_fttl = uvifs[vifi].uv_threshold; - resp->tr_rflags = TR_NO_ERR; - - /* - * obtain # of packets out on interface - */ - v_req.vifi = vifi; - if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0) - resp->tr_vifout = htonl(v_req.ocount); - - /* - * fill in scoping & pruning information - */ - if (rt) - for (gt = rt->rt_groups; gt; gt = gt->gt_next) { - if (gt->gt_mcastgrp >= group) - break; - } - else - gt = NULL; - - if (gt && gt->gt_mcastgrp == group) { - sg_req.src.s_addr = qry->tr_src; - sg_req.grp.s_addr = group; - if (ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0) - resp->tr_pktcnt = htonl(sg_req.pktcnt); - - if (VIFM_ISSET(vifi, gt->gt_scope)) - resp->tr_rflags = TR_SCOPED; - else if (gt->gt_prsent_timer) - resp->tr_rflags = TR_PRUNED; - else if (!VIFM_ISSET(vifi, gt->gt_grpmems)) - if (VIFM_ISSET(vifi, rt->rt_children) && - !VIFM_ISSET(vifi, rt->rt_leaves)) - resp->tr_rflags = TR_OPRUNED; - else - resp->tr_rflags = TR_NO_FWD; - } else { - if (scoped_addr(vifi, group)) - resp->tr_rflags = TR_SCOPED; - else if (rt && !VIFM_ISSET(vifi, rt->rt_children)) - resp->tr_rflags = TR_NO_FWD; - } - - /* - * if no rte exists, set NO_RTE error - */ - if (rt == NULL) { - src = dst; /* the dst address of resp. pkt */ - resp->tr_inaddr = 0; - resp->tr_rflags = TR_NO_RTE; - resp->tr_rmtaddr = 0; - } else { - /* get # of packets in on interface */ - v_req.vifi = rt->rt_parent; - if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0) - resp->tr_vifin = htonl(v_req.icount); - - MASK_TO_VAL(rt->rt_originmask, resp->tr_smask); - src = uvifs[rt->rt_parent].uv_lcl_addr; - resp->tr_inaddr = src; - resp->tr_rmtaddr = rt->rt_gateway; - if (!VIFM_ISSET(vifi, rt->rt_children)) { - log(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s", - inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2)); - resp->tr_rflags = TR_WRONG_IF; - } - if (rt->rt_metric >= UNREACHABLE) { - resp->tr_rflags = TR_NO_RTE; - /* Hack to send reply directly */ - rt = NULL; - } - } - -sendit: - /* - * if metric is 1 or no. of reports is 1, send response to requestor - * else send to upstream router. If the upstream router can't handle - * mtrace, set an error code and send to requestor anyway. - */ - log(LOG_DEBUG, 0, "rcount:%d, no:%d", rcount, no); - - if ((rcount + 1 == no) || (rt == NULL) || (rt->rt_metric == 1)) { - resptype = IGMP_MTRACE_RESP; - dst = qry->tr_raddr; - } else - if (!can_mtrace(rt->rt_parent, rt->rt_gateway)) { - dst = qry->tr_raddr; - resp->tr_rflags = TR_OLD_ROUTER; - resptype = IGMP_MTRACE_RESP; - } else { - dst = rt->rt_gateway; - resptype = IGMP_MTRACE; - } - - if (IN_MULTICAST(ntohl(dst))) { - /* - * Send the reply on a known multicast capable vif. - * If we don't have one, we can't source any multicasts anyway. - */ - if (phys_vif != -1) { - log(LOG_DEBUG, 0, "Sending reply to %s from %s", - inet_fmt(dst, s1), inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2)); - k_set_ttl(qry->tr_rttl); - send_igmp(uvifs[phys_vif].uv_lcl_addr, dst, - resptype, no, group, - datalen); - k_set_ttl(1); - } else - log(LOG_INFO, 0, "No enabled phyints -- %s", - "dropping traceroute reply"); - } else { - log(LOG_DEBUG, 0, "Sending %s to %s from %s", - resptype == IGMP_MTRACE_RESP ? "reply" : "request on", - inet_fmt(dst, s1), inet_fmt(src, s2)); - - send_igmp(src, dst, - resptype, no, group, - datalen); - } - return; -} diff --git a/usr.sbin/mrouted/prune.h b/usr.sbin/mrouted/prune.h deleted file mode 100644 index 57ae067ce74f..000000000000 --- a/usr.sbin/mrouted/prune.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: prune.h,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - -/* - * Group table - * - * Each group entry is a member of two doubly-linked lists: - * - * a) A list hanging off of the routing table entry for this source (rt_groups) - * sorted by group address under the routing entry (gt_next, gt_prev) - * b) An independent list pointed to by kernel_table, which is a list of - * active source,group's (gt_gnext, gt_gprev). - * - */ -struct gtable { - struct gtable *gt_next; /* pointer to the next entry */ - struct gtable *gt_prev; /* back pointer for linked list */ - struct gtable *gt_gnext; /* fwd pointer for group list */ - struct gtable *gt_gprev; /* rev pointer for group list */ - u_int32 gt_mcastgrp; /* multicast group associated */ - vifbitmap_t gt_scope; /* scoped interfaces */ - u_char gt_ttls[MAXVIFS]; /* ttl vector for forwarding */ - vifbitmap_t gt_grpmems; /* forw. vifs for src, grp */ - int gt_prsent_timer; /* prune timer for this group */ - int gt_timer; /* timer for this group entry */ - time_t gt_ctime; /* time of entry creation */ - u_char gt_grftsnt; /* graft sent/retransmit timer */ - struct stable *gt_srctbl; /* source table */ - struct ptable *gt_pruntbl; /* prune table */ - struct rtentry *gt_route; /* parent route */ -#ifdef RSRR - struct rsrr_cache *gt_rsrr_cache; /* RSRR cache */ -#endif /* RSRR */ -}; - -/* - * Source table - * - * When source-based prunes exist, there will be a struct ptable here as well. - */ -struct stable -{ - struct stable *st_next; /* pointer to the next entry */ - u_int32 st_origin; /* host origin of multicasts */ - u_long st_pktcnt; /* packet count for src-grp entry */ -}; - -/* - * structure to store incoming prunes. Can hang off of either group or source. - */ -struct ptable -{ - struct ptable *pt_next; /* pointer to the next entry */ - u_int32 pt_router; /* router that sent this prune */ - vifi_t pt_vifi; /* vif prune received on */ - int pt_timer; /* timer for prune */ -}; - -/* - * The packet format for a traceroute request. - */ -struct tr_query { - u_int32 tr_src; /* traceroute source */ - u_int32 tr_dst; /* traceroute destination */ - u_int32 tr_raddr; /* traceroute response address */ -#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) - struct { - u_int qid : 24; /* traceroute query id */ - u_int ttl : 8; /* traceroute response ttl */ - } q; -#else - struct { - u_int ttl : 8; /* traceroute response ttl */ - u_int qid : 24; /* traceroute query id */ - } q; -#endif /* BYTE_ORDER */ -}; - -#define tr_rttl q.ttl -#define tr_qid q.qid - -/* - * Traceroute response format. A traceroute response has a tr_query at the - * beginning, followed by one tr_resp for each hop taken. - */ -struct tr_resp { - u_int32 tr_qarr; /* query arrival time */ - u_int32 tr_inaddr; /* incoming interface address */ - u_int32 tr_outaddr; /* outgoing interface address */ - u_int32 tr_rmtaddr; /* parent address in source tree */ - u_int32 tr_vifin; /* input packet count on interface */ - u_int32 tr_vifout; /* output packet count on interface */ - u_int32 tr_pktcnt; /* total incoming packets for src-grp */ - u_char tr_rproto; /* routing protocol deployed on router */ - u_char tr_fttl; /* ttl required to forward on outvif */ - u_char tr_smask; /* subnet mask for src addr */ - u_char tr_rflags; /* forwarding error codes */ -}; - -/* defs within mtrace */ -#define QUERY 1 -#define RESP 2 -#define QLEN sizeof(struct tr_query) -#define RLEN sizeof(struct tr_resp) - -/* fields for tr_rflags (forwarding error codes) */ -#define TR_NO_ERR 0 -#define TR_WRONG_IF 1 -#define TR_PRUNED 2 -#define TR_OPRUNED 3 -#define TR_SCOPED 4 -#define TR_NO_RTE 5 -#define TR_NO_FWD 7 -#define TR_NO_SPACE 0x81 -#define TR_OLD_ROUTER 0x82 - -/* fields for tr_rproto (routing protocol) */ -#define PROTO_DVMRP 1 -#define PROTO_MOSPF 2 -#define PROTO_PIM 3 -#define PROTO_CBT 4 - -#define MASK_TO_VAL(x, i) { \ - u_int32 _x = ntohl(x); \ - (i) = 1; \ - while ((_x) <<= 1) \ - (i)++; \ - }; - -#define VAL_TO_MASK(x, i) { \ - x = htonl(~((1 << (32 - (i))) - 1)); \ - }; - -#define NBR_VERS(n) (((n)->al_pv << 8) + (n)->al_mv) diff --git a/usr.sbin/mrouted/route.c b/usr.sbin/mrouted/route.c deleted file mode 100644 index c2b6b9e8b932..000000000000 --- a/usr.sbin/mrouted/route.c +++ /dev/null @@ -1,1162 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: route.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - - -#include "defs.h" - - -/* - * This define statement saves a lot of space later - */ -#define RT_ADDR (struct rtentry *)&routing_table - -/* - * Exported variables. - */ -int routes_changed; /* 1=>some routes have changed */ -int delay_change_reports; /* 1=>postpone change reports */ - - -/* - * The routing table is shared with prune.c , so must not be static. - */ -struct rtentry *routing_table; /* pointer to list of route entries */ - -/* - * Private variables. - */ -static struct rtentry *rtp; /* pointer to a route entry */ -static struct rtentry *rt_end; /* pointer to last route entry */ -unsigned int nroutes; /* current number of route entries */ - -/* - * Private functions. - */ -static int init_children_and_leaves __P((struct rtentry *r, - vifi_t parent)); -static int find_route __P((u_int32 origin, u_int32 mask)); -static void create_route __P((u_int32 origin, u_int32 mask)); -static void discard_route __P((struct rtentry *prev_r)); -static int compare_rts __P((const void *rt1, const void *rt2)); -static int report_chunk __P((struct rtentry *start_rt, vifi_t vifi, - u_int32 dst)); - -/* - * Initialize the routing table and associated variables. - */ -void -init_routes() -{ - routing_table = NULL; - rt_end = RT_ADDR; - nroutes = 0; - routes_changed = FALSE; - delay_change_reports = FALSE; -} - - -/* - * Initialize the children and leaf bits for route 'r', along with the - * associated dominant, subordinate, and leaf timing data structures. - * Return TRUE if this changes the value of either the children or - * leaf bitmaps for 'r'. - */ -static int -init_children_and_leaves(r, parent) - register struct rtentry *r; - register vifi_t parent; -{ - register vifi_t vifi; - register struct uvif *v; - vifbitmap_t old_children, old_leaves; - - VIFM_COPY(r->rt_children, old_children); - VIFM_COPY(r->rt_leaves, old_leaves ); - - VIFM_CLRALL(r->rt_children); - VIFM_CLRALL(r->rt_leaves); - r->rt_flags &= ~RTF_LEAF_TIMING; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - r->rt_dominants [vifi] = 0; - r->rt_subordinates[vifi] = 0; - - if (vifi != parent && !(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { - VIFM_SET(vifi, r->rt_children); - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - } - else { - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - } - else { - r->rt_leaf_timers[vifi] = 0; - } - } - - return (!VIFM_SAME(r->rt_children, old_children) || - !VIFM_SAME(r->rt_leaves, old_leaves)); -} - - -/* - * A new vif has come up -- update the children and leaf bitmaps in all route - * entries to take that into account. - */ -void -add_vif_to_routes(vifi) - register vifi_t vifi; -{ - register struct rtentry *r; - register struct uvif *v; - - v = &uvifs[vifi]; - for (r = routing_table; r != NULL; r = r->rt_next) { - if (r->rt_metric != UNREACHABLE && - !VIFM_ISSET(vifi, r->rt_children)) { - VIFM_SET(vifi, r->rt_children); - r->rt_dominants [vifi] = 0; - r->rt_subordinates[vifi] = 0; - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - } - else { - VIFM_CLR(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - update_table_entry(r); - } - } -} - - -/* - * A vif has gone down -- expire all routes that have that vif as parent, - * and update the children bitmaps in all other route entries to take into - * account the failed vif. - */ -void -delete_vif_from_routes(vifi) - register vifi_t vifi; -{ - register struct rtentry *r; - - for (r = routing_table; r != NULL; r = r->rt_next) { - if (r->rt_metric != UNREACHABLE) { - if (vifi == r->rt_parent) { - del_table_entry(r, 0, DEL_ALL_ROUTES); - r->rt_timer = ROUTE_EXPIRE_TIME; - r->rt_metric = UNREACHABLE; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - else if (VIFM_ISSET(vifi, r->rt_children)) { - VIFM_CLR(vifi, r->rt_children); - VIFM_CLR(vifi, r->rt_leaves); - r->rt_subordinates[vifi] = 0; - r->rt_leaf_timers [vifi] = 0; - update_table_entry(r); - } - else { - r->rt_dominants[vifi] = 0; - } - } - } -} - - -/* - * A neighbor has failed or become unreachable. If that neighbor was - * considered a dominant or subordinate router in any route entries, - * take appropriate action. - */ -void -delete_neighbor_from_routes(addr, vifi) - register u_int32 addr; - register vifi_t vifi; -{ - register struct rtentry *r; - register struct uvif *v; - - v = &uvifs[vifi]; - for (r = routing_table; r != NULL; r = r->rt_next) { - if (r->rt_metric != UNREACHABLE) { - if (r->rt_dominants[vifi] == addr) { - VIFM_SET(vifi, r->rt_children); - r->rt_dominants [vifi] = 0; - r->rt_subordinates[vifi] = 0; - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - } - else { - VIFM_CLR(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - update_table_entry(r); - } - else if (r->rt_subordinates[vifi] == addr) { - r->rt_subordinates[vifi] = 0; - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - update_table_entry(r); - } - else { - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - } - else if (v->uv_neighbors == NULL && - r->rt_leaf_timers[vifi] != 0) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - update_table_entry(r); - } - } - } -} - - -/* - * Prepare for a sequence of ordered route updates by initializing a pointer - * to the start of the routing table. The pointer is used to remember our - * position in the routing table in order to avoid searching from the - * beginning for each update; this relies on having the route reports in - * a single message be in the same order as the route entries in the routing - * table. - */ -void -start_route_updates() -{ - rtp = RT_ADDR; -} - - -/* - * Starting at the route entry following the one to which 'rtp' points, - * look for a route entry matching the specified origin and mask. If a - * match is found, return TRUE and leave 'rtp' pointing at the found entry. - * If no match is found, return FALSE and leave 'rtp' pointing to the route - * entry preceding the point at which the new origin should be inserted. - * This code is optimized for the normal case in which the first entry to - * be examined is the matching entry. - */ -static int -find_route(origin, mask) - register u_int32 origin, mask; -{ - register struct rtentry *r; - - r = rtp->rt_next; - while (r != NULL) { - if (origin == r->rt_origin && mask == r->rt_originmask) { - rtp = r; - return (TRUE); - } - if (ntohl(mask) < ntohl(r->rt_originmask) || - (mask == r->rt_originmask && - ntohl(origin) < ntohl(r->rt_origin))) { - rtp = r; - r = r->rt_next; - } - else break; - } - return (FALSE); -} - -/* - * Create a new routing table entry for the specified origin and link it into - * the routing table. The shared variable 'rtp' is assumed to point to the - * routing entry after which the new one should be inserted. It is left - * pointing to the new entry. - * - * Only the origin, originmask, originwidth and flags fields are initialized - * in the new route entry; the caller is responsible for filling in the the - * rest. - */ -static void -create_route(origin, mask) - u_int32 origin, mask; -{ - register struct rtentry *r; - - if ((r = (struct rtentry *) malloc(sizeof(struct rtentry) + - (2 * numvifs * sizeof(u_int32)) + - (numvifs * sizeof(u_int)))) == NULL) { - log(LOG_ERR, 0, "ran out of memory"); /* fatal */ - } - r->rt_origin = origin; - r->rt_originmask = mask; - if (((char *)&mask)[3] != 0) r->rt_originwidth = 4; - else if (((char *)&mask)[2] != 0) r->rt_originwidth = 3; - else if (((char *)&mask)[1] != 0) r->rt_originwidth = 2; - else r->rt_originwidth = 1; - r->rt_flags = 0; - r->rt_dominants = (u_int32 *)(r + 1); - r->rt_subordinates = (u_int32 *)(r->rt_dominants + numvifs); - r->rt_leaf_timers = (u_int *)(r->rt_subordinates + numvifs); - r->rt_groups = NULL; - - r->rt_next = rtp->rt_next; - rtp->rt_next = r; - r->rt_prev = rtp; - if (r->rt_next != NULL) - (r->rt_next)->rt_prev = r; - else - rt_end = r; - rtp = r; - ++nroutes; -} - - -/* - * Discard the routing table entry following the one to which 'prev_r' points. - */ -static void -discard_route(prev_r) - register struct rtentry *prev_r; -{ - register struct rtentry *r; - - r = prev_r->rt_next; - prev_r->rt_next = r->rt_next; - if (prev_r->rt_next != NULL) - (prev_r->rt_next)->rt_prev = prev_r; - else - rt_end = prev_r; - free((char *)r); - --nroutes; -} - - -/* - * Process a route report for a single origin, creating or updating the - * corresponding routing table entry if necessary. 'src' is either the - * address of a neighboring router from which the report arrived, or zero - * to indicate a change of status of one of our own interfaces. - */ -void -update_route(origin, mask, metric, src, vifi) - u_int32 origin, mask; - u_int metric; - u_int32 src; - vifi_t vifi; -{ - register struct rtentry *r; - u_int adj_metric; - - /* - * Compute an adjusted metric, taking into account the cost of the - * subnet or tunnel over which the report arrived, and normalizing - * all unreachable/poisoned metrics into a single value. - */ - if (src != 0 && (metric < 1 || metric >= 2*UNREACHABLE)) { - log(LOG_WARNING, 0, - "%s reports out-of-range metric %u for origin %s", - inet_fmt(src, s1), metric, inet_fmts(origin, mask, s2)); - return; - } - adj_metric = metric + uvifs[vifi].uv_metric; - if (adj_metric > UNREACHABLE) adj_metric = UNREACHABLE; - - /* - * Look up the reported origin in the routing table. - */ - if (!find_route(origin, mask)) { - /* - * Not found. - * Don't create a new entry if the report says it's unreachable, - * or if the reported origin and mask are invalid. - */ - if (adj_metric == UNREACHABLE) { - return; - } - if (src != 0 && !inet_valid_subnet(origin, mask)) { - log(LOG_WARNING, 0, - "%s reports an invalid origin (%s) and/or mask (%08x)", - inet_fmt(src, s1), inet_fmt(origin, s2), ntohl(mask)); - return; - } - - /* - * OK, create the new routing entry. 'rtp' will be left pointing - * to the new entry. - */ - create_route(origin, mask); - - /* - * Now "steal away" any sources that belong under this route - * by deleting any cache entries they might have created - * and allowing the kernel to re-request them. - */ - steal_sources(rtp); - - rtp->rt_metric = UNREACHABLE; /* temporary; updated below */ - } - - /* - * We now have a routing entry for the reported origin. Update it? - */ - r = rtp; - if (r->rt_metric == UNREACHABLE) { - /* - * The routing entry is for a formerly-unreachable or new origin. - * If the report claims reachability, update the entry to use - * the reported route. - */ - if (adj_metric == UNREACHABLE) - return; - - r->rt_parent = vifi; - init_children_and_leaves(r, vifi); - - r->rt_gateway = src; - r->rt_timer = 0; - r->rt_metric = adj_metric; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - update_table_entry(r); - } - else if (src == r->rt_gateway) { - /* - * The report has come either from the interface directly-connected - * to the origin subnet (src and r->rt_gateway both equal zero) or - * from the gateway we have chosen as the best first-hop gateway back - * towards the origin (src and r->rt_gateway not equal zero). Reset - * the route timer and, if the reported metric has changed, update - * our entry accordingly. - */ - r->rt_timer = 0; - if (adj_metric == r->rt_metric) - return; - - if (adj_metric == UNREACHABLE) { - del_table_entry(r, 0, DEL_ALL_ROUTES); - r->rt_timer = ROUTE_EXPIRE_TIME; - } - else if (adj_metric < r->rt_metric) { - if (init_children_and_leaves(r, vifi)) { - update_table_entry(r); - } - } - r->rt_metric = adj_metric; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - else if (src == 0 || - (r->rt_gateway != 0 && - (adj_metric < r->rt_metric || - (adj_metric == r->rt_metric && - (ntohl(src) < ntohl(r->rt_gateway) || - r->rt_timer >= ROUTE_SWITCH_TIME))))) { - /* - * The report is for an origin we consider reachable; the report - * comes either from one of our own interfaces or from a gateway - * other than the one we have chosen as the best first-hop gateway - * back towards the origin. If the source of the update is one of - * our own interfaces, or if the origin is not a directly-connected - * subnet and the reported metric for that origin is better than - * what our routing entry says, update the entry to use the new - * gateway and metric. We also switch gateways if the reported - * metric is the same as the one in the route entry and the gateway - * associated with the route entry has not been heard from recently, - * or if the metric is the same but the reporting gateway has a lower - * IP address than the gateway associated with the route entry. - * Did you get all that? - */ - if (r->rt_parent != vifi || adj_metric < r->rt_metric) { - /* - * XXX Why do we do this if we are just changing the metric? - */ - r->rt_parent = vifi; - if (init_children_and_leaves(r, vifi)) { - update_table_entry(r); - } - } - r->rt_gateway = src; - r->rt_timer = 0; - r->rt_metric = adj_metric; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - else if (vifi != r->rt_parent) { - /* - * The report came from a vif other than the route's parent vif. - * Update the children and leaf info, if necessary. - */ - if (VIFM_ISSET(vifi, r->rt_children)) { - /* - * Vif is a child vif for this route. - */ - if (metric < r->rt_metric || - (metric == r->rt_metric && - ntohl(src) < ntohl(uvifs[vifi].uv_lcl_addr))) { - /* - * Neighbor has lower metric to origin (or has same metric - * and lower IP address) -- it becomes the dominant router, - * and vif is no longer a child for me. - */ - VIFM_CLR(vifi, r->rt_children); - VIFM_CLR(vifi, r->rt_leaves); - r->rt_dominants [vifi] = src; - r->rt_subordinates[vifi] = 0; - r->rt_leaf_timers [vifi] = 0; - update_table_entry(r); - } - else if (metric > UNREACHABLE) { /* "poisoned reverse" */ - /* - * Neighbor considers this vif to be on path to route's - * origin; if no subordinate recorded, record this neighbor - * as subordinate and clear the leaf flag. - */ - if (r->rt_subordinates[vifi] == 0) { - VIFM_CLR(vifi, r->rt_leaves); - r->rt_subordinates[vifi] = src; - r->rt_leaf_timers [vifi] = 0; - update_table_entry(r); - } - } - else if (src == r->rt_subordinates[vifi]) { - /* - * Current subordinate no longer considers this vif to be on - * path to route's origin; it is no longer a subordinate - * router, and we set the leaf confirmation timer to give - * us time to hear from other subordinates. - */ - r->rt_subordinates[vifi] = 0; - if (uvifs[vifi].uv_neighbors == NULL || - uvifs[vifi].uv_neighbors->al_next == NULL) { - VIFM_SET(vifi, r->rt_leaves); - update_table_entry(r); - } - else { - r->rt_leaf_timers [vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - } - - } - else if (src == r->rt_dominants[vifi] && - (metric > r->rt_metric || - (metric == r->rt_metric && - ntohl(src) > ntohl(uvifs[vifi].uv_lcl_addr)))) { - /* - * Current dominant no longer has a lower metric to origin - * (or same metric and lower IP address); we adopt the vif - * as our own child. - */ - VIFM_SET(vifi, r->rt_children); - r->rt_dominants [vifi] = 0; - if (metric > UNREACHABLE) { - r->rt_subordinates[vifi] = src; - } - else if (uvifs[vifi].uv_neighbors == NULL || - uvifs[vifi].uv_neighbors->al_next == NULL) { - VIFM_SET(vifi, r->rt_leaves); - } - else { - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - update_table_entry(r); - } - } -} - - -/* - * On every timer interrupt, advance the timer in each routing entry. - */ -void -age_routes() -{ - register struct rtentry *r; - register struct rtentry *prev_r; - register vifi_t vifi; - - for (prev_r = RT_ADDR, r = routing_table; - r != NULL; - prev_r = r, r = r->rt_next) { - - if ((r->rt_timer += TIMER_INTERVAL) < ROUTE_EXPIRE_TIME) { - /* - * Route is still good; see if any leaf timers need to be - * advanced. - */ - if (r->rt_flags & RTF_LEAF_TIMING) { - r->rt_flags &= ~RTF_LEAF_TIMING; - for (vifi = 0; vifi < numvifs; ++vifi) { - if (r->rt_leaf_timers[vifi] != 0) { - /* - * Unlike other timers, leaf timers decrement. - */ - if ((r->rt_leaf_timers[vifi] -= TIMER_INTERVAL) == 0){ -#ifdef NOTYET - /* If the vif is a physical leaf but has neighbors, - * it is not a tree leaf. If I am a leaf, then no - * interface with neighbors is a tree leaf. */ - if (!(((uvifs[vifi].uv_flags & VIFF_LEAF) || - (vifs_with_neighbors == 1)) && - (uvifs[vifi].uv_neighbors != NULL))) { -#endif - VIFM_SET(vifi, r->rt_leaves); - update_table_entry(r); -#ifdef NOTYET - } -#endif - } - else { - r->rt_flags |= RTF_LEAF_TIMING; - } - } - } - } - } - else if (r->rt_timer >= ROUTE_DISCARD_TIME) { - /* - * Time to garbage-collect the route entry. - */ - del_table_entry(r, 0, DEL_ALL_ROUTES); - discard_route(prev_r); - r = prev_r; - } - else if (r->rt_metric != UNREACHABLE) { - /* - * Time to expire the route entry. If the gateway is zero, - * i.e., it is a route to a directly-connected subnet, just - * set the timer back to zero; such routes expire only when - * the interface to the subnet goes down. - */ - if (r->rt_gateway == 0) { - r->rt_timer = 0; - } - else { - del_table_entry(r, 0, DEL_ALL_ROUTES); - r->rt_metric = UNREACHABLE; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - } - } -} - - -/* - * Mark all routes as unreachable. This function is called only from - * hup() in preparation for informing all neighbors that we are going - * off the air. For consistency, we ought also to delete all reachable - * route entries from the kernel, but since we are about to exit we rely - * on the kernel to do its own cleanup -- no point in making all those - * expensive kernel calls now. - */ -void -expire_all_routes() -{ - register struct rtentry *r; - - for (r = routing_table; r != NULL; r = r->rt_next) { - r->rt_metric = UNREACHABLE; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } -} - - -/* - * Delete all the routes in the routing table. - */ -void -free_all_routes() -{ - register struct rtentry *r; - - r = RT_ADDR; - - while (r->rt_next) - discard_route(r); -} - - -/* - * Process an incoming neighbor probe message. - */ -void -accept_probe(src, dst, p, datalen, level) - u_int32 src; - u_int32 dst; - char *p; - int datalen; - u_int32 level; -{ - vifi_t vifi; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - log(LOG_INFO, 0, - "ignoring probe from non-neighbor %s", inet_fmt(src, s1)); - return; - } - - update_neighbor(vifi, src, DVMRP_PROBE, p, datalen, level); -} - -struct newrt { - u_int32 mask; - u_int32 origin; - int metric; - int pad; -}; - -static int -compare_rts(rt1, rt2) - const void *rt1; - const void *rt2; -{ - register struct newrt *r1 = (struct newrt *)rt1; - register struct newrt *r2 = (struct newrt *)rt2; - register u_int32 m1 = ntohl(r1->mask); - register u_int32 m2 = ntohl(r2->mask); - register u_int32 o1, o2; - - if (m1 > m2) - return (-1); - if (m1 < m2) - return (1); - - /* masks are equal */ - o1 = ntohl(r1->origin); - o2 = ntohl(r2->origin); - if (o1 > o2) - return (-1); - if (o1 < o2) - return (1); - return (0); -} - -/* - * Process an incoming route report message. - */ -void -accept_report(src, dst, p, datalen, level) - u_int32 src, dst, level; - register char *p; - register int datalen; -{ - vifi_t vifi; - register int width, i, nrt = 0; - int metric; - u_int32 mask; - u_int32 origin; - struct newrt rt[4096]; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - log(LOG_INFO, 0, - "ignoring route report from non-neighbor %s", inet_fmt(src, s1)); - return; - } - - if (!update_neighbor(vifi, src, DVMRP_REPORT, NULL, 0, level)) - return; - - if (datalen > 2*4096) { - log(LOG_INFO, 0, - "ignoring oversize (%d bytes) route report from %s", - datalen, inet_fmt(src, s1)); - return; - } - - while (datalen > 0) { /* Loop through per-mask lists. */ - - if (datalen < 3) { - log(LOG_WARNING, 0, - "received truncated route report from %s", - inet_fmt(src, s1)); - return; - } - ((u_char *)&mask)[0] = 0xff; width = 1; - if ((((u_char *)&mask)[1] = *p++) != 0) width = 2; - if ((((u_char *)&mask)[2] = *p++) != 0) width = 3; - if ((((u_char *)&mask)[3] = *p++) != 0) width = 4; - if (!inet_valid_mask(ntohl(mask))) { - log(LOG_WARNING, 0, - "%s reports bogus netmask 0x%08x (%s)", - inet_fmt(src, s1), ntohl(mask), inet_fmt(mask, s2)); - return; - } - datalen -= 3; - - do { /* Loop through (origin, metric) pairs */ - if (datalen < width + 1) { - log(LOG_WARNING, 0, - "received truncated route report from %s", - inet_fmt(src, s1)); - return; - } - origin = 0; - for (i = 0; i < width; ++i) - ((char *)&origin)[i] = *p++; - metric = *p++; - datalen -= width + 1; - rt[nrt].mask = mask; - rt[nrt].origin = origin; - rt[nrt].metric = (metric & 0x7f); - ++nrt; - } while (!(metric & 0x80)); - } - - qsort((char*)rt, nrt, sizeof(rt[0]), compare_rts); - start_route_updates(); - /* - * If the last entry is default, change mask from 0xff000000 to 0 - */ - if (rt[nrt-1].origin == 0) - rt[nrt-1].mask = 0; - - log(LOG_DEBUG, 0, "Updating %d routes from %s to %s", nrt, - inet_fmt(src, s1), inet_fmt(dst, s2)); - for (i = 0; i < nrt; ++i) { - if (i != 0 && rt[i].origin == rt[i-1].origin && - rt[i].mask == rt[i-1].mask) { - log(LOG_WARNING, 0, "%s reports duplicate route for %s", - inet_fmt(src, s1), inet_fmts(rt[i].origin, rt[i].mask, s2)); - continue; - } - update_route(rt[i].origin, rt[i].mask, rt[i].metric, - src, vifi); - } - - if (routes_changed && !delay_change_reports) - report_to_all_neighbors(CHANGED_ROUTES); -} - - -/* - * Send a route report message to destination 'dst', via virtual interface - * 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. - */ -void -report(which_routes, vifi, dst) - int which_routes; - vifi_t vifi; - u_int32 dst; -{ - register struct rtentry *r; - register char *p; - register int i; - int datalen = 0; - int width = 0; - u_int32 mask = 0; - u_int32 src; - u_int32 nflags; - - src = uvifs[vifi].uv_lcl_addr; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - -#ifdef NOTYET - /* If I'm not a leaf, but the neighbor is a leaf, only advertise default */ - if ((vifs_with_neighbors != 1) && (uvifs[vifi].uv_flags & VIFF_LEAF)) { - *p++ = 0; /* 0xff000000 mask */ - *p++ = 0; - *p++ = 0; - *p++ = 0; /* class A net 0.0.0.0 == default */ - *p++ = 0x81; /*XXX metric 1, is this safe? */ - datalen += 5; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL), datalen); - return; - } -#endif - - nflags = (uvifs[vifi].uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS; - - for (r = rt_end; r != RT_ADDR; r = r->rt_prev) { - - if (which_routes == CHANGED_ROUTES && !(r->rt_flags & RTF_CHANGED)) - continue; - - /* - * If there is no room for this route in the current message, - * send the message and start a new one. - */ - if (datalen + ((r->rt_originmask == mask) ? - (width + 1) : - (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - mask = 0; - } - - if (r->rt_originmask != mask || datalen == 0) { - mask = r->rt_originmask; - width = r->rt_originwidth; - if (datalen != 0) *(p-1) |= 0x80; - *p++ = ((char *)&mask)[1]; - *p++ = ((char *)&mask)[2]; - *p++ = ((char *)&mask)[3]; - datalen += 3; - } - - for (i = 0; i < width; ++i) - *p++ = ((char *)&(r->rt_origin))[i]; - - *p++ = (r->rt_parent == vifi && r->rt_metric != UNREACHABLE) ? - (char)(r->rt_metric + UNREACHABLE) : /* "poisoned reverse" */ - (char)(r->rt_metric); - - datalen += width + 1; - } - - if (datalen != 0) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - } -} - - -/* - * Send a route report message to all neighboring routers. - * 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. - */ -void -report_to_all_neighbors(which_routes) - int which_routes; -{ - register vifi_t vifi; - register struct uvif *v; - register struct rtentry *r; - int routes_changed_before; - - /* - * Remember the state of the global routes_changed flag before - * generating the reports, and clear the flag. - */ - routes_changed_before = routes_changed; - routes_changed = FALSE; - - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (v->uv_neighbors != NULL) { - report(which_routes, vifi, - (v->uv_flags & VIFF_TUNNEL) ? v->uv_rmt_addr - : dvmrp_group); - } - } - - /* - * If there were changed routes before we sent the reports AND - * if no new changes occurred while sending the reports, clear - * the change flags in the individual route entries. If changes - * did occur while sending the reports, new reports will be - * generated at the next timer interrupt. - */ - if (routes_changed_before && !routes_changed) { - for (r = routing_table; r != NULL; r = r->rt_next) { - r->rt_flags &= ~RTF_CHANGED; - } - } - - /* - * Set a flag to inhibit further reports of changed routes until the - * next timer interrupt. This is to alleviate update storms. - */ - delay_change_reports = TRUE; -} - -/* - * Send a route report message to destination 'dst', via virtual interface - * 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. - */ -static int -report_chunk(start_rt, vifi, dst) - register struct rtentry *start_rt; - vifi_t vifi; - u_int32 dst; -{ - register struct rtentry *r; - register char *p; - register int i; - register int nrt = 0; - int datalen = 0; - int width = 0; - u_int32 mask = 0; - u_int32 src; - u_int32 nflags; - - src = uvifs[vifi].uv_lcl_addr; - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - - nflags = (uvifs[vifi].uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS; - - for (r = start_rt; r != RT_ADDR; r = r->rt_prev) { - -#ifdef NOTYET - /* Don't send poisoned routes back to parents if I am a leaf */ - if ((vifs_with_neighbors == 1) && (r->rt_parent == vifi) - && (r->rt_metric > 1)) { - ++nrt; - continue; - } -#endif - - /* - * If there is no room for this route in the current message, - * send it & return how many routes we sent. - */ - if (datalen + ((r->rt_originmask == mask) ? - (width + 1) : - (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - return (nrt); - } - if (r->rt_originmask != mask || datalen == 0) { - mask = r->rt_originmask; - width = r->rt_originwidth; - if (datalen != 0) *(p-1) |= 0x80; - *p++ = ((char *)&mask)[1]; - *p++ = ((char *)&mask)[2]; - *p++ = ((char *)&mask)[3]; - datalen += 3; - } - for (i = 0; i < width; ++i) - *p++ = ((char *)&(r->rt_origin))[i]; - - *p++ = (r->rt_parent == vifi && r->rt_metric != UNREACHABLE) ? - (char)(r->rt_metric + UNREACHABLE) : /* "poisoned reverse" */ - (char)(r->rt_metric); - ++nrt; - datalen += width + 1; - } - if (datalen != 0) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - } - return (nrt); -} - -/* - * send the next chunk of our routing table to all neighbors. - * return the length of the smallest chunk we sent out. - */ -int -report_next_chunk() -{ - register vifi_t vifi; - register struct uvif *v; - register struct rtentry *sr; - register int i, n = 0, min = 20000; - static int start_rt; - - if (nroutes <= 0) - return (0); - - /* - * find this round's starting route. - */ - for (sr = rt_end, i = start_rt; --i >= 0; ) { - sr = sr->rt_prev; - if (sr == RT_ADDR) - sr = rt_end; - } - - /* - * send one chunk of routes starting at this round's start to - * all our neighbors. - */ - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if ((v->uv_neighbors != NULL) -#ifdef NOTYET - && !(v->uv_flags & VIFF_LEAF) -#endif - ) { - n = report_chunk(sr, vifi, - (v->uv_flags & VIFF_TUNNEL) ? v->uv_rmt_addr - : dvmrp_group); - if (n < min) - min = n; - } - } - if (min == 20000) - min = 0; /* Neighborless router didn't send any routes */ - - n = min; - log(LOG_INFO, 0, "update %d starting at %d of %d", - n, (nroutes - start_rt), nroutes); - - start_rt = (start_rt + n) % nroutes; - return (n); -} - - -/* - * Print the contents of the routing table on file 'fp'. - */ -void -dump_routes(fp) - FILE *fp; -{ - register struct rtentry *r; - register vifi_t i; - - - fprintf(fp, - "Multicast Routing Table (%u %s)\n%s\n", - nroutes, (nroutes == 1) ? "entry" : "entries", - " Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs"); - - for (r = routing_table; r != NULL; r = r->rt_next) { - - fprintf(fp, " %-18s %-15s ", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - (r->rt_gateway == 0) ? "" : inet_fmt(r->rt_gateway, s2)); - - fprintf(fp, (r->rt_metric == UNREACHABLE) ? " NR " : "%4u ", - r->rt_metric); - - fprintf(fp, " %3u %3u ", r->rt_timer, r->rt_parent); - - for (i = 0; i < numvifs; ++i) { - if (VIFM_ISSET(i, r->rt_children)) { - fprintf(fp, " %u%c", - i, VIFM_ISSET(i, r->rt_leaves) ? '*' : ' '); - } - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); -} - -struct rtentry * -determine_route(src) - u_int32 src; -{ - struct rtentry *rt; - - for (rt = routing_table; rt != NULL; rt = rt->rt_next) { - if (rt->rt_origin == (src & rt->rt_originmask)) - break; - } - return rt; -} diff --git a/usr.sbin/mrouted/route.h b/usr.sbin/mrouted/route.h deleted file mode 100644 index 73159d50261e..000000000000 --- a/usr.sbin/mrouted/route.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: route.h,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - -/* - * Routing Table Entry, one per subnet from which a multicast could originate. - * (Note: all addresses, subnet numbers and masks are kept in NETWORK order.) - * - * The Routing Table is stored as a doubly-linked list of these structures, - * ordered by decreasing value of rt_originmask and, secondarily, by - * decreasing value of rt_origin within each rt_originmask value. - * This data structure is efficient for generating route reports, whether - * full or partial, for processing received full reports, for clearing the - * CHANGED flags, and for periodically advancing the timers in all routes. - * It is not so efficient for updating a small number of routes in response - * to a partial report. In a stable topology, the latter are rare; if they - * turn out to be costing a lot, we can add an auxiliary hash table for - * faster access to arbitrary route entries. - */ -struct rtentry { - struct rtentry *rt_next; /* link to next entry MUST BE FIRST */ - u_int32 rt_origin; /* subnet origin of multicasts */ - u_int32 rt_originmask; /* subnet mask for origin */ - short rt_originwidth; /* # bytes of origin subnet number */ - u_char rt_metric; /* cost of route back to origin */ - u_char rt_flags; /* RTF_ flags defined below */ - u_int32 rt_gateway; /* first-hop gateway back to origin */ - vifi_t rt_parent; /* incoming vif (ie towards origin) */ - vifbitmap_t rt_children; /* outgoing children vifs */ - 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 */ - 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 ALL_ROUTES 0 /* possible arguments to report() */ -#define CHANGED_ROUTES 1 /* and report_to_all_neighbors() */ diff --git a/usr.sbin/mrouted/rsrr.c b/usr.sbin/mrouted/rsrr.c deleted file mode 100644 index ea9628f55aea..000000000000 --- a/usr.sbin/mrouted/rsrr.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright (c) 1993 by the University of Southern California - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation in source and binary forms for non-commercial purposes - * and without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both the copyright notice and - * this permission notice appear in supporting documentation. and that - * any documentation, advertising materials, and other materials related - * to such distribution and use acknowledge that the software was - * developed by the University of Southern California, Information - * Sciences Institute. The name of the University may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about - * the suitability of this software for any purpose. THIS SOFTWARE IS - * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Other copyrights might apply to parts of this software and are so - * noted when applicable. - */ - -/* RSRR code written by Daniel Zappala, USC Information Sciences Institute, - * April 1995. - */ - -/* May 1995 -- Added support for Route Change Notification */ - -#ifdef RSRR - -#include "defs.h" -#include <sys/param.h> -#if (defined(BSD) && (BSD >= 199103)) -#include <stddef.h> -#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); \ - } - -/* - * Exported variables. - */ -int rsrr_socket; /* interface to reservation protocol */ - -/* - * Global RSRR variables. - */ -char rsrr_recv_buf[RSRR_MAX_LEN]; /* RSRR receive buffer */ -char rsrr_send_buf[RSRR_MAX_LEN]; /* RSRR send buffer */ - -struct sockaddr_un client_addr; -int client_length = sizeof(client_addr); - - -/* - * Procedure definitions needed internally. - */ -static void rsrr_accept __P((int recvlen)); -static void rsrr_accept_iq __P((void)); -static int rsrr_accept_rq __P((struct rsrr_rq *route_query, int flags, - struct gtable *gt_notify)); -static int rsrr_send __P((int sendlen)); -static void rsrr_cache __P((struct gtable *gt, - struct rsrr_rq *route_query)); - -/* Initialize RSRR socket */ -void -rsrr_init() -{ - int servlen; - struct sockaddr_un serv_addr; - - if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) - log(LOG_ERR, errno, "Can't create RSRR socket"); - - unlink(RSRR_SERV_PATH); - bzero((char *) &serv_addr, sizeof(serv_addr)); - serv_addr.sun_family = AF_UNIX; - strcpy(serv_addr.sun_path, RSRR_SERV_PATH); -#if (defined(BSD) && (BSD >= 199103)) - servlen = offsetof(struct sockaddr_un, sun_path) + - strlen(serv_addr.sun_path); - serv_addr.sun_len = servlen; -#else - servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path); -#endif - - if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0) - log(LOG_ERR, errno, "Can't bind RSRR socket"); - - if (register_input_handler(rsrr_socket,rsrr_read) < 0) - log(LOG_WARNING, 0, "Couldn't register RSRR as an input handler"); -} - -/* Read a message from the RSRR socket */ -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), - 0, (struct sockaddr *)&client_addr, &client_length); - if (rsrr_recvlen < 0) { - if (errno != EINTR) - 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 - * appropriate action. - */ -static void -rsrr_accept(recvlen) - int recvlen; -{ - struct rsrr_header *rsrr; - struct rsrr_rq *route_query; - - if (recvlen < RSRR_HEADER_LEN) { - log(LOG_WARNING, 0, - "Received RSRR packet of %d bytes, which is less than min size", - recvlen); - return; - } - - rsrr = (struct rsrr_header *) rsrr_recv_buf; - - if (rsrr->version > RSRR_MAX_VERSION) { - log(LOG_WARNING, 0, - "Received RSRR packet version %d, which I don't understand", - rsrr->version); - return; - } - - switch (rsrr->version) { - case 1: - switch (rsrr->type) { - case RSRR_INITIAL_QUERY: - /* Send Initial Reply to client */ - log(LOG_INFO, 0, "Received Initial Query\n"); - rsrr_accept_iq(); - break; - case RSRR_ROUTE_QUERY: - /* Check size */ - if (recvlen < RSRR_RQ_LEN) { - log(LOG_WARNING, 0, - "Received Route Query of %d bytes, which is too small", - recvlen); - break; - } - /* Get the query */ - route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN); - log(LOG_INFO, 0, - "Received Route Query for src %s grp %s notification %d", - inet_fmt(route_query->source_addr.s_addr, s1), - inet_fmt(route_query->dest_addr.s_addr,s2), - BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)); - /* Send Route Reply to client */ - rsrr_accept_rq(route_query,rsrr->flags,NULL); - break; - default: - log(LOG_WARNING, 0, - "Received RSRR packet type %d, which I don't handle", - rsrr->type); - break; - } - break; - - default: - log(LOG_WARNING, 0, - "Received RSRR packet version %d, which I don't understand", - rsrr->version); - break; - } -} - -/* Send an Initial Reply to the reservation protocol. */ -static void -rsrr_accept_iq() -{ - struct rsrr_header *rsrr; - struct rsrr_vif *vif_list; - struct uvif *v; - int vifi, sendlen; - - /* Check for space. There should be room for plenty of vifs, - * but we should check anyway. - */ - if (numvifs > RSRR_MAX_VIFS) { - log(LOG_WARNING, 0, - "Can't send RSRR Route Reply because %d is too many vifs %d", - numvifs); - return; - } - - /* Set up message */ - rsrr = (struct rsrr_header *) rsrr_send_buf; - rsrr->version = 1; - rsrr->type = RSRR_INITIAL_REPLY; - rsrr->flags = 0; - rsrr->num = numvifs; - - vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN); - - /* Include the vif list. */ - for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) { - vif_list[vifi].id = vifi; - vif_list[vifi].status = 0; - if (v->uv_flags & VIFF_DISABLED) - BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT); - vif_list[vifi].threshold = v->uv_threshold; - vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr; - } - - /* Get the size. */ - sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN; - - /* Send it. */ - log(LOG_INFO, 0, "Send RSRR Initial Reply"); - rsrr_send(sendlen); -} - -/* Send a Route Reply to the reservation protocol. The Route Query - * contains the query to which we are responding. The flags contain - * the incoming flags from the query or, for route change - * notification, the flags that should be set for the reply. The - * kernel table entry contains the routing info to use for a route - * change notification. - */ -static int -rsrr_accept_rq(route_query,flags,gt_notify) - struct rsrr_rq *route_query; - int flags; - struct gtable *gt_notify; -{ - struct rsrr_header *rsrr; - struct rsrr_rr *route_reply; - struct gtable *gt,local_g; - struct rtentry *r; - int sendlen,i; - u_long mcastgrp; - - /* Set up message */ - rsrr = (struct rsrr_header *) rsrr_send_buf; - rsrr->version = 1; - rsrr->type = RSRR_ROUTE_REPLY; - rsrr->flags = 0; - rsrr->num = 0; - - route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN); - route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr; - route_reply->source_addr.s_addr = route_query->source_addr.s_addr; - route_reply->query_id = route_query->query_id; - - /* Blank routing entry for error. */ - route_reply->in_vif = 0; - route_reply->reserved = 0; - route_reply->out_vif_bm = 0; - - /* Get the size. */ - sendlen = RSRR_RR_LEN; - - /* If kernel table entry is defined, then we are sending a Route Reply - * due to a Route Change Notification event. Use the kernel table entry - * to supply the routing info. - */ - if (gt_notify) { - /* Set flags */ - rsrr->flags = flags; - /* Include the routing entry. */ - route_reply->in_vif = gt_notify->gt_route->rt_parent; - route_reply->out_vif_bm = gt_notify->gt_grpmems; - - } else if (find_src_grp(route_query->source_addr.s_addr, 0, - route_query->dest_addr.s_addr)) { - - /* Found kernel entry. Code taken from add_table_entry() */ - gt = gtp ? gtp->gt_gnext : kernel_table; - - /* Include the routing entry. */ - route_reply->in_vif = gt->gt_route->rt_parent; - route_reply->out_vif_bm = gt->gt_grpmems; - - /* Cache reply if using route change notification. */ - if BIT_TST(flags,RSRR_NOTIFICATION_BIT) { - rsrr_cache(gt,route_query); - BIT_SET(rsrr->flags,RSRR_NOTIFICATION_BIT); - } - - } else { - /* No kernel entry; use routing table. */ - r = determine_route(route_query->source_addr.s_addr); - - if (r != NULL) { - /* We need to mimic what will happen if a data packet - * is forwarded by multicast routing -- the kernel will - * make an upcall and mrouted will install a route in the kernel. - * Our outgoing vif bitmap should reflect what that table - * will look like. Grab code from add_table_entry(). - * This is gross, but it's probably better to be accurate. - */ - - gt = &local_g; - mcastgrp = route_query->dest_addr.s_addr; - - gt->gt_mcastgrp = mcastgrp; - gt->gt_grpmems = 0; - gt->gt_scope = 0; - gt->gt_route = r; - - /* obtain the multicast group membership list */ - 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; - - /* Include the routing entry. */ - route_reply->in_vif = gt->gt_route->rt_parent; - route_reply->out_vif_bm = gt->gt_grpmems; - - } else { - /* Set error bit. */ - BIT_SET(rsrr->flags,RSRR_ERROR_BIT); - } - } - - if (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", - inet_fmt(route_reply->source_addr.s_addr,s1), - inet_fmt(route_reply->dest_addr.s_addr,s2), - route_reply->in_vif,route_reply->out_vif_bm); - - /* Send it. */ - return rsrr_send(sendlen); -} - -/* Send an RSRR message. */ -static int -rsrr_send(sendlen) - int sendlen; -{ - int error; - - /* Send it. */ - error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0, - (struct sockaddr *)&client_addr, client_length); - - /* Check for errors. */ - if (error < 0) { - log(LOG_WARNING, errno, "Failed send on RSRR socket"); - } else if (error != sendlen) { - log(LOG_WARNING, 0, - "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen); - } - return error; -} - -/* Cache a message being sent to a client. Currently only used for - * caching Route Reply messages for route change notification. - */ -static void -rsrr_cache(gt,route_query) - struct gtable *gt; - struct rsrr_rq *route_query; -{ - struct rsrr_cache *rc, **rcnp; - struct rsrr_header *rsrr; - - rsrr = (struct rsrr_header *) rsrr_send_buf; - - rcnp = >->gt_rsrr_cache; - while ((rc = *rcnp) != NULL) { - if ((rc->route_query.source_addr.s_addr == - route_query->source_addr.s_addr) && - (rc->route_query.dest_addr.s_addr == - route_query->dest_addr.s_addr) && - (!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) { - /* Cache entry already exists. - * Check if route notification bit has been cleared. - */ - if (!BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)) { - /* Delete cache entry. */ - *rcnp = rc->next; - free(rc); - } else { - /* Update */ - rc->route_query.query_id = route_query->query_id; - log(LOG_DEBUG, 0, - "Update cached query id %ld from client %s\n", - rc->route_query.query_id, rc->client_addr.sun_path); - } - return; - } - rcnp = &rc->next; - } - - /* Cache entry doesn't already exist. Create one and insert at - * front of list. - */ - rc = (struct rsrr_cache *) malloc(sizeof(struct rsrr_cache)); - if (rc == NULL) - log(LOG_ERR, 0, "ran out of memory"); - rc->route_query.source_addr.s_addr = route_query->source_addr.s_addr; - rc->route_query.dest_addr.s_addr = route_query->dest_addr.s_addr; - rc->route_query.query_id = route_query->query_id; - strcpy(rc->client_addr.sun_path, client_addr.sun_path); - rc->client_length = client_length; - rc->next = gt->gt_rsrr_cache; - gt->gt_rsrr_cache = rc; - log(LOG_DEBUG, 0, "Cached query id %ld from client %s\n", - rc->route_query.query_id,rc->client_addr.sun_path); -} - -/* Send all the messages in the cache. Currently this is used to send - * all the cached Route Reply messages for route change notification. - */ -void -rsrr_cache_send(gt,notify) - struct gtable *gt; - int notify; -{ - struct rsrr_cache *rc, **rcnp; - int flags = 0; - - if (notify) - BIT_SET(flags,RSRR_NOTIFICATION_BIT); - - rcnp = >->gt_rsrr_cache; - while ((rc = *rcnp) != NULL) { - if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) { - log(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n", - rc->route_query.query_id,rc->client_addr.sun_path); - /* Delete cache entry. */ - *rcnp = rc->next; - free(rc); - } else { - rcnp = &rc->next; - } - } -} - -/* Clean the cache by deleting all entries. */ -void -rsrr_cache_clean(gt) - struct gtable *gt; -{ - struct rsrr_cache *rc,*rc_next; - - printf("cleaning cache for group %s\n",inet_fmt(gt->gt_mcastgrp, s1)); - rc = gt->gt_rsrr_cache; - while (rc) { - rc_next = rc->next; - free(rc); - rc = rc_next; - } - gt->gt_rsrr_cache = NULL; -} - -void -rsrr_clean() -{ - unlink(RSRR_SERV_PATH); -} - -#endif /* RSRR */ diff --git a/usr.sbin/mrouted/rsrr.h b/usr.sbin/mrouted/rsrr.h deleted file mode 100644 index 8bc8c9176535..000000000000 --- a/usr.sbin/mrouted/rsrr.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 1993 by the University of Southern California - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation in source and binary forms for non-commercial purposes - * and without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both the copyright notice and - * this permission notice appear in supporting documentation. and that - * any documentation, advertising materials, and other materials related - * to such distribution and use acknowledge that the software was - * developed by the University of Southern California, Information - * Sciences Institute. The name of the University may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about - * the suitability of this software for any purpose. THIS SOFTWARE IS - * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Other copyrights might apply to parts of this software and are so - * noted when applicable. - */ - -#define RSRR_SERV_PATH "/tmp/.rsrr_svr" -/* Note this needs to be 14 chars for 4.3 BSD compatibility */ -#define RSRR_CLI_PATH "/tmp/.rsrr_cli" - -#define RSRR_MAX_LEN 2048 -#define RSRR_HEADER_LEN (sizeof(struct rsrr_header)) -#define RSRR_RQ_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rq)) -#define RSRR_RR_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rr)) -#define RSRR_VIF_LEN (sizeof(struct rsrr_vif)) - -/* Current maximum number of vifs. */ -#define RSRR_MAX_VIFS 32 - -/* Maximum acceptable version */ -#define RSRR_MAX_VERSION 1 - -/* RSRR message types */ -#define RSRR_ALL_TYPES 0 -#define RSRR_INITIAL_QUERY 1 -#define RSRR_INITIAL_REPLY 2 -#define RSRR_ROUTE_QUERY 3 -#define RSRR_ROUTE_REPLY 4 - -/* RSRR Initial Reply (Vif) Status bits - * Each definition represents the position of the bit from right to left. - * - * Right-most bit is the disabled bit, set if the vif is administratively - * disabled. - */ -#define RSRR_DISABLED_BIT 0 -/* All other bits are zeroes */ - -/* RSRR Route Query/Reply flag bits - * Each definition represents the position of the bit from right to left. - * - * Right-most bit is the Route Change Notification bit, set if the - * reservation protocol wishes to receive notification of - * a route change for the source-destination pair listed in the query. - * Notification is in the form of an unsolicitied Route Reply. - */ -#define RSRR_NOTIFICATION_BIT 0 -/* Next bit indicates an error returning the Route Reply. */ -#define RSRR_ERROR_BIT 1 -/* All other bits are zeroes */ - -/* Definition of an RSRR message header. - * An Initial Query uses only the header, and an Initial Reply uses - * the header and a list of vifs. - */ -struct rsrr_header { - u_char version; /* RSRR Version, currently 1 */ - u_char type; /* type of message, as defined above */ - u_char flags; /* flags; defined by type */ - u_char num; /* number; defined by type */ -}; - -/* Definition of a vif as seen by the reservation protocol. - * - * Routing gives the reservation protocol a list of vifs in the - * Initial Reply. - * - * We explicitly list the ID because we can't assume that all routing - * protocols will use the same numbering scheme. - * - * The status is a bitmask of status flags, as defined above. It is the - * responsibility of the reservation protocol to perform any status checks - * if it uses the MULTICAST_VIF socket option. - * - * The threshold indicates the ttl an outgoing packet needs in order to - * be forwarded. The reservation protocol must perform this check itself if - * it uses the MULTICAST_VIF socket option. - * - * The local address is the address of the physical interface over which - * packets are sent. - */ -struct rsrr_vif { - u_char id; /* vif id */ - u_char threshold; /* vif threshold ttl */ - u_short status; /* vif status bitmask */ - struct in_addr local_addr; /* vif local address */ -}; - -/* Definition of an RSRR Route Query. - * - * The query asks routing for the forwarding entry for a particular - * source and destination. The query ID uniquely identifies the query - * for the reservation protocol. Thus, the combination of the client's - * address and the query ID forms a unique identifier for routing. - * Flags are defined above. - */ -struct rsrr_rq { - struct in_addr dest_addr; /* destination */ - struct in_addr source_addr; /* source */ - u_long query_id; /* query ID */ -}; - -/* Definition of an RSRR Route Reply. - * - * Routing uses the reply to give the reservation protocol the - * forwarding entry for a source-destination pair. Routing copies the - * query ID from the query and fills in the incoming vif and a bitmask - * of the outgoing vifs. - * Flags are defined above. - */ -struct rsrr_rr { - struct in_addr dest_addr; /* destination */ - struct in_addr source_addr; /* source */ - u_long query_id; /* query ID */ - u_short in_vif; /* incoming vif */ - u_short reserved; /* reserved */ - u_long out_vif_bm; /* outgoing vif bitmask */ -}; diff --git a/usr.sbin/mrouted/rsrr_var.h b/usr.sbin/mrouted/rsrr_var.h deleted file mode 100644 index 9b1c09c1396e..000000000000 --- a/usr.sbin/mrouted/rsrr_var.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 1993 by the University of Southern California - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation in source and binary forms for non-commercial purposes - * and without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both the copyright notice and - * this permission notice appear in supporting documentation. and that - * any documentation, advertising materials, and other materials related - * to such distribution and use acknowledge that the software was - * developed by the University of Southern California, Information - * Sciences Institute. The name of the University may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about - * the suitability of this software for any purpose. THIS SOFTWARE IS - * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Other copyrights might apply to parts of this software and are so - * noted when applicable. - */ - -/* RSRR things that are only needed by mrouted. */ - -/* Cache of Route Query messages, distinguished by source, - * destination, and client addresses. Cache is flushed by RSRR client - * -- it sends notification when an unwanted Route Reply is received. - * Since this only happens during route changes, it is more likely - * that the cache will be flushed when the kernel table entry is - * deleted. */ -struct rsrr_cache { - struct rsrr_rq route_query; /* Cached Route Query */ - struct sockaddr_un client_addr; /* Client address */ - int client_length; /* Length of client */ - struct rsrr_cache *next; /* next cache item */ -}; - diff --git a/usr.sbin/mrouted/vif.c b/usr.sbin/mrouted/vif.c deleted file mode 100644 index 3716292d1cab..000000000000 --- a/usr.sbin/mrouted/vif.c +++ /dev/null @@ -1,1482 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: vif.c,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - - -#include "defs.h" -#include <fcntl.h> - -/* - * Exported variables. - */ -struct uvif uvifs[MAXVIFS]; /* array of virtual interfaces */ -vifi_t numvifs; /* number of vifs in use */ -int vifs_down; /* 1=>some interfaces are down */ -int phys_vif; /* An enabled vif */ -int udp_socket; /* Since the honkin' kernel doesn't support */ - /* ioctls on raw IP sockets, we need a UDP */ - /* socket as well as our IGMP (raw) socket. */ - /* How dumb. */ -int vifs_with_neighbors; /* == 1 if I am a leaf */ - -typedef struct { - vifi_t vifi; - struct listaddr *g; - int q_time; -} cbk_t; - -/* - * Forward declarations. - */ -static void start_vif __P((vifi_t vifi)); -static void start_vif2 __P((vifi_t vifi)); -static void stop_vif __P((vifi_t vifi)); -static void age_old_hosts __P((void)); -static void send_probe_on_vif __P((struct uvif *v)); -static int info_version __P((char *p)); -static void DelVif __P((void *arg)); -static int SetTimer __P((int vifi, struct listaddr *g)); -static int DeleteTimer __P((int id)); -static void SendQuery __P((void *arg)); -static int SetQueryTimer __P((struct listaddr *g, vifi_t vifi, int to_expire, - int q_time)); - - -/* - * Initialize the virtual interfaces, but do not install - * them in the kernel. Start routing on all vifs that are - * not down or disabled. - */ -void -init_vifs() -{ - vifi_t vifi; - struct uvif *v; - int enabled_vifs, enabled_phyints; - extern char *configfilename; - - numvifs = 0; - vifs_with_neighbors = 0; - vifs_down = FALSE; - - /* - * Configure the vifs based on the interface configuration of the - * the kernel and the contents of the configuration file. - * (Open a UDP socket for ioctl use in the config procedures.) - */ - if ((udp_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - log(LOG_ERR, errno, "UDP socket"); - log(LOG_INFO,0,"Getting vifs from kernel interfaces"); - config_vifs_from_kernel(); - log(LOG_INFO,0,"Getting vifs from %s",configfilename); - config_vifs_from_file(); - - /* - * Quit if there are fewer than two enabled vifs. - */ - enabled_vifs = 0; - enabled_phyints = 0; - phys_vif = -1; - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & VIFF_DISABLED)) { - ++enabled_vifs; - if (!(v->uv_flags & VIFF_TUNNEL)) { - if (phys_vif == -1) - phys_vif = vifi; - ++enabled_phyints; - } - } - } - if (enabled_vifs < 2) - log(LOG_ERR, 0, "can't forward: %s", - enabled_vifs == 0 ? "no enabled vifs" : "only one enabled vif"); - - if (enabled_phyints == 0) - log(LOG_WARNING, 0, - "no enabled interfaces, forwarding via tunnels only"); - - log(LOG_INFO, 0, "Installing vifs in mrouted..."); - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & VIFF_DISABLED)) { - if (!(v->uv_flags & VIFF_DOWN)) { - if (v->uv_flags & VIFF_TUNNEL) - log(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi, - inet_fmt(v->uv_lcl_addr, s1), - inet_fmt(v->uv_rmt_addr, s2)); - else - log(LOG_INFO, 0, "vif #%d, phyint %s", vifi, - inet_fmt(v->uv_lcl_addr, s1)); - start_vif2(vifi); - } else log(LOG_INFO, 0, - "%s is not yet up; vif #%u not in service", - v->uv_name, vifi); - } - } -} - -/* - * Start routing on all virtual interfaces that are not down or - * administratively disabled. - */ -void -init_installvifs() -{ - vifi_t vifi; - struct uvif *v; - - log(LOG_INFO, 0, "Installing vifs in kernel..."); - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & VIFF_DISABLED)) { - if (!(v->uv_flags & VIFF_DOWN)) { - if (v->uv_flags & VIFF_TUNNEL) - log(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi, - inet_fmt(v->uv_lcl_addr, s1), - inet_fmt(v->uv_rmt_addr, s2)); - else - log(LOG_INFO, 0, "vif #%d, phyint %s", vifi, - inet_fmt(v->uv_lcl_addr, s1)); - k_add_vif(vifi, &uvifs[vifi]); - } else log(LOG_INFO, 0, - "%s is not yet up; vif #%u not in service", - v->uv_name, vifi); - } - } -} - -/* - * See if any interfaces have changed from up state to down, or vice versa, - * including any non-multicast-capable interfaces that are in use as local - * tunnel end-points. Ignore interfaces that have been administratively - * disabled. - */ -void -check_vif_state() -{ - register vifi_t vifi; - register struct uvif *v; - struct ifreq ifr; - - vifs_down = FALSE; - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - - if (v->uv_flags & VIFF_DISABLED) continue; - - strncpy(ifr.ifr_name, v->uv_name, IFNAMSIZ); - if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0) - log(LOG_ERR, errno, - "ioctl SIOCGIFFLAGS for %s", ifr.ifr_name); - - if (v->uv_flags & VIFF_DOWN) { - if (ifr.ifr_flags & IFF_UP) { - v->uv_flags &= ~VIFF_DOWN; - start_vif(vifi); - log(LOG_INFO, 0, - "%s has come up; vif #%u now in service", - v->uv_name, vifi); - } - else vifs_down = TRUE; - } - else { - if (!(ifr.ifr_flags & IFF_UP)) { - stop_vif(vifi); - v->uv_flags |= VIFF_DOWN; - log(LOG_INFO, 0, - "%s has gone down; vif #%u taken out of service", - v->uv_name, vifi); - vifs_down = TRUE; - } - } - } -} - -/* - * Send a probe message on vif v - */ -static void -send_probe_on_vif(v) - register struct uvif *v; -{ - register char *p; - register int datalen = 0; - struct listaddr *nbr; - int i; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(dvmrp_genid))[i]; - datalen += 4; - - /* - * add the neighbor list on the interface to the message - */ - nbr = v->uv_neighbors; - - while (nbr) { - for (i = 0; i < 4; i++) - *p++ = ((char *)&nbr->al_addr)[i]; - datalen +=4; - nbr = nbr->al_next; - } - - send_igmp(v->uv_lcl_addr, - (v->uv_flags & VIFF_TUNNEL) ? v->uv_rmt_addr - : dvmrp_group, - IGMP_DVMRP, DVMRP_PROBE, - htonl(MROUTED_LEVEL | - ((v->uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS)), - datalen); -} - -/* - * Add a vifi to the kernel and start routing on it. - */ -static void -start_vif(vifi) - vifi_t vifi; -{ - /* - * Install the interface in the kernel's vif structure. - */ - k_add_vif(vifi, &uvifs[vifi]); - - start_vif2(vifi); -} - -/* - * Add a vifi to all the user-level data structures but don't add - * it to the kernel yet. - */ -static void -start_vif2(vifi) - vifi_t vifi; -{ - struct uvif *v; - u_int32 src; - struct phaddr *p; - - v = &uvifs[vifi]; - src = v->uv_lcl_addr; - - /* - * Update the existing route entries to take into account the new vif. - */ - add_vif_to_routes(vifi); - - if (!(v->uv_flags & VIFF_TUNNEL)) { - /* - * Join the DVMRP multicast group on the interface. - * (This is not strictly necessary, since the kernel promiscuously - * receives IGMP packets addressed to ANY IP multicast group while - * multicast routing is enabled. However, joining the group allows - * this host to receive non-IGMP packets as well, such as 'pings'.) - */ - k_join(dvmrp_group, src); - - /* - * Join the ALL-ROUTERS multicast group on the interface. - * This allows mtrace requests to loop back if they are run - * on the multicast router. - */ - k_join(allrtrs_group, src); - - /* - * Install an entry in the routing table for the subnet to which - * the interface is connected. - */ - start_route_updates(); - update_route(v->uv_subnet, v->uv_subnetmask, 0, 0, vifi); - for (p = v->uv_addrs; p; p = p->pa_next) { - start_route_updates(); - update_route(p->pa_subnet, p->pa_subnetmask, 0, 0, vifi); - } - - /* - * Until neighbors are discovered, assume responsibility for sending - * periodic group membership queries to the subnet. Send the first - * query. - */ - v->uv_flags |= VIFF_QUERIER; - send_igmp(src, allhosts_group, IGMP_HOST_MEMBERSHIP_QUERY, - (v->uv_flags & VIFF_IGMPV1) ? 0 : - IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0); - age_old_hosts(); - } - - v->uv_leaf_timer = LEAF_CONFIRMATION_TIME; - - /* - * Send a probe via the new vif to look for neighbors. - */ - send_probe_on_vif(v); -} - -/* - * Stop routing on the specified virtual interface. - */ -static void -stop_vif(vifi) - vifi_t vifi; -{ - struct uvif *v; - struct listaddr *a; - struct phaddr *p; - - v = &uvifs[vifi]; - - if (!(v->uv_flags & VIFF_TUNNEL)) { - /* - * Depart from the DVMRP multicast group on the interface. - */ - k_leave(dvmrp_group, v->uv_lcl_addr); - - /* - * Depart from the ALL-ROUTERS multicast group on the interface. - */ - k_leave(allrtrs_group, v->uv_lcl_addr); - - /* - * Update the entry in the routing table for the subnet to which - * the interface is connected, to take into account the interface - * failure. - */ - start_route_updates(); - update_route(v->uv_subnet, v->uv_subnetmask, UNREACHABLE, 0, vifi); - for (p = v->uv_addrs; p; p = p->pa_next) { - start_route_updates(); - update_route(p->pa_subnet, p->pa_subnetmask, UNREACHABLE, 0, vifi); - } - - /* - * Discard all group addresses. (No need to tell kernel; - * the k_del_vif() call, below, will clean up kernel state.) - */ - while (v->uv_groups != NULL) { - a = v->uv_groups; - v->uv_groups = a->al_next; - free((char *)a); - } - - v->uv_flags &= ~VIFF_QUERIER; - } - - /* - * Update the existing route entries to take into account the vif failure. - */ - delete_vif_from_routes(vifi); - - /* - * Delete the interface from the kernel's vif structure. - */ - k_del_vif(vifi); - - /* - * Discard all neighbor addresses. - */ - if (v->uv_neighbors) - vifs_with_neighbors--; - - while (v->uv_neighbors != NULL) { - a = v->uv_neighbors; - v->uv_neighbors = a->al_next; - free((char *)a); - } -} - - -/* - * stop routing on all vifs - */ -void -stop_all_vifs() -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *a; - struct vif_acl *acl; - - for (vifi = 0; vifi < numvifs; vifi++) { - v = &uvifs[vifi]; - while (v->uv_groups != NULL) { - a = v->uv_groups; - v->uv_groups = a->al_next; - free((char *)a); - } - while (v->uv_neighbors != NULL) { - a = v->uv_neighbors; - v->uv_neighbors = a->al_next; - free((char *)a); - } - while (v->uv_acl != NULL) { - acl = v->uv_acl; - v->uv_acl = acl->acl_next; - free((char *)acl); - } - } -} - - -/* - * Find the virtual interface from which an incoming packet arrived, - * based on the packet's source and destination IP addresses. - */ -vifi_t -find_vif(src, dst) - register u_int32 src; - register u_int32 dst; -{ - register vifi_t vifi; - register struct uvif *v; - register struct phaddr *p; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { - if (v->uv_flags & VIFF_TUNNEL) { - if (src == v->uv_rmt_addr && dst == v->uv_lcl_addr) - return(vifi); - } - else { - if ((src & v->uv_subnetmask) == v->uv_subnet && - ((v->uv_subnetmask == 0xffffffff) || - (src != v->uv_subnetbcast))) - return(vifi); - for (p=v->uv_addrs; p; p=p->pa_next) { - if ((src & p->pa_subnetmask) == p->pa_subnet && - ((p->pa_subnetmask == 0xffffffff) || - (src != p->pa_subnetbcast))) - return(vifi); - } - } - } - } - return (NO_VIF); -} - -static void -age_old_hosts() -{ - register vifi_t vifi; - register struct uvif *v; - register struct listaddr *g; - - /* - * Decrement the old-hosts-present timer for each - * active group on each vif. - */ - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) - for (g = v->uv_groups; g != NULL; g = g->al_next) - if (g->al_old) - g->al_old--; -} - - -/* - * Send group membership queries to all subnets for which I am querier. - */ -void -query_groups() -{ - register vifi_t vifi; - register struct uvif *v; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - if (v->uv_flags & VIFF_QUERIER) { - send_igmp(v->uv_lcl_addr, allhosts_group, - IGMP_HOST_MEMBERSHIP_QUERY, - (v->uv_flags & VIFF_IGMPV1) ? 0 : - IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0); - } - } - age_old_hosts(); -} - -/* - * Process an incoming host membership query - */ -void -accept_membership_query(src, dst, group, tmo) - u_int32 src, dst, group; - int tmo; -{ - register vifi_t vifi; - register struct uvif *v; - - if ((vifi = find_vif(src, dst)) == NO_VIF || - (uvifs[vifi].uv_flags & VIFF_TUNNEL)) { - log(LOG_INFO, 0, - "ignoring group membership query from non-adjacent host %s", - inet_fmt(src, s1)); - return; - } - - v = &uvifs[vifi]; - - /* - * If we consider ourselves the querier for this vif, but hear a - * query from a router with a lower IP address, yield to them. - * - * This is done here as well as in the neighbor discovery in case - * there is a querier that doesn't speak DVMRP. - * - * XXX If this neighbor doesn't speak DVMRP, then we need to create - * some neighbor state for him so that we can time him out! - */ - if ((v->uv_flags & VIFF_QUERIER) && - (ntohl(src) < ntohl(v->uv_lcl_addr))) { - v->uv_flags &= ~VIFF_QUERIER; - - } -} - -/* - * Process an incoming group membership report. - */ -void -accept_group_report(src, dst, group, r_type) - u_int32 src, dst, group; - int r_type; -{ - register vifi_t vifi; - register struct uvif *v; - register struct listaddr *g; - - if ((vifi = find_vif(src, dst)) == NO_VIF || - (uvifs[vifi].uv_flags & VIFF_TUNNEL)) { - log(LOG_INFO, 0, - "ignoring group membership report from non-adjacent host %s", - inet_fmt(src, s1)); - return; - } - - v = &uvifs[vifi]; - - /* - * Look for the group in our group list; if found, reset its timer. - */ - for (g = v->uv_groups; g != NULL; g = g->al_next) { - if (group == g->al_addr) { - if (r_type == IGMP_HOST_MEMBERSHIP_REPORT) - g->al_old = OLD_AGE_THRESHOLD; -#ifdef SNMP - g->al_genid = src; -#endif /* SNMP */ - - /** delete old timers, set a timer for expiration **/ - g->al_timer = GROUP_EXPIRE_TIME; - if (g->al_query) - g->al_query = DeleteTimer(g->al_query); - if (g->al_timerid) - g->al_timerid = DeleteTimer(g->al_timerid); - g->al_timerid = SetTimer(vifi, g); - break; - } - } - - /* - * If not found, add it to the list and update kernel cache. - */ - if (g == NULL) { - g = (struct listaddr *)malloc(sizeof(struct listaddr)); - if (g == NULL) - log(LOG_ERR, 0, "ran out of memory"); /* fatal */ - - g->al_addr = group; - if (r_type == IGMP_HOST_NEW_MEMBERSHIP_REPORT) - g->al_old = 0; - else - g->al_old = OLD_AGE_THRESHOLD; -#ifdef SNMP - g->al_genid = src; -#endif - - /** set a timer for expiration **/ - g->al_query = 0; - g->al_timer = GROUP_EXPIRE_TIME; - time(&g->al_ctime); - g->al_timerid = SetTimer(vifi, g); - g->al_next = v->uv_groups; - v->uv_groups = g; - - update_lclgrp(vifi, group); - } - - /* - * Check if a graft is necessary for this group - */ - chkgrp_graft(vifi, group); -} - - -void -accept_leave_message(src, dst, group) - u_int32 src, dst, group; -{ - register vifi_t vifi; - register struct uvif *v; - register struct listaddr *g; - - if ((vifi = find_vif(src, dst)) == NO_VIF || - (uvifs[vifi].uv_flags & VIFF_TUNNEL)) { - log(LOG_INFO, 0, - "ignoring group leave report from non-adjacent host %s", - inet_fmt(src, s1)); - return; - } - - v = &uvifs[vifi]; - - if (!(v->uv_flags & VIFF_QUERIER) || (v->uv_flags & VIFF_IGMPV1)) - return; - - /* - * Look for the group in our group list in order to set up a short-timeout - * query. - */ - for (g = v->uv_groups; g != NULL; g = g->al_next) { - if (group == g->al_addr) { - log(LOG_DEBUG, 0, - "[vif.c, _accept_leave_message] %d %d \n", - g->al_old, g->al_query); - - /* Ignore the leave message if there are old hosts present */ - if (g->al_old) - return; - - /* still waiting for a reply to a query, ignore the leave */ - if (g->al_query) - return; - - /** delete old timer set a timer for expiration **/ - if (g->al_timerid) - g->al_timerid = DeleteTimer(g->al_timerid); - - /** send a group specific querry **/ - g->al_timer = LEAVE_EXPIRE_TIME; - send_igmp(v->uv_lcl_addr, g->al_addr, - IGMP_HOST_MEMBERSHIP_QUERY, - LEAVE_EXPIRE_TIME / 3 * IGMP_TIMER_SCALE, - g->al_addr, 0); - g->al_query = SetQueryTimer(g, vifi, g->al_timer / 3, - LEAVE_EXPIRE_TIME / 3 * IGMP_TIMER_SCALE); - g->al_timerid = SetTimer(vifi, g); - break; - } - } -} - - -/* - * Send a periodic probe on all vifs. - * Useful to determine one-way interfaces. - * Detect neighbor loss faster. - */ -void -probe_for_neighbors() -{ - register vifi_t vifi; - register struct uvif *v; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - if (!(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { - send_probe_on_vif(v); - } - } -} - - -/* - * Send a list of all of our neighbors to the requestor, `src'. - */ -void -accept_neighbor_request(src, dst) - u_int32 src, dst; -{ - vifi_t vifi; - struct uvif *v; - u_char *p, *ncount; - struct listaddr *la; - int datalen; - u_int32 temp_addr, us, them = src; - - /* Determine which of our addresses to use as the source of our response - * to this query. - */ - if (IN_MULTICAST(ntohl(dst))) { /* query sent to a multicast group */ - int udp; /* find best interface to reply on */ - struct sockaddr_in addr; - int addrlen = sizeof(addr); - - addr.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = dst; - addr.sin_port = htons(2000); /* any port over 1024 will do... */ - if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0 - || connect(udp, (struct sockaddr *) &addr, sizeof(addr)) < 0 - || getsockname(udp, (struct sockaddr *) &addr, &addrlen) < 0) { - log(LOG_WARNING, errno, "Determining local address"); - close(udp); - return; - } - close(udp); - us = addr.sin_addr.s_addr; - } else /* query sent to us alone */ - us = dst; - -#define PUT_ADDR(a) temp_addr = ntohl(a); \ - *p++ = temp_addr >> 24; \ - *p++ = (temp_addr >> 16) & 0xFF; \ - *p++ = (temp_addr >> 8) & 0xFF; \ - *p++ = temp_addr & 0xFF; - - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - if (v->uv_flags & VIFF_DISABLED) - continue; - - ncount = 0; - - for (la = v->uv_neighbors; la; la = la->al_next) { - - /* Make sure that there's room for this neighbor... */ - if (datalen + (ncount == 0 ? 4 + 3 + 4 : 4) > MAX_DVMRP_DATA_LEN) { - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS, - htonl(MROUTED_LEVEL), datalen); - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - ncount = 0; - } - - /* Put out the header for this neighbor list... */ - if (ncount == 0) { - PUT_ADDR(v->uv_lcl_addr); - *p++ = v->uv_metric; - *p++ = v->uv_threshold; - ncount = p; - *p++ = 0; - datalen += 4 + 3; - } - - PUT_ADDR(la->al_addr); - datalen += 4; - (*ncount)++; - } - } - - if (datalen != 0) - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS, htonl(MROUTED_LEVEL), - datalen); -} - -/* - * Send a list of all of our neighbors to the requestor, `src'. - */ -void -accept_neighbor_request2(src, dst) - u_int32 src, dst; -{ - vifi_t vifi; - struct uvif *v; - u_char *p, *ncount; - struct listaddr *la; - int datalen; - u_int32 us, them = src; - - /* Determine which of our addresses to use as the source of our response - * to this query. - */ - if (IN_MULTICAST(ntohl(dst))) { /* query sent to a multicast group */ - int udp; /* find best interface to reply on */ - struct sockaddr_in addr; - int addrlen = sizeof(addr); - - addr.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = dst; - addr.sin_port = htons(2000); /* any port over 1024 will do... */ - if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0 - || connect(udp, (struct sockaddr *) &addr, sizeof(addr)) < 0 - || getsockname(udp, (struct sockaddr *) &addr, &addrlen) < 0) { - log(LOG_WARNING, errno, "Determining local address"); - close(udp); - return; - } - close(udp); - us = addr.sin_addr.s_addr; - } else /* query sent to us alone */ - us = dst; - - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - register u_short vflags = v->uv_flags; - register u_char rflags = 0; - if (vflags & VIFF_TUNNEL) - rflags |= DVMRP_NF_TUNNEL; - if (vflags & VIFF_SRCRT) - rflags |= DVMRP_NF_SRCRT; - if (vflags & VIFF_DOWN) - rflags |= DVMRP_NF_DOWN; - if (vflags & VIFF_DISABLED) - rflags |= DVMRP_NF_DISABLED; - if (vflags & VIFF_QUERIER) - rflags |= DVMRP_NF_QUERIER; - if (vflags & VIFF_LEAF) - rflags |= DVMRP_NF_LEAF; - ncount = 0; - la = v->uv_neighbors; - if (la == NULL) { - /* - * include down & disabled interfaces and interfaces on - * leaf nets. - */ - if (rflags & DVMRP_NF_TUNNEL) - rflags |= DVMRP_NF_DOWN; - if (datalen > MAX_DVMRP_DATA_LEN - 12) { - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, - htonl(MROUTED_LEVEL), datalen); - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - } - *(u_int*)p = v->uv_lcl_addr; - p += 4; - *p++ = v->uv_metric; - *p++ = v->uv_threshold; - *p++ = rflags; - *p++ = 1; - *(u_int*)p = v->uv_rmt_addr; - p += 4; - datalen += 12; - } else { - for ( ; la; la = la->al_next) { - /* Make sure that there's room for this neighbor... */ - if (datalen + (ncount == 0 ? 4+4+4 : 4) > MAX_DVMRP_DATA_LEN) { - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, - htonl(MROUTED_LEVEL), datalen); - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - ncount = 0; - } - /* Put out the header for this neighbor list... */ - if (ncount == 0) { - *(u_int*)p = v->uv_lcl_addr; - p += 4; - *p++ = v->uv_metric; - *p++ = v->uv_threshold; - *p++ = rflags; - ncount = p; - *p++ = 0; - datalen += 4 + 4; - } - *(u_int*)p = la->al_addr; - p += 4; - datalen += 4; - (*ncount)++; - } - } - } - if (datalen != 0) - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, htonl(MROUTED_LEVEL), - datalen); -} - -void -accept_info_request(src, dst, p, datalen) - u_int32 src, dst; - u_char *p; - int datalen; -{ - u_char *q; - int len; - int outlen = 0; - - q = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - - /* To be general, this must deal properly with breaking up over-sized - * packets. That implies passing a length to each function, and - * allowing each function to request to be called again. Right now, - * we're only implementing the one thing we are positive will fit into - * a single packet, so we wimp out. - */ - while (datalen > 0) { - len = 0; - switch (*p) { - case DVMRP_INFO_VERSION: - len = info_version(q); - break; - - case DVMRP_INFO_NEIGHBORS: - default: - log(LOG_INFO, 0, "ignoring unknown info type %d", *p); - break; - } - *(q+1) = len++; - outlen += len * 4; - q += len * 4; - len = (*(p+1) + 1) * 4; - p += len; - datalen -= len; - } - - if (outlen != 0) - send_igmp(INADDR_ANY, src, IGMP_DVMRP, DVMRP_INFO_REPLY, - htonl(MROUTED_LEVEL), outlen); -} - -/* - * Information response -- return version string - */ -static int -info_version(p) - char *p; -{ - int len; - extern char versionstring[]; - - *p++ = DVMRP_INFO_VERSION; - p++; /* skip over length */ - *p++ = 0; /* zero out */ - *p++ = 0; /* reserved fields */ - strcpy(p, versionstring); /* XXX strncpy!!! */ - - len = strlen(versionstring); - return ((len + 3) / 4); -} - -/* - * Process an incoming neighbor-list message. - */ -void -accept_neighbors(src, dst, p, datalen, level) - u_int32 src, dst, level; - u_char *p; - int datalen; -{ - log(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Process an incoming neighbor-list message. - */ -void -accept_neighbors2(src, dst, p, datalen, level) - u_int32 src, dst, level; - u_char *p; - int datalen; -{ - log(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list2 from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - -/* - * Process an incoming info reply message. - */ -void -accept_info_reply(src, dst, p, datalen) - u_int32 src, dst; - u_char *p; - int datalen; -{ - log(LOG_INFO, 0, "ignoring spurious DVMRP info reply from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Update the neighbor entry for neighbor 'addr' on vif 'vifi'. - * 'msgtype' is the type of DVMRP message received from the neighbor. - * Return TRUE if 'addr' is a valid neighbor, FALSE otherwise. - */ -int -update_neighbor(vifi, addr, msgtype, p, datalen, level) - vifi_t vifi; - u_int32 addr; - int msgtype; - char *p; - int datalen; - u_int32 level; -{ - register struct uvif *v; - register struct listaddr *n; - u_int32 genid = 0; - u_int32 router; - u_int32 send_tables = 0; - int do_reset = FALSE; - int nflags; - - v = &uvifs[vifi]; - nflags = (level >> 16) & 0xff; - - /* - * Confirm that 'addr' is a valid neighbor address on vif 'vifi'. - * IT IS ASSUMED that this was preceded by a call to find_vif(), which - * checks that 'addr' is either a valid remote tunnel endpoint or a - * non-broadcast address belonging to a directly-connected subnet. - * Therefore, here we check only that 'addr' is not our own address - * (due to an impostor or erroneous loopback) or an address of the form - * {subnet,0} ("the unknown host"). These checks are not performed in - * find_vif() because those types of address are acceptable for some - * types of IGMP message (such as group membership reports). - */ - if (!(v->uv_flags & VIFF_TUNNEL) && - (addr == v->uv_lcl_addr || - addr == v->uv_subnet )) { - log(LOG_WARNING, 0, - "received DVMRP message from 'the unknown host' or self: %s", - inet_fmt(addr, s1)); - return (FALSE); - } - - /* - * Look for addr in list of neighbors. - */ - for (n = v->uv_neighbors; n != NULL; n = n->al_next) { - if (addr == n->al_addr) { - break; - } - } - - /* - * Found it. Reset its timer, and check for a version change - */ - if (n) { - n->al_timer = 0; - - /* - * update the neighbors version and protocol number - * if changed => router went down and came up, - * so take action immediately. - */ - if ((n->al_pv != (level & 0xff)) || - (n->al_mv != ((level >> 8) & 0xff))) { - - do_reset = TRUE; - log(LOG_DEBUG, 0, - "version change neighbor %s [old:%d.%d, new:%d.%d]", - inet_fmt(addr, s1), - n->al_pv, n->al_mv, level&0xff, (level >> 8) & 0xff); - - n->al_pv = level & 0xff; - n->al_mv = (level >> 8) & 0xff; - } - } else { - /* - * If not found, add it to the list. If the neighbor has a lower - * IP address than me, yield querier duties to it. - */ - log(LOG_DEBUG, 0, "New neighbor %s on vif %d v%d.%d nf 0x%02x", - inet_fmt(addr, s1), vifi, level & 0xff, (level >> 8) & 0xff, - (level >> 16) & 0xff); - - n = (struct listaddr *)malloc(sizeof(struct listaddr)); - if (n == NULL) - log(LOG_ERR, 0, "ran out of memory"); /* fatal */ - - n->al_addr = addr; - n->al_pv = level & 0xff; - n->al_mv = (level >> 8) & 0xff; - n->al_genid = 0; - - time(&n->al_ctime); - n->al_timer = 0; - n->al_next = v->uv_neighbors; - - /* - * If we thought that we had no neighbors on this vif, send a route - * report to the vif. If this is just a new neighbor on the same - * vif, send the route report just to the new neighbor. - */ - if (v->uv_neighbors == NULL) { - send_tables = (v->uv_flags & VIFF_TUNNEL) ? addr : dvmrp_group; - vifs_with_neighbors++; - } else { - send_tables = addr; - } - - v->uv_neighbors = n; - - if (!(v->uv_flags & VIFF_TUNNEL) && - ntohl(addr) < ntohl(v->uv_lcl_addr)) - v->uv_flags &= ~VIFF_QUERIER; - } - - /* - * Check if the router gen-ids are the same. - * Need to reset the prune state of the router if not. - * Also check for one-way interfaces by seeing if we are in our - * neighbor's list of known routers. - */ - if (msgtype == DVMRP_PROBE) { - - /* Check genid neighbor flag. Also check version number; 3.3 and - * 3.4 didn't set this flag. */ - if ((((level >> 16) & 0xff) & NF_GENID) || - (((level & 0xff) == 3) && (((level >> 8) & 0xff) > 2))) { - - int i; - - if (datalen < 4) { - log(LOG_WARNING, 0, - "received truncated probe message from %s (len %d)", - inet_fmt(addr, s1), datalen); - return (FALSE); - } - - for (i = 0; i < 4; i++) - ((char *)&genid)[i] = *p++; - datalen -= 4; - - if (n->al_genid == 0) - n->al_genid = genid; - else if (n->al_genid != genid) { - log(LOG_DEBUG, 0, - "new genid neigbor %s on vif %d [old:%x, new:%x]", - inet_fmt(addr, s1), vifi, n->al_genid, genid); - - n->al_genid = genid; - do_reset = TRUE; - } - - /* - * loop through router list and check for one-way ifs. - */ - - v->uv_flags |= VIFF_ONEWAY; - - while (datalen > 0) { - if (datalen < 4) { - log(LOG_WARNING, 0, - "received truncated probe message from %s (len %d)", - inet_fmt(addr, s1), datalen); - return (FALSE); - } - for (i = 0; i < 4; i++) - ((char *)&router)[i] = *p++; - datalen -= 4; - if (router == v->uv_lcl_addr) { - v->uv_flags &= ~VIFF_ONEWAY; - break; - } - } - } - } - if (n->al_flags != nflags) { - n->al_flags = nflags; - - if (n->al_flags & NF_LEAF) { - /*XXX If we have non-leaf neighbors then we know we shouldn't - * mark this vif as a leaf. For now we just count on other - * probes and/or reports resetting the timer. */ - if (!v->uv_leaf_timer) - v->uv_leaf_timer = LEAF_CONFIRMATION_TIME; - } else { - /* If we get a leaf to non-leaf transition, we *must* update - * the routing table. */ - if (v->uv_flags & VIFF_LEAF && send_tables == 0) - send_tables = addr; - v->uv_flags &= ~VIFF_LEAF; - v->uv_leaf_timer = 0; - } - } - if (do_reset) { - reset_neighbor_state(vifi, addr); - if (!send_tables) - send_tables = addr; - } - if (send_tables) - report(ALL_ROUTES, vifi, send_tables); - - return (TRUE); -} - - -/* - * On every timer interrupt, advance the timer in each neighbor and - * group entry on every vif. - */ -void -age_vifs() -{ - register vifi_t vifi; - register struct uvif *v; - register struct listaddr *a, *prev_a, *n; - register u_int32 addr; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v ) { - if (v->uv_leaf_timer && (v->uv_leaf_timer -= TIMER_INTERVAL == 0)) { - v->uv_flags |= VIFF_LEAF; - } - - for (prev_a = (struct listaddr *)&(v->uv_neighbors), - a = v->uv_neighbors; - a != NULL; - prev_a = a, a = a->al_next) { - - if ((a->al_timer += TIMER_INTERVAL) < NEIGHBOR_EXPIRE_TIME) - continue; - - /* - * Neighbor has expired; delete it from the neighbor list, - * delete it from the 'dominants' and 'subordinates arrays of - * any route entries and assume querier duties unless there is - * another neighbor with a lower IP address than mine. - */ - addr = a->al_addr; - prev_a->al_next = a->al_next; - free((char *)a); - a = prev_a; - - delete_neighbor_from_routes(addr, vifi); - - if (v->uv_neighbors == NULL) - vifs_with_neighbors--; - - v->uv_leaf_timer = LEAF_CONFIRMATION_TIME; - - if (!(v->uv_flags & VIFF_TUNNEL)) { - v->uv_flags |= VIFF_QUERIER; - for (n = v->uv_neighbors; n != NULL; n = n->al_next) { - if (ntohl(n->al_addr) < ntohl(v->uv_lcl_addr)) { - v->uv_flags &= ~VIFF_QUERIER; - } - if (!(n->al_flags & NF_LEAF)) { - v->uv_leaf_timer = 0; - } - } - } - } - } -} - -/* - * Returns the neighbor info struct for a given neighbor - */ -struct listaddr * -neighbor_info(vifi, addr) - vifi_t vifi; - u_int32 addr; -{ - struct listaddr *u; - - for (u = uvifs[vifi].uv_neighbors; u; u = u->al_next) - if (u->al_addr == addr) - return u; - - return NULL; -} - -/* - * Print the contents of the uvifs array on file 'fp'. - */ -void -dump_vifs(fp) - FILE *fp; -{ - register vifi_t vifi; - register struct uvif *v; - register struct listaddr *a; - register struct phaddr *p; - struct sioc_vif_req v_req; - - fprintf(fp, "vifs_with_neighbors = %d\n", vifs_with_neighbors); - - if (vifs_with_neighbors == 1) - fprintf(fp,"[This host is a leaf]\n\n"); - - fprintf(fp, - "\nVirtual Interface Table\n%s", - "Vif Name Local-Address "); - fprintf(fp, - "M Thr Rate Flags\n"); - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - - fprintf(fp, "%2u %6s %-15s %6s: %-18s %2u %3u %5u ", - vifi, - v->uv_name, - inet_fmt(v->uv_lcl_addr, s1), - (v->uv_flags & VIFF_TUNNEL) ? - "tunnel": - "subnet", - (v->uv_flags & VIFF_TUNNEL) ? - inet_fmt(v->uv_rmt_addr, s2) : - inet_fmts(v->uv_subnet, v->uv_subnetmask, s3), - v->uv_metric, - v->uv_threshold, - v->uv_rate_limit); - - if (v->uv_flags & VIFF_ONEWAY) fprintf(fp, " one-way"); - if (v->uv_flags & VIFF_DOWN) fprintf(fp, " down"); - if (v->uv_flags & VIFF_DISABLED) fprintf(fp, " disabled"); - if (v->uv_flags & VIFF_QUERIER) fprintf(fp, " querier"); - if (v->uv_flags & VIFF_SRCRT) fprintf(fp, " src-rt"); - if (v->uv_flags & VIFF_LEAF) fprintf(fp, " leaf"); - if (v->uv_flags & VIFF_IGMPV1) fprintf(fp, " IGMPv1"); - fprintf(fp, "\n"); - - if (v->uv_addrs != NULL) { - fprintf(fp, " alternate subnets: %s\n", - inet_fmts(v->uv_addrs->pa_subnet, v->uv_addrs->pa_subnetmask, s1)); - for (p = v->uv_addrs->pa_next; p; p = p->pa_next) { - fprintf(fp, " %s\n", - inet_fmts(p->pa_subnet, p->pa_subnetmask, s1)); - } - } - - if (v->uv_neighbors != NULL) { - fprintf(fp, " peers: %s (%d.%d) (0x%x)\n", - inet_fmt(v->uv_neighbors->al_addr, s1), - v->uv_neighbors->al_pv, v->uv_neighbors->al_mv, - v->uv_neighbors->al_flags); - for (a = v->uv_neighbors->al_next; a != NULL; a = a->al_next) { - fprintf(fp, " %s (%d.%d) (0x%x)\n", - inet_fmt(a->al_addr, s1), a->al_pv, a->al_mv, - a->al_flags); - } - } - - if (v->uv_groups != NULL) { - fprintf(fp, " groups: %-15s\n", - inet_fmt(v->uv_groups->al_addr, s1)); - for (a = v->uv_groups->al_next; a != NULL; a = a->al_next) { - fprintf(fp, " %-15s\n", - inet_fmt(a->al_addr, s1)); - } - } - if (v->uv_acl != NULL) { - struct vif_acl *acl; - - fprintf(fp, " boundaries: %-18s\n", - inet_fmts(v->uv_acl->acl_addr, v->uv_acl->acl_mask, s1)); - for (acl = v->uv_acl->acl_next; acl != NULL; acl = acl->acl_next) { - fprintf(fp, " : %-18s\n", - inet_fmts(acl->acl_addr, acl->acl_mask, s1)); - } - } - v_req.vifi = vifi; - if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) < 0) { - log(LOG_WARNING, 0, - "SIOCGETVIFCNT fails"); - } - else { - fprintf(fp, " pkts in : %ld\n", - v_req.icount); - fprintf(fp, " pkts out: %ld\n", - v_req.ocount); - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); -} - -/* - * Time out record of a group membership on a vif - */ -static void -DelVif(arg) - void *arg; -{ - cbk_t *cbk = (cbk_t *)arg; - vifi_t vifi = cbk->vifi; - struct uvif *v = &uvifs[vifi]; - struct listaddr *a, **anp, *g = cbk->g; - - /* - * Group has expired - * delete all kernel cache entries with this group - */ - if (g->al_query) - DeleteTimer(g->al_query); - - delete_lclgrp(vifi, g->al_addr); - - anp = &(v->uv_groups); - while ((a = *anp) != NULL) { - if (a == g) { - *anp = a->al_next; - free((char *)a); - } else { - anp = &a->al_next; - } - } - - free(cbk); -} - -/* - * Set a timer to delete the record of a group membership on a vif. - */ -static int -SetTimer(vifi, g) - vifi_t vifi; - struct listaddr *g; -{ - cbk_t *cbk; - - cbk = (cbk_t *) malloc(sizeof(cbk_t)); - cbk->g = g; - cbk->vifi = vifi; - return timer_setTimer(g->al_timer, (cfunc_t)DelVif, (void *)cbk); -} - -/* - * Delete a timer that was set above. - */ -static int -DeleteTimer(id) - int id; -{ - timer_clearTimer(id); - return 0; -} - -/* - * Send a group-specific query. - */ -static void -SendQuery(arg) - void *arg; -{ - cbk_t *cbk = (cbk_t *)arg; - register struct uvif *v = &uvifs[cbk->vifi]; - - send_igmp(v->uv_lcl_addr, cbk->g->al_addr, - IGMP_HOST_MEMBERSHIP_QUERY, - cbk->q_time, cbk->g->al_addr, 0); - cbk->g->al_query = 0; - free(cbk); -} - -/* - * Set a timer to send a group-specific query. - */ -static int -SetQueryTimer(g, vifi, to_expire, q_time) - struct listaddr *g; - vifi_t vifi; - int to_expire, q_time; -{ - cbk_t *cbk; - - cbk = (cbk_t *) malloc(sizeof(cbk_t)); - cbk->g = g; - cbk->q_time = q_time; - cbk->vifi = vifi; - return timer_setTimer(to_expire, (cfunc_t)SendQuery, (void *)cbk); -} diff --git a/usr.sbin/mrouted/vif.h b/usr.sbin/mrouted/vif.h deleted file mode 100644 index 94f5f7a9ee7b..000000000000 --- a/usr.sbin/mrouted/vif.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - * - * - * $Id: vif.h,v 3.8 1995/11/29 22:36:57 fenner Rel $ - */ - -/* - * User level Virtual Interface structure - * - * A "virtual interface" is either a physical, multicast-capable interface - * (called a "phyint") or a virtual point-to-point link (called a "tunnel"). - * (Note: all addresses, subnet numbers and masks are kept in NETWORK order.) - */ -struct uvif { - u_short 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_threshold; /* min ttl required to forward on 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_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 */ - 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 */ -}; - -#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 */ - -struct phaddr { - struct phaddr *pa_next; - u_int32 pa_subnet; /* extra subnet */ - u_int32 pa_subnetmask; /* netmask of extra subnet */ - u_int32 pa_subnetbcast; /* broadcast of extra subnet */ -}; - -struct vif_acl { - struct vif_acl *acl_next; /* next acl member */ - u_int32 acl_addr; /* Group address */ - u_int32 acl_mask; /* Group addr. mask */ -}; - -struct 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 */ -}; - -#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 NO_VIF ((vifi_t)MAXVIFS) /* An invalid vif index */ |