* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)slave.c 2.3 (Berkeley) %G%";
#include <protocols/timed.h>
long electiontime
, refusetime
;
char candidate
[MAXHOSTNAMELEN
];
struct tsp
*msg
, to
, *readmsg();
struct sockaddr_in saveaddr
, msaveaddr
;
struct timeval time
, mytime
;
struct tsp
*answer
, *acksend();
struct sockaddr_in server
;
register struct netinfo
*ntp
;
fp
= fopen("/usr/adm/timed.masterlog", "w");
syslog(LOG_NOTICE
, "THIS MACHINE IS A SUBMASTER");
fprintf(fd
, "THIS MACHINE IS A SUBMASTER\n");
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
)
if (ntp
->status
== MASTER
)
syslog(LOG_NOTICE
, "THIS MACHINE IS A SLAVE");
fprintf(fd
, "THIS MACHINE IS A SLAVE\n");
(void)gettimeofday(&time
, (struct timezone
*)0);
electiontime
= time
.tv_sec
+ delay2
;
length
= sizeof(struct sockaddr_in
);
(void)gettimeofday(&time
, (struct timezone
*)0);
if (time
.tv_sec
> electiontime
) {
fprintf(fd
, "election timer expired\n");
wait
.tv_sec
= electiontime
- time
.tv_sec
+ 10;
msg
= readmsg(TSP_ANY
, (char *)ANYADDR
, &wait
, (struct netinfo
*)NULL
);
(void)gettimeofday(&time
, (struct timezone
*)0);
electiontime
= time
.tv_sec
+ delay2
;
if (seq
!= msg
->tsp_seq
) {
if ((status
& SUBMASTER
) == SUBMASTER
) {
synch((msg
->tsp_time
.tv_sec
* 1000) +
(msg
->tsp_time
.tv_usec
/ 1000));
adjclock(&(msg
->tsp_time
));
(void)strcpy(olddate
, date());
(void)settimeofday(&msg
->tsp_time
,
syslog(LOG_NOTICE
, "date changed by %s from: %s",
if ((status
& SUBMASTER
) == SUBMASTER
)
electiontime
= time
.tv_sec
+ delay2
;
msg
->tsp_type
= TSP_DATEACK
;
(void)strcpy(msg
->tsp_name
, hostname
);
length
= sizeof(struct sockaddr_in
);
if (sendto(sock
, (char *)msg
,
&saveaddr
, length
) < 0) {
syslog(LOG_ERR
, "sendto: %m");
msg
->tsp_type
= TSP_SLAVEUP
;
msg
->tsp_vers
= TSPVERSION
;
(void)strcpy(msg
->tsp_name
, hostname
);
length
= sizeof(struct sockaddr_in
);
if (sendto(sock
, (char *)msg
, sizeof(struct tsp
), 0,
syslog(LOG_ERR
, "sendto: %m");
delay2
= casual((long)MINTOUT
, (long)MAXTOUT
);
(void)gettimeofday(&time
, (struct timezone
*)0);
electiontime
= time
.tv_sec
+ delay2
;
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
if (ntp
->status
== MASTER
)
if (!(status
& MASTER
) || ntp
== NULL
) {
(void)gettimeofday(&time
, (struct timezone
*)0);
electiontime
= time
.tv_sec
+ delay2
;
ind
= addmach(msg
->tsp_name
, &from
);
if (hp
[ind
].seq
!= msg
->tsp_seq
) {
hp
[ind
].seq
= msg
->tsp_seq
;
to
.tsp_type
= TSP_SETTIME
;
(void)strcpy(to
.tsp_name
, hostname
);
* give the upcoming slave the time
* to check its input queue before
(void) gettimeofday(&mytime
,
to
.tsp_time
.tv_sec
= mytime
.tv_sec
;
answer
= acksend(&to
, &hp
[ind
].addr
,
"ERROR ON SETTIME machine: %s",
msg
->tsp_time
.tv_usec
= 0;
msg
->tsp_type
= TSP_DATEREQ
;
msg
->tsp_vers
= TSPVERSION
;
(void)strcpy(msg
->tsp_name
, hostname
);
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if (ntp
->status
== SLAVE
)
answer
= acksend(msg
, &ntp
->dest_addr
, (char *)ANYADDR
,
length
= sizeof(struct sockaddr_in
);
if (sendto(sock
, (char *)msg
,
sizeof(struct tsp
), 0, &saveaddr
,
syslog(LOG_ERR
, "sendto: %m");
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
if (ntp
->status
== MASTER
)
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if (ntp
->status
== SLAVE
)
answer
= acksend(msg
, &ntp
->dest_addr
, (char *)ANYADDR
,
msg
->tsp_type
= TSP_DATEACK
;
length
= sizeof(struct sockaddr_in
);
if (sendto(sock
, (char *)msg
,
sizeof(struct tsp
), 0, &saveaddr
,
syslog(LOG_ERR
, "sendto: %m");
fd
= fopen(tracefile
, "w");
fprintf(fd
, "Tracing started on: %s\n\n",
fprintf(fd
, "Tracing ended on: %s\n", date());
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
if (ntp
->status
== MASTER
)
addmach(msg
->tsp_name
, &from
);
(void)gettimeofday(&time
, (struct timezone
*)0);
electiontime
= time
.tv_sec
+ delay2
;
seq
= 0; /* reset sequence number */
if (time
.tv_sec
< refusetime
)
msg
->tsp_type
= TSP_REFUSE
;
msg
->tsp_type
= TSP_ACCEPT
;
refusetime
= time
.tv_sec
+ 30;
(void)strcpy(candidate
, msg
->tsp_name
);
(void)strcpy(msg
->tsp_name
, hostname
);
answer
= acksend(msg
, &server
, candidate
, TSP_ACK
,
syslog(LOG_ERR
, "problem in election\n");
msg
->tsp_type
= TSP_MSITEREQ
;
msg
->tsp_vers
= TSPVERSION
;
(void)strcpy(msg
->tsp_name
, hostname
);
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if (ntp
->status
== SLAVE
)
answer
= acksend(msg
, &ntp
->dest_addr
, (char *)ANYADDR
,
length
= sizeof(struct sockaddr_in
);
if (sendto(sock
, (char *)msg
,
&msaveaddr
, length
) < 0) {
syslog(LOG_ERR
, "sendto: %m");
fprintf(fd
, "garbage: ");
fprintf(fd
, "garbage: ");
* Used before answering a broadcast message to avoid network
* contention and likely collisions.
timeout
.tv_usec
= delay1
;
(void)select(0, (fd_set
*)NULL
, (fd_set
*)NULL
, (fd_set
*)NULL
,