Remove, the now very outdated, timed.

Submitted by:	Kyle Spiers ksspiers at gmail
Reviewed by:	bcr,brooks,bz,sbruno
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D18505
This commit is contained in:
gnn 2018-12-15 21:34:40 +00:00
parent fae3bd79a5
commit 222efc509d
40 changed files with 25 additions and 6307 deletions

View File

@ -38,6 +38,12 @@
# xargs -n1 | sort | uniq -d;
# done
# 20181214: Remove timed files
OLD_FILES+=etc/rc.d/timed
OLD_FILES+=usr/sbin/timed
OLD_FILES+=usr/sbin/timedc
OLD_FILES+=usr/share/man/man8/timed.8.gz
OLD_FILES+=usr/share/man/man8/timedc.8.gz
# 20181211: new clang import which bumps version from 6.0.1 to 7.0.1.
OLD_FILES+=usr/lib/clang/6.0.1/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/6.0.1/include/sanitizer/asan_interface.h

View File

@ -37,6 +37,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
prerequisites and upgrading, if you are not already using clang 3.5.0
or higher.
20181211:
Remove the timed and netdate programs from the base tree. Setting
the time with these deamons has been obsolete for over a decade.
20181126:
On amd64, arm64 and armv7 (architectures that install LLVM's ld.lld
linker as /usr/bin/ld) GNU ld is no longer installed as ld.bfd, as

View File

@ -5,7 +5,7 @@
PACKAGE=runtime
PROG= date
SRCS= date.c netdate.c vary.c
SRCS= date.c vary.c
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests

View File

@ -4,7 +4,6 @@
DIRDEPS = \
gnu/lib/csu \
include \
include/protocols \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \

View File

@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <utmpx.h>
#include "extern.h"
#include "vary.h"
#ifndef TM_YEAR_BASE
@ -67,7 +66,6 @@ __FBSDID("$FreeBSD$");
#endif
static time_t tval;
int retval;
static void badformat(void);
static void iso8601_usage(const char *);
@ -248,7 +246,7 @@ printdate(const char *buf)
(void)printf("%s\n", buf);
if (fflush(stdout))
err(1, "stdout");
exit(retval);
exit(EXIT_SUCCESS);
}
static void
@ -370,7 +368,7 @@ setthetime(const char *fmt, const char *p, int jflag, int nflag)
if (!jflag) {
/* set the time */
if (nflag || netsettime(tval)) {
if (nflag) {
utx.ut_type = OLD_TIME;
memset(utx.ut_id, 0, sizeof(utx.ut_id));
(void)gettimeofday(&utx.ut_tv, NULL);

View File

@ -1,37 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 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.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
* $FreeBSD$
*/
extern int retval;
int netsettime(time_t);

View File

@ -1,183 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1990, 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.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)netdate.c 8.1 (Berkeley) 5/31/93";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define TSPTYPES
#include <protocols/timed.h>
#include <err.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#define WAITACK 2 /* seconds */
#define WAITDATEACK 5 /* seconds */
/*
* Set the date in the machines controlled by timedaemons by communicating the
* new date to the local timedaemon. If the timedaemon is in the master state,
* it performs the correction on all slaves. If it is in the slave state, it
* notifies the master that a correction is needed.
* Returns 0 on success. Returns > 0 on failure, setting retval to 2;
*/
int
netsettime(time_t tval)
{
struct timeval tout;
struct servent *sp;
struct tsp msg;
struct sockaddr_in lsin, dest, from;
fd_set ready;
long waittime;
int s, port, timed_ack, found, lerr;
socklen_t length;
char hostname[MAXHOSTNAMELEN];
if ((sp = getservbyname("timed", "udp")) == NULL) {
warnx("timed/udp: unknown service");
return (retval = 2);
}
dest.sin_port = sp->s_port;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
if (errno != EAFNOSUPPORT)
warn("timed");
return (retval = 2);
}
memset(&lsin, 0, sizeof(lsin));
lsin.sin_family = AF_INET;
for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
lsin.sin_port = htons((u_short)port);
if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0)
break;
if (errno == EADDRINUSE)
continue;
if (errno != EADDRNOTAVAIL)
warn("bind");
goto bad;
}
if (port == IPPORT_RESERVED / 2) {
warnx("all ports in use");
goto bad;
}
memset(&msg, 0, sizeof(msg));
msg.tsp_type = TSP_SETDATE;
msg.tsp_vers = TSPVERSION;
if (gethostname(hostname, sizeof(hostname))) {
warn("gethostname");
goto bad;
}
(void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name));
msg.tsp_seq = htons((u_short)0);
msg.tsp_time.tv_sec = htonl((u_long)tval);
msg.tsp_time.tv_usec = htonl((u_long)0);
length = sizeof(struct sockaddr_in);
if (connect(s, (struct sockaddr *)&dest, length) < 0) {
warn("connect");
goto bad;
}
if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) {
if (errno != ECONNREFUSED)
warn("send");
goto bad;
}
timed_ack = -1;
waittime = WAITACK;
loop:
tout.tv_sec = waittime;
tout.tv_usec = 0;
FD_ZERO(&ready);
FD_SET(s, &ready);
found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
length = sizeof(lerr);
if (!getsockopt(s,
SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) {
if (lerr != ECONNREFUSED)
warnc(lerr, "send (delayed error)");
goto bad;
}
if (found > 0 && FD_ISSET(s, &ready)) {
length = sizeof(struct sockaddr_in);
if (recvfrom(s, &msg, sizeof(struct tsp), 0,
(struct sockaddr *)&from, &length) < 0) {
if (errno != ECONNREFUSED)
warn("recvfrom");
goto bad;
}
msg.tsp_seq = ntohs(msg.tsp_seq);
msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
switch (msg.tsp_type) {
case TSP_ACK:
timed_ack = TSP_ACK;
waittime = WAITDATEACK;
goto loop;
case TSP_DATEACK:
(void)close(s);
return (0);
default:
warnx("wrong ack received from timed: %s",
tsptype[msg.tsp_type]);
timed_ack = -1;
break;
}
}
if (timed_ack == -1)
warnx("can't reach time daemon, time set locally");
bad:
(void)close(s);
return (retval = 2);
}

View File

@ -291,10 +291,6 @@ SMRCD= sendmail
SMRCDPACKAGE= sendmail
.endif
.if ${MK_TIMED} != "no"
CONFS+= timed
.endif
.if ${MK_UNBOUND} != "no"
CONFGROUPS+= UNBOUND
UNBOUND+= local_unbound

View File

@ -1,19 +0,0 @@
#!/bin/sh
#
# $FreeBSD$
#
# PROVIDE: timed
# REQUIRE: DAEMON
# BEFORE: LOGIN
# KEYWORD: nojail shutdown
. /etc/rc.subr
name="timed"
desc="Time server daemon"
rcvar="timed_enable"
command="/usr/sbin/${name}"
load_rc_config $name
run_rc_command "$1"

View File

@ -1,6 +1,6 @@
.\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman.
.\" $FreeBSD$
.Dd November 26, 2018
.Dd December 15, 2018
.Dt SRC.CONF 5
.Os
.Sh NAME
@ -239,6 +239,17 @@ Disable the BSD licensed
.Pa crtbegin.o
and
.Pa crtend.o .
.Pp
This is a default setting on
powerpc/powerpc, powerpc/powerpc64, powerpc/powerpcspe and sparc64/sparc64.
.It Va WITH_BSD_CRTBEGIN
Enable the BSD licensed
.Pa crtbegin.o
and
.Pa crtend.o .
.Pp
This is a default setting on
amd64/amd64, arm/arm, arm/armv6, arm/armv7, arm64/aarch64, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf and riscv/riscv64.
.It Va WITH_BSD_GREP
Install BSD-licensed grep as '[ef]grep' instead of GNU grep.
.It Va WITHOUT_BSNMP
@ -1780,9 +1791,6 @@ Set to not build or install
.Xr tftp 1
and
.Xr tftpd 8 .
.It Va WITHOUT_TIMED
Set to not build or install
.Xr timed 8 .
.It Va WITHOUT_TOOLCHAIN
Set to not install header or
programs used for program development,

View File

@ -8513,14 +8513,6 @@ OLD_FILES+=usr/share/man/man1/tftp.1.gz
OLD_FILES+=usr/share/man/man8/tftpd.8.gz
.endif
.if ${MK_TIMED} == no
OLD_FILES+=usr/sbin/timed
OLD_FILES+=usr/sbin/timedc
OLD_FILES+=usr/share/man/man8/timed.8.gz
OLD_FILES+=usr/share/man/man8/timedc.8.gz
.endif
.if ${MK_TOOLCHAIN} == no
OLD_FILES+=usr/bin/addr2line
OLD_FILES+=usr/bin/as
OLD_FILES+=usr/bin/byacc

View File

@ -1,3 +0,0 @@
.\" $FreeBSD$
Set to not build or install
.Xr timed 8 .

View File

@ -201,7 +201,6 @@ SUBDIR.${MK_SENDMAIL}+= praliases
SUBDIR.${MK_SENDMAIL}+= sendmail
SUBDIR.${MK_TCP_WRAPPERS}+= tcpdchk
SUBDIR.${MK_TCP_WRAPPERS}+= tcpdmatch
SUBDIR.${MK_TIMED}+= timed
SUBDIR.${MK_TOOLCHAIN}+= config
SUBDIR.${MK_TOOLCHAIN}+= crunch
SUBDIR.${MK_UNBOUND}+= unbound

View File

@ -1,6 +0,0 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
SUBDIR= timed timedc
.include <bsd.subdir.mk>

View File

@ -1,145 +0,0 @@
# @(#)CHANGES 5.1 (Berkeley) 5/11/93
# $FreeBSD$
This new version is almost identical to the timed and timedc code
that has been shipped for years by a workstation vendor.
Among the many changes:
improve `timedc msite` to accept a list of hostnames.
change slave-masters to answer the packets generated by `timedc msite`
with the name of the real master, not their own. This makes it
possible to "chase the chain" of slave servers to the ultimate
master.
much improve the log caused by `timedc trace on`:
-made `timed -t` work.
-suppression of repeated entries, which both slowed down the daemon
(sometimes catastrophically) and tended to make disks fill up
even more quickly.
-better time stamps on log entries
-more messages
-dump information about slaves, master, and so on each time
a message asking the log be turned on is received, and
when the log is turned off.
-fewer CPU cycles
use a hash table to keep track of slaves, instead of the stupid linear
list. This becomes handy with hundreds of slaves, instead of
the original design limit of "a room with a few VAX's."
separate the main protocol timer from that used to look for other networks
to master.
time stamp packets received by the daemon, so that time corrections
are not made (even more) inaccurate by waiting in the internal,
timed queue while the daemon is processing other messages.
made -n and -i work with subnets not named in /etc/networks
compute the median of the measured clocks, instead of the average
of "good" times.
vastly improve the accuracy of the clock difference measure by
`timedc clockdiff`.
use adjtime() when possible, and directly set the clock only when
necessary.
when the requested adjustment is small, perform only part of it, to
damp oscillations and improve the long term accuracy of the
adjustments.
fix uncounted core-dumps on machines that do not allow dereferencing 0
in both the daemon and timedc.
fix "master loop detection".
fix several cases in which multi-homed masters could get into shouting
matches, consuming all available network bandwidth and CPU cycles
(which ever runs out first), and convincing all bystanders to stop
advancing their own clocks.
refuse to behave badly when other machines do. Instead of arguing forever,
go off and sulk when other machines refuse to play by the rules.
increase the maximum number of clients.
add "-F host,host2,..." to "freerun" or "trust" only some hosts. This
is handy both when only some machines should be trusted to let
root use the `date` command to change time in the network.
It is also handy when one machine has some other way of adjusting
its clock, whether NTP or a direct radio or atomic connection.
"-F localhost" causes `timed` to "trust" only itself.
It is also handy to build a hierarchy of timed masters crossing
networks. The TSP protocol has no provision of "goodness of clock",
no natural way to completely heal network paritions. Judicious
use of -F or -G can cause each gateway to trust only itself and
machines closer to a central machine with a radio or atomic clock.
add #ifdef code that supports NIS "netgroups" of trusted hosts, which
can be easier to administer than -F.
add #ifdef code to compute an aged total adjustment. This can be used
in systems that can make long term changes in their system clock
frequency, e.g. "timetrim" in the Silicon Graphics kernel.
Problems observed by others that are unresolved include:
Practically any users can send to the master TSP messages and this
way corrupt the reliability of the system. Authentication
of messages should be provided. Unfortunately, that would
require changing the protocol with all of the implied
compatibility problems. Fortunately, the new -F and -G args
can be used to cause the daemon to ignore time changes from
untrusted machines.
MAN. The limit of 1013 on the number of slaves hosts should be doc'ed.
It should be dynamically allocated with no limit. On a
large network, one host could possibly master over many
more than 30 hosts. Given the timers in the code and
effectively in the protocol, and the time required by each
master to talk to each slave, it is not practical to have
more than 200-300 slaves. The master cannot keep up because
the slave-chatting is single-threaded. when the master
gets behind, slaves start demanding elections. To
significantly increase the number of slaves would require
multi-treading things, and given that a network with more
than 300 directly addressable machines has worse problems
than keep the time of day right, not worth worrying about.
UGLY,CODE. timedc/cmds.c has a lots of repeated code in it.
**** The first thing is that each command is set up as if it
were an individual program taking argc and argv. A more
conventional calling style should be used. I don't think
any of the routines take more than a couple arguments.
UGLY. fxn definition syntax does't follow convention:
has type on same line.
**** It needs to be fixed at least enough that tags
will work on it. An entire cleanup might be nice later, but
is noncritical.
LOBBY(mildly),CODE: Would be very convenient if date(1) took a
+-<number> argument to set the time relatively. With
the advent of timed it is now reasonable to synchronize
with WWV, which is nearly impossible to do "by hand"
with just an absolute date, and scripts are too slow.
format could be +-nn...nn.ss, where the '.' is required
to remove ambiguity.
**** If you want to do it go ahead. It sounds useful. As far as
syntax goes, the normal format for the date should work just
fine for this. If the date is preceded by a plus or minus,
the change is relative, otherwise it is absolute.
Vernon Schryver.
vjs@sgi.com

View File

@ -1,16 +0,0 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
#
# optional flags are: MEASURE TESTING DEBUG
PROG= timed
MAN= timed.8
SRCS= acksend.c candidate.c correct.c master.c networkdelta.c readmsg.c \
slave.c timed.c byteorder.c measure.c cksum.c
LIBADD= util
WARNS?= 1
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View File

@ -1,21 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
include \
include/arpa \
include/protocols \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
lib/libutil \
lib/msun \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -1,127 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)acksend.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
struct tsp *answer;
extern u_short sequence;
void
xmit(int type, u_int seq, struct sockaddr_in *addr)
{
static struct tsp msg;
msg.tsp_type = type;
msg.tsp_seq = seq;
msg.tsp_vers = TSPVERSION;
(void)strcpy(msg.tsp_name, hostname);
bytenetorder(&msg);
if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
(struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) {
trace_sendto_err(addr->sin_addr);
}
}
/*
* Acksend implements reliable datagram transmission by using sequence
* numbers and retransmission when necessary.
* If `name' is ANYADDR, this routine implements reliable broadcast.
*
* Because this function calls readmsg(), none of its args may be in
* a message provided by readmsg().
* message this message
* addr to here
* ack look for this ack
* net receive from this network
* bad 1=losing patience
*/
struct tsp *
acksend(struct tsp *message, struct sockaddr_in *addr, char *name,
int ack, struct netinfo *net, int bad)
{
struct timeval twait;
int count;
long msec;
message->tsp_vers = TSPVERSION;
message->tsp_seq = sequence;
if (trace) {
fprintf(fd, "acksend: to %s: ",
(name == ANYADDR ? "broadcast" : name));
print(message, addr);
}
bytenetorder(message);
msec = 200;
count = bad ? 1 : 5; /* 5 packets in 6.4 seconds */
answer = NULL;
do {
if (!answer) {
/* do not go crazy transmitting just because the
* other guy cannot keep our sequence numbers
* straight.
*/
if (sendto(sock, (char *)message, sizeof(struct tsp),
0, (struct sockaddr*)addr,
sizeof(struct sockaddr)) < 0) {
trace_sendto_err(addr->sin_addr);
break;
}
}
mstotvround(&twait, msec);
answer = readmsg(ack, name, &twait, net);
if (answer != NULL) {
if (answer->tsp_seq != sequence) {
if (trace)
fprintf(fd,"acksend: seq # %u!=%u\n",
answer->tsp_seq, sequence);
continue;
}
break;
}
msec *= 2;
} while (--count > 0);
sequence++;
return(answer);
}

View File

@ -1,82 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)byteorder.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
/*
* Two routines to do the necessary byte swapping for timed protocol
* messages. Protocol is defined in /usr/include/protocols/timed.h
*/
void
bytenetorder(struct tsp *ptr)
{
ptr->tsp_seq = htons((u_short)ptr->tsp_seq);
switch (ptr->tsp_type) {
case TSP_SETTIME:
case TSP_ADJTIME:
case TSP_SETDATE:
case TSP_SETDATEREQ:
ptr->tsp_time.tv_sec = htonl((u_long)ptr->tsp_time.tv_sec);
ptr->tsp_time.tv_usec = htonl((u_long)ptr->tsp_time.tv_usec);
break;
default:
break; /* nothing more needed */
}
}
void
bytehostorder(struct tsp *ptr)
{
ptr->tsp_seq = ntohs((u_short)ptr->tsp_seq);
switch (ptr->tsp_type) {
case TSP_SETTIME:
case TSP_ADJTIME:
case TSP_SETDATE:
case TSP_SETDATEREQ:
ptr->tsp_time.tv_sec = ntohl((u_long)ptr->tsp_time.tv_sec);
ptr->tsp_time.tv_usec = ntohl((u_long)ptr->tsp_time.tv_usec);
break;
default:
break; /* nothing more needed */
}
}

View File

@ -1,164 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)candidate.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
/*
* `election' candidates a host as master: it is called by a slave
* which runs with the -M option set when its election timeout expires.
* Note the conservative approach: if a new timed comes up, or another
* candidate sends an election request, the candidature is withdrawn.
*/
int
election(struct netinfo *net)
{
struct tsp *resp, msg;
struct timeval then, wait;
struct tsp *answer;
struct hosttbl *htp;
char loop_lim = 0;
/* This code can get totally confused if it gets slightly behind. For
* example, if readmsg() has some QUIT messages waiting from the last
* round, we would send an ELECTION message, get the stale QUIT,
* and give up. This results in network storms when several machines
* do it at once.
*/
wait.tv_sec = 0;
wait.tv_usec = 0;
while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) {
if (trace)
fprintf(fd, "election: discarded stale REFUSE\n");
}
while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) {
if (trace)
fprintf(fd, "election: discarded stale QUIT\n");
}
again:
syslog(LOG_INFO, "This machine is a candidate time master");
if (trace)
fprintf(fd, "This machine is a candidate time master\n");
msg.tsp_type = TSP_ELECTION;
msg.tsp_vers = TSPVERSION;
(void)strcpy(msg.tsp_name, hostname);
bytenetorder(&msg);
if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
(struct sockaddr*)&net->dest_addr,
sizeof(struct sockaddr)) < 0) {
trace_sendto_err(net->dest_addr.sin_addr);
return(SLAVE);
}
(void)gettimeofday(&then, 0);
then.tv_sec += 3;
for (;;) {
(void)gettimeofday(&wait, 0);
timevalsub(&wait,&then,&wait);
resp = readmsg(TSP_ANY, ANYADDR, &wait, net);
if (!resp)
return(MASTER);
switch (resp->tsp_type) {
case TSP_ACCEPT:
(void)addmach(resp->tsp_name, &from,fromnet);
break;
case TSP_MASTERUP:
case TSP_MASTERREQ:
/*
* If another timedaemon is coming up at the same
* time, give up, and let it be the master.
*/
if (++loop_lim < 5
&& !good_host_name(resp->tsp_name)) {
(void)addmach(resp->tsp_name, &from,fromnet);
suppress(&from, resp->tsp_name, net);
goto again;
}
rmnetmachs(net);
return(SLAVE);
case TSP_QUIT:
case TSP_REFUSE:
/*
* Collision: change value of election timer
* using exponential backoff.
*
* Fooey.
* An exponential backoff on a delay starting at
* 6 to 15 minutes for a process that takes
* milliseconds is silly. It is particularly
* strange that the original code would increase
* the backoff without bound.
*/
rmnetmachs(net);
return(SLAVE);
case TSP_ELECTION:
/* no master for another round */
htp = addmach(resp->tsp_name,&from,fromnet);
msg.tsp_type = TSP_REFUSE;
(void)strcpy(msg.tsp_name, hostname);
answer = acksend(&msg, &htp->addr, htp->name,
TSP_ACK, 0, htp->noanswer);
if (!answer) {
syslog(LOG_ERR, "error in election from %s",
htp->name);
}
break;
case TSP_SLAVEUP:
(void)addmach(resp->tsp_name, &from,fromnet);
break;
case TSP_SETDATE:
case TSP_SETDATEREQ:
break;
default:
if (trace) {
fprintf(fd, "candidate: ");
print(resp, &from);
}
break;
}
}
}

View File

@ -1,83 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)cksum.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/types.h>
/*
* I N _ C K S U M
*
* Checksum routine for Internet Protocol family headers (C Version)
*
* There is no profit in a specialized version of the checksum
* function for any machine where int's are 32 bits and shorts are 16.
*
* All timed packets are smaller than 32K shorts, so there is no need to
* worry about carries except at the end.
*/
int
in_cksum(u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register u_short answer;
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 )
sum += (*(u_char *)w) << 8;
/*
* 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);
}

View File

@ -1,192 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)correct.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
#include <math.h>
#include <sys/types.h>
#include <sys/times.h>
static void adjclock(struct timeval *);
/*
* sends to the slaves the corrections for their clocks after fixing our
* own
*/
void
correct(long avdelta)
{
struct hosttbl *htp;
int corr;
struct timeval adjlocal, tmptv;
struct tsp to;
struct tsp *answer;
mstotvround(&adjlocal, avdelta);
for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
if (htp->delta != HOSTDOWN) {
corr = avdelta - htp->delta;
/* If the other machine is off in the weeds, set its time directly.
* If a slave gets the wrong day, the original code would simply
* fix the minutes. If you fix a network partition, you can get
* into such situations.
*/
if (htp->need_set
|| corr >= MAXADJ*1000
|| corr <= -MAXADJ*1000) {
htp->need_set = 0;
(void)gettimeofday(&tmptv,0);
timevaladd(&tmptv, &adjlocal);
to.tsp_time.tv_sec = tmptv.tv_sec;
to.tsp_time.tv_usec = tmptv.tv_usec;
to.tsp_type = TSP_SETTIME;
} else {
tmptv.tv_sec = to.tsp_time.tv_sec;
tmptv.tv_usec = to.tsp_time.tv_usec;
mstotvround(&tmptv, corr);
to.tsp_time.tv_sec = tmptv.tv_sec;
to.tsp_time.tv_usec = tmptv.tv_usec;
to.tsp_type = TSP_ADJTIME;
}
(void)strcpy(to.tsp_name, hostname);
answer = acksend(&to, &htp->addr, htp->name,
TSP_ACK, 0, 0);
if (!answer) {
htp->delta = HOSTDOWN;
syslog(LOG_WARNING,
"no reply to time correction from %s",
htp->name);
if (++htp->noanswer >= LOSTHOST) {
if (trace) {
fprintf(fd,
"purging %s for not answering\n",
htp->name);
(void)fflush(fd);
}
htp = remmach(htp);
}
}
}
}
/*
* adjust our own clock now that we are not sending it out
*/
adjclock(&adjlocal);
}
static void
adjclock(struct timeval *corr)
{
static int passes = 0;
static int smoother = 0;
long delta; /* adjustment in usec */
long ndelta;
struct timeval now;
struct timeval adj;
if (!timerisset(corr))
return;
adj = *corr;
if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) {
delta = adj.tv_sec*1000000 + adj.tv_usec;
/* If the correction is less than the minimum round
* trip time for an ICMP packet, and thus
* less than the likely error in the measurement,
* do not do the entire correction. Do half
* or a quarter of it.
*/
if (delta > -MIN_ROUND*1000
&& delta < MIN_ROUND*1000) {
if (smoother <= 4)
smoother++;
ndelta = delta >> smoother;
if (trace)
fprintf(fd,
"trimming delta %ld usec to %ld\n",
delta, ndelta);
adj.tv_usec = ndelta;
adj.tv_sec = 0;
} else if (smoother > 0) {
smoother--;
}
if (0 > adjtime(corr, 0)) {
syslog(LOG_ERR, "adjtime: %m");
}
if (passes > 1
&& (delta < -BIG_ADJ || delta > BIG_ADJ)) {
smoother = 0;
passes = 0;
syslog(LOG_WARNING,
"large time adjustment of %+.3f sec",
delta/1000000.0);
}
} else {
syslog(LOG_WARNING,
"clock correction %jd sec too large to adjust",
(intmax_t)adj.tv_sec);
(void) gettimeofday(&now, 0);
timevaladd(&now, corr);
if (settimeofday(&now, 0) < 0)
syslog(LOG_ERR, "settimeofday: %m");
}
}
/* adjust the time in a message by the time it
* spent in the queue
*/
void
adj_msg_time(struct tsp *msg, struct timeval *now)
{
msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
while (msg->tsp_time.tv_usec < 0) {
msg->tsp_time.tv_sec--;
msg->tsp_time.tv_usec += 1000000;
}
while (msg->tsp_time.tv_usec >= 1000000) {
msg->tsp_time.tv_sec++;
msg->tsp_time.tv_usec -= 1000000;
}
}

View File

@ -1,89 +0,0 @@
/* $FreeBSD$ */
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 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.
*
* @(#)extern.h 8.1 (Berkeley) 6/6/93
*/
struct hosttbl;
struct netinfo;
struct sockaddr_in;
struct timeval;
struct tsp;
struct hosttbl *addmach(char *, struct sockaddr_in *, struct netinfo *);
struct hosttbl *findhost(char *);
struct hosttbl *remmach(struct hosttbl *);
struct tsp *readmsg(int,
char *, struct timeval *, struct netinfo *);
struct tsp *acksend(struct tsp *,
struct sockaddr_in *, char *, int, struct netinfo *, int);
void addnetname(char *);
void adj_msg_time(struct tsp *, struct timeval *);
void bytehostorder(struct tsp *);
void bytenetorder(struct tsp *);
void byteorder(struct tsp *);
long casual(long, long);
int cksum(u_short *, int);
void correct(long);
char *date(void);
void doquit(struct tsp *);
int election(struct netinfo *);
void get_goodgroup(int);
int good_host_name(char *);
void ignoreack(void);
int in_cksum(u_short *, int);
void lookformaster(struct netinfo *);
void makeslave(struct netinfo *);
int master(void);
void masterack(void);
void masterup(struct netinfo *);
int measure(u_long, u_long, char *, struct sockaddr_in *, int);
void msterup(struct netinfo *);
void mstotvround(struct timeval *, long);
long networkdelta(void);
void newslave(struct tsp *);
void print(struct tsp *, struct sockaddr_in *);
void prthp(clock_t);
void rmnetmachs(struct netinfo *);
void setstatus(void);
void slave(void) __dead2;
void slaveack(void);
void spreadtime(void);
void suppress(struct sockaddr_in *, char *, struct netinfo *);
void synch(long);
void timevaladd(struct timeval *, struct timeval *);
void timevalsub(struct timeval *, struct timeval *, struct timeval *);
void traceoff(char *);
void traceon(void);
void xmit(int, u_int, struct sockaddr_in *);

View File

@ -1,171 +0,0 @@
/*-
* 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.
*
* @(#)globals.h 8.1 (Berkeley) 6/6/93
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <protocols/timed.h>
#define SECHR (60*60)
#define SECDAY (24*SECHR)
/* Best expected round trip for a measurement.
* This is essentially the number of milliseconds per CPU tick (CLK_TCK?).
* All delays shorter than this are usually reported as 0.
*/
#define MIN_ROUND ((1000-1)/CLK_TCK)
#define SAMPLEINTVL 240 /* synch() freq for master in sec */
#define MAXADJ 20 /* max adjtime() correction in sec */
#define MAX_TRIM 3000000 /* max drift in nsec/sec, 0.3% */
#define BIG_ADJ (MAX_TRIM/1000*SAMPLEINTVL*2) /* max good adj */
#define MINTOUT 360 /* election delays, 6-15 minutes */
#define MAXTOUT 900
#define BAD_STATUS (-1)
#define GOOD 1
#define UNREACHABLE 2
#define NONSTDTIME 3
#define HOSTDOWN 0x7fffffff
#define OFF 0
#define ON 1
#define MAX_HOPCNT 10 /* max value for tsp_hpcnt */
#define LOSTHOST 3 /* forget after this many failures */
#define VALID_RANGE (MAXADJ*1000) /* good times in milliseconds */
#define GOOD_RANGE (MIN_ROUND*2)
#define VGOOD_RANGE (MIN_ROUND-1)
/*
* Global and per-network states.
*/
#define NOMASTER 0 /* no good master */
#define SLAVE 1
#define MASTER 2
#define IGNORE 4
#define ALL (SLAVE|MASTER|IGNORE)
#define SUBMASTER (SLAVE|MASTER)
#define NHOSTS 1013 /* max of hosts controlled by timed
* This must be a prime number.
*/
struct hosttbl {
struct hosttbl *h_bak; /* hash chain */
struct hosttbl *h_fwd;
struct hosttbl *l_bak; /* "sequential" list */
struct hosttbl *l_fwd;
struct netinfo *ntp;
struct sockaddr_in addr;
char name[MAXHOSTNAMELEN];
u_char head; /* 1=head of hash chain */
u_char good; /* 0=trusted host, for averaging */
u_char noanswer; /* count of failures to answer */
u_char need_set; /* need a SETTIME */
u_short seq;
long delta;
};
/* closed hash table with internal chaining */
extern struct hosttbl hosttbl[NHOSTS+1];
#define self hosttbl[0]
#define hostname (self.name)
struct netinfo {
struct netinfo *next;
struct in_addr net;
u_int32_t mask;
struct in_addr my_addr;
struct sockaddr_in dest_addr; /* broadcast addr or point-point */
long status;
struct timeval slvwait; /* delay before sending our time */
int quit_count; /* recent QUITs */
};
#include "extern.h"
#define tvtomsround(tv) ((tv).tv_sec*1000 + ((tv).tv_usec + 500)/1000)
extern struct netinfo *nettab;
extern int status;
extern int trace;
extern int sock;
extern struct sockaddr_in from;
extern struct timeval from_when; /* when the last msg arrived */
extern u_short sequence; /* TSP message sequence number */
extern struct netinfo *fromnet, *slavenet;
extern FILE *fd;
extern long delay1, delay2;
extern int nslavenets; /* nets were I could be a slave */
extern int nmasternets; /* nets were I could be a master */
extern int nignorednets; /* ignored nets */
extern int nnets; /* nets I am connected to */
#define trace_msg(msg) {if (trace) fprintf(fd, msg);}
#define trace_sendto_err(addr) { \
int st_errno = errno; \
syslog(LOG_ERR, "%s %d: sendto %s: %m", \
__FILE__, __LINE__, inet_ntoa(addr)); \
if (trace) \
fprintf(fd, "%s %d: sendto %s: %d", __FILE__, __LINE__, \
inet_ntoa(addr), st_errno); \
}
# define max(a,b) (a<b ? b : a)
# define min(a,b) (a>b ? b : a)
# define abs(x) (x>=0 ? x : -(x))

View File

@ -1,843 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)master.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
#include <sys/file.h>
#include <sys/types.h>
#include <sys/times.h>
#include <setjmp.h>
#include <utmpx.h>
#include "pathnames.h"
extern int measure_delta;
extern jmp_buf jmpenv;
extern int Mflag;
extern int justquit;
static int dictate;
static int slvcount; /* slaves listening to our clock */
static void mchgdate(struct tsp *);
/*
* The main function of `master' is to periodically compute the differences
* (deltas) between its clock and the clocks of the slaves, to compute the
* network average delta, and to send to the slaves the differences between
* their individual deltas and the network delta.
* While waiting, it receives messages from the slaves (i.e. requests for
* master's name, remote requests to set the network time, ...), and
* takes the appropriate action.
*/
int
master(void)
{
struct hosttbl *htp;
long pollingtime;
#define POLLRATE 4
int polls;
struct timeval wait, ntime;
time_t tsp_time_sec;
struct tsp *msg, *answer, to;
char newdate[32];
struct sockaddr_in taddr;
char tname[MAXHOSTNAMELEN];
struct netinfo *ntp;
int i;
syslog(LOG_NOTICE, "This machine is master");
if (trace)
fprintf(fd, "This machine is master\n");
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
if (ntp->status == MASTER)
masterup(ntp);
}
(void)gettimeofday(&ntime, NULL);
pollingtime = ntime.tv_sec+3;
if (justquit)
polls = 0;
else
polls = POLLRATE-1;
/* Process all outstanding messages before spending the long time necessary
* to update all timers.
*/
loop:
(void)gettimeofday(&ntime, NULL);
wait.tv_sec = pollingtime - ntime.tv_sec;
if (wait.tv_sec < 0)
wait.tv_sec = 0;
wait.tv_usec = 0;
msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
if (!msg) {
(void)gettimeofday(&ntime, NULL);
if (ntime.tv_sec >= pollingtime) {
pollingtime = ntime.tv_sec + SAMPLEINTVL;
get_goodgroup(0);
/* If a bogus master told us to quit, we can have decided to ignore a
* network. Therefore, periodically try to take over everything.
*/
polls = (polls + 1) % POLLRATE;
if (0 == polls && nignorednets > 0) {
trace_msg("Looking for nets to re-master\n");
for (ntp = nettab; ntp; ntp = ntp->next) {
if (ntp->status == IGNORE
|| ntp->status == NOMASTER) {
lookformaster(ntp);
if (ntp->status == MASTER) {
masterup(ntp);
polls = POLLRATE-1;
}
}
if (ntp->status == MASTER
&& --ntp->quit_count < 0)
ntp->quit_count = 0;
}
if (polls != 0)
setstatus();
}
synch(0L);
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
to.tsp_type = TSP_LOOP;
to.tsp_vers = TSPVERSION;
to.tsp_seq = sequence++;
to.tsp_hopcnt = MAX_HOPCNT;
(void)strcpy(to.tsp_name, hostname);
bytenetorder(&to);
if (sendto(sock, (char *)&to,
sizeof(struct tsp), 0,
(struct sockaddr*)&ntp->dest_addr,
sizeof(ntp->dest_addr)) < 0) {
trace_sendto_err(ntp->dest_addr.sin_addr);
}
}
}
} else {
switch (msg->tsp_type) {
case TSP_MASTERREQ:
break;
case TSP_SLAVEUP:
newslave(msg);
break;
case TSP_SETDATE:
/*
* XXX check to see it is from ourself
*/
tsp_time_sec = msg->tsp_time.tv_sec;
(void)strlcpy(newdate, ctime(&tsp_time_sec),
sizeof(newdate));
if (!good_host_name(msg->tsp_name)) {
syslog(LOG_NOTICE,
"attempted date change by %s to %s",
msg->tsp_name, newdate);
spreadtime();
break;
}
mchgdate(msg);
(void)gettimeofday(&ntime, NULL);
pollingtime = ntime.tv_sec + SAMPLEINTVL;
break;
case TSP_SETDATEREQ:
if (!fromnet || fromnet->status != MASTER)
break;
tsp_time_sec = msg->tsp_time.tv_sec;
(void)strlcpy(newdate, ctime(&tsp_time_sec),
sizeof(newdate));
htp = findhost(msg->tsp_name);
if (htp == NULL) {
syslog(LOG_ERR,
"attempted SET DATEREQ by uncontrolled %s to %s",
msg->tsp_name, newdate);
break;
}
if (htp->seq == msg->tsp_seq)
break;
htp->seq = msg->tsp_seq;
if (!htp->good) {
syslog(LOG_NOTICE,
"attempted SET DATEREQ by untrusted %s to %s",
msg->tsp_name, newdate);
spreadtime();
break;
}
mchgdate(msg);
(void)gettimeofday(&ntime, NULL);
pollingtime = ntime.tv_sec + SAMPLEINTVL;
break;
case TSP_MSITE:
xmit(TSP_ACK, msg->tsp_seq, &from);
break;
case TSP_MSITEREQ:
break;
case TSP_TRACEON:
traceon();
break;
case TSP_TRACEOFF:
traceoff("Tracing ended at %s\n");
break;
case TSP_ELECTION:
if (!fromnet)
break;
if (fromnet->status == MASTER) {
pollingtime = 0;
(void)addmach(msg->tsp_name, &from,fromnet);
}
taddr = from;
(void)strcpy(tname, msg->tsp_name);
to.tsp_type = TSP_QUIT;
(void)strcpy(to.tsp_name, hostname);
answer = acksend(&to, &taddr, tname,
TSP_ACK, 0, 1);
if (answer == NULL) {
syslog(LOG_ERR, "election error by %s",
tname);
}
break;
case TSP_CONFLICT:
/*
* After a network partition, there can be
* more than one master: the first slave to
* come up will notify here the situation.
*/
if (!fromnet || fromnet->status != MASTER)
break;
(void)strcpy(to.tsp_name, hostname);
/* The other master often gets into the same state,
* with boring results if we stay at it forever.
*/
ntp = fromnet; /* (acksend() can leave fromnet=0 */
for (i = 0; i < 3; i++) {
to.tsp_type = TSP_RESOLVE;
(void)strcpy(to.tsp_name, hostname);
answer = acksend(&to, &ntp->dest_addr,
ANYADDR, TSP_MASTERACK,
ntp, 0);
if (!answer)
break;
htp = addmach(answer->tsp_name,&from,ntp);
to.tsp_type = TSP_QUIT;
msg = acksend(&to, &htp->addr, htp->name,
TSP_ACK, 0, htp->noanswer);
if (msg == NULL) {
syslog(LOG_ERR,
"no response from %s to CONFLICT-QUIT",
htp->name);
}
}
masterup(ntp);
pollingtime = 0;
break;
case TSP_RESOLVE:
if (!fromnet || fromnet->status != MASTER)
break;
/*
* do not want to call synch() while waiting
* to be killed!
*/
(void)gettimeofday(&ntime, NULL);
pollingtime = ntime.tv_sec + SAMPLEINTVL;
break;
case TSP_QUIT:
doquit(msg); /* become a slave */
break;
case TSP_LOOP:
if (!fromnet || fromnet->status != MASTER
|| !strcmp(msg->tsp_name, hostname))
break;
/*
* We should not have received this from a net
* we are master on. There must be two masters.
*/
htp = addmach(msg->tsp_name, &from,fromnet);
to.tsp_type = TSP_QUIT;
(void)strcpy(to.tsp_name, hostname);
answer = acksend(&to, &htp->addr, htp->name,
TSP_ACK, 0, 1);
if (!answer) {
syslog(LOG_WARNING,
"loop breakage: no reply from %s=%s to QUIT",
htp->name, inet_ntoa(htp->addr.sin_addr));
(void)remmach(htp);
}
case TSP_TEST:
if (trace) {
fprintf(fd,
"\tnets = %d, masters = %d, slaves = %d, ignored = %d\n",
nnets, nmasternets, nslavenets, nignorednets);
setstatus();
}
pollingtime = 0;
polls = POLLRATE-1;
break;
default:
if (trace) {
fprintf(fd, "garbage message: ");
print(msg, &from);
}
break;
}
}
goto loop;
}
/*
* change the system date on the master
*/
static void
mchgdate(struct tsp *msg)
{
char tname[MAXHOSTNAMELEN];
char olddate[32];
struct timeval otime, ntime, tmptv;
struct utmpx utx;
(void)strcpy(tname, msg->tsp_name);
xmit(TSP_DATEACK, msg->tsp_seq, &from);
(void)strlcpy(olddate, date(), sizeof(olddate));
/* adjust time for residence on the queue */
(void)gettimeofday(&otime, NULL);
adj_msg_time(msg,&otime);
tmptv.tv_sec = msg->tsp_time.tv_sec;
tmptv.tv_usec = msg->tsp_time.tv_usec;
timevalsub(&ntime, &tmptv, &otime);
if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
/*
* do not change the clock if we can adjust it
*/
dictate = 3;
synch(tvtomsround(ntime));
} else {
utx.ut_type = OLD_TIME;
(void)gettimeofday(&utx.ut_tv, NULL);
pututxline(&utx);
(void)settimeofday(&tmptv, 0);
utx.ut_type = NEW_TIME;
(void)gettimeofday(&utx.ut_tv, NULL);
pututxline(&utx);
spreadtime();
}
syslog(LOG_NOTICE, "date changed by %s from %s",
tname, olddate);
}
/*
* synchronize all of the slaves
*/
void
synch(long mydelta)
{
struct hosttbl *htp;
int measure_status;
struct timeval check, stop, wait;
if (slvcount > 0) {
if (trace)
fprintf(fd, "measurements starting at %s\n", date());
(void)gettimeofday(&check, NULL);
for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
if (htp->noanswer != 0) {
measure_status = measure(500, 100,
htp->name,
&htp->addr,0);
} else {
measure_status = measure(3000, 100,
htp->name,
&htp->addr,0);
}
if (measure_status != GOOD) {
/* The slave did not respond. We have
* just wasted lots of time on it.
*/
htp->delta = HOSTDOWN;
if (++htp->noanswer >= LOSTHOST) {
if (trace) {
fprintf(fd,
"purging %s for not answering ICMP\n",
htp->name);
(void)fflush(fd);
}
htp = remmach(htp);
}
} else {
htp->delta = measure_delta;
}
(void)gettimeofday(&stop, NULL);
timevalsub(&stop, &stop, &check);
if (stop.tv_sec >= 1) {
if (trace)
(void)fflush(fd);
/*
* ack messages periodically
*/
wait.tv_sec = 0;
wait.tv_usec = 0;
if (0 != readmsg(TSP_TRACEON,ANYADDR,
&wait,0))
traceon();
(void)gettimeofday(&check, NULL);
}
}
if (trace)
fprintf(fd, "measurements finished at %s\n", date());
}
if (!(status & SLAVE)) {
if (!dictate) {
mydelta = networkdelta();
} else {
dictate--;
}
}
if (trace && (mydelta != 0 || (status & SLAVE)))
fprintf(fd,"local correction of %ld ms.\n", mydelta);
correct(mydelta);
}
/*
* sends the time to each slave after the master
* has received the command to set the network time
*/
void
spreadtime(void)
{
struct hosttbl *htp;
struct tsp to;
struct tsp *answer;
struct timeval tmptv;
/* Do not listen to the consensus after forcing the time. This is because
* the consensus takes a while to reach the time we are dictating.
*/
dictate = 2;
for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
to.tsp_type = TSP_SETTIME;
(void)strcpy(to.tsp_name, hostname);
(void)gettimeofday(&tmptv, NULL);
to.tsp_time.tv_sec = tmptv.tv_sec;
to.tsp_time.tv_usec = tmptv.tv_usec;
answer = acksend(&to, &htp->addr, htp->name,
TSP_ACK, 0, htp->noanswer);
if (answer == NULL) {
/* We client does not respond, then we have
* just wasted lots of time on it.
*/
syslog(LOG_WARNING,
"no reply to SETTIME from %s", htp->name);
if (++htp->noanswer >= LOSTHOST) {
if (trace) {
fprintf(fd,
"purging %s for not answering",
htp->name);
(void)fflush(fd);
}
htp = remmach(htp);
}
}
}
}
void
prthp(clock_t delta)
{
static time_t next_time;
time_t this_time;
struct tms tm;
struct hosttbl *htp;
int length, l;
int i;
if (!fd) /* quit if tracing already off */
return;
this_time = times(&tm);
if ((time_t)(this_time + delta) < next_time)
return;
next_time = this_time + CLK_TCK;
fprintf(fd, "host table: %d entries at %s\n", slvcount, date());
htp = self.l_fwd;
length = 1;
for (i = 1; i <= slvcount; i++, htp = htp->l_fwd) {
l = strlen(htp->name) + 1;
if (length+l >= 80) {
fprintf(fd, "\n");
length = 0;
}
length += l;
fprintf(fd, " %s", htp->name);
}
fprintf(fd, "\n");
}
static struct hosttbl *newhost_hash;
static struct hosttbl *lasthfree = &hosttbl[0];
struct hosttbl * /* answer or 0 */
findhost(char *name)
{
int i, j;
struct hosttbl *htp;
char *p;
j= 0;
for (p = name, i = 0; i < 8 && *p != '\0'; i++, p++)
j = (j << 2) ^ *p;
newhost_hash = &hosttbl[j % NHOSTS];
htp = newhost_hash;
if (htp->name[0] == '\0')
return(0);
do {
if (!strcmp(name, htp->name))
return(htp);
htp = htp->h_fwd;
} while (htp != newhost_hash);
return(0);
}
/*
* add a host to the list of controlled machines if not already there
*/
struct hosttbl *
addmach(char *name, struct sockaddr_in *addr, struct netinfo *ntp)
{
struct hosttbl *ret, *p, *b, *f;
ret = findhost(name);
if (ret == NULL) {
if (slvcount >= NHOSTS) {
if (trace) {
fprintf(fd, "no more slots in host table\n");
prthp(CLK_TCK);
}
syslog(LOG_ERR, "no more slots in host table");
Mflag = 0;
longjmp(jmpenv, 2); /* give up and be a slave */
}
/* if our home hash slot is occupied, find a free entry
* in the hash table
*/
if (newhost_hash->name[0] != '\0') {
do {
ret = lasthfree;
if (++lasthfree > &hosttbl[NHOSTS])
lasthfree = &hosttbl[1];
} while (ret->name[0] != '\0');
if (!newhost_hash->head) {
/* Move an interloper using our home. Use
* scratch pointers in case the new head is
* pointing to itself.
*/
f = newhost_hash->h_fwd;
b = newhost_hash->h_bak;
f->h_bak = ret;
b->h_fwd = ret;
f = newhost_hash->l_fwd;
b = newhost_hash->l_bak;
f->l_bak = ret;
b->l_fwd = ret;
bcopy(newhost_hash,ret,sizeof(*ret));
ret = newhost_hash;
ret->head = 1;
ret->h_fwd = ret;
ret->h_bak = ret;
} else {
/* link to an existing chain in our home
*/
ret->head = 0;
p = newhost_hash->h_bak;
ret->h_fwd = newhost_hash;
ret->h_bak = p;
p->h_fwd = ret;
newhost_hash->h_bak = ret;
}
} else {
ret = newhost_hash;
ret->head = 1;
ret->h_fwd = ret;
ret->h_bak = ret;
}
ret->addr = *addr;
ret->ntp = ntp;
(void)strlcpy(ret->name, name, sizeof(ret->name));
ret->good = good_host_name(name);
ret->l_fwd = &self;
ret->l_bak = self.l_bak;
self.l_bak->l_fwd = ret;
self.l_bak = ret;
slvcount++;
ret->noanswer = 0;
ret->need_set = 1;
} else {
ret->noanswer = (ret->noanswer != 0);
}
/* need to clear sequence number anyhow */
ret->seq = 0;
return(ret);
}
/*
* remove the machine with the given index in the host table.
*/
struct hosttbl *
remmach(struct hosttbl *htp)
{
struct hosttbl *lprv, *hnxt, *f, *b;
if (trace)
fprintf(fd, "remove %s\n", htp->name);
/* get out of the lists */
htp->l_fwd->l_bak = lprv = htp->l_bak;
htp->l_bak->l_fwd = htp->l_fwd;
htp->h_fwd->h_bak = htp->h_bak;
htp->h_bak->h_fwd = hnxt = htp->h_fwd;
/* If we are in the home slot, pull up the chain */
if (htp->head && hnxt != htp) {
if (lprv == hnxt)
lprv = htp;
/* Use scratch pointers in case the new head is pointing to
* itself.
*/
f = hnxt->h_fwd;
b = hnxt->h_bak;
f->h_bak = htp;
b->h_fwd = htp;
f = hnxt->l_fwd;
b = hnxt->l_bak;
f->l_bak = htp;
b->l_fwd = htp;
hnxt->head = 1;
bcopy(hnxt, htp, sizeof(*htp));
lasthfree = hnxt;
} else {
lasthfree = htp;
}
lasthfree->name[0] = '\0';
lasthfree->h_fwd = NULL;
lasthfree->l_fwd = NULL;
slvcount--;
return lprv;
}
/*
* Remove all the machines from the host table that exist on the given
* network. This is called when a master transitions to a slave on a
* given network.
*/
void
rmnetmachs(struct netinfo *ntp)
{
struct hosttbl *htp;
if (trace)
prthp(CLK_TCK);
for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
if (ntp == htp->ntp)
htp = remmach(htp);
}
if (trace)
prthp(CLK_TCK);
}
void
masterup(struct netinfo *net)
{
xmit(TSP_MASTERUP, 0, &net->dest_addr);
/*
* Do not tell new slaves our time for a while. This ensures
* we do not tell them to start using our time, before we have
* found a good master.
*/
(void)gettimeofday(&net->slvwait, NULL);
}
void
newslave(struct tsp *msg)
{
struct hosttbl *htp;
struct tsp *answer, to;
struct timeval now, tmptv;
if (!fromnet || fromnet->status != MASTER)
return;
htp = addmach(msg->tsp_name, &from,fromnet);
htp->seq = msg->tsp_seq;
if (trace)
prthp(0);
/*
* If we are stable, send our time to the slave.
* Do not go crazy if the date has been changed.
*/
(void)gettimeofday(&now, NULL);
if (now.tv_sec >= fromnet->slvwait.tv_sec+3
|| now.tv_sec < fromnet->slvwait.tv_sec) {
to.tsp_type = TSP_SETTIME;
(void)strcpy(to.tsp_name, hostname);
(void)gettimeofday(&tmptv, NULL);
to.tsp_time.tv_sec = tmptv.tv_sec;
to.tsp_time.tv_usec = tmptv.tv_usec;
answer = acksend(&to, &htp->addr,
htp->name, TSP_ACK,
0, htp->noanswer);
if (answer) {
htp->need_set = 0;
} else {
syslog(LOG_WARNING,
"no reply to initial SETTIME from %s",
htp->name);
htp->noanswer = LOSTHOST;
}
}
}
/*
* react to a TSP_QUIT:
*/
void
doquit(struct tsp *msg)
{
if (fromnet->status == MASTER) {
if (!good_host_name(msg->tsp_name)) {
if (fromnet->quit_count <= 0) {
syslog(LOG_NOTICE,"untrusted %s told us QUIT",
msg->tsp_name);
suppress(&from, msg->tsp_name, fromnet);
fromnet->quit_count = 1;
return;
}
syslog(LOG_NOTICE, "untrusted %s told us QUIT twice",
msg->tsp_name);
fromnet->quit_count = 2;
fromnet->status = NOMASTER;
} else {
fromnet->status = SLAVE;
}
rmnetmachs(fromnet);
longjmp(jmpenv, 2); /* give up and be a slave */
} else {
if (!good_host_name(msg->tsp_name)) {
syslog(LOG_NOTICE, "untrusted %s told us QUIT",
msg->tsp_name);
fromnet->quit_count = 2;
}
}
}
void
traceon(void)
{
if (!fd) {
fd = fopen(_PATH_TIMEDLOG, "w");
if (!fd) {
trace = 0;
return;
}
fprintf(fd,"Tracing started at %s\n", date());
}
trace = 1;
get_goodgroup(1);
setstatus();
prthp(CLK_TCK);
}
void
traceoff(char *msg)
{
get_goodgroup(1);
setstatus();
prthp(CLK_TCK);
if (trace) {
fprintf(fd, msg, date());
(void)fclose(fd);
fd = NULL;
}
#ifdef GPROF
moncontrol(0);
_mcleanup();
moncontrol(1);
#endif
trace = OFF;
}

View File

@ -1,338 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)measure.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#define MSEC_DAY (SECDAY*1000)
#define PACKET_IN 1024
#define MSGS 5 /* timestamps to average */
#define TRIALS 10 /* max # of timestamps sent */
extern int sock_raw;
int measure_delta;
static n_short seqno = 0;
/*
* Measures the differences between machines' clocks using
* ICMP timestamp messages.
* maxmsec wait this many msec at most
* wmsec msec to wait for an answer
* print print complaints on stderr
*/
int /* status val defined in globals.h */
measure(u_long maxmsec, u_long wmsec, char *hname, struct sockaddr_in *addr, int print)
{
int length;
int measure_status;
int rcvcount, trials;
int cc, count;
fd_set ready;
long sendtime, recvtime, histime1, histime2;
long idelta, odelta, total;
long min_idelta, min_odelta;
struct timeval tdone, tcur, ttrans, twait, tout;
u_char packet[PACKET_IN], opacket[64];
register struct icmp *icp = (struct icmp *) packet;
register struct icmp *oicp = (struct icmp *) opacket;
struct ip *ip = (struct ip *) packet;
min_idelta = min_odelta = 0x7fffffff;
measure_status = HOSTDOWN;
measure_delta = HOSTDOWN;
trials = 0;
errno = 0;
/* open raw socket used to measure time differences */
if (sock_raw < 0) {
sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sock_raw < 0) {
syslog(LOG_ERR, "opening raw socket: %m");
goto quit;
}
}
/*
* empty the icmp input queue
*/
FD_ZERO(&ready);
for (;;) {
tout.tv_sec = tout.tv_usec = 0;
FD_SET(sock_raw, &ready);
if (select(sock_raw+1, &ready, 0,0, &tout)) {
length = sizeof(struct sockaddr_in);
cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
0,&length);
if (cc < 0)
goto quit;
continue;
}
break;
}
/*
* Choose the smallest transmission time in each of the two
* directions. Use these two latter quantities to compute the delta
* between the two clocks.
*/
oicp->icmp_type = ICMP_TSTAMP;
oicp->icmp_code = 0;
oicp->icmp_id = getpid();
oicp->icmp_rtime = 0;
oicp->icmp_ttime = 0;
oicp->icmp_seq = seqno;
FD_ZERO(&ready);
(void)gettimeofday(&tdone, NULL);
mstotvround(&tout, maxmsec);
timevaladd(&tdone, &tout); /* when we give up */
mstotvround(&twait, wmsec);
rcvcount = 0;
while (rcvcount < MSGS) {
(void)gettimeofday(&tcur, NULL);
/*
* keep sending until we have sent the max
*/
if (trials < TRIALS) {
trials++;
oicp->icmp_otime = htonl((tcur.tv_sec % SECDAY) * 1000
+ tcur.tv_usec / 1000);
oicp->icmp_cksum = 0;
oicp->icmp_cksum = in_cksum((u_short*)oicp,
sizeof(*oicp));
count = sendto(sock_raw, opacket, sizeof(*oicp), 0,
(struct sockaddr*)addr,
sizeof(struct sockaddr));
if (count < 0) {
if (measure_status == HOSTDOWN)
measure_status = UNREACHABLE;
goto quit;
}
++oicp->icmp_seq;
ttrans = tcur;
timevaladd(&ttrans, &twait);
} else {
ttrans = tdone;
}
while (rcvcount < trials) {
timevalsub(&tout, &ttrans, &tcur);
if (tout.tv_sec < 0)
tout.tv_sec = 0;
FD_SET(sock_raw, &ready);
count = select(sock_raw+1, &ready, (fd_set *)0,
(fd_set *)0, &tout);
(void)gettimeofday(&tcur, NULL);
if (count <= 0)
break;
length = sizeof(struct sockaddr_in);
cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
0,&length);
if (cc < 0)
goto quit;
/*
* got something. See if it is ours
*/
icp = (struct icmp *)(packet + (ip->ip_hl << 2));
if (cc < sizeof(*ip)
|| icp->icmp_type != ICMP_TSTAMPREPLY
|| icp->icmp_id != oicp->icmp_id
|| icp->icmp_seq < seqno
|| icp->icmp_seq >= oicp->icmp_seq)
continue;
sendtime = ntohl(icp->icmp_otime);
recvtime = ((tcur.tv_sec % SECDAY) * 1000 +
tcur.tv_usec / 1000);
total = recvtime-sendtime;
if (total < 0) /* do not hassle midnight */
continue;
rcvcount++;
histime1 = ntohl(icp->icmp_rtime);
histime2 = ntohl(icp->icmp_ttime);
/*
* a host using a time format different from
* msec. since midnight UT (as per RFC792) should
* set the high order bit of the 32-bit time
* value it transmits.
*/
if ((histime1 & 0x80000000) != 0) {
measure_status = NONSTDTIME;
goto quit;
}
measure_status = GOOD;
idelta = recvtime-histime2;
odelta = histime1-sendtime;
/* do not be confused by midnight */
if (idelta < -MSEC_DAY/2) idelta += MSEC_DAY;
else if (idelta > MSEC_DAY/2) idelta -= MSEC_DAY;
if (odelta < -MSEC_DAY/2) odelta += MSEC_DAY;
else if (odelta > MSEC_DAY/2) odelta -= MSEC_DAY;
/* save the quantization error so that we can get a
* measurement finer than our system clock.
*/
if (total < MIN_ROUND) {
measure_delta = (odelta - idelta)/2;
goto quit;
}
if (idelta < min_idelta)
min_idelta = idelta;
if (odelta < min_odelta)
min_odelta = odelta;
measure_delta = (min_odelta - min_idelta)/2;
}
if (tcur.tv_sec > tdone.tv_sec
|| (tcur.tv_sec == tdone.tv_sec
&& tcur.tv_usec >= tdone.tv_usec))
break;
}
quit:
seqno += TRIALS; /* allocate our sequence numbers */
/*
* If no answer is received for TRIALS consecutive times,
* the machine is assumed to be down
*/
if (measure_status == GOOD) {
if (trace) {
fprintf(fd,
"measured delta %4d, %d trials to %-15s %s\n",
measure_delta, trials,
inet_ntoa(addr->sin_addr), hname);
}
} else if (print) {
if (errno != 0)
warn("measure %s", hname);
} else {
if (errno != 0) {
syslog(LOG_ERR, "measure %s: %m", hname);
} else {
syslog(LOG_ERR, "measure: %s did not respond", hname);
}
if (trace) {
fprintf(fd,
"measure: %s failed after %d trials\n",
hname, trials);
(void)fflush(fd);
}
}
return(measure_status);
}
/*
* round a number of milliseconds into a struct timeval
*/
void
mstotvround(struct timeval *res, long x)
{
if (x < 0)
x = -((-x + 3)/5);
else
x = (x+3)/5;
x *= 5;
res->tv_sec = x/1000;
res->tv_usec = (x-res->tv_sec*1000)*1000;
if (res->tv_usec < 0) {
res->tv_usec += 1000000;
res->tv_sec--;
}
}
void
timevaladd(struct timeval *tv1, struct timeval *tv2)
{
tv1->tv_sec += tv2->tv_sec;
tv1->tv_usec += tv2->tv_usec;
if (tv1->tv_usec >= 1000000) {
tv1->tv_sec++;
tv1->tv_usec -= 1000000;
}
if (tv1->tv_usec < 0) {
tv1->tv_sec--;
tv1->tv_usec += 1000000;
}
}
void
timevalsub(struct timeval *res, struct timeval *tv1, struct timeval *tv2)
{
res->tv_sec = tv1->tv_sec - tv2->tv_sec;
res->tv_usec = tv1->tv_usec - tv2->tv_usec;
if (res->tv_usec >= 1000000) {
res->tv_sec++;
res->tv_usec -= 1000000;
}
if (res->tv_usec < 0) {
res->tv_sec--;
res->tv_usec += 1000000;
}
}

View File

@ -1,262 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)networkdelta.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
static long median(float, float *, long *, long *, unsigned int);
/*
* Compute a corrected date.
* Compute the median of the reasonable differences. First compute
* the median of all authorized differences, and then compute the
* median of all differences that are reasonably close to the first
* median.
*
* This differs from the original BSD implementation, which looked for
* the largest group of machines with essentially the same date.
* That assumed that machines with bad clocks would be uniformly
* distributed. Unfortunately, in real life networks, the distribution
* of machines is not uniform among models of machines, and the
* distribution of errors in clocks tends to be quite consistent
* for a given model. In other words, all model VI Supre Servres
* from GoFast Inc. tend to have about the same error.
* The original BSD implementation would chose the clock of the
* most common model, and discard all others.
*
* Therefore, get best we can do is to try to average over all
* of the machines in the network, while discarding "obviously"
* bad values.
*/
long
networkdelta(void)
{
struct hosttbl *htp;
long med;
long lodelta, hidelta;
long logood, higood;
long x[NHOSTS];
long *xp;
int numdelta;
float eps;
/*
* compute the median of the good values
*/
med = 0;
numdelta = 1;
xp = &x[0];
*xp = 0; /* account for ourself */
for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
if (htp->good
&& htp->noanswer == 0
&& htp->delta != HOSTDOWN) {
med += htp->delta;
numdelta++;
*++xp = htp->delta;
}
}
/*
* If we are the only trusted time keeper, then do not change our
* clock. There may be another time keeping service active.
*/
if (numdelta == 1)
return 0;
med /= numdelta;
eps = med - x[0];
if (trace)
fprintf(fd, "median of %d values starting at %ld is about ",
numdelta, med);
med = median(med, &eps, &x[0], xp+1, VALID_RANGE);
/*
* compute the median of all values near the good median
*/
hidelta = med + GOOD_RANGE;
lodelta = med - GOOD_RANGE;
higood = med + VGOOD_RANGE;
logood = med - VGOOD_RANGE;
xp = &x[0];
htp = &self;
do {
if (htp->noanswer == 0
&& htp->delta >= lodelta
&& htp->delta <= hidelta
&& (htp->good
|| (htp->delta >= logood
&& htp->delta <= higood))) {
*xp++ = htp->delta;
}
} while (&self != (htp = htp->l_fwd));
if (xp == &x[0]) {
if (trace)
fprintf(fd, "nothing close to median %ld\n", med);
return med;
}
if (xp == &x[1]) {
if (trace)
fprintf(fd, "only value near median is %ld\n", x[0]);
return x[0];
}
if (trace)
fprintf(fd, "median of %td values starting at %ld is ",
xp-&x[0], med);
return median(med, &eps, &x[0], xp, 1);
}
/*
* compute the median of an array of signed integers, using the idea
* in <<Numerical Recipes>>.
*/
static long
median(float a, float *eps_ptr, long *x, long *xlim, unsigned int gnuf)
/* float a; */ /* initial guess for the median */
/* float *eps_ptr; */ /* spacing near the median */
/* long *x, *xlim; */ /* the data */
/* unsigned int gnuf; */ /* good enough estimate */
{
long *xptr;
float ap = LONG_MAX; /* bounds on the median */
float am = -LONG_MAX;
float aa;
int npts; /* # of points above & below guess */
float xp; /* closet point above the guess */
float xm; /* closet point below the guess */
float eps;
float dum, sum, sumx;
int pass;
#define AMP 1.5 /* smoothing constants */
#define AFAC 1.5
eps = *eps_ptr;
if (eps < 1.0) {
eps = -eps;
if (eps < 1.0)
eps = 1.0;
}
for (pass = 1; ; pass++) { /* loop over the data */
sum = 0.0;
sumx = 0.0;
npts = 0;
xp = LONG_MAX;
xm = -LONG_MAX;
for (xptr = x; xptr != xlim; xptr++) {
float xx = *xptr;
dum = xx - a;
if (dum != 0.0) { /* avoid dividing by 0 */
if (dum > 0.0) {
npts++;
if (xx < xp)
xp = xx;
} else {
npts--;
if (xx > xm)
xm = xx;
dum = -dum;
}
dum = 1.0/(eps + dum);
sum += dum;
sumx += xx * dum;
}
}
if (ap-am < gnuf || sum == 0) {
if (trace)
fprintf(fd,
"%ld in %d passes; early out balance=%d\n",
(long)a, pass, npts);
return a; /* guess was good enough */
}
aa = (sumx/sum-a)*AMP;
if (npts >= 2) { /* guess was too low */
am = a;
aa = xp + max(0.0, aa);
if (aa > ap)
aa = (a + ap)/2;
} else if (npts <= -2) { /* guess was two high */
ap = a;
aa = xm + min(0.0, aa);
if (aa < am)
aa = (a + am)/2;
} else {
break; /* got it */
}
if (a == aa) {
if (trace)
fprintf(fd,
"%ld in %d passes; force out balance=%d\n",
(long)a, pass, npts);
return a;
}
eps = AFAC*abs(aa - a);
*eps_ptr = eps;
a = aa;
}
if (((x - xlim) % 2) != 0) { /* even number of points? */
if (npts == 0) /* yes, return an average */
a = (xp+xm)/2;
else if (npts > 0)
a = (a+xp)/2;
else
a = (xm+a)/2;
} else if (npts != 0) { /* odd number of points */
if (npts > 0)
a = xp;
else
a = xm;
}
if (trace)
fprintf(fd, "%ld in %d passes\n", (long)a, pass);
return a;
}

View File

@ -1,39 +0,0 @@
/*-
* 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.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*
* $FreeBSD$
*/
#include <paths.h>
#define _PATH_MASTERLOG "/var/log/timed.masterlog"
#define _PATH_TIMEDLOG "/var/log/timed.log"

View File

@ -1,504 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)readmsg.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#define TSPTYPES
#include "globals.h"
/*
* LOOKAT checks if the message is of the requested type and comes from
* the right machine, returning 1 in case of affirmative answer
*/
#define LOOKAT(msg, mtype, mfrom, netp, froms) \
(((mtype) == TSP_ANY || (mtype) == (msg).tsp_type) && \
((mfrom) == 0 || !strcmp((mfrom), (msg).tsp_name)) && \
((netp) == 0 || \
((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net.s_addr))
struct timeval rtime, rwait, rtout;
struct tsp msgin;
static struct tsplist {
struct tsp info;
struct timeval when;
struct sockaddr_in addr;
struct tsplist *p;
} msgslist;
struct sockaddr_in from;
struct netinfo *fromnet;
struct timeval from_when;
/*
* `readmsg' returns message `type' sent by `machfrom' if it finds it
* either in the receive queue, or in a linked list of previously received
* messages that it maintains.
* Otherwise it waits to see if the appropriate message arrives within
* `intvl' seconds. If not, it returns NULL.
*/
struct tsp *
readmsg(int type, char *machfrom, struct timeval *intvl, struct netinfo *netfrom)
{
int length;
fd_set ready;
static struct tsplist *head = &msgslist;
static struct tsplist *tail = &msgslist;
static int msgcnt = 0;
struct tsplist *prev;
register struct netinfo *ntp;
register struct tsplist *ptr;
ssize_t n;
if (trace) {
fprintf(fd, "readmsg: looking for %s from %s, %s\n",
tsptype[type], machfrom == NULL ? "ANY" : machfrom,
netfrom == NULL ? "ANYNET" : inet_ntoa(netfrom->net));
if (head->p != NULL) {
length = 1;
for (ptr = head->p; ptr != NULL; ptr = ptr->p) {
/* do not repeat the hundreds of messages */
if (++length > 3) {
if (ptr == tail) {
fprintf(fd,"\t ...%d skipped\n",
length);
} else {
continue;
}
}
fprintf(fd, length > 1 ? "\t" : "queue:\t");
print(&ptr->info, &ptr->addr);
}
}
}
ptr = head->p;
prev = head;
/*
* Look for the requested message scanning through the
* linked list. If found, return it and free the space
*/
while (ptr != NULL) {
if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
again:
msgin = ptr->info;
from = ptr->addr;
from_when = ptr->when;
prev->p = ptr->p;
if (ptr == tail)
tail = prev;
free((char *)ptr);
fromnet = NULL;
if (netfrom == NULL)
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
if ((ntp->mask & from.sin_addr.s_addr) ==
ntp->net.s_addr) {
fromnet = ntp;
break;
}
}
else
fromnet = netfrom;
if (trace) {
fprintf(fd, "readmsg: found ");
print(&msgin, &from);
}
/* The protocol can get far behind. When it does, it gets
* hopelessly confused. So delete duplicate messages.
*/
for (ptr = prev; (ptr = ptr->p) != NULL; prev = ptr) {
if (ptr->addr.sin_addr.s_addr
== from.sin_addr.s_addr
&& ptr->info.tsp_type == msgin.tsp_type) {
if (trace)
fprintf(fd, "\tdup ");
goto again;
}
}
msgcnt--;
return(&msgin);
} else {
prev = ptr;
ptr = ptr->p;
}
}
/*
* If the message was not in the linked list, it may still be
* coming from the network. Set the timer and wait
* on a select to read the next incoming message: if it is the
* right one, return it, otherwise insert it in the linked list.
*/
(void)gettimeofday(&rtout, NULL);
timevaladd(&rtout, intvl);
FD_ZERO(&ready);
for (;;) {
(void)gettimeofday(&rtime, NULL);
timevalsub(&rwait, &rtout, &rtime);
if (rwait.tv_sec < 0)
rwait.tv_sec = rwait.tv_usec = 0;
else if (rwait.tv_sec == 0
&& rwait.tv_usec < 1000000/CLK_TCK)
rwait.tv_usec = 1000000/CLK_TCK;
if (trace) {
fprintf(fd, "readmsg: wait %jd.%6ld at %s\n",
(intmax_t)rwait.tv_sec, rwait.tv_usec, date());
/* Notice a full disk, as we flush trace info.
* It is better to flush periodically than at
* every line because the tracing consists of bursts
* of many lines. Without care, tracing slows
* down the code enough to break the protocol.
*/
if (rwait.tv_sec != 0
&& EOF == fflush(fd))
traceoff("Tracing ended for cause at %s\n");
}
FD_SET(sock, &ready);
if (!select(sock+1, &ready, (fd_set *)0, (fd_set *)0,
&rwait)) {
if (rwait.tv_sec == 0 && rwait.tv_usec == 0)
return(0);
continue;
}
length = sizeof(from);
if ((n = recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 0,
(struct sockaddr*)&from, &length)) < 0) {
syslog(LOG_ERR, "recvfrom: %m");
exit(1);
}
/*
* The 4.3BSD protocol spec had a 32-byte tsp_name field, and
* this is still OS-dependent. Demand that the packet is at
* least long enough to hold a 4.3BSD packet.
*/
if (n < (ssize_t)(sizeof(struct tsp) - MAXHOSTNAMELEN + 32)) {
syslog(LOG_NOTICE,
"short packet (%zd/%zu bytes) from %s",
n, sizeof(struct tsp) - MAXHOSTNAMELEN + 32,
inet_ntoa(from.sin_addr));
continue;
}
(void)gettimeofday(&from_when, NULL);
bytehostorder(&msgin);
if (msgin.tsp_vers > TSPVERSION) {
if (trace) {
fprintf(fd,"readmsg: version mismatch\n");
/* should do a dump of the packet */
}
continue;
}
if (memchr(msgin.tsp_name,
'\0', sizeof msgin.tsp_name) == NULL) {
syslog(LOG_NOTICE, "hostname field not NUL terminated "
"in packet from %s", inet_ntoa(from.sin_addr));
continue;
}
fromnet = NULL;
for (ntp = nettab; ntp != NULL; ntp = ntp->next)
if ((ntp->mask & from.sin_addr.s_addr) ==
ntp->net.s_addr) {
fromnet = ntp;
break;
}
/*
* drop packets from nets we are ignoring permanently
*/
if (fromnet == NULL) {
/*
* The following messages may originate on
* this host with an ignored network address
*/
if (msgin.tsp_type != TSP_TRACEON &&
msgin.tsp_type != TSP_SETDATE &&
msgin.tsp_type != TSP_MSITE &&
msgin.tsp_type != TSP_TEST &&
msgin.tsp_type != TSP_TRACEOFF) {
if (trace) {
fprintf(fd,"readmsg: discard null net ");
print(&msgin, &from);
}
continue;
}
}
/*
* Throw away messages coming from this machine,
* unless they are of some particular type.
* This gets rid of broadcast messages and reduces
* master processing time.
*/
if (!strcmp(msgin.tsp_name, hostname)
&& msgin.tsp_type != TSP_SETDATE
&& msgin.tsp_type != TSP_TEST
&& msgin.tsp_type != TSP_MSITE
&& msgin.tsp_type != TSP_TRACEON
&& msgin.tsp_type != TSP_TRACEOFF
&& msgin.tsp_type != TSP_LOOP) {
if (trace) {
fprintf(fd, "readmsg: discard own ");
print(&msgin, &from);
}
continue;
}
/*
* Send acknowledgements here; this is faster and
* avoids deadlocks that would occur if acks were
* sent from a higher level routine. Different
* acknowledgements are necessary, depending on
* status.
*/
if (fromnet == NULL) /* do not de-reference 0 */
ignoreack();
else if (fromnet->status == MASTER)
masterack();
else if (fromnet->status == SLAVE)
slaveack();
else
ignoreack();
if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
if (trace) {
fprintf(fd, "readmsg: ");
print(&msgin, &from);
}
return(&msgin);
} else if (++msgcnt > NHOSTS*3) {
/* The protocol gets hopelessly confused if it gets too far
* behind. However, it seems able to recover from all cases of lost
* packets. Therefore, if we are swamped, throw everything away.
*/
if (trace)
fprintf(fd,
"readmsg: discarding %d msgs\n",
msgcnt);
msgcnt = 0;
while ((ptr=head->p) != NULL) {
head->p = ptr->p;
free((char *)ptr);
}
tail = head;
} else {
tail->p = (struct tsplist *)
malloc(sizeof(struct tsplist));
tail = tail->p;
tail->p = NULL;
tail->info = msgin;
tail->addr = from;
/* timestamp msgs so SETTIMEs are correct */
tail->when = from_when;
}
}
}
/*
* Send the necessary acknowledgements:
* only the type ACK is to be sent by a slave
*/
void
slaveack(void)
{
switch(msgin.tsp_type) {
case TSP_ADJTIME:
case TSP_SETTIME:
case TSP_ACCEPT:
case TSP_REFUSE:
case TSP_TRACEON:
case TSP_TRACEOFF:
case TSP_QUIT:
if (trace) {
fprintf(fd, "Slaveack: ");
print(&msgin, &from);
}
xmit(TSP_ACK,msgin.tsp_seq, &from);
break;
default:
if (trace) {
fprintf(fd, "Slaveack: no ack: ");
print(&msgin, &from);
}
break;
}
}
/*
* Certain packets may arrive from this machine on ignored networks.
* These packets should be acknowledged.
*/
void
ignoreack(void)
{
switch(msgin.tsp_type) {
case TSP_TRACEON:
case TSP_TRACEOFF:
case TSP_QUIT:
if (trace) {
fprintf(fd, "Ignoreack: ");
print(&msgin, &from);
}
xmit(TSP_ACK,msgin.tsp_seq, &from);
break;
default:
if (trace) {
fprintf(fd, "Ignoreack: no ack: ");
print(&msgin, &from);
}
break;
}
}
/*
* `masterack' sends the necessary acknowledgments
* to the messages received by a master
*/
void
masterack(void)
{
struct tsp resp;
resp = msgin;
resp.tsp_vers = TSPVERSION;
(void)strcpy(resp.tsp_name, hostname);
switch(msgin.tsp_type) {
case TSP_QUIT:
case TSP_TRACEON:
case TSP_TRACEOFF:
case TSP_MSITEREQ:
if (trace) {
fprintf(fd, "Masterack: ");
print(&msgin, &from);
}
xmit(TSP_ACK,msgin.tsp_seq, &from);
break;
case TSP_RESOLVE:
case TSP_MASTERREQ:
if (trace) {
fprintf(fd, "Masterack: ");
print(&msgin, &from);
}
xmit(TSP_MASTERACK,msgin.tsp_seq, &from);
break;
default:
if (trace) {
fprintf(fd,"Masterack: no ack: ");
print(&msgin, &from);
}
break;
}
}
/*
* Print a TSP message
*/
void
print(struct tsp *msg, struct sockaddr_in *addr)
{
char tm[26];
time_t tsp_time_sec;
if (msg->tsp_type >= TSPTYPENUMBER) {
fprintf(fd, "bad type (%u) on packet from %s\n",
msg->tsp_type, inet_ntoa(addr->sin_addr));
return;
}
switch (msg->tsp_type) {
case TSP_LOOP:
fprintf(fd, "%s %d %-6u #%d %-15s %s\n",
tsptype[msg->tsp_type],
msg->tsp_vers,
msg->tsp_seq,
msg->tsp_hopcnt,
inet_ntoa(addr->sin_addr),
msg->tsp_name);
break;
case TSP_SETTIME:
case TSP_SETDATE:
case TSP_SETDATEREQ:
tsp_time_sec = msg->tsp_time.tv_sec;
strncpy(tm, ctime(&tsp_time_sec)+3+1, sizeof(tm));
tm[15] = '\0'; /* ugh */
fprintf(fd, "%s %d %-6u %s %-15s %s\n",
tsptype[msg->tsp_type],
msg->tsp_vers,
msg->tsp_seq,
tm,
inet_ntoa(addr->sin_addr),
msg->tsp_name);
break;
case TSP_ADJTIME:
fprintf(fd, "%s %d %-6u (%d,%d) %-15s %s\n",
tsptype[msg->tsp_type],
msg->tsp_vers,
msg->tsp_seq,
msg->tsp_time.tv_sec,
msg->tsp_time.tv_usec,
inet_ntoa(addr->sin_addr),
msg->tsp_name);
break;
default:
fprintf(fd, "%s %d %-6u %-15s %s\n",
tsptype[msg->tsp_type],
msg->tsp_vers,
msg->tsp_seq,
inet_ntoa(addr->sin_addr),
msg->tsp_name);
break;
}
}

View File

@ -1,695 +0,0 @@
/*-
* 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
#if 0
static char sccsid[] = "@(#)slave.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "globals.h"
#include <setjmp.h>
#include <utmpx.h>
#include "pathnames.h"
extern jmp_buf jmpenv;
extern int Mflag;
extern int justquit;
extern u_short sequence;
static char master_name[MAXHOSTNAMELEN];
static struct netinfo *old_slavenet;
static int old_status;
static void schgdate(struct tsp *, char *);
static void setmaster(struct tsp *);
static void answerdelay(void);
void
slave(void)
{
int tries;
long electiontime, refusetime, looktime, looptime, adjtime;
u_short seq;
long fastelection;
#define FASTTOUT 3
struct in_addr cadr;
struct timeval otime;
struct sockaddr_in taddr;
char tname[MAXHOSTNAMELEN];
struct tsp *msg, to;
struct timeval ntime, wait, tmptv;
time_t tsp_time_sec;
struct tsp *answer;
int timeout();
char olddate[32];
char newdate[32];
struct netinfo *ntp;
struct hosttbl *htp;
struct utmpx utx;
old_slavenet = NULL;
seq = 0;
refusetime = 0;
adjtime = 0;
(void)gettimeofday(&ntime, NULL);
electiontime = ntime.tv_sec + delay2;
fastelection = ntime.tv_sec + FASTTOUT;
if (justquit)
looktime = electiontime;
else
looktime = fastelection;
looptime = fastelection;
if (slavenet)
xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr);
if (status & MASTER) {
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
if (ntp->status == MASTER)
masterup(ntp);
}
}
loop:
get_goodgroup(0);
(void)gettimeofday(&ntime, NULL);
if (ntime.tv_sec > electiontime) {
if (trace)
fprintf(fd, "election timer expired\n");
longjmp(jmpenv, 1);
}
if (ntime.tv_sec >= looktime) {
if (trace)
fprintf(fd, "Looking for nets to master\n");
if (Mflag && nignorednets > 0) {
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
if (ntp->status == IGNORE
|| ntp->status == NOMASTER) {
lookformaster(ntp);
if (ntp->status == MASTER) {
masterup(ntp);
} else if (ntp->status == MASTER) {
ntp->status = NOMASTER;
}
}
if (ntp->status == MASTER
&& --ntp->quit_count < 0)
ntp->quit_count = 0;
}
makeslave(slavenet); /* prune extras */
setstatus();
}
(void)gettimeofday(&ntime, NULL);
looktime = ntime.tv_sec + delay2;
}
if (ntime.tv_sec >= looptime) {
if (trace)
fprintf(fd, "Looking for loops\n");
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
if (ntp->status == MASTER) {
to.tsp_type = TSP_LOOP;
to.tsp_vers = TSPVERSION;
to.tsp_seq = sequence++;
to.tsp_hopcnt = MAX_HOPCNT;
(void)strcpy(to.tsp_name, hostname);
bytenetorder(&to);
if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
(struct sockaddr*)&ntp->dest_addr,
sizeof(ntp->dest_addr)) < 0) {
trace_sendto_err(ntp->dest_addr.sin_addr);
}
}
}
(void)gettimeofday(&ntime, NULL);
looptime = ntime.tv_sec + delay2;
}
wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec;
if (wait.tv_sec < 0)
wait.tv_sec = 0;
wait.tv_sec += FASTTOUT;
wait.tv_usec = 0;
msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
if (msg != NULL) {
/*
* filter stuff not for us
*/
switch (msg->tsp_type) {
case TSP_SETDATE:
case TSP_TRACEOFF:
case TSP_TRACEON:
/*
* XXX check to see they are from ourself
*/
break;
case TSP_TEST:
case TSP_MSITE:
break;
case TSP_MASTERUP:
if (!fromnet) {
if (trace) {
fprintf(fd, "slave ignored: ");
print(msg, &from);
}
goto loop;
}
break;
default:
if (!fromnet
|| fromnet->status == IGNORE
|| fromnet->status == NOMASTER) {
if (trace) {
fprintf(fd, "slave ignored: ");
print(msg, &from);
}
goto loop;
}
break;
}
/*
* now process the message
*/
switch (msg->tsp_type) {
case TSP_ADJTIME:
if (fromnet != slavenet)
break;
if (!good_host_name(msg->tsp_name)) {
syslog(LOG_NOTICE,
"attempted time adjustment by %s",
msg->tsp_name);
suppress(&from, msg->tsp_name, fromnet);
break;
}
/*
* Speed up loop detection in case we have a loop.
* Otherwise the clocks can race until the loop
* is found.
*/
(void)gettimeofday(&otime, NULL);
if (adjtime < otime.tv_sec)
looptime -= (looptime-otime.tv_sec)/2 + 1;
setmaster(msg);
if (seq != msg->tsp_seq) {
seq = msg->tsp_seq;
synch(tvtomsround(msg->tsp_time));
}
(void)gettimeofday(&ntime, NULL);
electiontime = ntime.tv_sec + delay2;
fastelection = ntime.tv_sec + FASTTOUT;
adjtime = ntime.tv_sec + SAMPLEINTVL*2;
break;
case TSP_SETTIME:
if (fromnet != slavenet)
break;
if (seq == msg->tsp_seq)
break;
seq = msg->tsp_seq;
/* adjust time for residence on the queue */
(void)gettimeofday(&otime, NULL);
adj_msg_time(msg,&otime);
/*
* the following line is necessary due to syslog
* calling ctime() which clobbers the static buffer
*/
(void)strlcpy(olddate, date(), sizeof(olddate));
tsp_time_sec = msg->tsp_time.tv_sec;
(void)strlcpy(newdate, ctime(&tsp_time_sec),
sizeof(newdate));
if (!good_host_name(msg->tsp_name)) {
syslog(LOG_NOTICE,
"attempted time setting by untrusted %s to %s",
msg->tsp_name, newdate);
suppress(&from, msg->tsp_name, fromnet);
break;
}
setmaster(msg);
tmptv.tv_sec = msg->tsp_time.tv_sec;
tmptv.tv_usec = msg->tsp_time.tv_usec;
timevalsub(&ntime, &tmptv, &otime);
if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
/*
* do not change the clock if we can adjust it
*/
synch(tvtomsround(ntime));
} else {
utx.ut_type = OLD_TIME;
gettimeofday(&utx.ut_tv, NULL);
pututxline(&utx);
(void)settimeofday(&tmptv, 0);
utx.ut_type = NEW_TIME;
gettimeofday(&utx.ut_tv, NULL);
pututxline(&utx);
syslog(LOG_NOTICE,
"date changed by %s from %s",
msg->tsp_name, olddate);
if (status & MASTER)
spreadtime();
}
(void)gettimeofday(&ntime, NULL);
electiontime = ntime.tv_sec + delay2;
fastelection = ntime.tv_sec + FASTTOUT;
/* This patches a bad protocol bug. Imagine a system with several networks,
* where there are a pair of redundant gateways between a pair of networks,
* each running timed. Assume that we start with a third machine mastering
* one of the networks, and one of the gateways mastering the other.
* Imagine that the third machine goes away and the non-master gateway
* decides to replace it. If things are timed just 'right,' we will have
* each gateway mastering one network for a little while. If a SETTIME
* message gets into the network at that time, perhaps from the newly
* masterful gateway as it was taking control, the SETTIME will loop
* forever. Each time a gateway receives it on its slave side, it will
* call spreadtime to forward it on its mastered network. We are now in
* a permanent loop, since the SETTIME msgs will keep any clock
* in the network from advancing. Normally, the 'LOOP' stuff will detect
* and correct the situation. However, with the clocks stopped, the
* 'looptime' timer cannot expire. While they are in this state, the
* masters will try to saturate the network with SETTIME packets.
*/
looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1;
break;
case TSP_MASTERUP:
if (slavenet && fromnet != slavenet)
break;
if (!good_host_name(msg->tsp_name)) {
suppress(&from, msg->tsp_name, fromnet);
if (electiontime > fastelection)
electiontime = fastelection;
break;
}
makeslave(fromnet);
setmaster(msg);
setstatus();
answerdelay();
xmit(TSP_SLAVEUP, 0, &from);
(void)gettimeofday(&ntime, NULL);
electiontime = ntime.tv_sec + delay2;
fastelection = ntime.tv_sec + FASTTOUT;
refusetime = 0;
break;
case TSP_MASTERREQ:
if (fromnet->status != SLAVE)
break;
(void)gettimeofday(&ntime, NULL);
electiontime = ntime.tv_sec + delay2;
break;
case TSP_SETDATE:
tsp_time_sec = msg->tsp_time.tv_sec;
(void)strlcpy(newdate, ctime(&tsp_time_sec),
sizeof(newdate));
schgdate(msg, newdate);
break;
case TSP_SETDATEREQ:
if (fromnet->status != MASTER)
break;
tsp_time_sec = msg->tsp_time.tv_sec;
(void)strlcpy(newdate, ctime(&tsp_time_sec),
sizeof(newdate));
htp = findhost(msg->tsp_name);
if (htp == NULL) {
syslog(LOG_WARNING,
"DATEREQ from uncontrolled machine");
break;
}
if (!htp->good) {
syslog(LOG_WARNING,
"attempted date change by untrusted %s to %s",
htp->name, newdate);
spreadtime();
break;
}
schgdate(msg, newdate);
break;
case TSP_TRACEON:
traceon();
break;
case TSP_TRACEOFF:
traceoff("Tracing ended at %s\n");
break;
case TSP_SLAVEUP:
newslave(msg);
break;
case TSP_ELECTION:
if (fromnet->status == SLAVE) {
(void)gettimeofday(&ntime, NULL);
electiontime = ntime.tv_sec + delay2;
fastelection = ntime.tv_sec + FASTTOUT;
seq = 0;
if (!good_host_name(msg->tsp_name)) {
syslog(LOG_NOTICE,
"suppress election of %s",
msg->tsp_name);
to.tsp_type = TSP_QUIT;
electiontime = fastelection;
} else if (cadr.s_addr != from.sin_addr.s_addr
&& ntime.tv_sec < refusetime) {
/* if the candidate has to repeat itself, the old code would refuse it
* the second time. That would prevent elections.
*/
to.tsp_type = TSP_REFUSE;
} else {
cadr.s_addr = from.sin_addr.s_addr;
to.tsp_type = TSP_ACCEPT;
refusetime = ntime.tv_sec + 30;
}
taddr = from;
(void)strcpy(tname, msg->tsp_name);
(void)strcpy(to.tsp_name, hostname);
answerdelay();
if (!acksend(&to, &taddr, tname,
TSP_ACK, 0, 0))
syslog(LOG_WARNING,
"no answer from candidate %s\n",
tname);
} else { /* fromnet->status == MASTER */
htp = addmach(msg->tsp_name, &from,fromnet);
to.tsp_type = TSP_QUIT;
(void)strcpy(to.tsp_name, hostname);
if (!acksend(&to, &htp->addr, htp->name,
TSP_ACK, 0, htp->noanswer)) {
syslog(LOG_ERR,
"no reply from %s to ELECTION-QUIT",
htp->name);
(void)remmach(htp);
}
}
break;
case TSP_CONFLICT:
if (fromnet->status != MASTER)
break;
/*
* After a network partition, there can be
* more than one master: the first slave to
* come up will notify here the situation.
*/
(void)strcpy(to.tsp_name, hostname);
/* The other master often gets into the same state,
* with boring results.
*/
ntp = fromnet; /* (acksend() can leave fromnet=0 */
for (tries = 0; tries < 3; tries++) {
to.tsp_type = TSP_RESOLVE;
answer = acksend(&to, &ntp->dest_addr,
ANYADDR, TSP_MASTERACK,
ntp, 0);
if (answer == NULL)
break;
htp = addmach(answer->tsp_name,&from,ntp);
to.tsp_type = TSP_QUIT;
answer = acksend(&to, &htp->addr, htp->name,
TSP_ACK, 0, htp->noanswer);
if (!answer) {
syslog(LOG_WARNING,
"conflict error: no reply from %s to QUIT",
htp->name);
(void)remmach(htp);
}
}
masterup(ntp);
break;
case TSP_MSITE:
if (!slavenet)
break;
taddr = from;
to.tsp_type = TSP_MSITEREQ;
to.tsp_vers = TSPVERSION;
to.tsp_seq = 0;
(void)strcpy(to.tsp_name, hostname);
answer = acksend(&to, &slavenet->dest_addr,
ANYADDR, TSP_ACK,
slavenet, 0);
if (answer != NULL
&& good_host_name(answer->tsp_name)) {
setmaster(answer);
to.tsp_type = TSP_ACK;
(void)strcpy(to.tsp_name, answer->tsp_name);
bytenetorder(&to);
if (sendto(sock, (char *)&to,
sizeof(struct tsp), 0,
(struct sockaddr*)&taddr,
sizeof(taddr)) < 0) {
trace_sendto_err(taddr.sin_addr);
}
}
break;
case TSP_MSITEREQ:
break;
case TSP_ACCEPT:
case TSP_REFUSE:
case TSP_RESOLVE:
break;
case TSP_QUIT:
doquit(msg); /* become a slave */
break;
case TSP_TEST:
electiontime = 0;
break;
case TSP_LOOP:
/* looking for loops of masters */
if (!(status & MASTER))
break;
if (fromnet->status == SLAVE) {
if (!strcmp(msg->tsp_name, hostname)) {
/*
* Someone forwarded our message back to
* us. There must be a loop. Tell the
* master of this network to quit.
*
* The other master often gets into
* the same state, with boring results.
*/
ntp = fromnet;
for (tries = 0; tries < 3; tries++) {
to.tsp_type = TSP_RESOLVE;
answer = acksend(&to, &ntp->dest_addr,
ANYADDR, TSP_MASTERACK,
ntp,0);
if (answer == NULL)
break;
taddr = from;
(void)strcpy(tname, answer->tsp_name);
to.tsp_type = TSP_QUIT;
(void)strcpy(to.tsp_name, hostname);
if (!acksend(&to, &taddr, tname,
TSP_ACK, 0, 1)) {
syslog(LOG_ERR,
"no reply from %s to slave LOOP-QUIT",
tname);
} else {
electiontime = 0;
}
}
(void)gettimeofday(&ntime, NULL);
looptime = ntime.tv_sec + FASTTOUT;
} else {
if (msg->tsp_hopcnt-- < 1)
break;
bytenetorder(msg);
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
if (ntp->status == MASTER
&& 0 > sendto(sock, (char *)msg,
sizeof(struct tsp), 0,
(struct sockaddr*)&ntp->dest_addr,
sizeof(ntp->dest_addr)))
trace_sendto_err(ntp->dest_addr.sin_addr);
}
}
} else { /* fromnet->status == MASTER */
/*
* We should not have received this from a net
* we are master on. There must be two masters,
* unless the packet was really from us.
*/
if (from.sin_addr.s_addr
== fromnet->my_addr.s_addr) {
if (trace)
fprintf(fd,"discarding forwarded LOOP\n");
break;
}
/*
* The other master often gets into the same
* state, with boring results.
*/
ntp = fromnet;
for (tries = 0; tries < 3; tries++) {
to.tsp_type = TSP_RESOLVE;
answer = acksend(&to, &ntp->dest_addr,
ANYADDR, TSP_MASTERACK,
ntp,0);
if (!answer)
break;
htp = addmach(answer->tsp_name,
&from,ntp);
to.tsp_type = TSP_QUIT;
(void)strcpy(to.tsp_name, hostname);
if (!acksend(&to,&htp->addr,htp->name,
TSP_ACK, 0, htp->noanswer)) {
syslog(LOG_ERR,
"no reply from %s to master LOOP-QUIT",
htp->name);
(void)remmach(htp);
}
}
(void)gettimeofday(&ntime, NULL);
looptime = ntime.tv_sec + FASTTOUT;
}
break;
default:
if (trace) {
fprintf(fd, "garbage message: ");
print(msg, &from);
}
break;
}
}
goto loop;
}
/*
* tell the world who our master is
*/
static void
setmaster(struct tsp *msg)
{
if (slavenet
&& (slavenet != old_slavenet
|| strcmp(msg->tsp_name, master_name)
|| old_status != status)) {
(void)strcpy(master_name, msg->tsp_name);
old_slavenet = slavenet;
old_status = status;
if (status & MASTER) {
syslog(LOG_NOTICE, "submaster to %s", master_name);
if (trace)
fprintf(fd, "submaster to %s\n", master_name);
} else {
syslog(LOG_NOTICE, "slave to %s", master_name);
if (trace)
fprintf(fd, "slave to %s\n", master_name);
}
}
}
/*
* handle date change request on a slave
*/
static void
schgdate(struct tsp *msg, char *newdate)
{
struct tsp to;
u_short seq;
struct sockaddr_in taddr;
struct timeval otime;
if (!slavenet)
return; /* no where to forward */
taddr = from;
seq = msg->tsp_seq;
syslog(LOG_INFO,
"forwarding date change by %s to %s",
msg->tsp_name, newdate);
/* adjust time for residence on the queue */
(void)gettimeofday(&otime, NULL);
adj_msg_time(msg, &otime);
to.tsp_type = TSP_SETDATEREQ;
to.tsp_time = msg->tsp_time;
(void)strcpy(to.tsp_name, hostname);
if (!acksend(&to, &slavenet->dest_addr,
ANYADDR, TSP_DATEACK,
slavenet, 0))
return; /* no answer */
xmit(TSP_DATEACK, seq, &taddr);
}
/*
* Used before answering a broadcast message to avoid network
* contention and likely collisions.
*/
static void
answerdelay(void)
{
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = delay1;
(void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
&timeout);
return;
}

View File

@ -1,288 +0,0 @@
.\" 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 .

View File

@ -1,832 +0,0 @@
/*-
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "globals.h"
#include <net/if.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <setjmp.h>
#include "pathnames.h"
#include <math.h>
#include <sys/types.h>
#include <sys/times.h>
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();
/* 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 */
}

View File

@ -1,15 +0,0 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
.PATH: ${.CURDIR:H}/timed
PROG= timedc
MAN= timedc.8
SRCS= cmds.c cmdtab.c timedc.c byteorder.c measure.c cksum.c
BINOWN= root
BINMODE= 4555
WARNS?= 1
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View File

@ -1,19 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
include \
include/arpa \
include/protocols \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -1,544 +0,0 @@
/*-
* 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.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "timedc.h"
#include <sys/file.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define TSPTYPES
#include <protocols/timed.h>
#define SECHR (60*60)
#define SECDAY (24*SECHR)
# define DATE_PROTO "udp"
# define DATE_PORT "time"
int sock;
int sock_raw;
char myname[MAXHOSTNAMELEN];
struct hostent *hp;
struct sockaddr_in server;
struct sockaddr_in dayaddr;
extern int measure_delta;
void bytenetorder(struct tsp *);
void bytehostorder(struct tsp *);
#define BU (2208988800UL) /* seconds before UNIX epoch */
/* compute the difference between our date and another machine
*/
static int /* difference in days from our time */
daydiff(char *hostname)
{
int i;
int trials;
struct timeval tout, now;
fd_set ready;
struct sockaddr from;
int fromlen;
unsigned long sec;
/* wait 2 seconds between 10 tries */
tout.tv_sec = 2;
tout.tv_usec = 0;
for (trials = 0; trials < 10; trials++) {
/* ask for the time */
sec = 0;
if (sendto(sock, &sec, sizeof(sec), 0,
(struct sockaddr*)&dayaddr, sizeof(dayaddr)) < 0) {
warn("sendto(sock)");
return 0;
}
for (;;) {
FD_ZERO(&ready);
FD_SET(sock, &ready);
i = select(sock+1, &ready, (fd_set *)0,
(fd_set *)0, &tout);
if (i < 0) {
if (errno == EINTR)
continue;
warn("select(date read)");
return 0;
}
if (0 == i)
break;
fromlen = sizeof(from);
if (recvfrom(sock,&sec,sizeof(sec),0,
&from,&fromlen) < 0) {
warn("recvfrom(date read)");
return 0;
}
sec = ntohl(sec);
if (sec < BU) {
warnx("%s says it is before 1970: %lu",
hostname, sec);
return 0;
}
sec -= BU;
(void)gettimeofday(&now, NULL);
return (sec - now.tv_sec);
}
}
/* if we get here, we tried too many times */
warnx("%s will not tell us the date", hostname);
return 0;
}
/*
* Clockdiff computes the difference between the time of the machine on
* which it is called and the time of the machines given as argument.
* The time differences measured by clockdiff are obtained using a sequence
* of ICMP TSTAMP messages which are returned to the sender by the IP module
* in the remote machine.
* In order to compare clocks of machines in different time zones, the time
* is transmitted (as a 32-bit value) in milliseconds since midnight UT.
* If a hosts uses a different time format, it should set the high order
* bit of the 32-bit quantity it transmits.
* However, VMS apparently transmits the time in milliseconds since midnight
* local time (rather than GMT) without setting the high order bit.
* Furthermore, it does not understand daylight-saving time. This makes
* clockdiff behaving inconsistently with hosts running VMS.
*
* In order to reduce the sensitivity to the variance of message transmission
* time, clockdiff sends a sequence of messages. Yet, measures between
* two `distant' hosts can be affected by a small error. The error can,
* however, be reduced by increasing the number of messages sent in each
* measurement.
*/
void
clockdiff(int argc, char *argv[])
{
int measure_status;
extern int measure(u_long, u_long, char *, struct sockaddr_in*, int);
register int avg_cnt;
register long avg;
struct servent *sp;
if (argc < 2) {
printf("usage: timedc clockdiff host ...\n");
return;
}
if (gethostname(myname, sizeof(myname) - 1) < 0)
err(1, "gethostname");
/* get the address for the date ready */
sp = getservbyname(DATE_PORT, DATE_PROTO);
if (!sp) {
warnx("%s/%s: unknown service", DATE_PORT, DATE_PROTO);
dayaddr.sin_port = 0;
} else {
dayaddr.sin_port = sp->s_port;
}
while (argc > 1) {
argc--; argv++;
hp = gethostbyname(*argv);
if (hp == NULL) {
warnx("%s: %s", *argv, hstrerror(h_errno));
continue;
}
server.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, &server.sin_addr.s_addr, hp->h_length);
for (avg_cnt = 0, avg = 0; avg_cnt < 16; avg_cnt++) {
measure_status = measure(10000,100, *argv, &server, 1);
if (measure_status != GOOD)
break;
avg += measure_delta;
}
if (measure_status == GOOD)
measure_delta = avg/avg_cnt;
switch (measure_status) {
case HOSTDOWN:
printf("%s is down\n", hp->h_name);
continue;
case NONSTDTIME:
printf("%s transmits a non-standard time format\n",
hp->h_name);
continue;
case UNREACHABLE:
printf("%s is unreachable\n", hp->h_name);
continue;
}
/*
* Try to get the date only after using ICMP timestamps to
* get the time. This is because the date protocol
* is optional.
*/
if (dayaddr.sin_port != 0) {
dayaddr.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, &dayaddr.sin_addr.s_addr,
hp->h_length);
avg = daydiff(*argv);
if (avg > SECDAY) {
printf("time on %s is %ld days ahead %s\n",
hp->h_name, avg/SECDAY, myname);
continue;
} else if (avg < -SECDAY) {
printf("time on %s is %ld days behind %s\n",
hp->h_name, -avg/SECDAY, myname);
continue;
}
}
if (measure_delta > 0) {
printf("time on %s is %d ms. ahead of time on %s\n",
hp->h_name, measure_delta, myname);
} else if (measure_delta == 0) {
printf("%s and %s have the same time\n",
hp->h_name, myname);
} else {
printf("time on %s is %d ms. behind time on %s\n",
hp->h_name, -measure_delta, myname);
}
}
return;
}
/*
* finds location of master timedaemon
*/
void
msite(int argc, char *argv[])
{
ssize_t cc;
fd_set ready;
struct sockaddr_in dest;
int i, length;
struct sockaddr_in from;
struct timeval tout;
struct tsp msg;
struct servent *srvp;
char *tgtname;
if (argc < 1) {
printf("usage: timedc msite [host ...]\n");
return;
}
srvp = getservbyname("timed", "udp");
if (srvp == NULL) {
warnx("timed/udp: unknown service");
return;
}
dest.sin_port = srvp->s_port;
dest.sin_family = AF_INET;
if (gethostname(myname, sizeof(myname) - 1) < 0)
err(1, "gethostname");
i = 1;
do {
tgtname = (i >= argc) ? myname : argv[i];
hp = gethostbyname(tgtname);
if (hp == NULL) {
warnx("%s: %s", tgtname, hstrerror(h_errno));
continue;
}
bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
(void)strlcpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
msg.tsp_type = TSP_MSITE;
msg.tsp_vers = TSPVERSION;
bytenetorder(&msg);
if (sendto(sock, &msg, sizeof(struct tsp), 0,
(struct sockaddr*)&dest,
sizeof(struct sockaddr)) < 0) {
warn("sendto");
continue;
}
tout.tv_sec = 15;
tout.tv_usec = 0;
FD_ZERO(&ready);
FD_SET(sock, &ready);
if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
&tout)) {
length = sizeof(from);
cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
(struct sockaddr *)&from, &length);
if (cc < 0) {
warn("recvfrom");
continue;
}
/*
* The 4.3BSD protocol spec had a 32-byte tsp_name field, and
* this is still OS-dependent. Demand that the packet is at
* least long enough to hold a 4.3BSD packet.
*/
if (cc < (sizeof(struct tsp) - MAXHOSTNAMELEN + 32)) {
fprintf(stderr,
"short packet (%zd/%zu bytes) from %s\n",
cc, sizeof(struct tsp) - MAXHOSTNAMELEN + 32,
inet_ntoa(from.sin_addr));
continue;
}
bytehostorder(&msg);
if (msg.tsp_type == TSP_ACK) {
printf("master timedaemon at %s is %s\n",
tgtname, msg.tsp_name);
} else {
if (msg.tsp_type >= TSPTYPENUMBER)
printf("unknown ack received: %u\n",
msg.tsp_type);
else
printf("wrong ack received: %s\n",
tsptype[msg.tsp_type]);
}
} else {
printf("communication error with %s\n", tgtname);
}
} while (++i < argc);
}
/*
* quits timedc
*/
void
quit(void)
{
exit(0);
}
/*
* Causes the election timer to expire on the selected hosts
* It sends just one udp message per machine, relying on
* reliability of communication channel.
*/
void
testing(int argc, char *argv[])
{
struct servent *srvp;
struct sockaddr_in sin;
struct tsp msg;
if (argc < 2) {
printf("usage: timedc election host1 [host2 ...]\n");
return;
}
srvp = getservbyname("timed", "udp");
if (srvp == NULL) {
warnx("timed/udp: unknown service");
return;
}
while (argc > 1) {
argc--; argv++;
hp = gethostbyname(*argv);
if (hp == NULL) {
warnx("%s: %s", *argv, hstrerror(h_errno));
argc--; argv++;
continue;
}
sin.sin_port = srvp->s_port;
sin.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, &sin.sin_addr.s_addr, hp->h_length);
msg.tsp_type = TSP_TEST;
msg.tsp_vers = TSPVERSION;
if (gethostname(myname, sizeof(myname) - 1) < 0)
err(1, "gethostname");
(void)strlcpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
bytenetorder(&msg);
if (sendto(sock, &msg, sizeof(struct tsp), 0,
(struct sockaddr*)&sin,
sizeof(struct sockaddr)) < 0) {
warn("sendto");
}
}
}
/*
* Enables or disables tracing on local timedaemon
*/
void
tracing(int argc, char *argv[])
{
int onflag;
int length;
ssize_t cc;
fd_set ready;
struct sockaddr_in dest;
struct sockaddr_in from;
struct timeval tout;
struct tsp msg;
struct servent *srvp;
if (argc != 2) {
printf("usage: timedc trace { on | off }\n");
return;
}
srvp = getservbyname("timed", "udp");
if (srvp == NULL) {
warnx("timed/udp: unknown service");
return;
}
dest.sin_port = srvp->s_port;
dest.sin_family = AF_INET;
if (gethostname(myname, sizeof(myname) - 1) < 0)
err(1, "gethostname");
hp = gethostbyname(myname);
bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
if (strcmp(argv[1], "on") == 0) {
msg.tsp_type = TSP_TRACEON;
onflag = ON;
} else {
msg.tsp_type = TSP_TRACEOFF;
onflag = OFF;
}
(void)strcpy(msg.tsp_name, myname);
msg.tsp_vers = TSPVERSION;
bytenetorder(&msg);
if (sendto(sock, &msg, sizeof(struct tsp), 0,
(struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) {
warn("sendto");
return;
}
tout.tv_sec = 5;
tout.tv_usec = 0;
FD_ZERO(&ready);
FD_SET(sock, &ready);
if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
length = sizeof(from);
cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
(struct sockaddr *)&from, &length);
if (cc < 0) {
warn("recvfrom");
return;
}
/*
* The 4.3BSD protocol spec had a 32-byte tsp_name field, and
* this is still OS-dependent. Demand that the packet is at
* least long enough to hold a 4.3BSD packet.
*/
if (cc < (sizeof(struct tsp) - MAXHOSTNAMELEN + 32)) {
fprintf(stderr, "short packet (%zd/%zu bytes) from %s\n",
cc, sizeof(struct tsp) - MAXHOSTNAMELEN + 32,
inet_ntoa(from.sin_addr));
return;
}
bytehostorder(&msg);
if (msg.tsp_type == TSP_ACK)
if (onflag)
printf("timed tracing enabled\n");
else
printf("timed tracing disabled\n");
else {
if (msg.tsp_type >= TSPTYPENUMBER)
printf("unknown ack received: %u\n",
msg.tsp_type);
else
printf("wrong ack received: %s\n",
tsptype[msg.tsp_type]);
}
} else
printf("communication error\n");
}
int
priv_resources(void)
{
int port;
struct sockaddr_in sin;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
warn("opening socket");
return(-1);
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
sin.sin_port = htons((u_short)port);
if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0)
break;
if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
warn("bind");
(void) close(sock);
return(-1);
}
}
if (port == IPPORT_RESERVED / 2) {
warnx("all reserved ports in use");
(void) close(sock);
return(-1);
}
sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sock_raw < 0) {
warn("opening raw socket");
(void) close(sock);
return(-1);
}
return(1);
}

View File

@ -1,59 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1983, 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
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "timedc.h"
char clockdiffhelp[] = "measures clock differences between machines";
char helphelp[] = "gets help on commands";
char msitehelp[] = "finds location of master";
char quithelp[] = "exits timedc";
char testinghelp[] = "causes election timers to expire";
char tracinghelp[] = "turns tracing on or off";
struct cmd cmdtab[] = {
{ "clockdiff", clockdiffhelp, clockdiff, 0 },
{ "election", testinghelp, testing, 1 },
{ "help", helphelp, help, 0 },
{ "msite", msitehelp, msite, 0 },
{ "quit", quithelp, quit, 0 },
{ "trace", tracinghelp, tracing, 1 },
{ "?", helphelp, help, 0 },
};
int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]);

View File

@ -1,52 +0,0 @@
/* $FreeBSD$ */
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 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.
*
* @(#)extern.h 8.1 (Berkeley) 6/6/93
*/
#if __STDC__
struct tsp;
#endif
extern struct cmd cmdtab[];
void bytehostorder(struct tsp *);
void bytenetorder(struct tsp *);
void clockdiff(int, char *[]);
void help(int, char *[]);
void intr(int);
void makeargv(void);
void msite(int, char *[]);
int priv_resources(void);
void quit(void);
void testing(int, char *[]);
void tracing(int, char *[]);

View File

@ -1,141 +0,0 @@
.\" 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 .

View File

@ -1,254 +0,0 @@
/*-
* 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 <ctype.h>
#include <err.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
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 (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);
}
}

View File

@ -1,61 +0,0 @@
/*-
* 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.
*
* @(#)timedc.h 8.1 (Berkeley) 6/6/93
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#define ON 1
#define OFF 0
#define GOOD 1
#define UNREACHABLE 2
#define NONSTDTIME 3
#define HOSTDOWN 0x7fffffff
struct cmd {
char *c_name; /* command name */
char *c_help; /* help message */
void (*c_handler)(); /* routine to do the work */
int c_priv; /* privileged command */
};
#include "extern.h"