From: deraadt Date: Wed, 18 Sep 1996 08:03:30 +0000 (+0000) Subject: new routed replaces rdisc X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=1e886c532e5c189137c1da0c3a03c223fcc26324;p=openbsd new routed replaces rdisc --- diff --git a/sbin/Makefile b/sbin/Makefile index be20236388e..877b4dde0ec 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -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 index 9ee24d378ae..00000000000 --- a/sbin/rdisc/Makefile +++ /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 diff --git a/sbin/rdisc/rdisc.8 b/sbin/rdisc/rdisc.8 deleted file mode 100644 index 15a128516b7..00000000000 --- a/sbin/rdisc/rdisc.8 +++ /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 index ede60d3b63b..00000000000 --- a/sbin/rdisc/rdisc.c +++ /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 -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#if __STDC__ -#include -#else -#include -#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 ] [-T ] \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 - -#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 - -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); -}