xref: /openbsd-src/usr.sbin/rarpd/rarpd.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: rarpd.c,v 1.52 2010/08/29 12:33:25 chl Exp $ */
2 /*	$NetBSD: rarpd.c,v 1.25 1998/04/23 02:48:33 mrg Exp $	*/
3 
4 /*
5  * Copyright (c) 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that: (1) source code distributions
10  * retain the above copyright notice and this paragraph in its entirety, (2)
11  * distributions including binary code include the above copyright notice and
12  * this paragraph in its entirety in the documentation or other materials
13  * provided with the distribution, and (3) all advertising materials mentioning
14  * features or use of this software display the following acknowledgement:
15  * ``This product includes software developed by the University of California,
16  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17  * the University nor the names of its contributors may be used to endorse
18  * or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  */
24 
25 /*
26  * rarpd - Reverse ARP Daemon
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <sys/param.h>
35 #include <unistd.h>
36 #include <sys/time.h>
37 #include <net/bpf.h>
38 #include <sys/socket.h>
39 #include <sys/ioctl.h>
40 #include <net/if.h>
41 #include <net/if_dl.h>
42 #include <net/if_types.h>
43 #include <netinet/in.h>
44 #include <netinet/if_ether.h>
45 #include <sys/file.h>
46 #include <errno.h>
47 #include <netdb.h>
48 #include <arpa/inet.h>
49 #include <dirent.h>
50 #include <util.h>
51 #include <ifaddrs.h>
52 #include <paths.h>
53 
54 #define FATAL		1	/* fatal error occurred */
55 #define NONFATAL	0	/* non fatal error occurred */
56 
57 /*
58  * The structures for each interface.
59  */
60 struct if_addr {
61 	in_addr_t ia_ipaddr;		/* IP address of this interface */
62 	in_addr_t ia_netmask;		/* subnet or net mask */
63 	struct if_addr *ia_next;
64 };
65 
66 struct if_info {
67 	int	ii_fd;			/* BPF file descriptor */
68 	char	ii_name[IFNAMSIZ];	/* if name, e.g. "en0" */
69 	u_char	ii_eaddr[ETHER_ADDR_LEN];	/* Ethernet address of this iface */
70 	struct if_addr *ii_addrs;	/* Networks this interface is on */
71 	struct if_info *ii_next;
72 };
73 /*
74  * The list of all interfaces that are being listened to.  rarp_loop()
75  * "selects" on the descriptors in this list.
76  */
77 struct if_info *iflist;
78 
79 int    rarp_open(char *);
80 void   init_one(char *);
81 void   init_all(void);
82 void   rarp_loop(void);
83 void   lookup_addrs(char *, struct if_info *);
84 void   usage(void);
85 void   rarp_process(struct if_info *, u_char *);
86 void   rarp_reply(struct if_info *, struct if_addr *,
87 	    struct ether_header *, u_int32_t, struct hostent *);
88 void   update_arptab(u_char *, u_int32_t);
89 void   error(int, const char *,...);
90 void   debug(const char *,...);
91 u_int32_t ipaddrtonetmask(u_int32_t);
92 int    rarp_bootable(u_int32_t);
93 
94 int	aflag = 0;		/* listen on "all" interfaces  */
95 int	dflag = 0;		/* print debugging messages */
96 int	fflag = 0;		/* don't fork */
97 int	lflag = 0;		/* log all replies */
98 int	tflag = 0;		/* tftpboot check */
99 
100 int
101 main(int argc, char *argv[])
102 {
103 	extern char *__progname;
104 	extern int optind, opterr;
105 	int op, devnull, f;
106 	pid_t pid;
107 
108 	/* All error reporting is done through syslogs. */
109 	openlog(__progname, LOG_PID | LOG_CONS, LOG_DAEMON);
110 
111 	opterr = 0;
112 	while ((op = getopt(argc, argv, "adflt")) != -1) {
113 		switch (op) {
114 		case 'a':
115 			++aflag;
116 			break;
117 		case 'd':
118 			++dflag;
119 			break;
120 		case 'f':
121 			++fflag;
122 			break;
123 		case 'l':
124 			++lflag;
125 			break;
126 		case 't':
127 			++tflag;
128 			break;
129 		default:
130 			usage();
131 			/* NOTREACHED */
132 		}
133 	}
134 	argc -= optind;
135 	argv += optind;
136 
137 	if ((aflag && argc > 0) || (!aflag && argc == 0))
138 		usage();
139 
140 	if (aflag)
141 		init_all();
142 	else
143 		while (argc > 0) {
144 			init_one(argv[0]);
145 			argc--;
146 			argv++;
147 		}
148 
149 	if ((!fflag) && (!dflag)) {
150 		pid = fork();
151 		if (pid > 0)
152 			/* Parent exits, leaving child in background. */
153 			exit(0);
154 		else
155 			if (pid == -1) {
156 				error(FATAL, "cannot fork");
157 				/* NOTREACHED */
158 			}
159 
160 		/* write pid file */
161 		pidfile(NULL);
162 
163 		/* Fade into the background */
164 		f = open(_PATH_TTY, O_RDWR);
165 		if (f >= 0) {
166 			if (ioctl(f, TIOCNOTTY, 0) < 0) {
167 				error(FATAL, "TIOCNOTTY: %s", strerror(errno));
168 				/* NOTREACHED */
169 			}
170 			(void) close(f);
171 		}
172 		(void) chdir("/");
173 		(void) setpgrp(0, getpid());
174 		devnull = open(_PATH_DEVNULL, O_RDWR);
175 		if (devnull >= 0) {
176 			(void) dup2(devnull, STDIN_FILENO);
177 			(void) dup2(devnull, STDOUT_FILENO);
178 			(void) dup2(devnull, STDERR_FILENO);
179 			if (devnull > 2)
180 				(void) close(devnull);
181 		}
182 	}
183 	rarp_loop();
184 	exit(0);
185 }
186 
187 /*
188  * Add 'ifname' to the interface list.  Lookup its IP address and network
189  * mask and Ethernet address, and open a BPF file for it.
190  */
191 void
192 init_one(char *ifname)
193 {
194 	struct if_info *p;
195 	int fd;
196 
197 	/* first check to see if this "if" was already opened? */
198 	for (p = iflist; p; p = p->ii_next)
199 		if (!strncmp(p->ii_name, ifname, IFNAMSIZ))
200 			return;
201 
202 	fd = rarp_open(ifname);
203 	if (fd < 0)
204 		return;
205 
206 	p = (struct if_info *)malloc(sizeof(*p));
207 	if (p == 0) {
208 		error(FATAL, "malloc: %s", strerror(errno));
209 		/* NOTREACHED */
210 	}
211 
212 	p->ii_next = iflist;
213 	iflist = p;
214 
215 	p->ii_fd = fd;
216 	strncpy(p->ii_name, ifname, IFNAMSIZ);
217 	p->ii_addrs = NULL;
218 	lookup_addrs(ifname, p);
219 }
220 /*
221  * Initialize all "candidate" interfaces that are in the system
222  * configuration list.  A "candidate" is up, not loopback and not
223  * point to point.
224  */
225 void
226 init_all(void)
227 {
228 	struct ifaddrs *ifap, *ifa;
229 	struct sockaddr_dl *sdl;
230 
231 	if (getifaddrs(&ifap) != 0) {
232 		error(FATAL, "getifaddrs: %s", strerror(errno));
233 		/* NOTREACHED */
234 	}
235 
236 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
237 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
238 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
239 		    sdl->sdl_alen != 6)
240 			continue;
241 
242 		if ((ifa->ifa_flags &
243 		    (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
244 			continue;
245 		init_one(ifa->ifa_name);
246 	}
247 	freeifaddrs(ifap);
248 }
249 
250 void
251 usage(void)
252 {
253 	(void) fprintf(stderr, "usage: rarpd [-adflt] if0 [... ifN]\n");
254 	exit(1);
255 }
256 
257 static int
258 bpf_open(void)
259 {
260 	int	fd, n = 0;
261 	char    device[sizeof "/dev/bpf0000000000"];
262 
263 	/* Go through all the minors and find one that isn't in use. */
264 	do {
265 		(void) snprintf(device, sizeof device, "/dev/bpf%d", n++);
266 		fd = open(device, O_RDWR);
267 	} while (fd < 0 && errno == EBUSY);
268 
269 	if (fd < 0) {
270 		error(FATAL, "%s: %s", device, strerror(errno));
271 		/* NOTREACHED */
272 	}
273 	return fd;
274 }
275 
276 static struct bpf_insn insns[] = {
277 	BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12),
278 	BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_REVARP, 0, 3),
279 	BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20),
280 	BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ARPOP_REVREQUEST, 0, 1),
281 	BPF_STMT(BPF_RET | BPF_K, sizeof(struct ether_arp) +
282 	    sizeof(struct ether_header)),
283 	BPF_STMT(BPF_RET | BPF_K, 0),
284 };
285 
286 static struct bpf_program filter = {
287 	sizeof insns / sizeof(insns[0]),
288 	insns
289 };
290 
291 /*
292  * Open a BPF file and attach it to the interface named 'device'.
293  * Set immediate mode, and set a filter that accepts only RARP requests.
294  */
295 int
296 rarp_open(char *device)
297 {
298 	int	fd, immediate;
299 	struct ifreq ifr;
300 	u_int   dlt;
301 
302 	fd = bpf_open();
303 
304 	/* Set immediate mode so packets are processed as they arrive. */
305 	immediate = 1;
306 	if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
307 		error(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
308 		/* NOTREACHED */
309 	}
310 
311 	(void) strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
312 	if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
313 		if (aflag) {	/* for -a skip not ethernet interfaces */
314 			close(fd);
315 			return -1;
316 		}
317 		error(FATAL, "BIOCSETIF: %s", strerror(errno));
318 		/* NOTREACHED */
319 	}
320 
321 	/*
322 	 * Check that the data link layer is an Ethernet; this code
323 	 * won't work with anything else.
324 	 */
325 	if (ioctl(fd, BIOCGDLT, (caddr_t) &dlt) < 0) {
326 		error(FATAL, "BIOCGDLT: %s", strerror(errno));
327 		/* NOTREACHED */
328 	}
329 	if (dlt != DLT_EN10MB) {
330 		if (aflag) {	/* for -a skip not ethernet interfaces */
331 			close(fd);
332 			return -1;
333 		}
334 		error(FATAL, "%s is not an ethernet", device);
335 		/* NOTREACHED */
336 	}
337 	/* Set filter program. */
338 	if (ioctl(fd, BIOCSETF, (caddr_t)&filter) < 0) {
339 		error(FATAL, "BIOCSETF: %s", strerror(errno));
340 		/* NOTREACHED */
341 	}
342 	return fd;
343 }
344 /*
345  * Perform various sanity checks on the RARP request packet.  Return
346  * false on failure and log the reason.
347  */
348 static int
349 rarp_check(u_char *p, int len)
350 {
351 	struct ether_header *ep = (struct ether_header *) p;
352 	struct ether_arp *ap = (struct ether_arp *) (p + sizeof(*ep));
353 
354 	(void) debug("got a packet");
355 
356 	if (len < sizeof(*ep) + sizeof(*ap)) {
357 		error(NONFATAL, "truncated request");
358 		return 0;
359 	}
360 	/* XXX This test might be better off broken out... */
361 	if (ntohs (ep->ether_type) != ETHERTYPE_REVARP ||
362 	    ntohs (ap->arp_hrd) != ARPHRD_ETHER ||
363 	    ntohs (ap->arp_op) != ARPOP_REVREQUEST ||
364 	    ntohs (ap->arp_pro) != ETHERTYPE_IP ||
365 	    ap->arp_hln != 6 || ap->arp_pln != 4) {
366 		error(NONFATAL, "request fails sanity check");
367 		return 0;
368 	}
369 	if (memcmp((char *) &ep->ether_shost, (char *) &ap->arp_sha, 6) != 0) {
370 		error(NONFATAL, "ether/arp sender address mismatch");
371 		return 0;
372 	}
373 	if (memcmp((char *) &ap->arp_sha, (char *) &ap->arp_tha, 6) != 0) {
374 		error(NONFATAL, "ether/arp target address mismatch");
375 		return 0;
376 	}
377 	return 1;
378 }
379 
380 /*
381  * Loop indefinitely listening for RARP requests on the
382  * interfaces in 'iflist'.
383  */
384 void
385 rarp_loop(void)
386 {
387 	int	cc, fd, fdsn, bufsize, maxfd = 0;
388 	fd_set  *fdsp, *lfdsp;
389 	u_char *buf, *bp, *ep;
390 	struct if_info *ii;
391 
392 	if (iflist == 0) {
393 		error(FATAL, "no interfaces");
394 		/* NOTREACHED */
395 	}
396 	if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) {
397 		error(FATAL, "BIOCGBLEN: %s", strerror(errno));
398 		/* NOTREACHED */
399 	}
400 	buf = (u_char *) malloc((unsigned) bufsize);
401 	if (buf == 0) {
402 		error(FATAL, "malloc: %s", strerror(errno));
403 		/* NOTREACHED */
404 	}
405 	/*
406 	 * Find the highest numbered file descriptor for select().
407 	 * Initialize the set of descriptors to listen to.
408 	 */
409 	for (ii = iflist; ii; ii = ii->ii_next)
410 		if (ii->ii_fd > maxfd)
411 			maxfd = ii->ii_fd;
412 
413 	fdsn = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask);
414 	if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
415 		error(FATAL, "malloc");
416 	if ((lfdsp = (fd_set *)malloc(fdsn)) == NULL)
417 		error(FATAL, "malloc");
418 
419 	memset(fdsp, 0, fdsn);
420 	for (ii = iflist; ii; ii = ii->ii_next)
421 		FD_SET(ii->ii_fd, fdsp);
422 
423 	while (1) {
424 		memcpy(lfdsp, fdsp, fdsn);
425 		if (select(maxfd + 1, lfdsp, (fd_set *) 0,
426 			(fd_set *) 0, (struct timeval *) 0) < 0) {
427 			error(FATAL, "select: %s", strerror(errno));
428 			/* NOTREACHED */
429 		}
430 		for (ii = iflist; ii; ii = ii->ii_next) {
431 			fd = ii->ii_fd;
432 			if (!FD_ISSET(fd, lfdsp))
433 				continue;
434 		again:
435 			cc = read(fd, (char *) buf, bufsize);
436 			/* Don't choke when we get ptraced */
437 			if (cc < 0 && errno == EINTR)
438 				goto again;
439 			/* Due to a SunOS bug, after 2^31 bytes, the file
440 			 * offset overflows and read fails with EINVAL.  The
441 			 * lseek() to 0 will fix things. */
442 			if (cc < 0) {
443 				if (errno == EINVAL &&
444 				    (lseek(fd, (off_t)0, SEEK_CUR) + bufsize) < 0) {
445 					(void) lseek(fd, (off_t)0, SEEK_SET);
446 					goto again;
447 				}
448 				error(FATAL, "read: %s", strerror(errno));
449 				/* NOTREACHED */
450 			}
451 			/* Loop through the packet(s) */
452 #define bhp ((struct bpf_hdr *)bp)
453 			bp = buf;
454 			ep = bp + cc;
455 			while (bp < ep) {
456 				int caplen, hdrlen;
457 
458 				caplen = bhp->bh_caplen;
459 				hdrlen = bhp->bh_hdrlen;
460 				if (rarp_check(bp + hdrlen, caplen))
461 					rarp_process(ii, bp + hdrlen);
462 				bp += BPF_WORDALIGN(hdrlen + caplen);
463 			}
464 		}
465 	}
466 }
467 
468 #ifndef TFTP_DIR
469 #define TFTP_DIR "/tftpboot"
470 #endif
471 
472 /*
473  * True if this server can boot the host whose IP address is 'addr'.
474  * This check is made by looking in the tftp directory for the
475  * configuration file.
476  */
477 int
478 rarp_bootable(u_int32_t addr)
479 {
480 	struct dirent *dent;
481 	char    ipname[40];
482 	static DIR *dd = 0;
483 	DIR *d;
484 
485 	(void) snprintf(ipname, sizeof ipname, "%08X", addr);
486 	/* If directory is already open, rewind it.  Otherwise, open it. */
487 	if ((d = dd))
488 		rewinddir(d);
489 	else {
490 		if (chdir(TFTP_DIR) == -1) {
491 			error(FATAL, "chdir: %s", strerror(errno));
492 			/* NOTREACHED */
493 		}
494 		d = opendir(".");
495 		if (d == 0) {
496 			error(FATAL, "opendir: %s", strerror(errno));
497 			/* NOTREACHED */
498 		}
499 		dd = d;
500 	}
501 	while ((dent = readdir(d)))
502 		if (strncmp(dent->d_name, ipname, 8) == 0)
503 			return 1;
504 	return 0;
505 }
506 
507 
508 /*
509  * Given a list of IP addresses, 'alist', return the first address that
510  * is on network 'net'; 'netmask' is a mask indicating the network portion
511  * of the address.
512  */
513 static u_int32_t
514 choose_ipaddr(u_int32_t **alist, u_int32_t net, u_int32_t netmask)
515 {
516 	for (; *alist; ++alist) {
517 		if ((**alist & netmask) == net)
518 			return **alist;
519 	}
520 	return 0;
521 }
522 /*
523  * Answer the RARP request in 'pkt', on the interface 'ii'.  'pkt' has
524  * already been checked for validity.  The reply is overlaid on the request.
525  */
526 void
527 rarp_process(struct if_info *ii, u_char *pkt)
528 {
529 	char    ename[MAXHOSTNAMELEN];
530 	u_int32_t  target_ipaddr;
531 	struct ether_header *ep;
532 	struct ether_addr *ea;
533 	struct hostent *hp;
534 	struct	in_addr in;
535 	struct if_addr *ia;
536 
537 	ep = (struct ether_header *) pkt;
538 	ea = (struct ether_addr *) &ep->ether_shost;
539 
540 	debug("%s", ether_ntoa(ea));
541 	if (ether_ntohost(ename, ea) != 0) {
542 		debug("ether_ntohost failed");
543 		return;
544 	}
545 	if ((hp = gethostbyname(ename)) == 0) {
546 		debug("gethostbyname (%s) failed", ename);
547 		return;
548 	}
549 
550 	/* Choose correct address from list. */
551 	if (hp->h_addrtype != AF_INET) {
552 		error(FATAL, "cannot handle non IP addresses");
553 		/* NOTREACHED */
554 	}
555 	for (target_ipaddr = 0, ia = ii->ii_addrs; ia; ia = ia->ia_next) {
556 		target_ipaddr = choose_ipaddr((u_int32_t **) hp->h_addr_list,
557 		    ia->ia_ipaddr & ia->ia_netmask, ia->ia_netmask);
558 		if (target_ipaddr)
559 			break;
560 	}
561 
562 	if (target_ipaddr == 0) {
563 		for (ia = ii->ii_addrs; ia; ia = ia->ia_next) {
564 			in.s_addr = ia->ia_ipaddr & ia->ia_netmask;
565 			error(NONFATAL, "cannot find %s on net %s",
566 			    ename, inet_ntoa(in));
567 		}
568 		return;
569 	}
570 	if (tflag == 0 || rarp_bootable(htonl(target_ipaddr)))
571 		rarp_reply(ii, ia, ep, target_ipaddr, hp);
572 	debug("reply sent");
573 }
574 
575 /*
576  * Lookup the ethernet address of the interface attached to the BPF
577  * file descriptor 'fd'; return it in 'eaddr'.
578  */
579 void
580 lookup_addrs(char *ifname, struct if_info *p)
581 {
582 	struct ifaddrs *ifap, *ifa;
583 	struct sockaddr_dl *sdl;
584 	u_char *eaddr = p->ii_eaddr;
585 	struct if_addr *ia, **iap = &p->ii_addrs;
586 	struct in_addr in;
587 	int found = 0;
588 
589 	if (getifaddrs(&ifap) != 0) {
590 		error(FATAL, "getifaddrs: %s", strerror(errno));
591 		/* NOTREACHED */
592 	}
593 
594 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
595 		if (strcmp(ifa->ifa_name, ifname))
596 			continue;
597 		sdl = (struct sockaddr_dl *) ifa->ifa_addr;
598 		if (sdl->sdl_family == AF_LINK &&
599 		    sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6) {
600 			memcpy((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
601 			if (dflag)
602 				fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n",
603 				    ifa->ifa_name,
604 				    eaddr[0], eaddr[1], eaddr[2],
605 				    eaddr[3], eaddr[4], eaddr[5]);
606 			found = 1;
607 		} else if (sdl->sdl_family == AF_INET) {
608 			ia = malloc (sizeof (struct if_addr));
609 			if (ia == NULL)
610 				error(FATAL, "lookup_addrs: malloc: %s",
611 				    strerror(errno));
612 			ia->ia_next = NULL;
613 			ia->ia_ipaddr =
614 			    ((struct sockaddr_in *) ifa->ifa_addr)->
615 			    sin_addr.s_addr;
616 			ia->ia_netmask =
617 			    ((struct sockaddr_in *) ifa->ifa_netmask)->
618 			    sin_addr.s_addr;
619 			/* If SIOCGIFNETMASK didn't work,
620 			   figure out a mask from the IP
621 			   address class. */
622 			if (ia->ia_netmask == 0)
623 				ia->ia_netmask =
624 				    ipaddrtonetmask(ia->ia_ipaddr);
625 			if (dflag) {
626 				in.s_addr = ia->ia_ipaddr;
627 				fprintf(stderr, "\t%s\n",
628 				    inet_ntoa(in));
629 			}
630 			*iap = ia;
631 			iap = &ia->ia_next;
632 		}
633 	}
634 	freeifaddrs(ifap);
635 	if (!found)
636 		error(FATAL, "lookup_addrs: Never saw interface `%s'!", ifname);
637 }
638 
639 int arptab_set(u_char *eaddr, u_int32_t host);
640 
641 /*
642  * Poke the kernel arp tables with the ethernet/ip address combinataion
643  * given.  When processing a reply, we must do this so that the booting
644  * host (i.e. the guy running rarpd), won't try to ARP for the hardware
645  * address of the guy being booted (he cannot answer the ARP).
646  */
647 void
648 update_arptab(u_char *ep, u_int32_t ipaddr)
649 {
650 #ifdef SIOCSARP
651 	struct sockaddr_in *sin;
652 	struct arpreq request;
653 	u_int32_t host;
654 	u_char *eaddr;
655 	int s;
656 
657 	request.arp_flags = 0;
658 	sin = (struct sockaddr_in *)&request.arp_pa;
659 	sin->sin_family = AF_INET;
660 	sin->sin_addr.s_addr = ipaddr;
661 	request.arp_ha.sa_family = AF_UNSPEC;
662 	/* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN,
663 	   because AF_UNSPEC is zero and the kernel assumes that a zero
664 	   sa_family means that the real sa_family value is in sa_len.  */
665 	request.arp_ha.sa_len = 16; /* XXX */
666 	memcpy((char *) request.arp_ha.sa_data, (char *) ep, 6);
667 
668 	s = socket(AF_INET, SOCK_DGRAM, 0);
669 	if (s < 0) {
670 		error(NONFATAL, "socket: %s", strerror(errno));
671 	} else {
672 		if (ioctl(s, SIOCSARP, (caddr_t)&request) < 0)
673 		    error(NONFATAL, "SIOCSARP: %s", strerror(errno));
674 		(void) close(s);
675 	}
676 #else
677 	if (arptab_set(ep, ipaddr) > 0)
678 		syslog(LOG_ERR, "couldn't update arp table");
679 #endif
680 }
681 /*
682  * Build a reverse ARP packet and sent it out on the interface.
683  * 'ep' points to a valid ARPOP_REVREQUEST.  The ARPOP_REVREPLY is built
684  * on top of the request, then written to the network.
685  *
686  * RFC 903 defines the ether_arp fields as follows.  The following comments
687  * are taken (more or less) straight from this document.
688  *
689  * ARPOP_REVREQUEST
690  *
691  * arp_sha is the hardware address of the sender of the packet.
692  * arp_spa is undefined.
693  * arp_tha is the 'target' hardware address.
694  *   In the case where the sender wishes to determine his own
695  *   protocol address, this, like arp_sha, will be the hardware
696  *   address of the sender.
697  * arp_tpa is undefined.
698  *
699  * ARPOP_REVREPLY
700  *
701  * arp_sha is the hardware address of the responder (the sender of the
702  *   reply packet).
703  * arp_spa is the protocol address of the responder (see the note below).
704  * arp_tha is the hardware address of the target, and should be the same as
705  *   that which was given in the request.
706  * arp_tpa is the protocol address of the target, that is, the desired address.
707  *
708  * Note that the requirement that arp_spa be filled in with the responder's
709  * protocol is purely for convenience.  For instance, if a system were to use
710  * both ARP and RARP, then the inclusion of the valid protocol-hardware
711  * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
712  * ARP request.
713  */
714 void
715 rarp_reply(struct if_info *ii, struct if_addr *ia, struct ether_header *ep,
716     u_int32_t ipaddr, struct hostent *hp)
717 {
718 	struct ether_arp *ap = (struct ether_arp *) (ep + 1);
719 	int len, n;
720 
721 	update_arptab((u_char *)&ap->arp_sha, ipaddr);
722 
723 	/* Build the rarp reply by modifying the rarp request in place. */
724 	ep->ether_type = htons(ETHERTYPE_REVARP);
725 	ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
726 	ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
727 	ap->arp_op = htons(ARPOP_REVREPLY);
728 
729 	memcpy((char *) &ep->ether_dhost, (char *) &ap->arp_sha, 6);
730 	memcpy((char *) &ep->ether_shost, (char *) ii->ii_eaddr, 6);
731 	memcpy((char *) &ap->arp_sha, (char *) ii->ii_eaddr, 6);
732 
733 	memcpy((char *) ap->arp_tpa, (char *) &ipaddr, 4);
734 	/* Target hardware is unchanged. */
735 	memcpy((char *) ap->arp_spa, (char *) &ia->ia_ipaddr, 4);
736 
737 	if (lflag) {
738 		struct ether_addr ea;
739 
740 		memcpy(&ea.ether_addr_octet, &ap->arp_sha, 6);
741 		syslog(LOG_INFO, "%s asked; %s replied", hp->h_name,
742 		    ether_ntoa(&ea));
743 	}
744 
745 	len = sizeof(*ep) + sizeof(*ap);
746 	n = write(ii->ii_fd, (char *) ep, len);
747 	if (n != len)
748 		error(NONFATAL, "write: only %d of %d bytes written", n, len);
749 }
750 /*
751  * Get the netmask of an IP address.  This routine is used if
752  * SIOCGIFNETMASK doesn't work.
753  */
754 u_int32_t
755 ipaddrtonetmask(u_int32_t addr)
756 {
757 	if (IN_CLASSA(addr))
758 		return IN_CLASSA_NET;
759 	if (IN_CLASSB(addr))
760 		return IN_CLASSB_NET;
761 	if (IN_CLASSC(addr))
762 		return IN_CLASSC_NET;
763 	error(FATAL, "unknown IP address class: %08X", addr);
764 	/* NOTREACHED */
765 }
766 
767 void
768 error(int fatal, const char *fmt,...)
769 {
770 	va_list ap;
771 
772 	if (dflag) {
773 		if (fatal)
774 			(void) fprintf(stderr, "rarpd: error: ");
775 		else
776 			(void) fprintf(stderr, "rarpd: warning: ");
777 		va_start(ap, fmt);
778 		(void) vfprintf(stderr, fmt, ap);
779 		va_end(ap);
780 		(void) fprintf(stderr, "\n");
781 	}
782 	va_start(ap, fmt);
783 	vsyslog(LOG_ERR, fmt, ap);
784 	va_end(ap);
785 	if (fatal)
786 		exit(1);
787 	/* NOTREACHED */
788 }
789 
790 void
791 debug(const char *fmt,...)
792 {
793 	va_list ap;
794 
795 	if (dflag) {
796 		va_start(ap, fmt);
797 		(void) fprintf(stderr, "rarpd: ");
798 		(void) vfprintf(stderr, fmt, ap);
799 		va_end(ap);
800 		(void) fprintf(stderr, "\n");
801 	}
802 }
803