diff options
author | Achim Gottinger <achim@gentoo.org> | 2000-11-15 16:33:16 +0000 |
---|---|---|
committer | Achim Gottinger <achim@gentoo.org> | 2000-11-15 16:33:16 +0000 |
commit | 8ecb7c9f438630fe381a3d1c722b336d59a9008c (patch) | |
tree | ecbe8288228ba17f728346d0bd9e997d1baf0af0 /net-misc/netkit-timed | |
parent | new pgk (diff) | |
download | gentoo-2-8ecb7c9f438630fe381a3d1c722b336d59a9008c.tar.gz gentoo-2-8ecb7c9f438630fe381a3d1c722b336d59a9008c.tar.bz2 gentoo-2-8ecb7c9f438630fe381a3d1c722b336d59a9008c.zip |
*** empty log message ***
Diffstat (limited to 'net-misc/netkit-timed')
-rw-r--r-- | net-misc/netkit-timed/files/digest-netkit-timed-0.17-r2 | 1 | ||||
-rw-r--r-- | net-misc/netkit-timed/files/timed.c | 984 |
2 files changed, 985 insertions, 0 deletions
diff --git a/net-misc/netkit-timed/files/digest-netkit-timed-0.17-r2 b/net-misc/netkit-timed/files/digest-netkit-timed-0.17-r2 new file mode 100644 index 000000000000..3d9b4090a062 --- /dev/null +++ b/net-misc/netkit-timed/files/digest-netkit-timed-0.17-r2 @@ -0,0 +1 @@ +MD5 1bffb4db753d9e5be227e444cf119bfe netkit-timed-0.17.tar.gz diff --git a/net-misc/netkit-timed/files/timed.c b/net-misc/netkit-timed/files/timed.c new file mode 100644 index 000000000000..b09e879838cc --- /dev/null +++ b/net-misc/netkit-timed/files/timed.c @@ -0,0 +1,984 @@ +/*- + * Copyright (c) 1985, 1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +char copyright[] = + "@(#) Copyright (c) 1985, 1993 The Regents of the University of California.\n" + "All rights reserved.\n"; + +/* + * From: @(#)timed.c 5.1 (Berkeley) 5/11/93 + */ +char timed_rcsid[] = + "$Id: timed.c,v 1.1 2000/11/15 16:33:16 achim Exp $"; + +#ifdef sgi +#ident "$Revision: 1.1 $" +#endif /* sgi */ + +#define TSPTYPES +#include "globals.h" +#include <net/if.h> + +#if 0 + #include <sys/file.h> + #include <sys/types.h> +#endif + +#include <sys/ioctl.h> +#include <setjmp.h> +#include <math.h> +#include <sys/times.h> +#ifdef sgi +#include <unistd.h> +#include <sys/syssgi.h> +#include <sys/schedctl.h> +#endif /* sgi */ + +#include "../../version.h" + +#ifdef __linux__ +/* from libbsd.a */ +int daemon(int, int); +#endif + + +int trace = 0; +int sock, sock_raw = -1; +int status = 0; +u_short sequence; /* sequence number */ +long delay1; +long delay2; + +int nslavenets; /* nets were I could be a slave */ +int nmasternets; /* nets were I could be a master */ +int nignorednets; /* ignored nets */ +int nnets; /* nets I am connected to */ + +FILE *fd; /* trace file FD */ + +sigjmp_buf jmpenv; + +struct netinfo *nettab = 0; +struct netinfo *slavenet; +int Mflag; +int justquit = 0; +int debug; + +static struct nets { + char *name; + unsigned long net; + struct nets *next; +} *nets = 0; + +struct hosttbl hosttbl[NHOSTS+1]; /* known hosts */ + +static struct goodhost { /* hosts that we trust */ + char name[MAXHOSTNAMELEN+1]; + struct goodhost *next; + char perm; +} *goodhosts; + +static char *goodgroup; /* net group of trusted hosts */ +static void checkignorednets(void); +static void pickslavenet(struct netinfo *); +static void add_good_host(char*,char); + +#ifdef sgi +char *timetrim_fn; +char *timetrim_wpat = "long timetrim = %ld;\ndouble tot_adj = %.0f;\ndouble tot_ticks = %.0f;\n/* timed version 2 */\n"; +char *timetrim_rpat = "long timetrim = %ld;\ndouble tot_adj = %lf;\ndouble tot_ticks = %lf;"; +long timetrim; +double tot_adj, hr_adj; /* totals in nsec */ +double tot_ticks, hr_ticks; + +int bufspace = 60*1024; +#endif + + +/* + * The timedaemons synchronize the clocks of hosts in a local area network. + * One daemon runs as master, all the others as slaves. The master + * performs the task of computing clock differences and sends correction + * values to the slaves. + * Slaves start an election to choose a new master when the latter disappears + * because of a machine crash, network partition, or when killed. + * A resolution protocol is used to kill all but one of the masters + * that happen to exist in segments of a partitioned network when the + * network partition is fixed. + * + * Authors: Riccardo Gusella & Stefano Zatti + * + * overhauled at Silicon Graphics + */ +int +main(int argc, char **argv) +{ + int on; + int ret; + int nflag, iflag; + struct timeval ntime; + struct servent *srvp; + char buf[BUFSIZ], *cp, *cplim; + struct ifconf ifc; + struct ifreq ifreq, ifreqf, *ifr; + register struct netinfo *ntp; + struct netinfo *ntip; + struct netinfo *savefromnet; + struct netent *nentp; + struct nets *nt; + struct sockaddr_in server; + u_short port; + char c; +#ifdef sgi + FILE *timetrim_st; +#endif + +#define IN_MSG "timed: -i and -n make no sense together\n" +#ifdef sgi + struct tms tms; +#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp] [-P trimfile]\n" +#else +#ifdef HAVENIS +#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n" +#else +#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...]\n" +#endif /* HAVENIS */ +#endif /* sgi */ + + ntip = NULL; + + on = 1; + nflag = OFF; + iflag = OFF; + +#ifdef sgi + if (0 > syssgi(SGI_GETTIMETRIM, &timetrim)) { + perror("timed: syssgi(GETTIMETRIM)"); + timetrim = 0; + } + tot_ticks = hr_ticks = times(&tms); +#endif /* sgi */ + + opterr = 0; + while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != EOF) { + switch (c) { + case 'M': + Mflag = 1; + break; + + case 't': + trace = 1; + break; + + case 'n': + if (iflag) { + fprintf(stderr, IN_MSG); + exit(1); + } else { + nflag = ON; + addnetname(optarg); + } + break; + + case 'i': + if (nflag) { + fprintf(stderr, IN_MSG); + exit(1); + } else { + iflag = ON; + addnetname(optarg); + } + break; + + case 'F': + add_good_host(optarg,1); + while (optind < argc && argv[optind][0] != '-') + add_good_host(argv[optind++], 1); + break; + + case 'd': + debug = 1; + break; + case 'G': + if (goodgroup != 0) { + fprintf(stderr,"timed: only one net group\n"); + exit(1); + } + goodgroup = optarg; + break; +#ifdef sgi + case 'P': + timetrim_fn = optarg; + break; +#endif /* sgi */ + + default: + fprintf(stderr, USAGE); + exit(1); + break; + } + } + if (optind < argc) { + fprintf(stderr, USAGE); + exit(1); + } + +#ifdef sgi + if (timetrim_fn == 0) { + ; + } else if (0 == (timetrim_st = fopen(timetrim_fn, "r+"))) { + if (errno != ENOENT) { + (void)fprintf(stderr,"timed: "); + perror(timetrim_fn); + timetrim_fn = 0; + } + } else { + int i; + long trim; + double adj, ticks; + + i = fscanf(timetrim_st, timetrim_rpat, + &trim, &adj, &ticks); + if (i < 1 + || trim > MAX_TRIM + || trim < -MAX_TRIM + || i == 2 + || (i == 3 + && trim != rint(adj*CLK_TCK/ticks))) { + if (trace && i != EOF) + (void)fprintf(stderr, + "timed: unrecognized contents in %s\n", + timetrim_fn); + } else { + if (0 > syssgi(SGI_SETTIMETRIM, + trim)) { + perror("timed: syssgi(SETTIMETRIM)"); + } else { + timetrim = trim; + } + if (i == 3) + tot_ticks -= ticks; + } + (void)fclose(timetrim_st); + } +#endif /* sgi */ + + /* If we care about which machine is the master, then we must + * be willing to be a master + */ + if (0 != goodgroup || 0 != goodhosts) + Mflag = 1; + + if (gethostname(hostname, sizeof(hostname) - 1) < 0) { + perror("gethostname"); + exit(1); + } + self.l_bak = &self; + self.l_fwd = &self; + self.h_bak = &self; + self.h_fwd = &self; + self.head = 1; + self.good = 1; + + if (goodhosts != 0) /* trust ourself */ + add_good_host(hostname,1); + + srvp = getservbyname("timed", "udp"); + if (srvp == 0) { + fprintf(stderr, "unknown service 'timed/udp'\n"); + exit(1); + } + port = srvp->s_port; + memset(&server, 0, sizeof(server)); + server.sin_port = srvp->s_port; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror("socket"); + exit(1); + } + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, + sizeof(on)) < 0) { + perror("setsockopt"); + exit(1); + } + if (bind(sock, (struct sockaddr*)&server, sizeof(server))) { + if (errno == EADDRINUSE) + fprintf(stderr,"timed: time daemon already running\n"); + else + perror("bind"); + exit(1); + } +#ifdef sgi + /* + * handle many slaves with our buffer + */ + if (0 > setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace, + sizeof(bufspace))) { + perror("setsockopt"); + exit(1); + } +#endif /* sgi */ + + /* choose a unique seed for random number generation */ + (void)gettimeofday(&ntime, 0); + srandom(ntime.tv_sec + ntime.tv_usec); + + sequence = random(); /* initial seq number */ + +#ifndef sgi + /* rounds kernel variable time to multiple of 5 ms. */ + ntime.tv_sec = 0; + ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000; + (void)adjtime(&ntime, (struct timeval *)0); +#endif /* sgi */ + + for (nt = nets; nt; nt = nt->next) { + nentp = getnetbyname(nt->name); + if (nentp == 0) { + nt->net = inet_network(nt->name); + if (nt->net != INADDR_NONE) + nentp = getnetbyaddr(nt->net, AF_INET); + } + if (nentp != 0) { + nt->net = nentp->n_net; + } else if (nt->net == INADDR_NONE) { + fprintf(stderr, "timed: unknown net %s\n", nt->name); + exit(1); + } else if (nt->net == INADDR_ANY) { + fprintf(stderr, "timed: bad net %s\n", nt->name); + exit(1); + } else { + fprintf(stderr, + "timed: warning: %s unknown in /etc/networks\n", + nt->name); + } + + /* WTF? */ + /* + if (0 == (nt->net & 0xff000000)) + nt->net <<= 8; + if (0 == (nt->net & 0xff000000)) + nt->net <<= 8; + if (0 == (nt->net & 0xff000000)) + nt->net <<= 8; + */ + nt->net = htonl(nt->net); + + } + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { + perror("timed: get interface configuration"); + exit(1); + } + ntp = NULL; +#ifdef sgi +#define size(p) (sizeof(*ifr) - sizeof(ifr->ifr_name)) /* XXX hack. kludge */ +#else +#define size(p) max((p).sa_len, sizeof(p)) +#endif + cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ + +/* for (cp = buf; cp < cplim; + cp += sizeof (ifr->ifr_name) + sizeof(ifr->ifr_addr)) { */ + + for (cp = buf; cp < cplim; cp += sizeof(struct ifreq)) { + ifr = (struct ifreq *)cp; + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + if (!ntp) + ntp = (struct netinfo*)malloc(sizeof(struct netinfo)); + bzero(ntp,sizeof(*ntp)); + ntp->my_addr=((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; + ntp->status = NOMASTER; + ifreq = *ifr; + ifreqf = *ifr; + + if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreqf) < 0) { + perror("get interface flags"); + continue; + } + if ((ifreqf.ifr_flags & IFF_UP) == 0) + continue; + if ((ifreqf.ifr_flags & IFF_BROADCAST) == 0 && + (ifreqf.ifr_flags & IFF_POINTOPOINT) == 0) { + continue; + } + + + if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) { + perror("get netmask"); + continue; + } + ntp->mask = ((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr.s_addr; + + if (ifreqf.ifr_flags & IFF_BROADCAST) { + if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { + perror("get broadaddr"); + continue; + } + ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr; + /* What if the broadcast address is all ones? + * So we cannot just mask ntp->dest_addr. */ + ntp->net = ntp->my_addr; + ntp->net.s_addr &= ntp->mask; + } else { + if (ioctl(sock, SIOCGIFDSTADDR, + (char *)&ifreq) < 0) { + perror("get destaddr"); + continue; + } + ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr; + ntp->net = ntp->dest_addr.sin_addr; + } + + ntp->dest_addr.sin_port = port; + + for (nt = nets; nt; nt = nt->next) { + if (ntp->net.s_addr == nt->net) + break; + } + if ((nflag && !nt) || (iflag && nt)) + continue; + + ntp->next = NULL; + if (nettab == NULL) { + nettab = ntp; + } else { + ntip->next = ntp; + } + ntip = ntp; + ntp = NULL; + } + if (ntp) + (void) free((char *)ntp); + if (nettab == NULL) { + fprintf(stderr, "timed: no network usable\n"); + exit(1); + } + + +#ifdef sgi + (void)schedctl(RENICE,0,10); /* run fast to get good time */ + + /* ticks to delay before responding to a broadcast */ + delay1 = casual(0, CLK_TCK/10); +#else + + /* microseconds to delay before responding to a broadcast */ + delay1 = casual(1, 100*1000); +#endif /* sgi */ + + /* election timer delay in secs. */ + delay2 = casual(MINTOUT, MAXTOUT); + + +#ifdef sgi + (void)_daemonize(debug ? _DF_NOFORK|_DF_NOCHDIR : 0, sock, -1, -1); +#else + if (!debug) + daemon(debug, 0); +#endif /* sgi */ + + if (trace) + traceon(); + openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON); + + /* + * keep returning here + */ + ret = sigsetjmp(jmpenv, 1); + savefromnet = fromnet; + setstatus(); + + if (Mflag) { + switch (ret) { + + case 0: + checkignorednets(); + pickslavenet(0); + break; + case 1: + /* Just lost our master */ + if (slavenet != 0) + slavenet->status = election(slavenet); + if (!slavenet || slavenet->status == MASTER) { + checkignorednets(); + pickslavenet(0); + } else { + makeslave(slavenet); /* prune extras */ + } + break; + + case 2: + /* Just been told to quit */ + justquit = 1; + pickslavenet(savefromnet); + break; + } + + setstatus(); + if (!(status & MASTER) && sock_raw != -1) { + /* sock_raw is not being used now */ + (void)close(sock_raw); + sock_raw = -1; + } + + if (status == MASTER) + master(); + else + slave(); + + } else { + if (sock_raw != -1) { + (void)close(sock_raw); + sock_raw = -1; + } + + if (ret) { + /* we just lost our master or were told to quit */ + justquit = 1; + } + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == MASTER) + rmnetmachs(ntp); + ntp->status = NOMASTER; + } + checkignorednets(); + pickslavenet(0); + setstatus(); + + slave(); + } + /* NOTREACHED */ + return 0; +} + + +/* suppress an upstart, untrustworthy, self-appointed master + */ +void +suppress(struct sockaddr_in *addr, + char *name, + struct netinfo *net) +{ + struct sockaddr_in tgt; + char tname[MAXHOSTNAMELEN]; + struct tsp msg; + static struct timeval wait; + + if (trace) + fprintf(fd, "suppress: %s\n", name); + tgt = *addr; + (void)strcpy(tname, name); + + while (0 != readmsg(TSP_ANY, ANYADDR, &wait, net)) { + if (trace) + fprintf(fd, "suppress:\tdiscarded packet from %s\n", + name); + } + + syslog(LOG_NOTICE, "suppressing false master %s", tname); + msg.tsp_type = TSP_QUIT; + (void)strcpy(msg.tsp_name, hostname); + (void)acksend(&msg, &tgt, tname, TSP_ACK, 0, 1); +} + +void +lookformaster(struct netinfo *ntp) +{ + struct tsp resp, conflict, *answer; + struct timeval ntime; + char mastername[MAXHOSTNAMELEN]; + struct sockaddr_in masteraddr; + + get_goodgroup(0); + ntp->status = SLAVE; + + /* look for master */ + resp.tsp_type = TSP_MASTERREQ; + (void)strcpy(resp.tsp_name, hostname); + answer = acksend(&resp, &ntp->dest_addr, ANYADDR, + TSP_MASTERACK, ntp, 0); + if (answer != 0 && !good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + answer = 0; + } + if (answer == 0) { + /* + * Various conditions can cause conflict: races between + * two just started timedaemons when no master is + * present, or timedaemons started during an election. + * A conservative approach is taken. Give up and became a + * slave, postponing election of a master until first + * timer expires. + */ + ntime.tv_sec = ntime.tv_usec = 0; + answer = readmsg(TSP_MASTERREQ, ANYADDR, &ntime, ntp); + if (answer != 0) { + if (!good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + } + return; + } + + ntime.tv_sec = ntime.tv_usec = 0; + answer = readmsg(TSP_MASTERUP, ANYADDR, &ntime, ntp); + if (answer != 0) { + if (!good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + } + return; + } + + ntime.tv_sec = ntime.tv_usec = 0; + answer = readmsg(TSP_ELECTION, ANYADDR, &ntime, ntp); + if (answer != 0) { + if (!good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + } + return; + } + + if (Mflag) + ntp->status = MASTER; + else + ntp->status = NOMASTER; + return; + } + + ntp->status = SLAVE; + (void)strcpy(mastername, answer->tsp_name); + masteraddr = from; + + /* + * If network has been partitioned, there might be other + * masters; tell the one we have just acknowledged that + * it has to gain control over the others. + */ + ntime.tv_sec = 0; + ntime.tv_usec = 300000; + answer = readmsg(TSP_MASTERACK, ANYADDR, &ntime, ntp); + /* + * checking also not to send CONFLICT to ack'ed master + * due to duplicated MASTERACKs + */ + if (answer != NULL && + strcmp(answer->tsp_name, mastername) != 0) { + conflict.tsp_type = TSP_CONFLICT; + (void)strcpy(conflict.tsp_name, hostname); + if (!acksend(&conflict, &masteraddr, mastername, + TSP_ACK, 0, 0)) { + syslog(LOG_ERR, + "error on sending TSP_CONFLICT"); + } + } +} + +/* + * based on the current network configuration, set the status, and count + * networks; + */ +void setstatus(void) +{ + struct netinfo *ntp; + + status = 0; + nmasternets = nslavenets = nnets = nignorednets = 0; + if (trace) + fprintf(fd, "Net status:\n"); + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + switch ((int)ntp->status) { + case MASTER: + nmasternets++; + break; + case SLAVE: + nslavenets++; + break; + case NOMASTER: + case IGNORE: + nignorednets++; + break; + } + if (trace) { + fprintf(fd, "\t%-16s", inet_ntoa(ntp->net)); + switch ((int)ntp->status) { + case NOMASTER: + fprintf(fd, "NOMASTER\n"); + break; + case MASTER: + fprintf(fd, "MASTER\n"); + break; + case SLAVE: + fprintf(fd, "SLAVE\n"); + break; + case IGNORE: + fprintf(fd, "IGNORE\n"); + break; + default: + fprintf(fd, "invalid state %d\n", + (int)ntp->status); + break; + } + } + nnets++; + status |= ntp->status; + } + status &= ~IGNORE; + if (trace) + fprintf(fd, + "\tnets=%d masters=%d slaves=%d ignored=%d delay2=%ld\n", + nnets, nmasternets, nslavenets, nignorednets, delay2); +} + +void +makeslave(struct netinfo *net) +{ + register struct netinfo *ntp; + + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == SLAVE && ntp != net) + ntp->status = IGNORE; + } + slavenet = net; +} + +/* + * Try to become master over ignored nets.. + */ +static void +checkignorednets(void) +{ + register struct netinfo *ntp; + + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (!Mflag && ntp->status == SLAVE) + break; + + if (ntp->status == IGNORE || ntp->status == NOMASTER) { + lookformaster(ntp); + if (!Mflag && ntp->status == SLAVE) + break; + } + } +} + +/* + * choose a good network on which to be a slave + * The ignored networks must have already been checked. + * Take a hint about for a good network. + */ +static void +pickslavenet(struct netinfo *ntp) +{ + if (slavenet != 0 && slavenet->status == SLAVE) { + makeslave(slavenet); /* prune extras */ + return; + } + + if (ntp == 0 || ntp->status != SLAVE) { + for (ntp = nettab; ntp != 0; ntp = ntp->next) { + if (ntp->status == SLAVE) + break; + } + } + makeslave(ntp); +} + +/* + * returns a random number in the range [inf, sup] + */ +long +casual(long inf, long sup) +{ + double value; + + value = ((double)(random() & 0x7fffffff)) / (0x7fffffff*1.0); + return(inf + (sup - inf)*value); +} + +char *date(void) +{ +#ifdef sgi + struct timeval tv; + static char tm[32]; + + (void)gettimeofday(&tv, (struct timezone *)0); + (void)cftime(tm, "%D %T", &tv.tv_sec); + return (tm); +#else +/* struct timeval tv; */ + time_t tm; + time(&tm); + return (ctime(&tm)); +#endif /* sgi */ +} + +void +addnetname(char *name) +{ + register struct nets **netlist = &nets; + + while (*netlist) + netlist = &((*netlist)->next); + *netlist = (struct nets *)malloc(sizeof **netlist); + if (*netlist == 0) { + fprintf(stderr,"malloc failed\n"); + exit(1); + } + bzero((char *)*netlist, sizeof(**netlist)); + (*netlist)->name = name; +} + +/* note a host as trustworthy */ +static void +add_good_host(char* name, + char perm) /* 1=not part of the netgroup */ +{ + register struct goodhost *ghp; + register struct hostent *hentp; + + ghp = (struct goodhost*)malloc(sizeof(*ghp)); + if (!ghp) { + syslog(LOG_ERR, "malloc failed"); + exit(1); + } + + bzero((char*)ghp, sizeof(*ghp)); + (void)strncpy(&ghp->name[0], name, sizeof(ghp->name)); + ghp->next = goodhosts; + ghp->perm = perm; + goodhosts = ghp; + + hentp = gethostbyname(name); + if (0 == hentp && perm) + (void)fprintf(stderr, "unknown host %s\n", name); +} + + +/* update our image of the net-group of trustworthy hosts + */ +void +get_goodgroup(int force) +{ +# define NG_DELAY (30*60*CLK_TCK) /* 30 minutes */ + const unsigned long last_update = -NG_DELAY; + unsigned long new_update; +/* struct hosttbl *htp; */ + struct goodhost *ghp, **ghpp; +/* char *mach, *usr, *dom; */ + struct tms tm; + + + /* if no netgroup, then we are finished */ + if (goodgroup == 0 || !Mflag) + return; + + /* Do not chatter with the netgroup master too often. + */ + new_update = times(&tm); + if (new_update < last_update + NG_DELAY + && !force) + return; + last_update = new_update; + + /* forget the old temporary entries */ + ghpp = &goodhosts; + while (0 != (ghp = *ghpp)) { + if (!ghp->perm) { + *ghpp = ghp->next; + free((char*)ghp); + } else { + ghpp = &ghp->next; + } + } + +#ifdef HAVENIS + /* quit now if we are not one of the trusted masters + */ + if (!innetgr(goodgroup, &hostname[0], 0,0)) { + if (trace) + (void)fprintf(fd, "get_goodgroup: %s not in %s\n", + &hostname[0], goodgroup); + return; + } + if (trace) + (void)fprintf(fd, "get_goodgroup: %s in %s\n", + &hostname[0], goodgroup); + + /* mark the entire netgroup as trusted */ + (void)setnetgrent(goodgroup); + while (getnetgrent(&mach,&usr,&dom)) { + if (0 != mach) + add_good_host(mach,0); + } + (void)endnetgrent(); + + /* update list of slaves */ + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + htp->good = good_host_name(&htp->name[0]); + } +#endif /* HAVENIS */ +} + +/* see if a machine is trustworthy + * 1=trust hp to change our date + */ + +int good_host_name(char *name) +{ + register struct goodhost *ghp = goodhosts; + register char c; + + if (!ghp || !Mflag) /* trust everyone if no one named */ + return 1; + + c = *name; + do { + if (c == ghp->name[0] + && !strcasecmp(name, ghp->name)) + return 1; /* found him, so say so */ + } while (0 != (ghp = ghp->next)); + + if (!strcasecmp(name,hostname)) /* trust ourself */ + return 1; + + return 0; /* did not find him */ +} |