--- netkit-rwho-0.17.orig/rwhod/rwhod.c
+++ netkit-rwho-0.17/rwhod/rwhod.c
@@ -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 <phil@fifi.org> (added options & implemented 
+ * them.
+
  */
 
 char copyright[] =
@@ -47,6 +51,7 @@
 #include <signal.h>
 #include <sys/ioctl.h>
 #include <sys/file.h>
+#include <sys/types.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
@@ -69,11 +74,13 @@
 #include <arpa/inet.h>
 #include <pwd.h>
 #include <grp.h>
-
-#include "daemon.h"
+#include <time.h>
+#include <stdint.h>
 
 #include "../version.h"
 
+typedef struct sockaddr_in SA;
+
 #define ENDIAN	LITTLE_ENDIAN
 
 /*
@@ -95,7 +102,16 @@
 static void	broadcaster(void);
 static int	configure(int s);
 static int	verify(const char *name);
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2)
 static int	getloadavg(double ptr[3], int n);
+#endif
+
+/* 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
@@ -103,21 +119,30 @@
  * 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))
@@ -126,24 +151,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;
+	char *user = "rwhod";
 	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:h?fu:")) != EOF) {
 	    switch (opt) {
 	      case 'b':
 		  use_broadcast = 1;
@@ -155,31 +204,61 @@
 		  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 '?':
+	      case 'h':
 	      default:
-		  fprintf(stderr, "usage: rwhod [-bpa] [-u user]\n");
-		  exit(1);
-		  break;
+		  usage();
 	    }
 	}
 	if (optind<argc) {
-	    fprintf(stderr, "usage: rwhod [-bpa] [-u user]\n");
-	    exit(1);
+		usage();
 	}
-	if (!use_pointopoint && !use_broadcast) {
+	if (!use_pointopoint && !use_broadcast && !wanted_neigh) {
 		/* use none is nonsensical; default to all */
 		use_pointopoint = 1;
 		use_broadcast = 1;
 	}
-	
-	sp = getservbyname("who", "udp");
-	if (sp == 0) {
-		fprintf(stderr, "rwhod: udp/who: unknown service\n");
+	if ((use_pointopoint || use_broadcast) && wanted_neigh) {
+		fprintf(stderr, "rwhod: cannot specify both -i and one of -b "
+			"-p -a\n");
 		exit(1);
 	}
+
 #ifndef DEBUG
 	daemon(1, 0);
 #endif
@@ -189,53 +268,20 @@
 		exit(1);
 	}
 	(void) signal(SIGHUP, huphandler);
-	openlog("rwhod", LOG_PID, LOG_DAEMON);
-
-	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);
-	}
 
 	(void) umask(022);
 
 	signal(SIGTERM, termhandler);
-	child_pid = fork();
-	if (child_pid < 0) {
-		syslog(LOG_ERR, "fork: %m");
-		exit(1);
-	}
-	if (child_pid == 0) {
-		broadcaster();
-		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) {
+	if ((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 (pw->pw_uid) {
 		if (setgroups(1, &pw->pw_gid) < 0
 		 || setgid(pw->pw_gid) < 0
 		 || setuid(pw->pw_uid) < 0) {
@@ -244,10 +290,28 @@
 		}
 	}
 
+	if (!configure(sk))
+		exit(1);
+
+	child_pid = fork();
+	if (child_pid < 0) {
+		syslog(LOG_ERR, "fork: %m");
+		exit(1);
+	}
+	if (child_pid == 0) {
+		broadcaster();
+		exit(0);
+	}
+
+	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,
@@ -257,6 +321,8 @@
 				syslog(LOG_WARNING, "recv: %m");
 			continue;
 		}
+		if (cc < WHDRSIZE)
+			continue;
 		if (from.sin_port != sp->s_port) {
 			syslog(LOG_WARNING, "%d: bad from port",
 				ntohs(from.sin_port));
@@ -266,14 +332,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);
+			syslog(LOG_WARNING, "malformed host name from %s",
+				inet_ntoa(from.sin_addr));
 			continue;
 		}
 		snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname);
@@ -306,7 +382,7 @@
 		}
 #endif
 		wd.wd_recvtime = time(NULL);
-		write(whod, (char *)&wd, cc);
+		write(whod, &wd, cc);
 		if (fstat(whod, &st) < 0 || st.st_size > cc)
 			ftruncate(whod, cc);
 		(void) close(whod);
@@ -345,9 +421,6 @@
 	size_t		mynamelen;
 	struct whod	mywd;
 
-	if (!configure(sk))
-		exit(1);
-
 	/*
 	 * Establish host name as returned by system.
 	 */
@@ -357,7 +430,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);
 	strncpy(mywd.wd_hostname, myname, mynamelen);
@@ -448,7 +521,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++;
 	}
@@ -460,10 +535,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)) {
@@ -472,6 +547,7 @@
 	}
 }
 
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2)
 /*
  * Taken from:
  *
@@ -518,6 +594,7 @@
 	fclose(fp);
 	return 0;
 }
+#endif	/* __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) */
 
 
 void
@@ -566,7 +643,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
@@ -584,10 +661,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);
 	}
@@ -600,7 +678,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 &&
@@ -614,63 +696,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);
 }
 
@@ -692,7 +881,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));
@@ -746,3 +935,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 <ifname>] [-u user]...\n");
+	exit(1);
+}
