xref: /openbsd-src/usr.sbin/rarpd/rarpd.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: rarpd.c,v 1.53 2012/04/06 18:03:52 deraadt 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, maxfd = 0;
388 	u_int	bufsize;
389 	fd_set  *fdsp, *lfdsp;
390 	u_char	*buf, *bp, *ep;
391 	struct if_info *ii;
392 
393 	if (iflist == 0) {
394 		error(FATAL, "no interfaces");
395 		/* NOTREACHED */
396 	}
397 	if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) {
398 		error(FATAL, "BIOCGBLEN: %s", strerror(errno));
399 		/* NOTREACHED */
400 	}
401 	buf = (u_char *) malloc((size_t) bufsize);
402 	if (buf == 0) {
403 		error(FATAL, "malloc: %s", strerror(errno));
404 		/* NOTREACHED */
405 	}
406 	/*
407 	 * Find the highest numbered file descriptor for select().
408 	 * Initialize the set of descriptors to listen to.
409 	 */
410 	for (ii = iflist; ii; ii = ii->ii_next)
411 		if (ii->ii_fd > maxfd)
412 			maxfd = ii->ii_fd;
413 
414 	fdsn = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask);
415 	if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
416 		error(FATAL, "malloc");
417 	if ((lfdsp = (fd_set *)malloc(fdsn)) == NULL)
418 		error(FATAL, "malloc");
419 
420 	memset(fdsp, 0, fdsn);
421 	for (ii = iflist; ii; ii = ii->ii_next)
422 		FD_SET(ii->ii_fd, fdsp);
423 
424 	while (1) {
425 		memcpy(lfdsp, fdsp, fdsn);
426 		if (select(maxfd + 1, lfdsp, (fd_set *) 0,
427 			(fd_set *) 0, (struct timeval *) 0) < 0) {
428 			error(FATAL, "select: %s", strerror(errno));
429 			/* NOTREACHED */
430 		}
431 		for (ii = iflist; ii; ii = ii->ii_next) {
432 			fd = ii->ii_fd;
433 			if (!FD_ISSET(fd, lfdsp))
434 				continue;
435 		again:
436 			cc = read(fd, (char *) buf, bufsize);
437 			/* Don't choke when we get ptraced */
438 			if (cc < 0 && errno == EINTR)
439 				goto again;
440 			/* Due to a SunOS bug, after 2^31 bytes, the file
441 			 * offset overflows and read fails with EINVAL.  The
442 			 * lseek() to 0 will fix things. */
443 			if (cc < 0) {
444 				if (errno == EINVAL &&
445 				    (lseek(fd, (off_t)0, SEEK_CUR) + bufsize) < 0) {
446 					(void) lseek(fd, (off_t)0, SEEK_SET);
447 					goto again;
448 				}
449 				error(FATAL, "read: %s", strerror(errno));
450 				/* NOTREACHED */
451 			}
452 			/* Loop through the packet(s) */
453 #define bhp ((struct bpf_hdr *)bp)
454 			bp = buf;
455 			ep = bp + cc;
456 			while (bp < ep) {
457 				int caplen, hdrlen;
458 
459 				caplen = bhp->bh_caplen;
460 				hdrlen = bhp->bh_hdrlen;
461 				if (rarp_check(bp + hdrlen, caplen))
462 					rarp_process(ii, bp + hdrlen);
463 				bp += BPF_WORDALIGN(hdrlen + caplen);
464 			}
465 		}
466 	}
467 }
468 
469 #ifndef TFTP_DIR
470 #define TFTP_DIR "/tftpboot"
471 #endif
472 
473 /*
474  * True if this server can boot the host whose IP address is 'addr'.
475  * This check is made by looking in the tftp directory for the
476  * configuration file.
477  */
478 int
479 rarp_bootable(u_int32_t addr)
480 {
481 	struct dirent *dent;
482 	char    ipname[40];
483 	static DIR *dd = 0;
484 	DIR *d;
485 
486 	(void) snprintf(ipname, sizeof ipname, "%08X", addr);
487 	/* If directory is already open, rewind it.  Otherwise, open it. */
488 	if ((d = dd))
489 		rewinddir(d);
490 	else {
491 		if (chdir(TFTP_DIR) == -1) {
492 			error(FATAL, "chdir: %s", strerror(errno));
493 			/* NOTREACHED */
494 		}
495 		d = opendir(".");
496 		if (d == 0) {
497 			error(FATAL, "opendir: %s", strerror(errno));
498 			/* NOTREACHED */
499 		}
500 		dd = d;
501 	}
502 	while ((dent = readdir(d)))
503 		if (strncmp(dent->d_name, ipname, 8) == 0)
504 			return 1;
505 	return 0;
506 }
507 
508 
509 /*
510  * Given a list of IP addresses, 'alist', return the first address that
511  * is on network 'net'; 'netmask' is a mask indicating the network portion
512  * of the address.
513  */
514 static u_int32_t
515 choose_ipaddr(u_int32_t **alist, u_int32_t net, u_int32_t netmask)
516 {
517 	for (; *alist; ++alist) {
518 		if ((**alist & netmask) == net)
519 			return **alist;
520 	}
521 	return 0;
522 }
523 /*
524  * Answer the RARP request in 'pkt', on the interface 'ii'.  'pkt' has
525  * already been checked for validity.  The reply is overlaid on the request.
526  */
527 void
528 rarp_process(struct if_info *ii, u_char *pkt)
529 {
530 	char    ename[MAXHOSTNAMELEN];
531 	u_int32_t  target_ipaddr;
532 	struct ether_header *ep;
533 	struct ether_addr *ea;
534 	struct hostent *hp;
535 	struct	in_addr in;
536 	struct if_addr *ia;
537 
538 	ep = (struct ether_header *) pkt;
539 	ea = (struct ether_addr *) &ep->ether_shost;
540 
541 	debug("%s", ether_ntoa(ea));
542 	if (ether_ntohost(ename, ea) != 0) {
543 		debug("ether_ntohost failed");
544 		return;
545 	}
546 	if ((hp = gethostbyname(ename)) == 0) {
547 		debug("gethostbyname (%s) failed", ename);
548 		return;
549 	}
550 
551 	/* Choose correct address from list. */
552 	if (hp->h_addrtype != AF_INET) {
553 		error(FATAL, "cannot handle non IP addresses");
554 		/* NOTREACHED */
555 	}
556 	for (target_ipaddr = 0, ia = ii->ii_addrs; ia; ia = ia->ia_next) {
557 		target_ipaddr = choose_ipaddr((u_int32_t **) hp->h_addr_list,
558 		    ia->ia_ipaddr & ia->ia_netmask, ia->ia_netmask);
559 		if (target_ipaddr)
560 			break;
561 	}
562 
563 	if (target_ipaddr == 0) {
564 		for (ia = ii->ii_addrs; ia; ia = ia->ia_next) {
565 			in.s_addr = ia->ia_ipaddr & ia->ia_netmask;
566 			error(NONFATAL, "cannot find %s on net %s",
567 			    ename, inet_ntoa(in));
568 		}
569 		return;
570 	}
571 	if (tflag == 0 || rarp_bootable(htonl(target_ipaddr)))
572 		rarp_reply(ii, ia, ep, target_ipaddr, hp);
573 	debug("reply sent");
574 }
575 
576 /*
577  * Lookup the ethernet address of the interface attached to the BPF
578  * file descriptor 'fd'; return it in 'eaddr'.
579  */
580 void
581 lookup_addrs(char *ifname, struct if_info *p)
582 {
583 	struct ifaddrs *ifap, *ifa;
584 	struct sockaddr_dl *sdl;
585 	u_char *eaddr = p->ii_eaddr;
586 	struct if_addr *ia, **iap = &p->ii_addrs;
587 	struct in_addr in;
588 	int found = 0;
589 
590 	if (getifaddrs(&ifap) != 0) {
591 		error(FATAL, "getifaddrs: %s", strerror(errno));
592 		/* NOTREACHED */
593 	}
594 
595 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
596 		if (strcmp(ifa->ifa_name, ifname))
597 			continue;
598 		sdl = (struct sockaddr_dl *) ifa->ifa_addr;
599 		if (sdl->sdl_family == AF_LINK &&
600 		    sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6) {
601 			memcpy((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
602 			if (dflag)
603 				fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n",
604 				    ifa->ifa_name,
605 				    eaddr[0], eaddr[1], eaddr[2],
606 				    eaddr[3], eaddr[4], eaddr[5]);
607 			found = 1;
608 		} else if (sdl->sdl_family == AF_INET) {
609 			ia = malloc (sizeof (struct if_addr));
610 			if (ia == NULL)
611 				error(FATAL, "lookup_addrs: malloc: %s",
612 				    strerror(errno));
613 			ia->ia_next = NULL;
614 			ia->ia_ipaddr =
615 			    ((struct sockaddr_in *) ifa->ifa_addr)->
616 			    sin_addr.s_addr;
617 			ia->ia_netmask =
618 			    ((struct sockaddr_in *) ifa->ifa_netmask)->
619 			    sin_addr.s_addr;
620 			/* If SIOCGIFNETMASK didn't work,
621 			   figure out a mask from the IP
622 			   address class. */
623 			if (ia->ia_netmask == 0)
624 				ia->ia_netmask =
625 				    ipaddrtonetmask(ia->ia_ipaddr);
626 			if (dflag) {
627 				in.s_addr = ia->ia_ipaddr;
628 				fprintf(stderr, "\t%s\n",
629 				    inet_ntoa(in));
630 			}
631 			*iap = ia;
632 			iap = &ia->ia_next;
633 		}
634 	}
635 	freeifaddrs(ifap);
636 	if (!found)
637 		error(FATAL, "lookup_addrs: Never saw interface `%s'!", ifname);
638 }
639 
640 int arptab_set(u_char *eaddr, u_int32_t host);
641 
642 /*
643  * Poke the kernel arp tables with the ethernet/ip address combinataion
644  * given.  When processing a reply, we must do this so that the booting
645  * host (i.e. the guy running rarpd), won't try to ARP for the hardware
646  * address of the guy being booted (he cannot answer the ARP).
647  */
648 void
649 update_arptab(u_char *ep, u_int32_t ipaddr)
650 {
651 #ifdef SIOCSARP
652 	struct sockaddr_in *sin;
653 	struct arpreq request;
654 	u_int32_t host;
655 	u_char *eaddr;
656 	int s;
657 
658 	request.arp_flags = 0;
659 	sin = (struct sockaddr_in *)&request.arp_pa;
660 	sin->sin_family = AF_INET;
661 	sin->sin_addr.s_addr = ipaddr;
662 	request.arp_ha.sa_family = AF_UNSPEC;
663 	/* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN,
664 	   because AF_UNSPEC is zero and the kernel assumes that a zero
665 	   sa_family means that the real sa_family value is in sa_len.  */
666 	request.arp_ha.sa_len = 16; /* XXX */
667 	memcpy((char *) request.arp_ha.sa_data, (char *) ep, 6);
668 
669 	s = socket(AF_INET, SOCK_DGRAM, 0);
670 	if (s < 0) {
671 		error(NONFATAL, "socket: %s", strerror(errno));
672 	} else {
673 		if (ioctl(s, SIOCSARP, (caddr_t)&request) < 0)
674 		    error(NONFATAL, "SIOCSARP: %s", strerror(errno));
675 		(void) close(s);
676 	}
677 #else
678 	if (arptab_set(ep, ipaddr) > 0)
679 		syslog(LOG_ERR, "couldn't update arp table");
680 #endif
681 }
682 /*
683  * Build a reverse ARP packet and sent it out on the interface.
684  * 'ep' points to a valid ARPOP_REVREQUEST.  The ARPOP_REVREPLY is built
685  * on top of the request, then written to the network.
686  *
687  * RFC 903 defines the ether_arp fields as follows.  The following comments
688  * are taken (more or less) straight from this document.
689  *
690  * ARPOP_REVREQUEST
691  *
692  * arp_sha is the hardware address of the sender of the packet.
693  * arp_spa is undefined.
694  * arp_tha is the 'target' hardware address.
695  *   In the case where the sender wishes to determine his own
696  *   protocol address, this, like arp_sha, will be the hardware
697  *   address of the sender.
698  * arp_tpa is undefined.
699  *
700  * ARPOP_REVREPLY
701  *
702  * arp_sha is the hardware address of the responder (the sender of the
703  *   reply packet).
704  * arp_spa is the protocol address of the responder (see the note below).
705  * arp_tha is the hardware address of the target, and should be the same as
706  *   that which was given in the request.
707  * arp_tpa is the protocol address of the target, that is, the desired address.
708  *
709  * Note that the requirement that arp_spa be filled in with the responder's
710  * protocol is purely for convenience.  For instance, if a system were to use
711  * both ARP and RARP, then the inclusion of the valid protocol-hardware
712  * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
713  * ARP request.
714  */
715 void
716 rarp_reply(struct if_info *ii, struct if_addr *ia, struct ether_header *ep,
717     u_int32_t ipaddr, struct hostent *hp)
718 {
719 	struct ether_arp *ap = (struct ether_arp *) (ep + 1);
720 	int len, n;
721 
722 	update_arptab((u_char *)&ap->arp_sha, ipaddr);
723 
724 	/* Build the rarp reply by modifying the rarp request in place. */
725 	ep->ether_type = htons(ETHERTYPE_REVARP);
726 	ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER);
727 	ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP);
728 	ap->arp_op = htons(ARPOP_REVREPLY);
729 
730 	memcpy((char *) &ep->ether_dhost, (char *) &ap->arp_sha, 6);
731 	memcpy((char *) &ep->ether_shost, (char *) ii->ii_eaddr, 6);
732 	memcpy((char *) &ap->arp_sha, (char *) ii->ii_eaddr, 6);
733 
734 	memcpy((char *) ap->arp_tpa, (char *) &ipaddr, 4);
735 	/* Target hardware is unchanged. */
736 	memcpy((char *) ap->arp_spa, (char *) &ia->ia_ipaddr, 4);
737 
738 	if (lflag) {
739 		struct ether_addr ea;
740 
741 		memcpy(&ea.ether_addr_octet, &ap->arp_sha, 6);
742 		syslog(LOG_INFO, "%s asked; %s replied", hp->h_name,
743 		    ether_ntoa(&ea));
744 	}
745 
746 	len = sizeof(*ep) + sizeof(*ap);
747 	n = write(ii->ii_fd, (char *) ep, len);
748 	if (n != len)
749 		error(NONFATAL, "write: only %d of %d bytes written", n, len);
750 }
751 /*
752  * Get the netmask of an IP address.  This routine is used if
753  * SIOCGIFNETMASK doesn't work.
754  */
755 u_int32_t
756 ipaddrtonetmask(u_int32_t addr)
757 {
758 	if (IN_CLASSA(addr))
759 		return IN_CLASSA_NET;
760 	if (IN_CLASSB(addr))
761 		return IN_CLASSB_NET;
762 	if (IN_CLASSC(addr))
763 		return IN_CLASSC_NET;
764 	error(FATAL, "unknown IP address class: %08X", addr);
765 	/* NOTREACHED */
766 }
767 
768 void
769 error(int fatal, const char *fmt,...)
770 {
771 	va_list ap;
772 
773 	if (dflag) {
774 		if (fatal)
775 			(void) fprintf(stderr, "rarpd: error: ");
776 		else
777 			(void) fprintf(stderr, "rarpd: warning: ");
778 		va_start(ap, fmt);
779 		(void) vfprintf(stderr, fmt, ap);
780 		va_end(ap);
781 		(void) fprintf(stderr, "\n");
782 	}
783 	va_start(ap, fmt);
784 	vsyslog(LOG_ERR, fmt, ap);
785 	va_end(ap);
786 	if (fatal)
787 		exit(1);
788 	/* NOTREACHED */
789 }
790 
791 void
792 debug(const char *fmt,...)
793 {
794 	va_list ap;
795 
796 	if (dflag) {
797 		va_start(ap, fmt);
798 		(void) fprintf(stderr, "rarpd: ");
799 		(void) vfprintf(stderr, fmt, ap);
800 		va_end(ap);
801 		(void) fprintf(stderr, "\n");
802 	}
803 }
804