candidate.c revision 50479
117683Spst/*- 275107Sfenner * Copyright (c) 1985, 1993 398530Sfenner * The Regents of the University of California. All rights reserved. 475107Sfenner * 575107Sfenner * Redistribution and use in source and binary forms, with or without 698530Sfenner * modification, are permitted provided that the following conditions 775107Sfenner * are met: 817683Spst * 1. Redistributions of source code must retain the above copyright 917683Spst * notice, this list of conditions and the following disclaimer. 1026175Sfenner * 2. Redistributions in binary form must reproduce the above copyright 1117683Spst * notice, this list of conditions and the following disclaimer in the 1217683Spst * documentation and/or other materials provided with the distribution. 1317683Spst * 3. All advertising materials mentioning features or use of this software 1417683Spst * must display the following acknowledgement: 1517683Spst * This product includes software developed by the University of 1617683Spst * California, Berkeley and its contributors. 1717683Spst * 4. Neither the name of the University nor the names of its contributors 1817683Spst * may be used to endorse or promote products derived from this software 1917683Spst * without specific prior written permission. 2017683Spst * 2117683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2217683Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2317683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2417683Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2517683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2617683Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2717683Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2817683Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2917683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117683Spst * SUCH DAMAGE. 3275107Sfenner */ 3375107Sfenner 3417683Spst#ifndef lint 3517683Spst#if 0 3617683Spststatic char sccsid[] = "@(#)candidate.c 8.1 (Berkeley) 6/6/93"; 3717683Spst#endif 3817683Spststatic const char rcsid[] = 3917683Spst "$FreeBSD: head/usr.sbin/timed/timed/candidate.c 50479 1999-08-28 01:35:59Z peter $"; 4017683Spst#endif /* not lint */ 4117683Spst 4217683Spst#include "globals.h" 4317683Spst 4417683Spst/* 4517683Spst * `election' candidates a host as master: it is called by a slave 4617683Spst * which runs with the -M option set when its election timeout expires. 4717683Spst * Note the conservative approach: if a new timed comes up, or another 4817683Spst * candidate sends an election request, the candidature is withdrawn. 4917683Spst */ 5026175Sfennerint 5126175Sfennerelection(net) 5217683Spst struct netinfo *net; 5317683Spst{ 5475107Sfenner struct tsp *resp, msg; 5517683Spst struct timeval then, wait; 5675107Sfenner struct tsp *answer; 5775107Sfenner struct hosttbl *htp; 5875107Sfenner char loop_lim = 0; 5975107Sfenner 6075107Sfenner/* This code can get totally confused if it gets slightly behind. For 6175107Sfenner * example, if readmsg() has some QUIT messages waiting from the last 6275107Sfenner * round, we would send an ELECTION message, get the stale QUIT, 6375107Sfenner * and give up. This results in network storms when several machines 6475107Sfenner * do it at once. 6575107Sfenner */ 6675107Sfenner wait.tv_sec = 0; 6775107Sfenner wait.tv_usec = 0; 6875107Sfenner while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) { 6975107Sfenner if (trace) 7075107Sfenner fprintf(fd, "election: discarded stale REFUSE\n"); 7175107Sfenner } 7298530Sfenner while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) { 7375107Sfenner if (trace) 7475107Sfenner fprintf(fd, "election: discarded stale QUIT\n"); 7575107Sfenner } 7675107Sfenner 7775107Sfenneragain: 7875107Sfenner syslog(LOG_INFO, "This machine is a candidate time master"); 7975107Sfenner if (trace) 8075107Sfenner fprintf(fd, "This machine is a candidate time master\n"); 8175107Sfenner msg.tsp_type = TSP_ELECTION; 8275107Sfenner msg.tsp_vers = TSPVERSION; 8375107Sfenner (void)strcpy(msg.tsp_name, hostname); 8475107Sfenner bytenetorder(&msg); 8575107Sfenner if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, 8675107Sfenner (struct sockaddr*)&net->dest_addr, 8775107Sfenner sizeof(struct sockaddr)) < 0) { 8875107Sfenner trace_sendto_err(net->dest_addr.sin_addr); 8975107Sfenner return(SLAVE); 9075107Sfenner } 9175107Sfenner 9275107Sfenner (void)gettimeofday(&then, 0); 9375107Sfenner then.tv_sec += 3; 9475107Sfenner for (;;) { 9575107Sfenner (void)gettimeofday(&wait, 0); 9675107Sfenner timevalsub(&wait,&then,&wait); 9775107Sfenner resp = readmsg(TSP_ANY, ANYADDR, &wait, net); 9875107Sfenner if (!resp) 9975107Sfenner return(MASTER); 10075107Sfenner 10175107Sfenner switch (resp->tsp_type) { 10275107Sfenner 10375107Sfenner case TSP_ACCEPT: 10475107Sfenner (void)addmach(resp->tsp_name, &from,fromnet); 10575107Sfenner break; 10675107Sfenner 10775107Sfenner case TSP_MASTERUP: 10875107Sfenner case TSP_MASTERREQ: 10975107Sfenner /* 11075107Sfenner * If another timedaemon is coming up at the same 11175107Sfenner * time, give up, and let it be the master. 11275107Sfenner */ 11375107Sfenner if (++loop_lim < 5 11417683Spst && !good_host_name(resp->tsp_name)) { 11517683Spst (void)addmach(resp->tsp_name, &from,fromnet); 11626175Sfenner suppress(&from, resp->tsp_name, net); 11726175Sfenner goto again; 11826175Sfenner } 11926175Sfenner rmnetmachs(net); 12098530Sfenner return(SLAVE); 12126175Sfenner 12226175Sfenner case TSP_QUIT: 12326175Sfenner case TSP_REFUSE: 12426175Sfenner /* 12526175Sfenner * Collision: change value of election timer 12626175Sfenner * using exponential backoff. 12726175Sfenner * 12826175Sfenner * Fooey. 12926175Sfenner * An exponential backoff on a delay starting at 13026175Sfenner * 6 to 15 minutes for a process that takes 13117683Spst * milliseconds is silly. It is particularly 13217683Spst * strange that the original code would increase 13317683Spst * the backoff without bound. 13417683Spst */ 13517683Spst rmnetmachs(net); 13617683Spst return(SLAVE); 13717683Spst 13817683Spst case TSP_ELECTION: 13917683Spst /* no master for another round */ 14017683Spst htp = addmach(resp->tsp_name,&from,fromnet); 14117683Spst msg.tsp_type = TSP_REFUSE; 14217683Spst (void)strcpy(msg.tsp_name, hostname); 14317683Spst answer = acksend(&msg, &htp->addr, htp->name, 14417683Spst TSP_ACK, 0, htp->noanswer); 14526175Sfenner if (!answer) { 14675107Sfenner syslog(LOG_ERR, "error in election from %s", 14717683Spst htp->name); 14817683Spst } 14917683Spst break; 15075107Sfenner 15175107Sfenner case TSP_SLAVEUP: 15275107Sfenner (void)addmach(resp->tsp_name, &from,fromnet); 15375107Sfenner break; 15475107Sfenner 15575107Sfenner case TSP_SETDATE: 15675107Sfenner case TSP_SETDATEREQ: 15775107Sfenner break; 15875107Sfenner 15975107Sfenner default: 16017683Spst if (trace) { 16117683Spst fprintf(fd, "candidate: "); 16217683Spst print(resp, &from); 16326175Sfenner } 16475107Sfenner break; 16526175Sfenner } 16626175Sfenner } 16717683Spst} 16817683Spst