new routed replaces rdisc
authorderaadt <deraadt@openbsd.org>
Wed, 18 Sep 1996 08:03:30 +0000 (08:03 +0000)
committerderaadt <deraadt@openbsd.org>
Wed, 18 Sep 1996 08:03:30 +0000 (08:03 +0000)
sbin/Makefile
sbin/rdisc/Makefile [deleted file]
sbin/rdisc/rdisc.8 [deleted file]
sbin/rdisc/rdisc.c [deleted file]

index be20236..877b4dd 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.19 1996/09/02 11:30:09 pefo Exp $
+#      $OpenBSD: Makefile,v 1.20 1996/09/18 08:03:30 deraadt Exp $
 #      $NetBSD: Makefile,v 1.29 1996/05/14 17:39:21 ws Exp $
 
 # Not ported: XNSrouted enpload scsiformat startslip
@@ -6,7 +6,7 @@
 
 SUBDIR=        badsect disklabel ccdconfig dmesg fastboot ifconfig init ipf ipfstat \
        ipnat kbd mknod modload modunload mount mountd ncheck_ffs nfsd nfsiod \
-       nologin ping quotacheck rdisc reboot route routed savecore scsi \
+       nologin ping quotacheck reboot route routed savecore scsi \
        shutdown slattach swapon ttyflags umount
 
 # support for various file systems
diff --git a/sbin/rdisc/Makefile b/sbin/rdisc/Makefile
deleted file mode 100644 (file)
index 9ee24d3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#      $OpenBSD: Makefile,v 1.1 1996/08/02 23:39:08 tholo Exp $
-
-PROG=  rdisc
-MAN=   rdisc.8
-BINMODE=555
-
-.include <bsd.prog.mk>
diff --git a/sbin/rdisc/rdisc.8 b/sbin/rdisc/rdisc.8
deleted file mode 100644 (file)
index 15a1285..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-'\"macro stdmacro
-.\"
-.\"    $OpenBSD: rdisc.8,v 1.1 1996/08/02 23:39:08 tholo Exp $
-.\"
-.\" Rdisc (this program) was developed by Sun Microsystems, Inc. and is 
-.\" provided for unrestricted use provided that this legend is included on 
-.\" all tape media and as a part of the software program in whole or part.  
-.\" Users may copy or modify Rdisc without charge, and they may freely 
-.\" distribute it.
-.\"
-.\" RDISC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
-.\" WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
-.\"
-.\" Rdisc is provided with no support and without any obligation on the
-.\" part of Sun Microsystems, Inc. to assist in its use, correction,
-.\" modification or enhancement.
-.\"
-.\" SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
-.\" INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY RDISC
-.\" OR ANY PART THEREOF.
-.\"
-.\" In no event will Sun Microsystems, Inc. be liable for any lost revenue
-.\" or profits or other special, indirect and consequential damages, even if
-.\" Sun has been advised of the possibility of such damages.
-.\"
-.\" Sun Microsystems, Inc.
-.\" 2550 Garcia Avenue
-.\" Mountain View, California  94043
-.\"
-.nr X
-.TH rdisc 8C "22 Jan 1996"
-.SH NAME
-rdisc \- network router discovery daemon
-.SH SYNOPSIS
-.B rdisc
-[
-.B \-sfa
-]
-.LP
-.B rdisc
-.B \-r
-[
-.BI \-p " preference"
-] [
-.BI \-T " interval"
-]
-.SH DESCRIPTION
-.IX "rdisc" "" "\fLrdisc\fP \(em ICMP router discovery daemon"
-.IX "Internet" "ICMP router discovery daemon" ""  "ICMP router discovery daemon \(em \fLrdisc\fP"
-.IX "Internet Control Message Protocol" "See ICMP"
-.IX "ICMP" "router discovery daemon" "" "router discovery daemon \(em \fLrdisc\fP"  
-.LP
-\f4rdisc\f1
-implements the 
-.SM ICMP
-router discover protocol.
-The first form of the command is used on hosts and the
-second form is used on routers.
-On a host \f4rdisc\f1 is invoked at 
-boot time to populate the network routing tables with default routes. 
-On a router it is also invoked at boot time in order to start
-advertising the router to all the hosts.
-.SS "Host (First Form)"
-.PP
-On a host \f4rdisc\f1
-listens on the \f4ALL_HOSTS\f1 (224.0.0.1) multicast address 
-for \f4ROUTER_ADVERTISE\f1 messages from routers. The received
-messages are handled by first ignoring
-those listed router addresses with which the host does not share a network.
-Among the remaining addresses the ones with the highest preference are selected
-as default routers and a default route is entered in the kernel routing
-table for each one of them.
-.LP
-Optionally, \f4rdisc\f1 can avoid waiting for routers to announce 
-themselves by sending out a few \f4ROUTER_SOLICITATION\f1 messages
-to the \f4ALL_ROUTERS\f1 (224.0.0.2) multicast address when it is started.
-.LP
-A timer is associated with each router address and the address will
-no longer be considered for inclusion in the the routing tables if the 
-timer expires before a new 
-.I advertise
-message is received from the router.
-The address will also be excluded from consideration if the host receives an 
-.I advertise
-message with the preference being maximally negative.
-.SS "Router (Second Form)"
-.PP
-When 
-\f4rdisc\f1
-is started on a router, it uses the
-\f4SIOCGIFCONF\f1
-.BR ioctl (2)
-to find the interfaces configured into the system and it starts
-listening on the \f4ALL_ROUTERS\f1 multicast address on all the interfaces
-that support multicast.
-It sends out
-.I advertise
-messages to the \f4ALL_HOSTS\f1 multicast address advertising all its
-.BM IP
-addresses.
-A few initial 
-.I advertise
-messages are sent out during the first 30 seconds and after that it will
-transmit 
-.I advertise
-messages approximately every 600 seconds.
-.LP
-When \f4rdisc\f1
-receives a 
-.I solicitation
-message it sends an 
-.I advertise 
-message to the host that sent the 
-.I solicitation
-message.
-.LP
-When
-.B rdisc
-is terminated by a signal it sends out an
-.I advertise
-message with the preference being maximally negative.
-.br
-.ne 1i
-.SH OPTIONS
-.TP 15
-.B \-a
-Accept all routers independently of the preference they have in their 
-.I advertise
-messages.
-Normally
-.B rdisc
-only accepts (and enters in the kernel routing tables) 
-the router or routers with the highest preference.
-.TP
-.B \-f
-Run
-.B rdisc 
-forever even if no routers are found.
-Normally 
-.B rdisc 
-gives up if it has not received any 
-.I advertise 
-message after after soliciting three times,
-in which case it exits with a non-zero exit code.
-If 
-.B \-f 
-is not specified in the first form then 
-.B \-s
-must be specified.
-.TP
-.BI \-p " preference"
-Set the preference transmitted in the 
-.I solicitation
-messages.
-The default is zero.
-.TP
-.B \-r
-Act as a router as opposed to a host.
-.TP
-.B \-s
-Send three 
-.I solicitation
-messages initially to quickly discover the routers
-when the system is booted.
-When 
-.B \-s
-is specified 
-.B rdisc
-exits with a non-zero exit code if it can not find any routers.
-This can be overridden with the
-.B \-f
-option.
-.TP
-.BI \-T " interval"
-Set the interval between transmitting the
-.I advertise
-messages.
-The default time is 600 seconds.
-.SH "SEE ALSO"
-.BR routed (8)
-.BR icmp (4),
-.BR inet (4)
-.LP
-Deering, S.E.,ed
-.RI `` "ICMP Router Discovery Messages" ,''
-.SM RFC
-1256, Network Information Center,
-.SM SRI
-International, Menlo Park, Calif.,
-September 1991.
diff --git a/sbin/rdisc/rdisc.c b/sbin/rdisc/rdisc.c
deleted file mode 100644 (file)
index ede60d3..0000000
+++ /dev/null
@@ -1,1614 +0,0 @@
-/*
- *     $OpenBSD: rdisc.c,v 1.1 1996/08/02 23:39:08 tholo Exp $
- *
- * Rdisc (this program) was developed by Sun Microsystems, Inc. and is
- * provided for unrestricted use provided that this legend is included on
- * all tape media and as a part of the software program in whole or part.
- * Users may copy or modify Rdisc without charge, and they may freely
- * distribute it.
- *
- * RDISC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Rdisc is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY RDISC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California  94043
- */
-#include <stdio.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-
-#include <sys/ioctl.h>
-#include <net/if.h>
-
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-
-#include <netdb.h>
-#include <arpa/inet.h>
-
-#include <string.h>
-#include <syslog.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <err.h>
-#include <sys/cdefs.h>
-
-#if __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-/*
- * TBD
- *     Use 255.255.255.255 for broadcasts - not the interface broadcast
- *     address.
- */
-
-#ifdef lint
-#define ALLIGN(ptr)    (ptr ? 0 : 0)
-#else
-#define ALLIGN(ptr)    (ptr)
-#endif
-
-
-#define ICMP_ROUTER_ADVERTISEMENT      9
-#define ICMP_ROUTER_SOLICITATION       10
-
-#define ALL_HOSTS_ADDRESS              "224.0.0.1"
-#define ALL_ROUTERS_ADDRESS            "224.0.0.2"
-
-#define MAXIFS 32
-
-/* Router constants */
-#define        MAX_INITIAL_ADVERT_INTERVAL     16
-#define        MAX_INITIAL_ADVERTISEMENTS      3
-#define        MAX_RESPONSE_DELAY              2       /* Not used */
-
-/* Host constants */
-#define MAX_SOLICITATIONS              3
-#define SOLICITATION_INTERVAL          3
-#define MAX_SOLICITATION_DELAY         1       /* Not used */
-
-#define IGNORE_PREFERENCE      0x80000000      /* Maximum negative */
-
-#define MAX_ADV_INT 600
-
-/* Statics */
-int num_interfaces;
-struct interface {
-       struct in_addr  address;        /* Used to identify the interface */
-       struct in_addr  localaddr;      /* Actual address if the interface */
-       int             preference;
-       int             flags;
-       struct in_addr  bcastaddr;
-       struct in_addr  remoteaddr;
-       struct in_addr  netmask;
-};
-struct interface *interfaces;
-int interfaces_size;                   /* Number of elements in interfaces */
-
-
-#define        MAXPACKET       4096    /* max packet size */
-u_char packet[MAXPACKET];
-
-char usage[] =
-"Usage:        rdisc [-s] [-v] [-f] [-a] [send_address] [receive_address]\n\
-        rdisc -r [-v] [-p <preference>] [-T <secs>] \n\
-               [send_address] [receive_address]\n";
-
-
-int s;                 /* Socket file descriptor */
-struct sockaddr_in whereto;/* Address to send to */
-
-/* Common variables */
-int verbose = 0;
-int debug = 0;
-int trace = 0;
-int solicit = 0;
-int responder;
-int ntransmitted = 0;
-int nreceived = 0;
-int forever = 0;       /* Never give up on host. If 0 defer fork until
-                        * first response.
-                        */
-
-/* Router variables */
-int max_adv_int = MAX_ADV_INT;
-int min_adv_int;
-int lifetime;
-int initial_advert_interval = MAX_INITIAL_ADVERT_INTERVAL;
-int initial_advertisements = MAX_INITIAL_ADVERTISEMENTS;
-int preference = 0;            /* Setable with -p option */
-
-/* Host variables */
-int max_solicitations = MAX_SOLICITATIONS;
-unsigned int solicitation_interval = SOLICITATION_INTERVAL;
-int best_preference = 1;       /* Set to record only the router(s) with the
-                                  best preference in the kernel. Not set
-                                  puts all routes in the kernel. */
-
-/* Prototypes */
-void   do_fork         __P((void));
-int    main            __P((int, char **));
-void   timer           __P((int));
-void   solicitor       __P((struct sockaddr_in *));
-void   advertise       __P((struct sockaddr_in *));
-char * pr_type         __P((int));
-char * pr_name         __P((struct in_addr));
-void   pr_pack         __P((char *, int, struct sockaddr_in *));
-int    in_cksum        __P((u_short *, int));
-void   finish          __P((int));
-int    isbroadcast     __P((struct sockaddr_in *));
-int    ismulticast     __P((struct sockaddr_in *));
-int    sendbcast       __P((int, char *, int));
-int    sendbcastif     __P((int, char *, int, struct interface *));
-int    sendmcast       __P((int, char *, int, struct sockaddr_in *));
-int    sendmcastif     __P((int, char *, int, struct sockaddr_in *, struct interface *));
-void   init            __P((void));
-void   initifs         __P((int));
-int    support_multicast       __P((void));
-int    is_directly_connected   __P((struct in_addr));
-struct table * find_router     __P((struct in_addr));
-int    max_preference  __P((void));
-void   age_table       __P((int));
-void   record_router   __P((struct in_addr, long, int));
-void   add_route       __P((struct in_addr));
-void   del_route       __P((struct in_addr));
-void   rtioctl         __P((struct in_addr, int));
-void   initlog         __P((void));
-void   logerr          __P((char *fmt, ...));
-void   logtrace        __P((char *fmt, ...));
-void   logdebug        __P((char *fmt, ...));
-void   logperror       __P((char *str));
-void   prusage         __P((void));
-int    join            __P((int sock, struct sockaddr_in *sin));
-
-
-void
-prusage()
-{
-       (void) fprintf(stderr, usage);
-       exit(1);
-}
-
-void
-do_fork()
-{
-       int t;
-       long pid;
-
-       if (trace)
-               return;
-
-       if ((pid = fork()))
-               exit(0);
-
-       for (t = 0; t < 20; t++)
-               if (t != s)
-                       (void) close(t);
-
-       (void) setsid ();
-
-       initlog();
-}
-
-/*
- *                     M A I N
- */
-char    *sendaddress, *recvaddress;
-
-int
-main(argc, argv)
-       int argc;
-       char *argv[];
-{
-       struct sigaction sa;
-       struct sockaddr_in from;
-       struct sockaddr_in *to = &whereto;
-       struct sockaddr_in joinaddr;
-       int val;
-       int c;
-
-       min_adv_int =( max_adv_int * 3 / 4);
-       lifetime = (3*max_adv_int);
-
-       while ((c = getopt(argc, argv, "dtvsrabfT:p:")) != EOF) {
-               switch(c) {
-               case 'd':
-                       debug = 1;
-                       break;
-               case 't':
-                       trace = 1;
-                       break;
-               case 'v':
-                       verbose++;
-                       break;
-               case 's':
-                       solicit = 1;
-                       break;
-               case 'r':
-                       responder = 1;
-                       break;
-               case 'a':
-                       best_preference = 0;
-                       break;
-               case 'b':
-                       best_preference = 1;
-                       break;
-               case 'f':
-                       forever = 1;
-                       break;
-               case 'T':
-                       val = strtol(optarg, (char **)NULL, 0);
-                       if (val < 4 || val > 1800) {
-                               (void) fprintf(stderr,
-                                 "Bad Max Advertizement Interval\n");
-                               exit(1);
-                       }
-                       max_adv_int = val;
-                       min_adv_int =( max_adv_int * 3 / 4);
-                       lifetime = (3*max_adv_int);
-                       break;
-               case 'p':
-                       val = strtol(optarg, (char **)NULL, 0);
-                       preference = val;
-                       break;
-               default:
-                       prusage();
-                       /* NOTREACHED*/
-               }
-       }
-       argc -= optind;
-       argv += optind;
-
-       if( argc < 1)  {
-               if (support_multicast()) {
-                       if (responder)
-                               sendaddress = ALL_HOSTS_ADDRESS;
-                       else
-                               sendaddress = ALL_ROUTERS_ADDRESS;
-               } else
-                       sendaddress = "255.255.255.255";
-       } else {
-               sendaddress = argv[0];
-               argc--; argv++;
-       }
-
-       if (argc < 1) {
-               if (support_multicast()) {
-                       if (responder)
-                               recvaddress = ALL_ROUTERS_ADDRESS;
-                       else
-                               recvaddress = ALL_HOSTS_ADDRESS;
-               } else
-                       recvaddress = "255.255.255.255";
-       } else {
-               recvaddress = argv[0];
-               argc--; argv++;
-       }
-       if (argc != 0) {
-               (void) fprintf(stderr, "Extra paramaters\n");
-               prusage();
-               /* NOTREACHED */
-       }
-
-       if (solicit && responder) {
-               prusage();
-               /* NOTREACHED */
-       }
-
-       if (!(solicit && !forever)) {
-               do_fork();
-/*
- * Added the next line to stop forking a second time
- * Fraser Gardiner - Sun Microsystems Australia
- */
-               forever = 1;
-       }
-
-       bzero( (char *)&whereto, sizeof(struct sockaddr_in) );
-       to->sin_family = AF_INET;
-       to->sin_addr.s_addr = inet_addr(sendaddress);
-
-       bzero( (char *)&joinaddr, sizeof(struct sockaddr_in) );
-       joinaddr.sin_family = AF_INET;
-       joinaddr.sin_addr.s_addr = inet_addr(recvaddress);
-
-       if (responder) {
-               /* TBD fix this to be more random */
-               srandom((int)gethostid()+(int)time((time_t *)NULL));
-       }
-
-       if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
-               logperror("socket");
-               exit(5);
-       }
-
-       setvbuf( stdout, NULL, _IOLBF, 0 );
-
-       (void) signal( SIGINT, finish );
-       (void) signal( SIGTERM, finish );
-       (void) signal( SIGHUP, initifs );
-
-       init();
-       if (join(s, &joinaddr) < 0) {
-               logerr("Failed joining addresses\n");
-               exit (2);
-       }
-
-
-       /*
-        * Make sure that this signal actually interrupts (rather than
-        * restarts) the recvfrom call below.
-        */
-       memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = timer;
-       sigemptyset(&sa.sa_mask);
-       sa.sa_flags = 0;        /* note: no SA_RESTART */
-       (void) sigaction(SIGALRM, &sa, (struct sigaction *)NULL);
-       timer(0);       /* start things going */
-
-       for (;;) {
-               int len = sizeof (packet);
-               int fromlen = sizeof (from);
-               int cc;
-
-               if ( (cc=recvfrom(s, (char *)packet, len, 0,
-                                 (struct sockaddr *)&from, &fromlen)) < 0) {
-                       if( errno == EINTR )
-                               continue;
-                       logperror("recvfrom");
-                       continue;
-               }
-               pr_pack( (char *)packet, cc, &from );
-       }
-       /*NOTREACHED*/
-}
-
-#define TIMER_INTERVAL         3
-#define GETIFCONF_TIMER        30
-
-int left_until_advertise;
-
-/* Called every TIMER_INTERVAL */
-void timer(sig)
-     int sig;
-{
-       static int left_until_getifconf;
-       static int left_until_solicit;
-
-       left_until_getifconf -= TIMER_INTERVAL;
-       left_until_advertise -= TIMER_INTERVAL;
-       left_until_solicit -= TIMER_INTERVAL;
-
-       if (left_until_getifconf < 0) {
-               initifs(0);
-               left_until_getifconf = GETIFCONF_TIMER;
-       }
-       if (responder && left_until_advertise <= 0) {
-               ntransmitted++;
-               advertise(&whereto);
-               if (ntransmitted < initial_advertisements)
-                       left_until_advertise = initial_advert_interval;
-               else
-                       left_until_advertise = min_adv_int +
-                               ((max_adv_int - min_adv_int) *
-                                (random() % 1000)/1000);
-       } else if (solicit && left_until_solicit <= 0) {
-               ntransmitted++;
-               solicitor(&whereto);
-               if (ntransmitted < max_solicitations)
-                       left_until_solicit = solicitation_interval;
-               else {
-                       solicit = 0;
-                       if (!forever && nreceived == 0)
-                               exit(5);
-               }
-       }
-       age_table(TIMER_INTERVAL);
-       (void) alarm(TIMER_INTERVAL);
-}
-
-/*
- *                     S O L I C I T O R
- *
- * Compose and transmit an ICMP ROUTER SOLICITATION REQUEST packet.
- * The IP packet will be added on by the kernel.
- */
-void
-solicitor(sin)
-       struct sockaddr_in *sin;
-{
-       static u_char outpack[MAXPACKET];
-       register struct icmp *icp = (struct icmp *) ALLIGN(outpack);
-       int packetlen, i;
-
-       if (verbose) {
-               logtrace("Sending solicitation to %s\n",
-                        pr_name(sin->sin_addr));
-       }
-       icp->icmp_type = ICMP_ROUTER_SOLICITATION;
-       icp->icmp_code = 0;
-       icp->icmp_cksum = 0;
-       icp->icmp_void = 0; /* Reserved */
-       packetlen = 8;
-
-       /* Compute ICMP checksum here */
-       icp->icmp_cksum = in_cksum( (u_short *)icp, packetlen );
-
-       if (isbroadcast(sin))
-               i = sendbcast(s, (char *)outpack, packetlen);
-       else if (ismulticast(sin))
-               i = sendmcast( s, (char *)outpack, packetlen, sin);
-       else
-               i = sendto( s, (char *)outpack, packetlen, 0,
-                          (struct sockaddr *)sin, sizeof(struct sockaddr));
-
-       if( i < 0 || i != packetlen )  {
-               if( i<0 ) {
-                   logperror("sendto");
-               }
-               logerr("wrote %s %d chars, ret=%d\n",
-                       sendaddress, packetlen, i );
-       }
-}
-
-/*
- *                     A V E R T I S E
- *
- * Compose and transmit an ICMP ROUTER ADVERTISEMENT packet.
- * The IP packet will be added on by the kernel.
- */
-void
-advertise(sin)
-       struct sockaddr_in *sin;
-{
-       static u_char outpack[MAXPACKET];
-       register struct icmp *rap = (struct icmp *) ALLIGN(outpack);
-       struct icmp_ra_addr *ap;
-       int packetlen, i, cc;
-
-       if (verbose) {
-               logtrace("Sending advertisement to %s\n",
-                        pr_name(sin->sin_addr));
-       }
-
-       for (i = 0; i < num_interfaces; i++) {
-               rap->icmp_type = ICMP_ROUTER_ADVERTISEMENT;
-               rap->icmp_code = 0;
-               rap->icmp_cksum = 0;
-               rap->icmp_num_addrs = 0;
-               rap->icmp_wpa = 2;
-               rap->icmp_lifetime = lifetime;
-               packetlen = 8;
-
-               /*
-                * TODO handle multiple logical interfaces per
-                * physical interface. (increment with rap->icmp_wpa * 4 for
-                * each address.)
-                */
-               ap = (struct icmp_ra_addr *)ALLIGN(outpack + ICMP_MINLEN);
-               ap->ira_addr = interfaces[i].localaddr.s_addr;
-               ap->ira_preference = interfaces[i].preference;
-               packetlen += rap->icmp_wpa * 4;
-               rap->icmp_num_addrs++;
-
-
-               /* Compute ICMP checksum here */
-               rap->icmp_cksum = in_cksum( (u_short *)rap, packetlen );
-
-               if (isbroadcast(sin))
-                       cc = sendbcastif(s, (char *)outpack, packetlen,
-                                       &interfaces[i]);
-               else if (ismulticast(sin))
-                       cc = sendmcastif( s, (char *)outpack, packetlen, sin,
-                                       &interfaces[i]);
-               else {
-                       struct interface *ifp = &interfaces[i];
-                       /*
-                        * Verify that the interface matches the destination
-                        * address.
-                        */
-                       if ((sin->sin_addr.s_addr & ifp->netmask.s_addr) ==
-                           (ifp->address.s_addr & ifp->netmask.s_addr)) {
-                               if (debug) {
-                                       logdebug("Unicast to %s ",
-                                                pr_name(sin->sin_addr));
-                                       logdebug("on interface %s\n",
-                                                pr_name(ifp->address));
-                               }
-                               cc = sendto( s, (char *)outpack, packetlen, 0,
-                                           (struct sockaddr *)sin,
-                                           sizeof(struct sockaddr));
-                       } else
-                               cc = packetlen;
-               }
-               if( cc < 0 || cc != packetlen )  {
-                       if (cc < 0) {
-                               logperror("sendto");
-                       } else {
-                               logerr("wrote %s %d chars, ret=%d\n",
-                                      sendaddress, packetlen, cc );
-                       }
-               }
-       }
-}
-
-/*
- *                     P R _ T Y P E
- *
- * Convert an ICMP "type" field to a printable string.
- */
-char *
-pr_type( t )
-register int t;
-{
-       static char *ttab[] = {
-               "Echo Reply",
-               "ICMP 1",
-               "ICMP 2",
-               "Dest Unreachable",
-               "Source Quench",
-               "Redirect",
-               "ICMP 6",
-               "ICMP 7",
-               "Echo",
-               "Router Advertise",
-               "Router Solicitation",
-               "Time Exceeded",
-               "Parameter Problem",
-               "Timestamp",
-               "Timestamp Reply",
-               "Info Request",
-               "Info Reply",
-               "Netmask Request",
-               "Netmask Reply"
-       };
-
-       if ( t < 0 || t > 16 )
-               return("OUT-OF-RANGE");
-
-       return(ttab[t]);
-}
-
-/*
- *                     P R _ N A M E
- *
- * Return a string name for the given IP address.
- */
-char *pr_name(addr)
-    struct in_addr addr;
-{
-       char *inet_ntoa();
-       struct hostent *phe;
-       static char buf[256];
-
-       phe = gethostbyaddr((char *)&addr.s_addr, 4, AF_INET);
-       if (phe == NULL)
-               return( inet_ntoa(addr));
-       (void) sprintf(buf, "%s (%s)", phe->h_name, inet_ntoa(addr));
-       return(buf);
-}
-
-/*
- *                     P R _ P A C K
- *
- * Print out the packet, if it came from us.  This logic is necessary
- * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
- * which arrive ('tis only fair).  This permits multiple copies of this
- * program to be run without having intermingled output (or statistics!).
- */
-void
-pr_pack( buf, cc, from )
-char *buf;
-int cc;
-struct sockaddr_in *from;
-{
-       struct ip *ip;
-       register struct icmp *icp;
-       register int i;
-       int hlen;
-
-       ip = (struct ip *) ALLIGN(buf);
-       hlen = ip->ip_hl << 2;
-       if (cc < hlen + ICMP_MINLEN) {
-               if (verbose)
-                       logtrace("packet too short (%d bytes) from %s\n", cc,
-                                pr_name(from->sin_addr));
-               return;
-       }
-       cc -= hlen;
-       icp = (struct icmp *)ALLIGN(buf + hlen);
-       if (ip->ip_p == 0) {
-               /*
-                * Assume that we are running on a pre-4.3BSD system
-                * such as SunOS before 4.0
-                */
-                icp = (struct icmp *)ALLIGN(buf);
-       }
-       switch (icp->icmp_type) {
-       case ICMP_ROUTER_ADVERTISEMENT: {
-               struct icmp *rap = (struct icmp *)ALLIGN(icp);
-               struct icmp_ra_addr *ap;
-
-               if (responder)
-                       break;
-
-               /* TBD verify that the link is multicast or broadcast */
-               /* XXX Find out the link it came in over? */
-#ifdef notdef
-               if (debug) {
-                       logdebug("ROUTER_ADVERTISEMENT: \n");
-                       pr_hex(buf+hlen, cc);
-               }
-#endif notdef
-               if (in_cksum((u_short *)ALLIGN(buf+hlen), cc)) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Bad checksum\n",
-                                        pr_type((int)rap->icmp_type),
-                                        pr_name(from->sin_addr));
-                       return;
-               }
-               if (rap->icmp_code != 0) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Code = %d\n",
-                                        pr_type((int)rap->icmp_type),
-                                        pr_name(from->sin_addr),
-                                        rap->icmp_code);
-                       return;
-               }
-               if (rap->icmp_num_addrs < 1) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: No addresses\n",
-                                        pr_type((int)rap->icmp_type),
-                                        pr_name(from->sin_addr));
-                       return;
-               }
-               if (rap->icmp_wpa < 2) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Words/addr = %d\n",
-                                        pr_type((int)rap->icmp_type),
-                                        pr_name(from->sin_addr),
-                                        rap->icmp_wpa);
-                       return;
-               }
-               if ((unsigned)cc <
-                   ICMP_MINLEN + rap->icmp_num_addrs * rap->icmp_wpa * 4) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Too short %d, %d\n",
-                                             pr_type((int)rap->icmp_type),
-                                             pr_name(from->sin_addr),
-                                             cc,
-                                             ICMP_MINLEN +
-                                             rap->icmp_num_addrs * rap->icmp_wpa * 4);
-                       return;
-               }
-               rap->icmp_lifetime = ntohs(rap->icmp_lifetime);
-               if (rap->icmp_lifetime < 4) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Lifetime = %d\n",
-                                             pr_type((int)rap->icmp_type),
-                                             pr_name(from->sin_addr),
-                                             rap->icmp_lifetime);
-                       return;
-               }
-               if (verbose)
-                       logtrace("ICMP %s from %s, lifetime %d\n",
-                                     pr_type((int)rap->icmp_type),
-                                     pr_name(from->sin_addr),
-                                     rap->icmp_lifetime);
-
-               /* Check that at least one router address is a neighboor
-                * on the arriving link.
-                */
-               for (i = 0; (unsigned)i < rap->icmp_num_addrs; i++) {
-                       struct in_addr ina;
-                       ap = (struct icmp_ra_addr *)
-                               ALLIGN(buf + hlen + ICMP_MINLEN +
-                                      i * rap->icmp_wpa * 4);
-                       ina.s_addr = ap->ira_addr;
-                       if (verbose)
-                               logtrace("\taddress %s, preference 0x%x\n",
-                                             pr_name(ina),
-                                             ntohl(ap->ira_preference));
-                       if (!responder) {
-                               if (is_directly_connected(ina))
-                                       record_router(ina,
-                                                     (long)ntohl(ap->ira_preference),
-                                                     rap->icmp_lifetime);
-                       }
-               }
-               nreceived++;
-               if (!forever) {
-                       do_fork();
-                       forever = 1;
-/*
- * The next line was added so that the alarm is set for the new procces
- * Fraser Gardiner Sun Microsystems Australia
- */
-                       (void) alarm(TIMER_INTERVAL);
-               }
-               break;
-       }
-
-       case ICMP_ROUTER_SOLICITATION: {
-               struct sockaddr_in sin;
-
-               if (!responder)
-                       break;
-
-               /* TBD verify that the link is multicast or broadcast */
-               /* XXX Find out the link it came in over? */
-#ifdef notdef
-               if (debug) {
-                       logdebug("ROUTER_SOLICITATION: \n");
-                       pr_hex(buf+hlen, cc);
-               }
-#endif notdef
-               if (in_cksum((u_short *)ALLIGN(buf+hlen), cc)) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Bad checksum\n",
-                                             pr_type((int)icp->icmp_type),
-                                             pr_name(from->sin_addr));
-                       return;
-               }
-               if (icp->icmp_code != 0) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Code = %d\n",
-                                             pr_type((int)icp->icmp_type),
-                                             pr_name(from->sin_addr),
-                                             icp->icmp_code);
-                       return;
-               }
-
-               if (cc < ICMP_MINLEN) {
-                       if (verbose)
-                               logtrace("ICMP %s from %s: Too short %d, %d\n",
-                                             pr_type((int)icp->icmp_type),
-                                             pr_name(from->sin_addr),
-                                             cc,
-                                             ICMP_MINLEN);
-                       return;
-               }
-
-               if (verbose)
-                       logtrace("ICMP %s from %s\n",
-                                     pr_type((int)icp->icmp_type),
-                                     pr_name(from->sin_addr));
-
-               if (!responder)
-                       break;
-
-               /* Check that ip_src is either a neighboor
-                * on the arriving link or 0.
-                */
-               sin.sin_family = AF_INET;
-               if (ip->ip_src.s_addr == 0) {
-                       /* If it was sent to the broadcast address we respond
-                        * to the broadcast address.
-                        */
-                       if (IN_CLASSD(ip->ip_dst.s_addr))
-                               sin.sin_addr.s_addr = INADDR_ALLHOSTS_GROUP;
-                       else
-                               sin.sin_addr.s_addr = INADDR_BROADCAST;
-                       /* Restart the timer when we broadcast */
-                       left_until_advertise = min_adv_int +
-                               ((max_adv_int - min_adv_int)
-                                * (random() % 1000)/1000);
-               }
-               else {
-                       if (!is_directly_connected(ip->ip_src)) {
-                               if (verbose)
-                                       logtrace("ICMP %s from %s: source not directly connected\n",
-                                                     pr_type((int)icp->icmp_type),
-                                                     pr_name(from->sin_addr));
-                               break;
-                       }
-                       sin.sin_addr.s_addr = ip->ip_src.s_addr;
-               }
-               nreceived++;
-               ntransmitted++;
-               advertise(&sin);
-               break;
-       }
-       } /* end switch */
-}
-
-
-/*
- *                     I N _ C K S U M
- *
- * Checksum routine for Internet Protocol family headers (C Version)
- *
- */
-int
-in_cksum(addr, len)
-u_short *addr;
-int len;
-{
-       register int nleft = len;
-       register u_short *w = addr;
-       register u_short answer;
-       u_short odd_byte = 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 *)(&odd_byte) = *(u_char *)w;
-               sum += odd_byte;
-       }
-
-       /*
-        * 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);
-}
-
-/*
- *                     F I N I S H
- *
- * Print out statistics, and give up.
- * Heavily buffered STDIO is used here, so that all the statistics
- * will be written with 1 sys-write call.  This is nice when more
- * than one copy of the program is running on a terminal;  it prevents
- * the statistics output from becomming intermingled.
- */
-void
-finish(sig)
-       int sig;
-{
-       if (responder) {
-               int i;
-
-               /* Send out a packet with a preference so that all
-                * hosts will know that we are dead.
-                */
-               logerr("terminated\n");
-               for (i = 0; i < num_interfaces; i++)
-                       interfaces[i].preference = IGNORE_PREFERENCE;
-               ntransmitted++;
-               advertise(&whereto);
-       }
-       if (verbose) {
-           logtrace("\n----%s rdisc Statistics----\n", sendaddress );
-           logtrace("%d packets transmitted, ", ntransmitted );
-           logtrace("%d packets received, ", nreceived );
-           (void) fflush(stdout);
-       }
-       exit(0);
-}
-
-#include <ctype.h>
-
-#ifdef notdef
-pr_hex(data, len)
-int len;
-unsigned char *data;
-{
-       FILE *out;
-
-       out = stdout;
-
-       while (len) {
-               register int i;
-               char charstring[17];
-
-               (void)strcpy(charstring,"                "); /* 16 spaces */
-               for (i = 0; i < 16; i++) {
-                       /* output the bytes one at a time,
-                        * not going pas "len" bytes
-                        */
-                       if (len) {
-                               char ch = *data & 0x7f; /* strip parity */
-                               if (!isprint((u_char)ch))
-                                       ch = ' '; /* ensure printable */
-                               charstring[i] = ch;
-                               (void) fprintf(out,"%02x ",*data++);
-                               len--;
-                       } else
-                               (void) fprintf(out,"   ");
-                       if (i==7)
-                               (void) fprintf(out,"   ");
-               }
-
-               (void) fprintf(out,"    *%s*\n",charstring);
-       }
-}
-#endif notdef
-
-int
-isbroadcast(sin)
-       struct sockaddr_in *sin;
-{
-       return (sin->sin_addr.s_addr == INADDR_BROADCAST);
-}
-
-int
-ismulticast(sin)
-       struct sockaddr_in *sin;
-{
-       return (IN_CLASSD(ntohl(sin->sin_addr.s_addr)));
-}
-
-/* From libc/rpc/pmap_rmt.c */
-
-int
-sendbcast(s, packet, packetlen)
-       int s;
-       char *packet;
-       int packetlen;
-{
-       int i, cc;
-
-       for (i = 0; i < num_interfaces; i++) {
-               if ((interfaces[i].flags & IFF_BROADCAST) == 0)
-                       continue;
-               cc = sendbcastif(s, packet, packetlen, &interfaces[i]);
-               if (cc!= packetlen) {
-                       return (cc);
-               }
-       }
-       return (packetlen);
-}
-
-int
-sendbcastif(s, packet, packetlen, ifp)
-       int s;
-       char *packet;
-       int packetlen;
-       struct interface *ifp;
-{
-       int cc;
-       struct sockaddr_in baddr;
-
-       baddr.sin_family = AF_INET;
-
-       if ((ifp->flags & IFF_BROADCAST) == 0)
-               return (packetlen);
-
-       baddr.sin_addr = ifp->bcastaddr;
-       if (debug)
-               logdebug("Broadcast to %s\n",
-                        pr_name(baddr.sin_addr));
-       cc = sendto(s, packet, packetlen, 0,
-                   (struct sockaddr *)&baddr, sizeof (struct sockaddr));
-       if (cc!= packetlen) {
-               logperror("sendbcast: sendto");
-               logerr("Cannot send broadcast packet to %s\n",
-                      pr_name(baddr.sin_addr));
-       }
-       return (cc);
-}
-
-int
-sendmcast(s, packet, packetlen, sin)
-       int s;
-       char *packet;
-       int packetlen;
-       struct sockaddr_in *sin;
-{
-       int i, cc;
-
-       for (i = 0; i < num_interfaces; i++) {
-               if ((interfaces[i].flags & IFF_MULTICAST) == 0)
-                       continue;
-               cc = sendmcastif(s, packet, packetlen, sin, &interfaces[i]);
-               if (cc!= packetlen) {
-                       return (cc);
-               }
-       }
-       return (packetlen);
-}
-
-int
-sendmcastif(s, packet, packetlen, sin, ifp)
-       int s;
-       char *packet;
-       int packetlen;
-       struct sockaddr_in *sin;
-       struct interface *ifp;
-{
-       int cc;
-       struct sockaddr_in ifaddr;
-
-       ifaddr.sin_family = AF_INET;
-
-       if ((ifp->flags & IFF_MULTICAST) == 0)
-               return (packetlen);
-
-       ifaddr.sin_addr = ifp->address;
-       if (debug)
-               logdebug("Multicast to interface %s\n",
-                        pr_name(ifaddr.sin_addr));
-       if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
-                      (char *)&ifaddr.sin_addr,
-                      sizeof(ifaddr.sin_addr)) < 0) {
-               logperror("setsockopt (IP_MULTICAST_IF)");
-               logerr("Cannot send multicast packet over interface %s\n",
-                      pr_name(ifaddr.sin_addr));
-               return (-1);
-       }
-       cc = sendto(s, packet, packetlen, 0,
-                   (struct sockaddr *)sin, sizeof (struct sockaddr));
-       if (cc!= packetlen) {
-               logperror("sendmcast: sendto");
-               logerr("Cannot send multicast packet over interface %s\n",
-                      pr_name(ifaddr.sin_addr));
-       }
-       return (cc);
-}
-
-void
-init()
-{
-       int i;
-
-       initifs(0);
-       for (i = 0; i < interfaces_size; i++)
-               interfaces[i].preference = preference;
-}
-
-void
-initifs(sig)
-       int sig;
-{
-       int     sock;
-       struct ifconf ifc;
-       struct ifreq ifreq, *ifrp, *ifend;
-       struct sockaddr_in *sin;
-       int n, i;
-       char *buf;
-       int numifs;
-       unsigned bufsize;
-
-       sock = socket(AF_INET, SOCK_DGRAM, 0);
-       if (sock < 0) {
-               logperror("initifs: socket");
-               return;
-       }
-#ifdef SIOCGIFNUM
-       if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
-               numifs = MAXIFS;
-       }
-#else
-       numifs = MAXIFS;
-#endif
-       bufsize = numifs * sizeof(struct ifreq);
-       buf = (char *)malloc(bufsize);
-       if (buf == NULL) {
-               logerr("out of memory\n");
-               (void) close(sock);
-               return;
-       }
-       bzero(buf, bufsize);
-       if (interfaces)
-               interfaces = (struct interface *)ALLIGN(realloc((char *)interfaces,
-                                        numifs * sizeof(struct interface)));
-       else
-               interfaces = (struct interface *)ALLIGN(malloc(numifs *
-                                               sizeof(struct interface)));
-       if (interfaces == NULL) {
-               logerr("out of memory\n");
-               (void) close(sock);
-               (void) free(buf);
-               return;
-       }
-       interfaces_size = numifs;
-
-       ifc.ifc_len = bufsize;
-       ifc.ifc_buf = buf;
-       if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-               logperror("initifs: ioctl (get interface configuration)");
-               (void) close(sock);
-               (void) free(buf);
-               return;
-       }
-       ifrp = (struct ifreq *)buf;
-       ifend = (struct ifreq *)(buf + ifc.ifc_len);
-       for (i = 0; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) {
-               ifreq = *ifrp;
-               if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
-                       logperror("initifs: ioctl (get interface flags)");
-                       n = 0;
-                       continue;
-               }
-               n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
-               if (n < sizeof(*ifrp))
-                   n = sizeof(*ifrp);
-               if (ifrp->ifr_addr.sa_family != AF_INET)
-                       continue;
-               if ((ifreq.ifr_flags & IFF_UP) == 0)
-                       continue;
-               if (ifreq.ifr_flags & IFF_LOOPBACK)
-                       continue;
-               if ((ifreq.ifr_flags & (IFF_MULTICAST | IFF_BROADCAST)) == 0)
-                       continue;
-               sin = (struct sockaddr_in *)ALLIGN(&ifrp->ifr_addr);
-               interfaces[i].localaddr = sin->sin_addr;
-               interfaces[i].flags = ifreq.ifr_flags;
-               interfaces[i].netmask.s_addr = (unsigned long)0xffffffff;
-               if (ifreq.ifr_flags & IFF_POINTOPOINT) {
-                       if (ioctl(sock, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
-                               logperror("initifs: ioctl (get destination addr)");
-                               continue;
-                       }
-                       sin = (struct sockaddr_in *)ALLIGN(&ifreq.ifr_addr);
-                       /* A pt-pt link is identified by the remote address */
-                       interfaces[i].address = sin->sin_addr;
-                       interfaces[i].remoteaddr = sin->sin_addr;
-                       /* Simulate broadcast for pt-pt */
-                       interfaces[i].bcastaddr = sin->sin_addr;
-                       interfaces[i].flags |= IFF_BROADCAST;
-               } else {
-                       /* Non pt-pt links are identified by the local address */
-                       interfaces[i].address = interfaces[i].localaddr;
-                       interfaces[i].remoteaddr = interfaces[i].address;
-                       if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
-                               logperror("initifs: ioctl (get netmask)");
-                               continue;
-                       }
-                       sin = (struct sockaddr_in *)ALLIGN(&ifreq.ifr_addr);
-                       interfaces[i].netmask = sin->sin_addr;
-                       if (ifreq.ifr_flags & IFF_BROADCAST) {
-                               if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
-                                       logperror("initifs: ioctl (get broadcast address)");
-                                       continue;
-                               }
-                               sin = (struct sockaddr_in *)ALLIGN(&ifreq.ifr_addr);
-                               interfaces[i].bcastaddr = sin->sin_addr;
-                       }
-               }
-#ifdef notdef
-               if (debug)
-                       logdebug("Found interface %s, flags 0x%x\n",
-                                pr_name(interfaces[i].localaddr),
-                                interfaces[i].flags);
-#endif
-               i++;
-       }
-       num_interfaces = i;
-#ifdef notdef
-       if (debug)
-               logdebug("Found %d interfaces\n", num_interfaces);
-#endif
-       (void) close(sock);
-       (void) free(buf);
-}
-
-int
-join(sock, sin)
-       int sock;
-       struct sockaddr_in *sin;
-{
-       int i;
-       struct ip_mreq mreq;
-
-       if (isbroadcast(sin))
-               return (0);
-
-       mreq.imr_multiaddr = sin->sin_addr;
-       for (i = 0; i < num_interfaces; i++) {
-               mreq.imr_interface = interfaces[i].address;
-
-               if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-                              (char *)&mreq, sizeof(mreq)) < 0) {
-                       logperror("setsockopt (IP_ADD_MEMBERSHIP)");
-                       return (-1);
-               }
-       }
-       return (0);
-}
-
-int support_multicast()
-{
-       int sock;
-       u_char ttl = 1;
-
-       sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-       if (sock < 0) {
-               logperror("support_multicast: socket");
-               return (0);
-       }
-
-       if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
-                      (char *)&ttl, sizeof(ttl)) < 0) {
-               (void) close(sock);
-               return (0);
-       }
-       (void) close(sock);
-       return (1);
-}
-
-int
-is_directly_connected(in)
-       struct in_addr in;
-{
-       int i;
-
-       for (i = 0; i < num_interfaces; i++) {
-               /* Check that the subnetwork numbers match */
-
-               if ((in.s_addr & interfaces[i].netmask.s_addr ) ==
-                   (interfaces[i].remoteaddr.s_addr & interfaces[i].netmask.s_addr))
-                       return (1);
-       }
-       return (0);
-}
-
-
-/*
- * TABLES
- */
-struct table {
-       struct in_addr  router;
-       int             preference;
-       int             remaining_time;
-       int             in_kernel;
-       struct table    *next;
-};
-
-struct table *table;
-
-struct table *
-find_router(addr)
-       struct in_addr addr;
-{
-       struct table *tp;
-
-       tp = table;
-       while (tp) {
-               if (tp->router.s_addr == addr.s_addr)
-                       return (tp);
-               tp = tp->next;
-       }
-       return (NULL);
-}
-
-int max_preference()
-{
-       struct table *tp;
-       int max = (int)IGNORE_PREFERENCE;
-
-       tp = table;
-       while (tp) {
-               if (tp->preference > max)
-                       max = tp->preference;
-               tp = tp->next;
-       }
-       return (max);
-}
-
-
-/* Note: this might leave the kernel with no default route for a short time. */
-void
-age_table(time)
-       int time;
-{
-       struct table **tpp, *tp;
-       int recalculate_max = 0;
-       int max = max_preference();
-
-       tpp = &table;
-       while (*tpp != NULL) {
-               tp = *tpp;
-               tp->remaining_time -= time;
-               if (tp->remaining_time <= 0) {
-                       *tpp = tp->next;
-                       if (tp->in_kernel)
-                               del_route(tp->router);
-                       if (best_preference &&
-                           tp->preference == max)
-                               recalculate_max++;
-                       free((char *)tp);
-               } else {
-                       tpp = &tp->next;
-               }
-       }
-       if (recalculate_max) {
-               int max = max_preference();
-
-               if (max != IGNORE_PREFERENCE) {
-                       tp = table;
-                       while (tp) {
-                               if (tp->preference == max && !tp->in_kernel) {
-                                       add_route(tp->router);
-                                       tp->in_kernel++;
-                               }
-                               tp = tp->next;
-                       }
-               }
-       }
-}
-
-void
-record_router(router, preference, ttl)
-       struct in_addr  router;
-       long            preference;
-       int             ttl;
-{
-       struct table *tp;
-       int old_max = max_preference();
-       int changed_up = 0;     /* max preference could have increased */
-       int changed_down = 0;   /* max preference could have decreased */
-
-       if (debug)
-               logdebug("Recording %s, preference 0x%x\n",
-                             pr_name(router),
-                             preference);
-       tp = find_router(router);
-       if (tp) {
-               if (tp->preference > preference &&
-                   tp->preference == old_max)
-                       changed_down++;
-               else if (preference > tp->preference)
-                       changed_up++;
-               tp->preference = preference;
-               tp->remaining_time = ttl;
-       } else {
-               if (preference > old_max)
-                       changed_up++;
-               tp = (struct table *)ALLIGN(malloc(sizeof(struct table)));
-               if (tp == NULL) {
-                       logerr("Out of memory\n");
-                       return;
-               }
-               tp->router = router;
-               tp->preference = preference;
-               tp->remaining_time = ttl;
-               tp->in_kernel = 0;
-               tp->next = table;
-               table = tp;
-       }
-       if (!tp->in_kernel &&
-           (!best_preference || tp->preference == max_preference()) &&
-           tp->preference != IGNORE_PREFERENCE) {
-               add_route(tp->router);
-               tp->in_kernel++;
-       }
-       if (tp->preference == IGNORE_PREFERENCE && tp->in_kernel) {
-               del_route(tp->router);
-               tp->in_kernel = 0;
-       }
-       if (best_preference && changed_down) {
-               /* Check if we should add routes */
-               int new_max = max_preference();
-               if (new_max != IGNORE_PREFERENCE) {
-                       tp = table;
-                       while (tp) {
-                               if (tp->preference == new_max &&
-                                   !tp->in_kernel) {
-                                       add_route(tp->router);
-                                       tp->in_kernel++;
-                               }
-                               tp = tp->next;
-                       }
-               }
-       }
-       if (best_preference && (changed_up || changed_down)) {
-               /* Check if we should remove routes already in the kernel */
-               int new_max = max_preference();
-               tp = table;
-               while (tp) {
-                       if (tp->preference < new_max && tp->in_kernel) {
-                               del_route(tp->router);
-                               tp->in_kernel = 0;
-                       }
-                       tp = tp->next;
-               }
-       }
-}
-
-
-#include <net/route.h>
-
-void
-add_route(addr)
-       struct in_addr addr;
-{
-       if (debug)
-               logdebug("Add default route to %s\n", pr_name(addr));
-       rtioctl(addr, RTM_ADD);
-}
-
-void
-del_route(addr)
-       struct in_addr addr;
-{
-       if (debug)
-               logdebug("Delete default route to %s\n", pr_name(addr));
-       rtioctl(addr, RTM_DELETE);
-}
-
-void
-rtioctl(addr, op)
-       struct in_addr addr;
-       int     op;
-{
-       int sock;
-       struct {
-               struct rt_msghdr m_rtm;
-               struct sockaddr_in m_dst;
-               struct sockaddr_in m_gateway;
-               struct sockaddr_in m_netmask;
-       } m_rtmsg;
-       static int seq = 0;
-
-       bzero(&m_rtmsg, sizeof(m_rtmsg));
-
-       m_rtmsg.m_rtm.rtm_type = op;
-       m_rtmsg.m_rtm.rtm_flags = RTF_GATEWAY | RTF_UP;         /* XXX more? */
-       m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
-       m_rtmsg.m_rtm.rtm_seq = ++seq;
-       m_rtmsg.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
-
-       /* initialise route metrics to zero.. tcp may fill these in */
-       bzero(&m_rtmsg.m_rtm.rtm_rmx, sizeof(m_rtmsg.m_rtm.rtm_rmx));
-
-       m_rtmsg.m_rtm.rtm_inits = 0;
-       m_rtmsg.m_rtm.rtm_msglen = sizeof(m_rtmsg);
-
-       m_rtmsg.m_dst.sin_len = sizeof(struct sockaddr_in);
-       m_rtmsg.m_dst.sin_family = AF_INET;
-       m_rtmsg.m_dst.sin_addr.s_addr = 0;              /* default */
-
-       /* XXX: is setting a zero length right? */
-       m_rtmsg.m_netmask.sin_len = 0;
-       m_rtmsg.m_netmask.sin_family = AF_INET;
-       m_rtmsg.m_netmask.sin_addr.s_addr = 0;          /* default */
-
-       m_rtmsg.m_gateway.sin_len = sizeof(struct sockaddr_in);
-       m_rtmsg.m_gateway.sin_family = AF_INET;
-       m_rtmsg.m_gateway.sin_addr = addr;              /* gateway */
-
-       sock = socket(PF_ROUTE, SOCK_RAW, 0);
-       if (sock < 0) {
-               logperror("rtioctl: socket");
-               return;
-       }
-       if (write(sock, &m_rtmsg, sizeof(m_rtmsg)) != sizeof(m_rtmsg)) {
-               if (!(op == RTM_ADD && errno == EEXIST))
-                       logperror("rtioctl: write");
-       }
-       close(sock);
-}
-
-
-
-/*
- * LOGGER
- */
-
-
-static int logging = 0;
-
-void
-initlog()
-{
-       logging++;
-       openlog("rdisc", LOG_PID | LOG_CONS, LOG_DAEMON);
-}
-
-/* VARARGS1 */
-void
-#if __STDC__
-logerr(char *fmt, ...)
-#else
-logerr(fmt, va_alist)
-       char *fmt;
-       va_dcl
-#endif
-{
-       va_list ap;
-
-#if __STDC__
-       va_start(ap, fmt);
-#else
-       va_start(ap);
-#endif
-
-       if (logging)
-               vsyslog(LOG_ERR, fmt, ap);
-       else
-               (void) vfprintf(stderr, fmt, ap);
-
-       va_end(ap);
-}
-
-/* VARARGS1 */
-void
-#if __STDC__
-logtrace(char *fmt, ...)
-#else
-logtrace(fmt, va_alist)
-       char *fmt;
-       va_dcl
-#endif
-{
-       va_list ap;
-
-#if __STDC__
-       va_start(ap, fmt);
-#else
-       va_start(ap);
-#endif
-
-       if (logging)
-               vsyslog(LOG_INFO, fmt, ap);
-       else
-               (void) vfprintf(stdout, fmt, ap);
-
-       va_end(ap);
-}
-
-/* VARARGS1 */
-void
-#if __STDC__
-logdebug(char *fmt, ...)
-#else
-logdebug(fmt, va_alist)
-       char *fmt;
-       va_dcl
-#endif
-{
-       va_list ap;
-
-#if __STDC__
-       va_start(ap, fmt);
-#else
-       va_start(ap);
-#endif
-
-       if (logging)
-               vsyslog(LOG_DEBUG, fmt, ap);
-       else
-               (void) vfprintf(stdout, fmt, ap);
-
-       va_end(ap);
-}
-
-void
-logperror(str)
-       char *str;
-{
-       if (logging)
-               syslog(LOG_ERR, "%s: %m", str);
-       else
-               (void) warn("%s", str);
-}