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