- resp.tsp_type = TSP_SLAVEUP;
- resp.tsp_vers = TSPVERSION;
- (void)strcpy(resp.tsp_name, hostname);
- bytenetorder(&resp);
- if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
- &ntip->dest_addr, sizeof(struct sockaddr_in)) < 0) {
- syslog(LOG_ERR, "sendto: %m");
+ setstatus();
+ checkignorednets();
+ makeslave(firstslavenet());
+ }
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+ if (ntp->status == MASTER)
+ ntp->status = IGNORE;
+ setstatus();
+ slave();
+ }
+}
+
+/*
+ * Try to become master over ignored nets..
+ */
+checkignorednets()
+{
+ register struct netinfo *ntp;
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+ if (ntp->status == IGNORE)
+ lookformaster(ntp);
+}
+
+lookformaster(ntp)
+ register struct netinfo *ntp;
+{
+ struct tsp resp, conflict, *answer, *readmsg(), *acksend();
+ struct timeval time;
+ char mastername[MAXHOSTNAMELEN];
+ struct sockaddr_in masteraddr;
+
+ ntp->status = SLAVE;
+ /* look for master */
+ resp.tsp_type = TSP_MASTERREQ;
+ (void)strcpy(resp.tsp_name, hostname);
+ answer = acksend(&resp, &ntp->dest_addr, (char *)ANYADDR,
+ TSP_MASTERACK, ntp);
+ if (answer == NULL) {
+ /*
+ * Various conditions can cause conflict: race between
+ * two just started timedaemons when no master is
+ * present, or timedaemon started during an election.
+ * Conservative approach is taken: give up and became a
+ * slave postponing election of a master until first
+ * timer expires.
+ */
+ time.tv_sec = time.tv_usec = 0;
+ answer = readmsg(TSP_MASTERREQ, (char *)ANYADDR,
+ &time, ntp);
+ if (answer != NULL) {
+ ntp->status = SLAVE;
+ return;
+ }
+
+ time.tv_sec = time.tv_usec = 0;
+ answer = readmsg(TSP_MASTERUP, (char *)ANYADDR,
+ &time, ntp);
+ if (answer != NULL) {
+ ntp->status = SLAVE;
+ return;
+ }
+
+ time.tv_sec = time.tv_usec = 0;
+ answer = readmsg(TSP_ELECTION, (char *)ANYADDR,
+ &time, ntp);
+ if (answer != NULL) {
+ ntp->status = SLAVE;
+ return;
+ }
+ ntp->status = MASTER;
+ } else {
+ (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.
+ */
+ time.tv_sec = 0;
+ time.tv_usec = 300000;
+ answer = readmsg(TSP_MASTERACK, (char *)ANYADDR, &time,
+ 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, (struct netinfo *)NULL) == NULL) {
+ syslog(LOG_ERR,
+ "error on sending TSP_CONFLICT");