--- netkit-rwho-0.17/rwhod/rwhod.c 2000-07-23 05:19:48.000000000 +0200 +++ netkit-rwho-0.17-new/rwhod/rwhod.c 2004-10-25 16:57:35.002325112 +0200 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,7 @@ static int configure(int s); static int verify(const char *name); static int getloadavg(double ptr[3], int n); +static void sendspool(char *myname); /* * We communicate with each neighbor in @@ -114,6 +116,7 @@ static struct neighbor *neighbors; static struct servent *sp; static int sk; +static int route = 0; static int use_pointopoint = 0; static int use_broadcast = 0; static int need_init = 1; @@ -123,6 +126,7 @@ - ((caddr_t) 0)) static void huphandler(int); +static time_t getsendtime(char *); static void termhandler(int); static void sendpacket(struct whod *); static void getboottime(struct whod *); @@ -137,14 +141,18 @@ char *user = NULL; int on = 1; int opt; + size_t len; if (getuid()) { fprintf(stderr, "rwhod: not super user\n"); exit(1); } - while ((opt = getopt(argc, argv, "bpau:")) != EOF) { + while ((opt = getopt(argc, argv, "rbpau:")) != EOF) { switch (opt) { + case 'r': + route = 1; + break; case 'b': use_broadcast = 1; break; @@ -201,6 +209,7 @@ } sine.sin_family = AF_INET; sine.sin_port = sp->s_port; + len = sizeof(sine); if (bind(sk, (struct sockaddr *)&sine, sizeof(sine)) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); @@ -247,7 +256,7 @@ for (;;) { struct whod wd; int cc, whod; - size_t len = sizeof(from); + len = sizeof(from); memset(&wd, 0, sizeof(wd)); cc = recvfrom(sk, (char *)&wd, sizeof(struct whod), 0, @@ -276,6 +285,8 @@ from.sin_addr); continue; } + if((time_t)ntohl(wd.wd_sendtime) == getsendtime(wd.wd_hostname)) + continue; snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname); /* * Rather than truncating and growing the file each time, @@ -325,6 +336,28 @@ exit(0); } +static time_t getsendtime(char *hostname) +{ + int f, ret; + struct whod wd; + char path[64]; + + snprintf(path, sizeof(path), "whod.%s", hostname); + if((f = open(path, O_RDONLY)) < 0) { + if(errno != ENOENT) + fprintf(stderr, "rwhod: %s: %s\n", path, strerror(errno)); + return(0); + } + if((ret = read(f, &wd, sizeof(wd))) < 0) { + fprintf(stderr, "rwhod: %s: %s\n", path, strerror(errno)); + return(0); + } + close(f); + if(ret < WHDRSIZE) + return(0); + return(wd.wd_sendtime); +} + /* * Obtain boot time again */ @@ -366,6 +399,8 @@ getboottime(&mywd); while (1) { + if(route) + sendspool(mywd.wd_hostname); sendpacket(&mywd); (void) sleep(AL_INTERVAL); } @@ -390,6 +425,56 @@ return size > 0; } +static int down(time_t rcv, time_t now) { + return (now - rcv > 11 * 60); +} + +static void sendspool(char *myname) +{ + DIR *dirp; + struct dirent *dp; + int i, f, ret; + struct whod wd; + struct whoent *we; + struct neighbor *np; + + if((dirp = opendir(".")) == NULL) { + fprintf(stderr, "rwhod: opening spool dir: %s\n", strerror(errno)); + exit(1); + } + while((dp = readdir(dirp)) != NULL) { + if(strncmp(dp->d_name, "whod.", 5)) + continue; + if(!strcmp(dp->d_name + 5, myname)) + continue; + if((f = open(dp->d_name, O_RDONLY)) < 0) { + fprintf(stderr, "rwhod: %s: %s\n", dp->d_name, strerror(errno)); + continue; + } + if((ret = read(f, &wd, sizeof(wd))) < 0) { + fprintf(stderr, "rwhod: %s: %s\n", dp->d_name, strerror(errno)); + continue; + } + close(f); + if(ret < WHDRSIZE) + continue; + if(down(wd.wd_recvtime, time(NULL))) + continue; + wd.wd_sendtime = htonl(wd.wd_sendtime); + for(i = 0; i < 3; i++) + wd.wd_loadav[i] = htonl(wd.wd_loadav[i]); + wd.wd_boottime = htonl(wd.wd_boottime); + for(we = wd.wd_we; (char *)we < ((char *)&wd) + ret; we++) { + we->we_idle = htonl(we->we_idle); + we->we_utmp.out_time = htonl(we->we_utmp.out_time); + } + for(np = neighbors; np != NULL; np = np->n_next) { + if(sendto(sk, &wd, ret, 0, (struct sockaddr *) np->n_addr, np->n_addrlen) < 0) + syslog(LOG_ERR, "sendto(%s): %m", inet_ntoa(((struct sockaddr_in *)np->n_addr)->sin_addr)); + } + } + closedir(dirp); +} static void sendpacket(struct whod *wd)