mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
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:
parent
17ca94cfc0
commit
53fc043d41
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342139
|
@ -38,6 +38,12 @@
|
||||||
# xargs -n1 | sort | uniq -d;
|
# xargs -n1 | sort | uniq -d;
|
||||||
# done
|
# 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.
|
# 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/allocator_interface.h
|
||||||
OLD_FILES+=usr/lib/clang/6.0.1/include/sanitizer/asan_interface.h
|
OLD_FILES+=usr/lib/clang/6.0.1/include/sanitizer/asan_interface.h
|
||||||
|
|
4
UPDATING
4
UPDATING
|
@ -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
|
prerequisites and upgrading, if you are not already using clang 3.5.0
|
||||||
or higher.
|
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:
|
20181126:
|
||||||
On amd64, arm64 and armv7 (architectures that install LLVM's ld.lld
|
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
|
linker as /usr/bin/ld) GNU ld is no longer installed as ld.bfd, as
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
PACKAGE=runtime
|
PACKAGE=runtime
|
||||||
PROG= date
|
PROG= date
|
||||||
SRCS= date.c netdate.c vary.c
|
SRCS= date.c vary.c
|
||||||
|
|
||||||
HAS_TESTS=
|
HAS_TESTS=
|
||||||
SUBDIR.${MK_TESTS}+= tests
|
SUBDIR.${MK_TESTS}+= tests
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
DIRDEPS = \
|
DIRDEPS = \
|
||||||
gnu/lib/csu \
|
gnu/lib/csu \
|
||||||
include \
|
include \
|
||||||
include/protocols \
|
|
||||||
include/xlocale \
|
include/xlocale \
|
||||||
lib/${CSU_DIR} \
|
lib/${CSU_DIR} \
|
||||||
lib/libc \
|
lib/libc \
|
||||||
|
|
|
@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utmpx.h>
|
#include <utmpx.h>
|
||||||
|
|
||||||
#include "extern.h"
|
|
||||||
#include "vary.h"
|
#include "vary.h"
|
||||||
|
|
||||||
#ifndef TM_YEAR_BASE
|
#ifndef TM_YEAR_BASE
|
||||||
|
@ -67,7 +66,6 @@ __FBSDID("$FreeBSD$");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static time_t tval;
|
static time_t tval;
|
||||||
int retval;
|
|
||||||
|
|
||||||
static void badformat(void);
|
static void badformat(void);
|
||||||
static void iso8601_usage(const char *);
|
static void iso8601_usage(const char *);
|
||||||
|
@ -248,7 +246,7 @@ printdate(const char *buf)
|
||||||
(void)printf("%s\n", buf);
|
(void)printf("%s\n", buf);
|
||||||
if (fflush(stdout))
|
if (fflush(stdout))
|
||||||
err(1, "stdout");
|
err(1, "stdout");
|
||||||
exit(retval);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -370,7 +368,7 @@ setthetime(const char *fmt, const char *p, int jflag, int nflag)
|
||||||
|
|
||||||
if (!jflag) {
|
if (!jflag) {
|
||||||
/* set the time */
|
/* set the time */
|
||||||
if (nflag || netsettime(tval)) {
|
if (nflag) {
|
||||||
utx.ut_type = OLD_TIME;
|
utx.ut_type = OLD_TIME;
|
||||||
memset(utx.ut_id, 0, sizeof(utx.ut_id));
|
memset(utx.ut_id, 0, sizeof(utx.ut_id));
|
||||||
(void)gettimeofday(&utx.ut_tv, NULL);
|
(void)gettimeofday(&utx.ut_tv, NULL);
|
||||||
|
|
|
@ -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);
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -291,10 +291,6 @@ SMRCD= sendmail
|
||||||
SMRCDPACKAGE= sendmail
|
SMRCDPACKAGE= sendmail
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${MK_TIMED} != "no"
|
|
||||||
CONFS+= timed
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.if ${MK_UNBOUND} != "no"
|
.if ${MK_UNBOUND} != "no"
|
||||||
CONFGROUPS+= UNBOUND
|
CONFGROUPS+= UNBOUND
|
||||||
UNBOUND+= local_unbound
|
UNBOUND+= local_unbound
|
||||||
|
|
|
@ -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"
|
|
|
@ -1,6 +1,6 @@
|
||||||
.\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman.
|
.\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman.
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.Dd November 26, 2018
|
.Dd December 15, 2018
|
||||||
.Dt SRC.CONF 5
|
.Dt SRC.CONF 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -239,6 +239,17 @@ Disable the BSD licensed
|
||||||
.Pa crtbegin.o
|
.Pa crtbegin.o
|
||||||
and
|
and
|
||||||
.Pa crtend.o .
|
.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
|
.It Va WITH_BSD_GREP
|
||||||
Install BSD-licensed grep as '[ef]grep' instead of GNU grep.
|
Install BSD-licensed grep as '[ef]grep' instead of GNU grep.
|
||||||
.It Va WITHOUT_BSNMP
|
.It Va WITHOUT_BSNMP
|
||||||
|
@ -1780,9 +1791,6 @@ Set to not build or install
|
||||||
.Xr tftp 1
|
.Xr tftp 1
|
||||||
and
|
and
|
||||||
.Xr tftpd 8 .
|
.Xr tftpd 8 .
|
||||||
.It Va WITHOUT_TIMED
|
|
||||||
Set to not build or install
|
|
||||||
.Xr timed 8 .
|
|
||||||
.It Va WITHOUT_TOOLCHAIN
|
.It Va WITHOUT_TOOLCHAIN
|
||||||
Set to not install header or
|
Set to not install header or
|
||||||
programs used for program development,
|
programs used for program development,
|
||||||
|
|
|
@ -8513,14 +8513,6 @@ OLD_FILES+=usr/share/man/man1/tftp.1.gz
|
||||||
OLD_FILES+=usr/share/man/man8/tftpd.8.gz
|
OLD_FILES+=usr/share/man/man8/tftpd.8.gz
|
||||||
.endif
|
.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/addr2line
|
||||||
OLD_FILES+=usr/bin/as
|
OLD_FILES+=usr/bin/as
|
||||||
OLD_FILES+=usr/bin/byacc
|
OLD_FILES+=usr/bin/byacc
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
.\" $FreeBSD$
|
|
||||||
Set to not build or install
|
|
||||||
.Xr timed 8 .
|
|
|
@ -201,7 +201,6 @@ SUBDIR.${MK_SENDMAIL}+= praliases
|
||||||
SUBDIR.${MK_SENDMAIL}+= sendmail
|
SUBDIR.${MK_SENDMAIL}+= sendmail
|
||||||
SUBDIR.${MK_TCP_WRAPPERS}+= tcpdchk
|
SUBDIR.${MK_TCP_WRAPPERS}+= tcpdchk
|
||||||
SUBDIR.${MK_TCP_WRAPPERS}+= tcpdmatch
|
SUBDIR.${MK_TCP_WRAPPERS}+= tcpdmatch
|
||||||
SUBDIR.${MK_TIMED}+= timed
|
|
||||||
SUBDIR.${MK_TOOLCHAIN}+= config
|
SUBDIR.${MK_TOOLCHAIN}+= config
|
||||||
SUBDIR.${MK_TOOLCHAIN}+= crunch
|
SUBDIR.${MK_TOOLCHAIN}+= crunch
|
||||||
SUBDIR.${MK_UNBOUND}+= unbound
|
SUBDIR.${MK_UNBOUND}+= unbound
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
SUBDIR= timed timedc
|
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
|
|
@ -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
|
|
|
@ -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>
|
|
|
@ -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
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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 */
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 *);
|
|
|
@ -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))
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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"
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 .
|
|
|
@ -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 */
|
|
||||||
}
|
|
|
@ -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>
|
|
|
@ -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
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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]);
|
|
|
@ -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 *[]);
|
|
|
@ -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 .
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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"
|
|
Loading…
Reference in a new issue