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