Index: stable/12/usr.sbin/timed/timed/timed.8 =================================================================== --- stable/12/usr.sbin/timed/timed/timed.8 (revision 343939) +++ stable/12/usr.sbin/timed/timed/timed.8 (revision 343940) @@ -1,288 +1,294 @@ .\" Copyright (c) 1980, 1991, 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. 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. .\" .\" @(#)timed.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" .Dd February 11, 2008 .Dt TIMED 8 .Os .Sh NAME .Nm timed .Nd time server daemon .Sh SYNOPSIS .Nm .Op Fl dtM .Op Fl i Ar network | Fl n Ar network .Op Fl F Ar host ... .Sh DESCRIPTION The .Nm utility is a time server daemon which is normally invoked at boot time from the .Xr rc.conf 5 file. It synchronizes the host's time with the time of other machines, which are also running .Nm , in a local area network. These time servers will slow down the clocks of some machines and speed up the clocks of others to bring them to the average network time. The average network time is computed from measurements of clock differences using the .Tn ICMP timestamp request message. .Pp The following options are available: .Bl -tag -width indent .It Fl d Enable debugging mode; do not detach from the terminal. .It Fl i Ar network Add .Ar network to the list of networks to ignore. All other networks to which the machine is directly connected are used by .Nm . This option may be specified multiple times to add more than one network to the list. .It Fl F Ar host ... .Bl -dash -compact .It Create a list of trusted hosts. .It Can take one or more parameters. .It .Nm will only accept trusted hosts as masters. If it finds an untrusted host claiming to be master, .Nm will suppress incoming messages from that host and call for a new election. .It Use real host names (resolvable by RDNS) not aliases (eg in .Xr named 8 parlance: use A names, not C names). .It Use full names eg time1.domain.com not time1. .It .Fl F automatically includes the functionality of .Fl M (so .Fl M does not need to asserted). .It If .Fl F is not specified, all hosts on connected networks are treated as trustworthy. .El .It Fl M Allow this host to become a .Nm master if necessary. .It Fl n Ar network Add .Ar network to the list of allowed networks. All other networks to which the machine is directly connected are ignored by .Nm . This option may be specified multiple times to add more than one network to the list. .It Fl t Enable tracing of received messages and log to the file .Pa /var/log/timed.log . Tracing can be turned on or off while .Nm is running with the .Xr timedc 8 utility. .El .Pp The .Fl n and .Fl i flags are mutually exclusive and require as arguments real networks to which the host is connected (see .Xr networks 5 ) . If neither flag is specified, .Nm will listen on all connected networks. .Pp A .Nm running without the .Fl M nor .Fl F flags will always remain a slave. If the .Fl F flag is not used, .Nm will treat all machines as trustworthy. .Pp The .Nm utility is based on a master-slave scheme. When .Nm is started on a machine, it asks the master for the network time and sets the host's clock to that time. After that, it accepts synchronization messages periodically sent by the master and calls .Xr adjtime 2 to perform the needed corrections on the host's clock. .Pp It also communicates with .Xr date 1 in order to set the date globally, and with .Xr timedc 8 , a .Nm control utility. If the machine running the master becomes unreachable, the slaves will elect a new master from among those slaves which are running with at least one of the .Fl M and .Fl F flags. .Pp At startup .Nm normally checks for a master time server on each network to which it is connected, except as modified by the .Fl n and .Fl i options described above. It will request synchronization service from the first master server located. If permitted by the .Fl M or .Fl F flags, it will provide synchronization service on any attached networks on which no trusted master server was detected. Such a server propagates the time computed by the top-level master. The .Nm utility will periodically check for the presence of a master on those networks for which it is operating as a slave. If it finds that there are no trusted masters on a network, it will begin the election process on that network. .Pp One way to synchronize a group of machines is to use .Xr ntpd 8 to synchronize the clock of one machine to a distant standard or a radio receiver and .Fl F Ar hostname to tell its .Nm to trust only itself. .Pp Messages printed by the kernel on the system console occur with interrupts disabled. This means that the clock stops while they are printing. A machine with many disk or network hardware problems and consequent messages cannot keep good time by itself. Each message typically causes the clock to lose a dozen milliseconds. A time daemon can correct the result. .Pp Messages in the system log about machines that failed to respond usually indicate machines that crashed or were turned off. Complaints about machines that failed to respond to initial time settings are often associated with .Dq multi-homed machines that looked for time masters on more than one network and eventually chose to become a slave on the other network. .Sh WARNINGS Temporal chaos will result if two or more time daemons attempt to adjust the same clock. If both .Nm and another time daemon are run on the same machine, ensure that the .Fl F flag is used, so that .Nm never attempts to adjust the local clock. .Pp The protocol is based on .Tn UDP/IP broadcasts. All machines within the range of a broadcast that are using the .Tn TSP protocol must cooperate. There cannot be more than a single administrative domain using the .Fl F flag among all machines reached by a broadcast packet. Failure to follow this rule is usually indicated by complaints concerning .Dq untrusted machines in the system log. .Sh FILES .Bl -tag -width /var/log/timed.masterlog -compact .It Pa /var/log/timed.log tracing file for .Nm .It Pa /var/log/timed.masterlog log file for master .Nm .El .Sh SEE ALSO .Xr date 1 , .Xr adjtime 2 , .Xr gettimeofday 2 , .Xr icmp 4 , .Xr networks 5 , .Xr ntpd 8 , .Xr timedc 8 .Rs .%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD" .%A R. Gusella .%A S. Zatti .Re .Sh HISTORY The .Nm utility appeared in .Bx 4.3 . +.Pp +The latest +.Nm +code has been made available as a port (net/timed) in preparation of removal +from base in +.Fx 13.0 . Index: stable/12/usr.sbin/timed/timed/timed.c =================================================================== --- stable/12/usr.sbin/timed/timed/timed.c (revision 343939) +++ stable/12/usr.sbin/timed/timed/timed.c (revision 343940) @@ -1,832 +1,835 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * 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. 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1985, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)timed.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include "globals.h" #include #include #include #include #include "pathnames.h" #include #include #include 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 */ jmp_buf jmpenv; struct netinfo *nettab = NULL; struct netinfo *slavenet; int Mflag; int justquit = 0; int debug; static struct nets { char *name; long net; struct nets *next; } *nets = NULL; struct hosttbl hosttbl[NHOSTS+1]; /* known hosts */ static struct goodhost { /* hosts that we trust */ char name[MAXHOSTNAMELEN]; 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 *, int); static void usage(void); /* * 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; int c; #ifdef lint ntip = NULL; #endif on = 1; nflag = OFF; iflag = OFF; opterr = 0; while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != -1) { switch (c) { case 'M': Mflag = 1; break; case 't': trace = 1; break; case 'n': if (iflag) { errx(1, "-i and -n make no sense together"); } else { nflag = ON; addnetname(optarg); } break; case 'i': if (nflag) { errx(1, "-i and -n make no sense together"); } 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 != NULL) errx(1, "only one net group"); goodgroup = optarg; break; default: usage(); break; } } if (optind < argc) usage(); + fprintf(stderr, "TIMED will be removed from FreeBSD-13, and will be " + "provided as a port (net/timed) or package (timed).\n"); + /* If we care about which machine is the master, then we must * be willing to be a master */ if (goodgroup != NULL || goodhosts != NULL) Mflag = 1; if (gethostname(hostname, sizeof(hostname) - 1) < 0) err(1, "gethostname"); self.l_bak = &self; self.l_fwd = &self; self.h_bak = &self; self.h_fwd = &self; self.head = 1; self.good = 1; if (goodhosts != NULL) /* trust ourself */ add_good_host(hostname,1); srvp = getservbyname("timed", "udp"); if (srvp == NULL) errx(1, "timed/udp: unknown service"); port = srvp->s_port; bzero(&server, sizeof(struct sockaddr_in)); server.sin_port = srvp->s_port; server.sin_family = AF_INET; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) err(1, "socket"); if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) err(1, "setsockopt"); if (bind(sock, (struct sockaddr*)&server, sizeof(server))) { if (errno == EADDRINUSE) warnx("time daemon already running"); else warn("bind"); exit(1); } sequence = arc4random(); /* initial seq number */ (void)gettimeofday(&ntime, NULL); /* 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); for (nt = nets; nt; nt = nt->next) { nentp = getnetbyname(nt->name); if (nentp == NULL) { nt->net = inet_network(nt->name); if (nt->net != INADDR_NONE) nentp = getnetbyaddr(nt->net, AF_INET); } if (nentp != NULL) { nt->net = nentp->n_net; } else if (nt->net == INADDR_NONE) { errx(1, "unknown net %s", nt->name); } else if (nt->net == INADDR_ANY) { errx(1, "bad net %s", nt->name); } else { warnx("warning: %s unknown in /etc/networks", nt->name); } if (0 == (nt->net & 0xff000000)) nt->net <<= 8; if (0 == (nt->net & 0xff000000)) nt->net <<= 8; if (0 == (nt->net & 0xff000000)) nt->net <<= 8; } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) err(1, "get interface configuration"); ntp = NULL; #define size(p) max((p).sa_len, sizeof(p)) cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { 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) { warn("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) { warn("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) { warn("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) { warn("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 == htonl(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) errx(1, "no network usable"); /* microseconds to delay before responding to a broadcast */ delay1 = casual(1, 100*1000); /* election timer delay in secs. */ delay2 = casual(MINTOUT, MAXTOUT); if (!debug) daemon(debug, 0); if (trace) traceon(); openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON); /* * keep returning here */ ret = setjmp(jmpenv); savefromnet = fromnet; setstatus(); if (Mflag) { switch (ret) { case 0: checkignorednets(); pickslavenet(0); break; case 1: /* Just lost our master */ if (slavenet != NULL) 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); } static void usage(void) { #ifdef HAVENIS fprintf(stderr, "usage: timed [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n"); #else fprintf(stderr, "usage: timed [-dtM] [-i net|-n net] [-F host1 host2 ...]\n"); #endif /* HAVENIS */ exit(1); } /* * 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)strlcpy(tname, name, sizeof(tname)); 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 != NULL && !good_host_name(answer->tsp_name)) { suppress(&from, answer->tsp_name, ntp); ntp->status = NOMASTER; answer = NULL; } if (answer == NULL) { /* * 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 != NULL) { 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 != NULL) { 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 != NULL) { 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 != NULL && slavenet->status == SLAVE) { makeslave(slavenet); /* prune extras */ return; } if (ntp == NULL || ntp->status != SLAVE) { for (ntp = nettab; ntp != NULL; 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) { time_t tv_sec; tv_sec = time(NULL); return (ctime(&tv_sec)); } void addnetname(char *name) { register struct nets **netlist = &nets; while (*netlist) netlist = &((*netlist)->next); *netlist = (struct nets *)malloc(sizeof **netlist); if (*netlist == NULL) errx(1, "malloc failed"); bzero((char *)*netlist, sizeof(**netlist)); (*netlist)->name = name; } /* note a host as trustworthy * perm 1=not part of the netgroup */ static void add_good_host(char *name, int perm) { 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 (hentp == NULL && perm) warnx("unknown host %s", 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 */ static unsigned long last_update = -NG_DELAY; unsigned long new_update; struct goodhost *ghp, **ghpp; #ifdef HAVENIS struct hosttbl *htp; char *mach, *usr, *dom; #endif /* HAVENIS */ struct tms tm; /* if no netgroup, then we are finished */ if (goodgroup == NULL || !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 ((ghp = *ghpp) != NULL) { if (!ghp->perm) { *ghpp = ghp->next; free(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 (mach != NULL) 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 */ int /* 1=trust hp to change our date */ 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 ((ghp = ghp->next) != NULL); if (!strcasecmp(name,hostname)) /* trust ourself */ return 1; return 0; /* did not find him */ } Index: stable/12/usr.sbin/timed/timedc/timedc.8 =================================================================== --- stable/12/usr.sbin/timed/timedc/timedc.8 (revision 343939) +++ stable/12/usr.sbin/timed/timedc/timedc.8 (revision 343940) @@ -1,141 +1,147 @@ .\" Copyright (c) 1980, 1991, 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. 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. .\" .\" @(#)timedc.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" .Dd June 6, 1993 .Dt TIMEDC 8 .Os .Sh NAME .Nm timedc .Nd timed control program .Sh SYNOPSIS .Nm .Op Ar command Op Ar argument ... .Sh DESCRIPTION The .Nm utility is used to control the operation of the .Xr timed 8 program. It may be used to: .Bl -bullet .It Measure the differences between machines' clocks, .It Find the location where the master time server is running, .It Enable or disable tracing of messages received by .Xr timed 8 , and .It Perform various debugging actions. .El .Pp Without any arguments, .Nm will prompt for commands from the standard input. If arguments are supplied, .Nm interprets the first argument as a command and the remaining arguments as parameters to the command. The standard input may be redirected causing .Nm to read commands from a file. Commands may be abbreviated; recognized commands are: .Pp .Bl -tag -width Ds -compact .It Ic \&? Op Ar command ... .Pp .It Ic help Op Ar command ... Print a short description of each command specified in the argument list, or, if no arguments are given, a list of the recognized commands. .Pp .It Ic clockdiff Ar host ... Compute the differences between the clock of the host machine and the clocks of the machines given as arguments. .Pp .It Ic msite Op Ar host ... Show the master time server for specified host(s). .Pp .It Xo .Ic trace .Li \&{ Ar on Li \&| .Ar off \&} .Xc Enable or disable the tracing of incoming messages to .Xr timed 8 in the file .Pa /var/log/timed.log . .Pp .It Ic election Ar host1 Op Ar host2 ... Asks the daemon on the target host to reset its "election" timers and to ensure that a time master has been elected. .Pp .It Ic quit Exit from timedc. .El .Pp Other commands may be included for use in testing and debugging .Xr timed 8 ; the help command and the program source may be consulted for details. .Sh FILES .Bl -tag -width /var/log/timed.masterlog -compact .It Pa /var/log/timed.log tracing file for timed .It Pa /var/log/timed.masterlog log file for master timed .El .Sh DIAGNOSTICS .Bl -diag .It ?Ambiguous command abbreviation matches more than one command .It ?Invalid command no match found .It ?Privileged command command can be executed by root only .El .Sh SEE ALSO .Xr date 1 , .Xr adjtime 2 , .Xr icmp 4 , .Xr timed 8 .Rs .%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD" .%A R. Gusella .%A S. Zatti .Re .Sh HISTORY The .Nm utility appeared in .Bx 4.3 . +.Pp +The latest +.Nm +code has been made available as a port (net/timed) in preparation of removal +from base in +.Fx 13.0 . Index: stable/12/usr.sbin/timed/timedc/timedc.c =================================================================== --- stable/12/usr.sbin/timed/timedc/timedc.c (revision 343939) +++ stable/12/usr.sbin/timed/timedc/timedc.c (revision 343940) @@ -1,254 +1,257 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * 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. 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1985, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include "timedc.h" #include #include #include #include #include #include #include #include int trace = 0; FILE *fd = NULL; int margc; int fromatty; #define MAX_MARGV 20 char *margv[MAX_MARGV]; char cmdline[200]; jmp_buf toplevel; static struct cmd *getcmd(char *); int main(int argc, char *argv[]) { register struct cmd *c; openlog("timedc", 0, LOG_AUTH); /* * security dictates! */ if (priv_resources() < 0) errx(1, "could not get privileged resources"); if (setuid(getuid()) != 0) err(1, "setuid()"); if (--argc > 0) { c = getcmd(*++argv); if (c == (struct cmd *)-1) { printf("?Ambiguous command\n"); exit(1); } if (c == NULL) { printf("?Invalid command\n"); exit(1); } if (c->c_priv && getuid()) { printf("?Privileged command\n"); exit(1); } (*c->c_handler)(argc, argv); exit(0); } fromatty = isatty(fileno(stdin)); + if (fromatty) + printf("TIMEDC will be removed from FreeBSD-13, and will be " + "provided as a port (net/timed) or package (timed).\n"); if (setjmp(toplevel)) putchar('\n'); (void) signal(SIGINT, intr); for (;;) { if (fromatty) { printf("timedc> "); (void) fflush(stdout); } if (fgets(cmdline, sizeof(cmdline), stdin) == NULL) quit(); if (cmdline[0] == 0) break; makeargv(); if (margv[0] == NULL) continue; c = getcmd(margv[0]); if (c == (struct cmd *)-1) { printf("?Ambiguous command\n"); continue; } if (c == NULL) { printf("?Invalid command\n"); continue; } if (c->c_priv && getuid()) { printf("?Privileged command\n"); continue; } (*c->c_handler)(margc, margv); } return 0; } void intr(int signo __unused) { if (!fromatty) exit(0); longjmp(toplevel, 1); } static struct cmd * getcmd(char *name) { register char *p, *q; register struct cmd *c, *found; register int nmatches, longest; extern int NCMDS; longest = 0; nmatches = 0; found = NULL; for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { p = c->c_name; for (q = name; *q == *p++; q++) if (*q == 0) /* exact match? */ return(c); if (!*q) { /* the name was a prefix */ if (q - name > longest) { longest = q - name; nmatches = 1; found = c; } else if (q - name == longest) nmatches++; } } if (nmatches > 1) return((struct cmd *)-1); return(found); } /* * Slice a string up into argc/argv. */ void makeargv(void) { register char *cp; register char **argp = margv; margc = 0; for (cp = cmdline; margc < MAX_MARGV - 1 && *cp; ) { while (isspace(*cp)) cp++; if (*cp == '\0') break; *argp++ = cp; margc += 1; while (*cp != '\0' && !isspace(*cp)) cp++; if (*cp == '\0') break; *cp++ = '\0'; } *argp++ = NULL; } #define HELPINDENT (sizeof ("directory")) /* * Help command. */ void help(int argc, char *argv[]) { register struct cmd *c; if (argc == 1) { register int i, j, w; int columns, width = 0, lines; extern int NCMDS; printf("Commands may be abbreviated. Commands are:\n\n"); for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { int len = strlen(c->c_name); if (len > width) width = len; } width = (width + 8) &~ 7; columns = 80 / width; if (columns == 0) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { for (j = 0; j < columns; j++) { c = cmdtab + j * lines + i; printf("%s", c->c_name); if (c + lines >= &cmdtab[NCMDS]) { printf("\n"); break; } w = strlen(c->c_name); while (w < width) { w = (w + 8) &~ 7; putchar('\t'); } } } return; } while (--argc > 0) { register char *arg; arg = *++argv; c = getcmd(arg); if (c == (struct cmd *)-1) printf("?Ambiguous help command %s\n", arg); else if (c == (struct cmd *)0) printf("?Invalid help command %s\n", arg); else printf("%-*s\t%s\n", (int)HELPINDENT, c->c_name, c->c_help); } }