/* * 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); }
/* * 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"); }
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 != 0) { length = 1; for (ptr = head->p; ptr != 0; 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; } } }