+/*
+ * 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");
+ exit(1);
+ }
+ }
+ }
+}
+/*
+ * based on the current network configuration, set the status, and count
+ * networks;
+ */
+setstatus()
+{
+ register 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 IGNORE:
+ nignorednets++;
+ break;
+ }
+ if (trace) {
+ fprintf(fd, "\t%-16s", inet_ntoa(ntp->net));
+ switch ((int)ntp->status) {
+ 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\n",
+ nnets, nmasternets, nslavenets, nignorednets);
+}
+
+makeslave(net)
+ 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;
+}
+
+struct netinfo *
+firstslavenet()
+{
+ register struct netinfo *ntp;
+
+ for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+ if (ntp->status == SLAVE)
+ return (ntp);
+ return ((struct netinfo *)0);
+}
+
+/*