diff -ruN netkit-rwho-0.17.old/ruptime/ruptime.c netkit-rwho-0.17/ruptime/ruptime.c --- netkit-rwho-0.17.old/ruptime/ruptime.c 1999-12-12 07:33:39.000000000 -0800 +++ netkit-rwho-0.17/ruptime/ruptime.c 2005-12-06 21:08:35.000000000 -0800 @@ -212,7 +212,7 @@ static char resbuf[32]; int days, hours, minutes; - if (tval < 0 || tval > 999*24*60*60) { + if (tval < 0) { (void)snprintf(resbuf, sizeof(resbuf), "%s ??:??", updown); return(resbuf); } @@ -220,10 +220,10 @@ hours = minutes / 60; minutes %= 60; days = hours / 24; hours %= 24; if (days) - (void)snprintf(resbuf, sizeof(resbuf), "%s %3d+%02d:%02d", + (void)snprintf(resbuf, sizeof(resbuf), "%s %4d+%02d:%02d", updown, days, hours, minutes); else - (void)snprintf(resbuf, sizeof(resbuf), "%s %2d:%02d", + (void)snprintf(resbuf, sizeof(resbuf), "%s %2d:%02d", updown, hours, minutes); return(resbuf); } diff -ruN netkit-rwho-0.17.old/rwho/Makefile netkit-rwho-0.17/rwho/Makefile --- netkit-rwho-0.17.old/rwho/Makefile 1999-12-12 10:05:05.000000000 -0800 +++ netkit-rwho-0.17/rwho/Makefile 2005-12-06 21:08:35.000000000 -0800 @@ -3,8 +3,6 @@ include ../MCONFIG include ../MRULES -CFLAGS += -I../include - rwho: rwho.o $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ diff -ruN netkit-rwho-0.17.old/rwhod/Makefile netkit-rwho-0.17/rwhod/Makefile --- netkit-rwho-0.17.old/rwhod/Makefile 1999-07-31 23:00:13.000000000 -0700 +++ netkit-rwho-0.17/rwhod/Makefile 2005-12-06 21:08:35.000000000 -0800 @@ -3,8 +3,11 @@ include ../MCONFIG include ../MRULES -CFLAGS += -I../include -OBJS = rwhod.o daemon.o +ifneq ($(USE_GLIBC),1) +CFLAGS += -D_GNU_SOURCE +endif + +OBJS = rwhod.o rwhod: $(OBJS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ diff -ruN netkit-rwho-0.17.old/rwhod/rwhod.8 netkit-rwho-0.17/rwhod/rwhod.8 --- netkit-rwho-0.17.old/rwhod/rwhod.8 2000-07-30 16:57:06.000000000 -0700 +++ netkit-rwho-0.17/rwhod/rwhod.8 2005-12-06 21:08:35.000000000 -0800 @@ -32,7 +32,10 @@ .\" from: @(#)rwhod.8 6.5 (Berkeley) 3/16/91 .\" $Id: rwhod.8,v 1.16 2000/07/30 23:57:06 dholland Exp $ .\" -.Dd May 13, 1997 +.\" Modified by Philippe Troin : added interface +.\" options and forwarding. + +.Dd March 10, 1999 .Dt RWHOD 8 .Os "Linux NetKit (0.17)" .Sh NAME @@ -40,7 +43,8 @@ .Nd system status server .Sh SYNOPSIS .Nm rwhod -.Op Fl bpa +.Op Fl bpaf +.Op -i ... .Op Fl u Ar user .Sh DESCRIPTION .Nm Rwhod @@ -67,22 +71,6 @@ in the ``rwho'' service specification; see .Xr services 5 . .Pp -If the -.Fl b -flag is supplied, only broadcast interfaces, such as ethernets, will -be used. -If the -.Fl p -flag is supplied, only point-to-point interfaces will be used. If the -.Fl a -flag is supplied, or no flags are supplied, all interfaces will be -used. -.Pp -If the -.Fl u -flag is supplied, rwhod will run as the specified user instead of as -root. -.Pp The messages sent and received, are of the form: .Bd -literal -offset indent struct outmp { @@ -145,16 +133,78 @@ .Nm Rwhod recomputes the system boot time every 30 minutes because on some (non-Linux) systems it is not a totally reliable process. +.Sh FLAGS +If the +.Fl b +flag is supplied, only broadcast interfaces, such as ethernets, will +be used. +If the +.Fl p +flag is supplied, only point-to-point interfaces will be used. If the +.Fl a +flag is supplied, or no flags are supplied, all interfaces will be +used. +.Pp +Alternately, you may specify interfaces by name by providing one or +more +.Fl i +options followed by the interface name. +.Pp +If the +.Fl u +flag is supplied, rwhod will run as the specified user instead of as +root. +.Pp +.Nm Rwhod +can also forward packets between interfaces if started with +.Fl f. +Please read the +.Xr CAVEATS +section before enabling +.Xr rwhod +forwarding. +.Sh CAVEATS +While +.Xr rwhod +listens on any interface present on the host, it will only send (or +forward) to the interfaces determined by the +.Fl a b p i +flags. +.Pp +When operating in forwarding mode (with +.Fl f +), +.Xr rwhod +forwards all correct rwhod packets received on an interface to all the +other interfaces. You can create a broadcast storm if there is a +loop in your network and all the routers in the loop run in forwarding +mode. To prevent this from happenning, +.Xr rwhod +will shut down forwarding (and log the event to the syslog) if more +than one +.Xr rwhod +packet is forwarded per second on average over the last three +minutes. If this happens, you must break the loop of forwarding routers. .Sh SEE ALSO .Xr rwho 1 , .Xr ruptime 1 .Sh BUGS -There should be a way to relay status information between networks. +Some kind of proxying feature might be useful if your router doesn't +run +.Xr rwhod. +.Pp People often interpret the server dying -or network communtication failures +or network communication failures as a machine going down. +.Pp +.Xr Rwhod +doesn't refresh its interface list, which might be useful when using +.Fl a b p. .Sh HISTORY The .Nm command appeared in .Bx 4.2 . +.Pp +Philippe Troin implemented forwarding and interface +selection flags. diff -ruN netkit-rwho-0.17.old/rwhod/rwhod.c netkit-rwho-0.17/rwhod/rwhod.c --- netkit-rwho-0.17.old/rwhod/rwhod.c 2005-12-06 21:08:06.000000000 -0800 +++ netkit-rwho-0.17/rwhod/rwhod.c 2005-12-06 21:12:57.000000000 -0800 @@ -29,6 +29,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + + * Modified by Philippe Troin (added options & implemented + * them. + */ char copyright[] = @@ -47,6 +51,7 @@ #include #include #include +#include #include #include @@ -71,10 +76,10 @@ #include #include -#include "daemon.h" - #include "../version.h" +typedef struct sockaddr_in SA; + #define ENDIAN LITTLE_ENDIAN /* @@ -98,27 +103,44 @@ static int verify(const char *name); int getloadavg(double ptr[3], int n); + +/* This is the list of interface we want to listen on */ +struct wanted_neigh { + struct wanted_neigh *w_next; + char *w_ifname; + enum { W_USED_NOT, W_USED_ONCE, W_USED_MULTI } w_used; +}; + /* * We communicate with each neighbor in * a list constructed at the time we're * started up. Neighbors are currently * directly connected via a hardware interface. */ -struct neighbor { +struct neighbor { struct neighbor *n_next; char *n_name; /* interface name */ - char *n_addr; /* who to send to */ + SA *n_myaddr; /* My address on this i/f */ + SA *n_mask; /* Netmask on this i/f */ + SA *n_dstaddr; /* who to send to */ int n_addrlen; /* size of address */ int n_flags; /* should forward?, interface flags */ }; +static struct wanted_neigh *wanted_neigh; static struct neighbor *neighbors; static struct servent *sp; static int sk; -static int use_pointopoint = 0; -static int use_broadcast = 0; +static int use_pointopoint; +static int use_broadcast; static int need_init = 1; -static int child_pid = 0; +static int child_pid; +static int use_forwarding; +static int forwarded_packets; + +/* Max number of packets to forward between each alarm() tick. + If this number is exceeded, then the forwarding is switched off. */ +#define MAX_FWD_PACKETS (AL_INTERVAL) #define WHDRSIZE (((caddr_t) &((struct whod *) 0)->wd_we) \ - ((caddr_t) 0)) @@ -127,24 +149,48 @@ static void termhandler(int); static void sendpacket(struct whod *); static void getboottime(struct whod *); +static void forward(const SA *, const struct whod *, int cc); +static void usage(void); int main(int argc, char *argv[]) { + struct wanted_neigh *wn; + int wn_dup; struct sockaddr_in from; - struct passwd *pw = 0; + struct passwd *pw; struct stat st; char path[64]; char *user = NULL; int on = 1; int opt; + time_t before; if (getuid()) { fprintf(stderr, "rwhod: not super user\n"); + } + openlog("rwhod", LOG_PID, LOG_DAEMON); + sp = getservbyname("who", "udp"); + if (sp == 0) { + fprintf(stderr, "rwhod: udp/who: unknown service\n"); + exit(1); + } + if ((sk = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "socket: %m"); + exit(1); + } + if (setsockopt(sk, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { + syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); + exit(1); + } + sine.sin_family = AF_INET; + sine.sin_port = sp->s_port; + if (bind(sk, (struct sockaddr *)&sine, sizeof(sine)) < 0) { + syslog(LOG_ERR, "bind: %m"); exit(1); } - while ((opt = getopt(argc, argv, "bpau:")) != EOF) { + while ((opt = getopt(argc, argv, "bpai:fu:")) != EOF) { switch (opt) { case 'b': use_broadcast = 1; @@ -156,29 +202,57 @@ use_broadcast = 1; use_pointopoint = 1; break; + case 'f': + use_forwarding = 1; + break; + case 'i': + wn_dup = 0; + for (wn = wanted_neigh; wn; wn = wn->w_next) { + if (strcmp(wn->w_ifname, optarg)== 0) { + wn_dup = 1; + break; + } + } + if (wn_dup) { + fprintf(stderr, "rwhod: warning: " + "duplicate interface %s in arguments\n", + optarg); + } else { + wn = malloc(sizeof(struct wanted_neigh)); + if (wn == NULL) { + fprintf(stderr, "rwhod: out of memory\n"); + exit(2); + } + wn->w_next = wanted_neigh; + wn->w_ifname = malloc(strlen(optarg)+1); + wn->w_used = W_USED_NOT; + if (wn->w_ifname == NULL) { + fprintf(stderr, "rwhod: out of memory\n"); + exit(2); + } + strcpy(wn->w_ifname, optarg); + wanted_neigh = wn; + } + break; case 'u': user = optarg; break; case '?': default: - fprintf(stderr, "usage: rwhod [-bpa] [-u user]\n"); - exit(1); - break; + usage(); } } if (optinds_port; - if (bind(sk, (struct sockaddr *)&sine, sizeof(sine)) < 0) { - syslog(LOG_ERR, "bind: %m"); - exit(1); - } (void) umask(022); signal(SIGTERM, termhandler); + + if (user) { + /* We have to drop privs in two steps--first get the + * account info, then drop privs after chroot */ + if ((pw = getpwnam(user)) == NULL) { + syslog(LOG_ERR, "unknown user: %s", user); + exit(1); + } + + /* Now drop privs */ + if (pw->pw_uid) { + if (setgroups(1, &pw->pw_gid) < 0 + || setgid(pw->pw_gid) < 0 + || setuid(pw->pw_uid) < 0) { + syslog(LOG_ERR,"failed to drop privilege: %m"); + exit(1); + } + } + } + + if (!configure(sk)) + exit(1); + child_pid = fork(); if (child_pid < 0) { syslog(LOG_ERR, "fork: %m"); @@ -220,35 +301,15 @@ exit(0); } - /* We have to drop privs in two steps--first get the - * account info, then drop privs after chroot */ - if (user && (pw = getpwnam(user)) == NULL) { - syslog(LOG_ERR, "unknown user: %s", user); - exit(1); - } - - /* Chroot to the spool directory - * (note this is already our $cwd) */ - if (chroot(_PATH_RWHODIR) < 0) { - syslog(LOG_ERR, "chroot(%s): %m", _PATH_RWHODIR); - kill(child_pid, SIGTERM); - exit(1); - } - - /* Now drop privs */ - if (pw) { - if (setgroups(1, &pw->pw_gid) < 0 - || setgid(pw->pw_gid) < 0 - || setuid(pw->pw_uid) < 0) { - syslog(LOG_ERR, "failed to drop privilege: %m"); - exit(1); - } - } - + before = 0; for (;;) { struct whod wd; int cc, whod; +#ifdef __GLIBC__ + socklen_t len = sizeof(from); +#else size_t len = sizeof(from); +#endif memset(&wd, 0, sizeof(wd)); cc = recvfrom(sk, (char *)&wd, sizeof(struct whod), 0, @@ -262,6 +323,12 @@ syslog(LOG_WARNING, "packet too small"); continue; } + if (cc < WHDRSIZE) { + syslog(LOG_WARNING, "packet too small"); + continue; + } + if (cc < WHDRSIZE) + continue; if (from.sin_port != sp->s_port) { syslog(LOG_WARNING, "%d: bad from port", ntohs(from.sin_port)); @@ -271,14 +338,24 @@ continue; if (wd.wd_type != WHODTYPE_STATUS) continue; + + if (use_forwarding) { + time_t now = time(NULL); + if ((uintmax_t) (now - before) >= AL_INTERVAL) { + before = now; + forwarded_packets = 0; + } + forward(&from, &wd, cc); + } + /* * Ensure null termination of the name within the packet. * Otherwise we might overflow or read past the end. */ wd.wd_hostname[sizeof(wd.wd_hostname)-1] = 0; if (!verify(wd.wd_hostname)) { - syslog(LOG_WARNING, "malformed host name from %x", - from.sin_addr.s_addr); + syslog(LOG_WARNING, "malformed host name from %s", + inet_ntoa(from.sin_addr)); continue; } snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname); @@ -350,9 +427,6 @@ size_t mynamelen; struct whod mywd; - if (!configure(sk)) - exit(1); - /* * Establish host name as returned by system. */ @@ -362,7 +436,7 @@ } if ((cp = index(myname, '.')) != NULL) *cp = '\0'; - mynamelen = strlen(myname); + mynamelen = strlen(myname) + 1; if (mynamelen > sizeof(mywd.wd_hostname)) mynamelen = sizeof(mywd.wd_hostname) - 1; strncpy(mywd.wd_hostname, myname, mynamelen); @@ -453,7 +527,9 @@ } we = wd->wd_we; for (i = 0; i < nutmps; i++) { - if (stat(we->we_utmp.out_line, &stb) >= 0) + const char *p = we->we_utmp.out_line; + + if (!strchr(p, ':') && stat(p, &stb) >= 0) we->we_idle = htonl(now - stb.st_atime); we++; } @@ -465,10 +541,10 @@ wd->wd_vers = WHODVERSION; wd->wd_type = WHODTYPE_STATUS; for (np = neighbors; np != NULL; np = np->n_next) { - if (sendto(sk, (char *)wd, cc, 0, - (struct sockaddr *) np->n_addr, np->n_addrlen) < 0) + if (sendto(sk, wd, cc, 0, + (struct sockaddr *) np->n_dstaddr, np->n_addrlen) < 0) syslog(LOG_ERR, "sendto(%s): %m", - inet_ntoa(((struct sockaddr_in *)np->n_addr)->sin_addr)); + inet_ntoa(np->n_dstaddr->sin_addr)); } if (nutmps && chdir(_PATH_RWHODIR)) { @@ -477,6 +553,7 @@ } } +#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) /* * Taken from: * @@ -523,6 +600,7 @@ fclose(fp); return 0; } +#endif /* __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) */ void @@ -571,7 +649,7 @@ exit(1); } (void) lseek(kmemf, (long)nl[NL_BOOTTIME].n_value, L_SET); - (void) read(kmemf, (char *)&wd->wd_boottime, + (void) read(kmemf, &wd->wd_boottime, sizeof (wd->wd_boottime)); wd->wd_boottime = htonl(wd->wd_boottime); #endif @@ -589,10 +667,11 @@ struct ifreq ifreq, *ifr; struct sockaddr_in *sn; register struct neighbor *np; + struct wanted_neigh *wn; ifc.ifc_len = sizeof (buf); ifc.ifc_buf = buf; - if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { syslog(LOG_ERR, "ioctl (get interface configuration)"); return (0); } @@ -605,7 +684,11 @@ #endif cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; +#ifdef linux + cp += sizeof(struct ifreq)) { +#else cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { +#endif ifr = (struct ifreq *)cp; for (np = neighbors; np != NULL; np = np->n_next) if (np->n_name && @@ -619,63 +702,170 @@ continue; np->n_name = malloc(strlen(ifr->ifr_name) + 1); if (np->n_name == NULL) { - free((char *)np); + free(np); continue; } strcpy(np->n_name, ifr->ifr_name); np->n_addrlen = sizeof (ifr->ifr_addr); - np->n_addr = malloc(np->n_addrlen); - if (np->n_addr == NULL) { + + np->n_dstaddr = malloc(np->n_addrlen); + if (np->n_dstaddr == NULL) { + free(np->n_name); + free(np); + continue; + } + bzero(np->n_dstaddr, np->n_addrlen); + + np->n_myaddr = malloc(np->n_addrlen); + if (np->n_myaddr == NULL) { + free(np->n_dstaddr); free(np->n_name); - free((char *)np); + free(np); continue; } - bcopy((char *)&ifr->ifr_addr, np->n_addr, np->n_addrlen); - if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + bzero(np->n_myaddr, np->n_addrlen); + + np->n_mask = malloc(np->n_addrlen); + if (np->n_mask == NULL) { + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); + free(np); + continue; + } + bzero(np->n_mask, np->n_addrlen); + + /* Initialize both my address and destination address by + the interface address. The destination address will be + overwritten when the interface has IFF_BROADCAST or + IFF_POINTOPOINT. */ + bcopy(&ifr->ifr_addr, np->n_dstaddr, np->n_addrlen); + bcopy(&ifr->ifr_addr, np->n_myaddr, np->n_addrlen); + + if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) { syslog(LOG_ERR, "ioctl (get interface flags)"); - free((char *)np); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); + free(np); continue; } if ((ifreq.ifr_flags & IFF_UP) == 0 || - (ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) { - free((char *)np); + (ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0 || + (ifreq.ifr_flags & IFF_LOOPBACK) != 0) { + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); + free(np); continue; } + if (wanted_neigh) { + int found = 0; + for (wn = wanted_neigh; wn; wn = wn->w_next) + if (strcmp(wn->w_ifname, ifreq.ifr_name)==0) { + found = 1; + break; + } + if (!found) { + free(np->n_mask); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); + free(np); + continue; + } + switch (wn->w_used) { + case W_USED_NOT: + wn->w_used = W_USED_ONCE; + break; + case W_USED_ONCE: + syslog(LOG_ERR, + "specified interface %s more than once", + wn->w_ifname); + wn->w_used = W_USED_MULTI; + break; + case W_USED_MULTI: + /* oh well... don't tell again... */ + break; + default: + syslog(LOG_CRIT, "w_used=%d on %s", + wn->w_used, wn->w_ifname); + abort(); + } + } np->n_flags = ifreq.ifr_flags; if (np->n_flags & IFF_POINTOPOINT) { - if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { + if (ioctl(s, SIOCGIFDSTADDR, &ifreq) < 0) { syslog(LOG_ERR, "ioctl (get dstaddr)"); + free(np->n_mask); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); free(np); continue; } - if (!use_pointopoint) { + if (!wanted_neigh && !use_pointopoint) { + free(np->n_mask); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); free(np); continue; } /* we assume addresses are all the same size */ - bcopy((char *)&ifreq.ifr_dstaddr, - np->n_addr, np->n_addrlen); + bcopy(&ifreq.ifr_dstaddr, np->n_dstaddr, np->n_addrlen); } if (np->n_flags & IFF_BROADCAST) { - if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { + if (ioctl(s, SIOCGIFBRDADDR, &ifreq) < 0) { syslog(LOG_ERR, "ioctl (get broadaddr)"); + free(np->n_mask); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); free(np); continue; } - if (!use_broadcast) { + if (!wanted_neigh && !use_broadcast) { + free(np->n_mask); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); free(np); continue; } /* we assume addresses are all the same size */ - bcopy((char *)&ifreq.ifr_broadaddr, - np->n_addr, np->n_addrlen); + bcopy(&ifreq.ifr_broadaddr, np->n_dstaddr, np->n_addrlen); + + /* Get netmask */ + if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) { + syslog(LOG_ERR, "ioctl (get netmask)"); + free(np->n_mask); + free(np->n_myaddr); + free(np->n_dstaddr); + free(np->n_name); + free(np); + continue; + } + bcopy((char*)&ifreq.ifr_netmask, + np->n_mask, np->n_addrlen); } /* gag, wish we could get rid of Internet dependencies */ - sn = (struct sockaddr_in *)np->n_addr; + sn = (SA *)np->n_dstaddr; sn->sin_port = sp->s_port; np->n_next = neighbors; neighbors = np; } + + /* Check for unfound i/f */ + for (wn = wanted_neigh; wn; wn = wn->w_next) + if (wn->w_used == W_USED_NOT) + syslog(LOG_WARNING, "didn't find interface %s", + wn->w_ifname); + + /* Dump out used i/f */ + for (np = neighbors; np; np = np->n_next) + syslog(LOG_INFO, "sending on interface %s", np->n_name); + return (1); } @@ -697,7 +887,7 @@ { register struct whod *w = (struct whod *)buf; register struct whoent *we; - struct sockaddr_in *sn = (struct sockaddr_in *)to; + struct sockaddr_in *sn = (SA *)to; char *interval(); printf("sendto %x.%d\n", ntohl(sn->sin_addr.s_addr), ntohs(sn->sin_port)); @@ -751,3 +941,63 @@ return (resbuf); } #endif + +/* Eventually forward the packet */ +static void +forward(const SA *from, const struct whod *wd, int cc) +{ + struct neighbor *np; + int looped_back = 0; + + /* Scan to see if the packet was sent by us */ + for (np = neighbors; np != NULL; np = np->n_next) + if (from->sin_addr.s_addr == + np->n_myaddr->sin_addr.s_addr) { + looped_back = 1; + break; + } + + if (!looped_back) { + sigset_t saved_set; + sigset_t mask_set; + + sigemptyset(&mask_set); + sigaddset(&mask_set, SIGALRM); + sigprocmask(SIG_BLOCK, &mask_set, &saved_set); + + if (++forwarded_packets > MAX_FWD_PACKETS) { + syslog(LOG_ERR, "too many forward requests, " + "disabling forwarding"); + use_forwarding = 0; + } + + sigprocmask(SIG_SETMASK, &saved_set, NULL); + + /* Re-broadcast packet on all interfaces... */ + for (np = neighbors; np != NULL; np = np->n_next) { + /* .. but do not rebroadcast on the incoming interface */ + if (((np->n_flags & IFF_BROADCAST) && + (from->sin_addr.s_addr & + np->n_mask->sin_addr.s_addr) != + (np->n_myaddr->sin_addr.s_addr & + np->n_mask->sin_addr.s_addr)) || + ((np->n_flags & IFF_POINTOPOINT) && + (from->sin_addr.s_addr) != + np->n_dstaddr->sin_addr.s_addr)) { + if (sendto(sk, wd, cc, 0, + (struct sockaddr *)np->n_dstaddr, + np->n_addrlen) < 0) + syslog(LOG_ERR, + "forwarding sendto(%s): %m", + inet_ntoa(np->n_dstaddr->sin_addr)); + } + } + } +} + +static void +usage() +{ + fprintf(stderr, "usage: rwhod [-bpaf] [-i ] [-u user]...\n"); + exit(1); +}