Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / rarpd / rarpd.c
1 /*
2  * Copyright (c) 1990, 1991, 1992, 1993, 1996
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * @(#) Copyright (c) 1990, 1991, 1992, 1993, 1996 The Regents of the University of California.  All rights reserved.
22  * $FreeBSD: src/usr.sbin/rarpd/rarpd.c,v 1.23.2.4 2002/12/01 19:19:34 dwmalone Exp $
23  * $DragonFly: src/usr.sbin/rarpd/rarpd.c,v 1.2 2003/06/17 04:30:02 dillon Exp $
24  */
25
26 /*
27  * rarpd - Reverse ARP Daemon
28  *
29  * Usage:       rarpd -a [ -dfsv ] [-t directory] [ hostname ]
30  *              rarpd [ -dfsv ] [-t directory] interface [ hostname ]
31  *
32  * 'hostname' is optional solely for backwards compatibility with Sun's rarpd.
33  * Currently, the argument is ignored.
34  */
35 #include <sys/param.h>
36 #include <sys/file.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39 #include <sys/time.h>
40
41 #include <net/bpf.h>
42 #include <net/ethernet.h>
43 #include <net/if.h>
44 #include <net/if_types.h>
45 #include <net/if_dl.h>
46 #include <net/route.h>
47
48 #include <netinet/in.h>
49 #include <netinet/if_ether.h>
50
51 #include <arpa/inet.h>
52
53 #include <errno.h>
54 #include <netdb.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <stdlib.h>
60 #include <unistd.h>
61
62 #if defined(SUNOS4) || defined(__FreeBSD__) /* XXX */
63 #define HAVE_DIRENT_H
64 #endif
65
66 #ifdef HAVE_DIRENT_H
67 #include <dirent.h>
68 #else
69 #include <sys/dir.h>
70 #endif
71
72 /* Cast a struct sockaddr to a structaddr_in */
73 #define SATOSIN(sa) ((struct sockaddr_in *)(sa))
74
75 #ifndef TFTP_DIR
76 #define TFTP_DIR "/tftpboot"
77 #endif
78
79 #if BSD >= 199200
80 #define ARPSECS (20 * 60)               /* as per code in netinet/if_ether.c */
81 #define REVARP_REQUEST ARPOP_REVREQUEST
82 #define REVARP_REPLY ARPOP_REVREPLY
83 #endif
84
85 #ifndef ETHERTYPE_REVARP
86 #define ETHERTYPE_REVARP 0x8035
87 #define REVARP_REQUEST 3
88 #define REVARP_REPLY 4
89 #endif
90
91 /*
92  * Map field names in ether_arp struct.  What a pain in the neck.
93  */
94 #ifdef SUNOS3
95 #undef arp_sha
96 #undef arp_spa
97 #undef arp_tha
98 #undef arp_tpa
99 #define arp_sha arp_xsha
100 #define arp_spa arp_xspa
101 #define arp_tha arp_xtha
102 #define arp_tpa arp_xtpa
103 #endif
104
105 /*
106  * The structure for each interface.
107  */
108 struct if_info {
109         struct  if_info *ii_next;
110         int     ii_fd;          /* BPF file descriptor */
111         u_long  ii_ipaddr;      /* IP address of this interface */
112         u_long  ii_netmask;     /* subnet or net mask */
113         u_char  ii_eaddr[6];    /* Ethernet address of this interface */
114         char ii_ifname[sizeof(((struct ifreq *)0)->ifr_name) + 1];
115 };
116
117 /*
118  * The list of all interfaces that are being listened to.  rarp_loop()
119  * "selects" on the descriptors in this list.
120  */
121 struct if_info *iflist;
122
123 int verbose;                    /* verbose messages */
124 int s;                          /* inet datagram socket */
125 const char *tftp_dir = TFTP_DIR;        /* tftp directory */
126
127 int dflag;                      /* messages to stdout/stderr, not syslog(3) */
128 int sflag;                      /* ignore /tftpboot */
129
130 static  u_char zero[6];
131
132 static int      bpf_open(void);
133 static u_long   choose_ipaddr(u_long **, u_long, u_long);
134 static char     *eatoa(u_char *);
135 static int      expand_syslog_m(const char *fmt, char **newfmt);
136 static void     init(char *);
137 static void     init_one(struct ifreq *, char *);
138 static char     *intoa(u_long);
139 static u_long   ipaddrtonetmask(u_long);
140 static void     logmsg(int, const char *, ...) __printflike(2, 3);
141 static int      rarp_bootable(u_long);
142 static int      rarp_check(u_char *, u_int);
143 static void     rarp_loop(void);
144 static int      rarp_open(char *);
145 static void     rarp_process(struct if_info *, u_char *, u_int);
146 static void     rarp_reply(struct if_info *, struct ether_header *,
147                 u_long, u_int);
148 static void     update_arptab(u_char *, u_long);
149 static void     usage(void);
150
151 int
152 main(int argc, char *argv[])
153 {
154         int op;
155         char *ifname, *hostname, *name;
156
157         int aflag = 0;          /* listen on "all" interfaces  */
158         int fflag = 0;          /* don't fork */
159
160         if ((name = strrchr(argv[0], '/')) != NULL)
161                 ++name;
162         else
163                 name = argv[0];
164         if (*name == '-')
165                 ++name;
166
167         /*
168          * All error reporting is done through syslog, unless -d is specified
169          */
170         openlog(name, LOG_PID | LOG_CONS, LOG_DAEMON);
171
172         opterr = 0;
173         while ((op = getopt(argc, argv, "adfst:v")) != -1) {
174                 switch (op) {
175                 case 'a':
176                         ++aflag;
177                         break;
178
179                 case 'd':
180                         ++dflag;
181                         break;
182
183                 case 'f':
184                         ++fflag;
185                         break;
186
187                 case 's':
188                         ++sflag;
189                         break;
190
191                 case 't':
192                         tftp_dir = optarg;
193                         break;
194
195                 case 'v':
196                         ++verbose;
197                         break;
198
199                 default:
200                         usage();
201                         /* NOTREACHED */
202                 }
203         }
204         ifname = argv[optind++];
205         hostname =  ifname ? argv[optind] : NULL;
206         if ((aflag && ifname) || (!aflag && ifname == NULL))
207                 usage();
208
209         if (aflag)
210                 init(NULL);
211         else
212                 init(ifname);
213
214         if (!fflag) {
215                 if (daemon(0,0)) {
216                         logmsg(LOG_ERR, "cannot fork");
217                         exit(1);
218                 }
219         }
220         rarp_loop();
221         return(0);
222 }
223
224 /*
225  * Add to the interface list.
226  */
227 void
228 init_one(struct ifreq *ifrp, char *target)
229 {
230         struct if_info *ii;
231         struct sockaddr_dl *ll;
232         int family;
233         struct ifreq ifr;
234
235         family = ifrp->ifr_addr.sa_family;
236         switch (family) {
237
238         case AF_INET:
239 #if BSD >= 199100
240         case AF_LINK:
241 #endif
242                 (void)strncpy(ifr.ifr_name, ifrp->ifr_name,
243                     sizeof(ifrp->ifr_name));
244                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifr) == -1) {
245                         logmsg(LOG_ERR,
246                             "SIOCGIFFLAGS: %.*s: %m",
247                                 (int)sizeof(ifrp->ifr_name), ifrp->ifr_name);
248                         exit(1);
249                 }
250                 if ((ifr.ifr_flags & IFF_UP) == 0 ||
251                     (ifr.ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0)
252                         return;
253                 break;
254
255
256         default:
257                 return;
258         }
259
260         /* Don't bother going any further if not the target interface */
261         if (target != NULL &&
262             strncmp(ifrp->ifr_name, target, sizeof(ifrp->ifr_name)) != 0)
263                 return;
264
265         /* Look for interface in list */
266         for (ii = iflist; ii != NULL; ii = ii->ii_next)
267                 if (strncmp(ifrp->ifr_name, ii->ii_ifname,
268                     sizeof(ifrp->ifr_name)) == 0)
269                         break;
270
271         /* Allocate a new one if not found */
272         if (ii == NULL) {
273                 ii = (struct if_info *)malloc(sizeof(*ii));
274                 if (ii == NULL) {
275                         logmsg(LOG_ERR, "malloc: %m");
276                         exit(1);
277                 }
278                 bzero(ii, sizeof(*ii));
279                 ii->ii_fd = -1;
280                 (void)strncpy(ii->ii_ifname, ifrp->ifr_name,
281                     sizeof(ifrp->ifr_name));
282                 ii->ii_ifname[sizeof(ii->ii_ifname) - 1] = '\0';
283                 ii->ii_next = iflist;
284                 iflist = ii;
285         }
286
287         switch (family) {
288
289         case AF_INET:
290                 if (ioctl(s, SIOCGIFADDR, (char *)&ifr) == -1) {
291                         logmsg(LOG_ERR, "ipaddr SIOCGIFADDR: %s: %m",
292                             ii->ii_ifname);
293                         exit(1);
294                 }
295                 ii->ii_ipaddr = SATOSIN(&ifr.ifr_addr)->sin_addr.s_addr;
296                 if (ioctl(s, SIOCGIFNETMASK, (char *)&ifr) == -1) {
297                         logmsg(LOG_ERR, "SIOCGIFNETMASK: %m");
298                         exit(1);
299                 }
300                 ii->ii_netmask = SATOSIN(&ifr.ifr_addr)->sin_addr.s_addr;
301                 if (ii->ii_netmask == 0)
302                         ii->ii_netmask = ipaddrtonetmask(ii->ii_ipaddr);
303                 if (ii->ii_fd < 0) {
304                         ii->ii_fd = rarp_open(ii->ii_ifname);
305 #if BSD < 199100
306                         /* Use BPF descriptor to get ethernet address. */
307                         if (ioctl(ii->ii_fd, SIOCGIFADDR, (char *)&ifr) == -1) {
308                                 logmsg(LOG_ERR, "eaddr SIOCGIFADDR: %s: %m",
309                                     ii->ii_ifname);
310                                 exit(1);
311                         }
312                         bcopy(&ifr.ifr_addr.sa_data[0], ii->ii_eaddr, 6);
313 #endif
314                 }
315                 break;
316
317 #if BSD >= 199100
318                 case AF_LINK:
319                         ll = (struct sockaddr_dl *)&ifrp->ifr_addr;
320                         if (ll->sdl_type == IFT_ETHER)
321                                 bcopy(LLADDR(ll), ii->ii_eaddr, 6);
322                         break;
323 #endif
324                 }
325 }
326 /*
327  * Initialize all "candidate" interfaces that are in the system
328  * configuration list.  A "candidate" is up, not loopback and not
329  * point to point.
330  */
331 void
332 init(char *target)
333 {
334         u_int n;
335         struct ifreq *ifrp, *ifend;
336         struct if_info *ii, *nii, *lii;
337         struct ifconf ifc;
338         struct ifreq ibuf[16];
339
340         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
341                 logmsg(LOG_ERR, "socket: %m");
342                 exit(1);
343         }
344         ifc.ifc_len = sizeof ibuf;
345         ifc.ifc_buf = (caddr_t)ibuf;
346         if ((ioctl(s, SIOCGIFCONF, (char *)&ifc) == -1) ||
347             ((u_int)ifc.ifc_len < sizeof(struct ifreq))) {
348                 logmsg(LOG_ERR, "SIOCGIFCONF: %m");
349                 exit(1);
350         }
351         ifrp = ibuf;
352         ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
353         while (ifrp < ifend) {
354                 init_one(ifrp, target);
355
356 #if BSD >= 199100
357                 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
358                 if (n < sizeof(*ifrp))
359                         n = sizeof(*ifrp);
360                 ifrp = (struct ifreq *)((char *)ifrp + n);
361 #else
362                 ++ifrp;
363 #endif
364         }
365
366         /* Throw away incomplete interfaces */
367         lii = NULL;
368         for (ii = iflist; ii != NULL; ii = nii) {
369                 nii = ii->ii_next;
370                 if (ii->ii_ipaddr == 0 ||
371                     bcmp(ii->ii_eaddr, zero, 6) == 0) {
372                         if (lii == NULL)
373                                 iflist = nii;
374                         else
375                                 lii->ii_next = nii;
376                         if (ii->ii_fd >= 0)
377                                 close(ii->ii_fd);
378                         free(ii);
379                         continue;
380                 }
381                 lii = ii;
382         }
383
384         /* Verbose stuff */
385         if (verbose)
386                 for (ii = iflist; ii != NULL; ii = ii->ii_next)
387                         logmsg(LOG_DEBUG, "%s %s 0x%08lx %s",
388                             ii->ii_ifname, intoa(ntohl(ii->ii_ipaddr)),
389                             (u_long)ntohl(ii->ii_netmask), eatoa(ii->ii_eaddr));
390 }
391
392 void
393 usage(void)
394 {
395         (void)fprintf(stderr, "usage: rarpd [-adfsv] [-t directory] [interface]\n");
396         exit(1);
397 }
398
399 int
400 bpf_open(void)
401 {
402         int fd;
403         int n = 0;
404         char device[sizeof "/dev/bpf000"];
405
406         /*
407          * Go through all the minors and find one that isn't in use.
408          */
409         do {
410                 (void)sprintf(device, "/dev/bpf%d", n++);
411                 fd = open(device, O_RDWR);
412         } while ((fd == -1) && (errno == EBUSY));
413
414         if (fd == -1) {
415                 logmsg(LOG_ERR, "%s: %m", device);
416                 exit(1);
417         }
418         return fd;
419 }
420
421 /*
422  * Open a BPF file and attach it to the interface named 'device'.
423  * Set immediate mode, and set a filter that accepts only RARP requests.
424  */
425 int
426 rarp_open(char *device)
427 {
428         int fd;
429         struct ifreq ifr;
430         u_int dlt;
431         int immediate;
432
433         static struct bpf_insn insns[] = {
434                 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 12),
435                 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ETHERTYPE_REVARP, 0, 3),
436                 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 20),
437                 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, REVARP_REQUEST, 0, 1),
438                 BPF_STMT(BPF_RET|BPF_K, sizeof(struct ether_arp) +
439                          sizeof(struct ether_header)),
440                 BPF_STMT(BPF_RET|BPF_K, 0),
441         };
442         static struct bpf_program filter = {
443                 sizeof insns / sizeof(insns[0]),
444                 insns
445         };
446
447         fd = bpf_open();
448         /*
449          * Set immediate mode so packets are processed as they arrive.
450          */
451         immediate = 1;
452         if (ioctl(fd, BIOCIMMEDIATE, &immediate) == -1) {
453                 logmsg(LOG_ERR, "BIOCIMMEDIATE: %m");
454                 exit(1);
455         }
456         (void)strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
457         if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) == -1) {
458                 logmsg(LOG_ERR, "BIOCSETIF: %m");
459                 exit(1);
460         }
461         /*
462          * Check that the data link layer is an Ethernet; this code won't
463          * work with anything else.
464          */
465         if (ioctl(fd, BIOCGDLT, (caddr_t)&dlt) == -1) {
466                 logmsg(LOG_ERR, "BIOCGDLT: %m");
467                 exit(1);
468         }
469         if (dlt != DLT_EN10MB) {
470                 logmsg(LOG_ERR, "%s is not an ethernet", device);
471                 exit(1);
472         }
473         /*
474          * Set filter program.
475          */
476         if (ioctl(fd, BIOCSETF, (caddr_t)&filter) == -1) {
477                 logmsg(LOG_ERR, "BIOCSETF: %m");
478                 exit(1);
479         }
480         return fd;
481 }
482
483 /*
484  * Perform various sanity checks on the RARP request packet.  Return
485  * false on failure and log the reason.
486  */
487 int
488 rarp_check(u_char *p, u_int len)
489 {
490         struct ether_header *ep = (struct ether_header *)p;
491         struct ether_arp *ap = (struct ether_arp *)(p + sizeof(*ep));
492
493         if (len < sizeof(*ep) + sizeof(*ap)) {
494                 logmsg(LOG_ERR, "truncated request, got %u, expected %lu",
495                                 len, (u_long)(sizeof(*ep) + sizeof(*ap)));
496                 return 0;
497         }
498         /*
499          * XXX This test might be better off broken out...
500          */
501         if (ntohs(ep->ether_type) != ETHERTYPE_REVARP ||
502             ntohs(ap->arp_hrd) != ARPHRD_ETHER ||
503             ntohs(ap->arp_op) != REVARP_REQUEST ||
504             ntohs(ap->arp_pro) != ETHERTYPE_IP ||
505             ap->arp_hln != 6 || ap->arp_pln != 4) {
506                 logmsg(LOG_DEBUG, "request fails sanity check");
507                 return 0;
508         }
509         if (bcmp((char *)&ep->ether_shost, (char *)&ap->arp_sha, 6) != 0) {
510                 logmsg(LOG_DEBUG, "ether/arp sender address mismatch");
511                 return 0;
512         }
513         if (bcmp((char *)&ap->arp_sha, (char *)&ap->arp_tha, 6) != 0) {
514                 logmsg(LOG_DEBUG, "ether/arp target address mismatch");
515                 return 0;
516         }
517         return 1;
518 }
519
520 #ifndef FD_SETSIZE
521 #define FD_SET(n, fdp) ((fdp)->fds_bits[0] |= (1 << (n)))
522 #define FD_ISSET(n, fdp) ((fdp)->fds_bits[0] & (1 << (n)))
523 #define FD_ZERO(fdp) ((fdp)->fds_bits[0] = 0)
524 #endif
525
526 /*
527  * Loop indefinitely listening for RARP requests on the
528  * interfaces in 'iflist'.
529  */
530 void
531 rarp_loop(void)
532 {
533         u_char *buf, *bp, *ep;
534         int cc, fd;
535         fd_set fds, listeners;
536         int bufsize, maxfd = 0;
537         struct if_info *ii;
538
539         if (iflist == NULL) {
540                 logmsg(LOG_ERR, "no interfaces");
541                 exit(1);
542         }
543         if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) == -1) {
544                 logmsg(LOG_ERR, "BIOCGBLEN: %m");
545                 exit(1);
546         }
547         buf = malloc(bufsize);
548         if (buf == NULL) {
549                 logmsg(LOG_ERR, "malloc: %m");
550                 exit(1);
551         }
552
553         while (1) {
554                 /*
555                  * Find the highest numbered file descriptor for select().
556                  * Initialize the set of descriptors to listen to.
557                  */
558                 FD_ZERO(&fds);
559                 for (ii = iflist; ii != NULL; ii = ii->ii_next) {
560                         FD_SET(ii->ii_fd, &fds);
561                         if (ii->ii_fd > maxfd)
562                                 maxfd = ii->ii_fd;
563                 }
564                 listeners = fds;
565                 if (select(maxfd + 1, &listeners, NULL, NULL, NULL) == -1) {
566                         /* Don't choke when we get ptraced */
567                         if (errno == EINTR)
568                                 continue;
569                         logmsg(LOG_ERR, "select: %m");
570                         exit(1);
571                 }
572                 for (ii = iflist; ii != NULL; ii = ii->ii_next) {
573                         fd = ii->ii_fd;
574                         if (!FD_ISSET(fd, &listeners))
575                                 continue;
576                 again:
577                         cc = read(fd, (char *)buf, bufsize);
578                         /* Don't choke when we get ptraced */
579                         if ((cc == -1) && (errno == EINTR))
580                                 goto again;
581 #if defined(SUNOS3) || defined(SUNOS4)
582                         /*
583                          * Due to a SunOS bug, after 2^31 bytes, the
584                          * file offset overflows and read fails with
585                          * EINVAL.  The lseek() to 0 will fix things.
586                          */
587                         if (cc == -1) {
588                                 if (errno == EINVAL &&
589                                     (long)(tell(fd) + bufsize) < 0) {
590                                         (void)lseek(fd, 0, 0);
591                                         goto again;
592                                 }
593                                 logmsg(LOG_ERR, "read: %m");
594                                 exit(1);
595                         }
596 #endif
597
598                         /* Loop through the packet(s) */
599 #define bhp ((struct bpf_hdr *)bp)
600                         bp = buf;
601                         ep = bp + cc;
602                         while (bp < ep) {
603                                 u_int caplen, hdrlen;
604
605                                 caplen = bhp->bh_caplen;
606                                 hdrlen = bhp->bh_hdrlen;
607                                 if (rarp_check(bp + hdrlen, caplen))
608                                         rarp_process(ii, bp + hdrlen, caplen);
609                                 bp += BPF_WORDALIGN(hdrlen + caplen);
610                         }
611                 }
612         }
613 #undef bhp
614 }
615
616 /*
617  * True if this server can boot the host whose IP address is 'addr'.
618  * This check is made by looking in the tftp directory for the
619  * configuration file.
620  */
621 int
622 rarp_bootable(u_long addr)
623 {
624 #ifdef HAVE_DIRENT_H
625         struct dirent *dent;
626 #else
627         struct direct *dent;
628 #endif
629         DIR *d;
630         char ipname[9];
631         static DIR *dd = NULL;
632
633         (void)sprintf(ipname, "%08lX", (u_long)ntohl(addr));
634
635         /*
636          * If directory is already open, rewind it.  Otherwise, open it.
637          */
638         if ((d = dd) != NULL)
639                 rewinddir(d);
640         else {
641                 if (chdir(tftp_dir) == -1) {
642                         logmsg(LOG_ERR, "chdir: %s: %m", tftp_dir);
643                         exit(1);
644                 }
645                 d = opendir(".");
646                 if (d == NULL) {
647                         logmsg(LOG_ERR, "opendir: %m");
648                         exit(1);
649                 }
650                 dd = d;
651         }
652         while ((dent = readdir(d)) != NULL)
653                 if (strncmp(dent->d_name, ipname, 8) == 0)
654                         return 1;
655         return 0;
656 }
657
658 /*
659  * Given a list of IP addresses, 'alist', return the first address that
660  * is on network 'net'; 'netmask' is a mask indicating the network portion
661  * of the address.
662  */
663 u_long
664 choose_ipaddr(u_long **alist, u_long net, u_long netmask)
665 {
666         for (; *alist; ++alist)
667                 if ((**alist & netmask) == net)
668                         return **alist;
669         return 0;
670 }
671
672 /*
673  * Answer the RARP request in 'pkt', on the interface 'ii'.  'pkt' has
674  * already been checked for validity.  The reply is overlaid on the request.
675  */
676 void
677 rarp_process(struct if_info *ii, u_char *pkt, u_int len)
678 {
679         struct ether_header *ep;
680         struct hostent *hp;
681         u_long target_ipaddr;
682         char ename[256];
683
684         ep = (struct ether_header *)pkt;
685         /* should this be arp_tha? */
686         if (ether_ntohost(ename, (struct ether_addr *)&ep->ether_shost) != 0) {
687                 logmsg(LOG_ERR, "cannot map %s to name",
688                         eatoa(ep->ether_shost));
689                 return;
690         }
691
692         if ((hp = gethostbyname(ename)) == NULL) {
693                 logmsg(LOG_ERR, "cannot map %s to IP address", ename);
694                 return;
695         }
696
697         /*
698          * Choose correct address from list.
699          */
700         if (hp->h_addrtype != AF_INET) {
701                 logmsg(LOG_ERR, "cannot handle non IP addresses for %s",
702                                                                 ename);
703                 return;
704         }
705         target_ipaddr = choose_ipaddr((u_long **)hp->h_addr_list,
706                                       ii->ii_ipaddr & ii->ii_netmask,
707                                       ii->ii_netmask);
708         if (target_ipaddr == 0) {
709                 logmsg(LOG_ERR, "cannot find %s on net %s",
710                        ename, intoa(ntohl(ii->ii_ipaddr & ii->ii_netmask)));
711                 return;
712         }
713         if (sflag || rarp_bootable(target_ipaddr))
714                 rarp_reply(ii, ep, target_ipaddr, len);
715         else if (verbose > 1)
716                 logmsg(LOG_INFO, "%s %s at %s DENIED (not bootable)",
717                     ii->ii_ifname,
718                     eatoa(ep->ether_shost),
719                     intoa(ntohl(target_ipaddr)));
720 }
721
722 /*
723  * Poke the kernel arp tables with the ethernet/ip address combinataion
724  * given.  When processing a reply, we must do this so that the booting
725  * host (i.e. the guy running rarpd), won't try to ARP for the hardware
726  * address of the guy being booted (he cannot answer the ARP).
727  */
728 #if BSD >= 199200
729 struct sockaddr_inarp sin_inarp = {
730         sizeof(struct sockaddr_inarp), AF_INET, 0,
731         {0},
732         {0},
733         0, 0
734 };
735 struct sockaddr_dl sin_dl = {
736         sizeof(struct sockaddr_dl), AF_LINK, 0, IFT_ETHER, 0, 6,
737         0, ""
738 };
739 struct {
740         struct rt_msghdr rthdr;
741         char rtspace[512];
742 } rtmsg;
743
744 void
745 update_arptab(u_char *ep, u_long ipaddr)
746 {
747         int cc;
748         struct sockaddr_inarp *ar, *ar2;
749         struct sockaddr_dl *ll, *ll2;
750         struct rt_msghdr *rt;
751         int xtype, xindex;
752         static pid_t pid;
753         int r;
754         static int seq;
755
756         r = socket(PF_ROUTE, SOCK_RAW, 0);
757         if (r == -1) {
758                 logmsg(LOG_ERR, "raw route socket: %m");
759                 exit(1);
760         }
761         pid = getpid();
762
763         ar = &sin_inarp;
764         ar->sin_addr.s_addr = ipaddr;
765         ll = &sin_dl;
766         bcopy(ep, LLADDR(ll), 6);
767
768         /* Get the type and interface index */
769         rt = &rtmsg.rthdr;
770         bzero(rt, sizeof(rtmsg));
771         rt->rtm_version = RTM_VERSION;
772         rt->rtm_addrs = RTA_DST;
773         rt->rtm_type = RTM_GET;
774         rt->rtm_seq = ++seq;
775         ar2 = (struct sockaddr_inarp *)rtmsg.rtspace;
776         bcopy(ar, ar2, sizeof(*ar));
777         rt->rtm_msglen = sizeof(*rt) + sizeof(*ar);
778         errno = 0;
779         if ((write(r, rt, rt->rtm_msglen) == -1) && (errno != ESRCH)) {
780                 logmsg(LOG_ERR, "rtmsg get write: %m");
781                 close(r);
782                 return;
783         }
784         do {
785                 cc = read(r, rt, sizeof(rtmsg));
786         } while (cc > 0 && (rt->rtm_seq != seq || rt->rtm_pid != pid));
787         if (cc == -1) {
788                 logmsg(LOG_ERR, "rtmsg get read: %m");
789                 close(r);
790                 return;
791         }
792         ll2 = (struct sockaddr_dl *)((u_char *)ar2 + ar2->sin_len);
793         if (ll2->sdl_family != AF_LINK) {
794                 /*
795                  * XXX I think this means the ip address is not on a
796                  * directly connected network (the family is AF_INET in
797                  * this case).
798                  */
799                 logmsg(LOG_ERR, "bogus link family (%d) wrong net for %08lX?\n",
800                     ll2->sdl_family, ipaddr);
801                 close(r);
802                 return;
803         }
804         xtype = ll2->sdl_type;
805         xindex = ll2->sdl_index;
806
807         /* Set the new arp entry */
808         bzero(rt, sizeof(rtmsg));
809         rt->rtm_version = RTM_VERSION;
810         rt->rtm_addrs = RTA_DST | RTA_GATEWAY;
811         rt->rtm_inits = RTV_EXPIRE;
812         rt->rtm_rmx.rmx_expire = time(0) + ARPSECS;
813         rt->rtm_flags = RTF_HOST | RTF_STATIC;
814         rt->rtm_type = RTM_ADD;
815         rt->rtm_seq = ++seq;
816
817         bcopy(ar, ar2, sizeof(*ar));
818
819         ll2 = (struct sockaddr_dl *)((u_char *)ar2 + sizeof(*ar2));
820         bcopy(ll, ll2, sizeof(*ll));
821         ll2->sdl_type = xtype;
822         ll2->sdl_index = xindex;
823
824         rt->rtm_msglen = sizeof(*rt) + sizeof(*ar2) + sizeof(*ll2);
825         errno = 0;
826         if ((write(r, rt, rt->rtm_msglen) == -1) && (errno != EEXIST)) {
827                 logmsg(LOG_ERR, "rtmsg add write: %m");
828                 close(r);
829                 return;
830         }
831         do {
832                 cc = read(r, rt, sizeof(rtmsg));
833         } while (cc > 0 && (rt->rtm_seq != seq || rt->rtm_pid != pid));
834         close(r);
835         if (cc == -1) {
836                 logmsg(LOG_ERR, "rtmsg add read: %m");
837                 return;
838         }
839 }
840 #else
841 void
842 update_arptab(u_char *ep, u_long ipaddr)
843 {
844         struct arpreq request;
845         struct sockaddr_in *sin;
846
847         request.arp_flags = 0;
848         sin = (struct sockaddr_in *)&request.arp_pa;
849         sin->sin_family = AF_INET;
850         sin->sin_addr.s_addr = ipaddr;
851         request.arp_ha.sa_family = AF_UNSPEC;
852         bcopy((char *)ep, (char *)request.arp_ha.sa_data, 6);
853
854         if (ioctl(s, SIOCSARP, (caddr_t)&request) == -1)
855                 logmsg(LOG_ERR, "SIOCSARP: %m");
856 }
857 #endif
858
859 /*
860  * Build a reverse ARP packet and sent it out on the interface.
861  * 'ep' points to a valid REVARP_REQUEST.  The REVARP_REPLY is built
862  * on top of the request, then written to the network.
863  *
864  * RFC 903 defines the ether_arp fields as follows.  The following comments
865  * are taken (more or less) straight from this document.
866  *
867  * REVARP_REQUEST
868  *
869  * arp_sha is the hardware address of the sender of the packet.
870  * arp_spa is undefined.
871  * arp_tha is the 'target' hardware address.
872  *   In the case where the sender wishes to determine his own
873  *   protocol address, this, like arp_sha, will be the hardware
874  *   address of the sender.
875  * arp_tpa is undefined.
876  *
877  * REVARP_REPLY
878  *
879  * arp_sha is the hardware address of the responder (the sender of the
880  *   reply packet).
881  * arp_spa is the protocol address of the responder (see the note below).
882  * arp_tha is the hardware address of the target, and should be the same as
883  *   that which was given in the request.
884  * arp_tpa is the protocol address of the target, that is, the desired address.
885  *
886  * Note that the requirement that arp_spa be filled in with the responder's
887  * protocol is purely for convenience.  For instance, if a system were to use
888  * both ARP and RARP, then the inclusion of the valid protocol-hardware
889  * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent
890  * ARP request.
891  */
892 void
893 rarp_reply(struct if_info *ii, struct ether_header *ep, u_long ipaddr,
894                 u_int len)
895 {
896         u_int n;
897         struct ether_arp *ap = (struct ether_arp *)(ep + 1);
898
899         update_arptab((u_char *)&ap->arp_sha, ipaddr);
900
901         /*
902          * Build the rarp reply by modifying the rarp request in place.
903          */
904         ap->arp_op = htons(REVARP_REPLY);
905
906 #ifdef BROKEN_BPF
907         ep->ether_type = ETHERTYPE_REVARP;
908 #endif
909         bcopy((char *)&ap->arp_sha, (char *)&ep->ether_dhost, 6);
910         bcopy((char *)ii->ii_eaddr, (char *)&ep->ether_shost, 6);
911         bcopy((char *)ii->ii_eaddr, (char *)&ap->arp_sha, 6);
912
913         bcopy((char *)&ipaddr, (char *)ap->arp_tpa, 4);
914         /* Target hardware is unchanged. */
915         bcopy((char *)&ii->ii_ipaddr, (char *)ap->arp_spa, 4);
916
917         /* Zero possible garbage after packet. */
918         bzero((char *)ep + (sizeof(*ep) + sizeof(*ap)),
919                         len - (sizeof(*ep) + sizeof(*ap)));
920         n = write(ii->ii_fd, (char *)ep, len);
921         if (n != len)
922                 logmsg(LOG_ERR, "write: only %d of %d bytes written", n, len);
923         if (verbose)
924                 logmsg(LOG_INFO, "%s %s at %s REPLIED", ii->ii_ifname,
925                     eatoa(ap->arp_tha),
926                     intoa(ntohl(ipaddr)));
927 }
928
929 /*
930  * Get the netmask of an IP address.  This routine is used if
931  * SIOCGIFNETMASK doesn't work.
932  */
933 u_long
934 ipaddrtonetmask(u_long addr)
935 {
936         addr = ntohl(addr);
937         if (IN_CLASSA(addr))
938                 return htonl(IN_CLASSA_NET);
939         if (IN_CLASSB(addr))
940                 return htonl(IN_CLASSB_NET);
941         if (IN_CLASSC(addr))
942                 return htonl(IN_CLASSC_NET);
943         logmsg(LOG_DEBUG, "unknown IP address class: %08lX", addr);
944         return htonl(0xffffffff);
945 }
946
947 /*
948  * A faster replacement for inet_ntoa().
949  */
950 char *
951 intoa(u_long addr)
952 {
953         char *cp;
954         u_int byte;
955         int n;
956         static char buf[sizeof(".xxx.xxx.xxx.xxx")];
957
958         cp = &buf[sizeof buf];
959         *--cp = '\0';
960
961         n = 4;
962         do {
963                 byte = addr & 0xff;
964                 *--cp = byte % 10 + '0';
965                 byte /= 10;
966                 if (byte > 0) {
967                         *--cp = byte % 10 + '0';
968                         byte /= 10;
969                         if (byte > 0)
970                                 *--cp = byte + '0';
971                 }
972                 *--cp = '.';
973                 addr >>= 8;
974         } while (--n > 0);
975
976         return cp + 1;
977 }
978
979 char *
980 eatoa(u_char *ea)
981 {
982         static char buf[sizeof("xx:xx:xx:xx:xx:xx")];
983
984         (void)sprintf(buf, "%x:%x:%x:%x:%x:%x",
985             ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
986         return (buf);
987 }
988
989 void
990 logmsg(int pri, const char *fmt, ...)
991 {
992         va_list v;
993         FILE *fp;
994         char *newfmt;
995
996         va_start(v, fmt);
997         if (dflag) {
998                 if (pri == LOG_ERR)
999                         fp = stderr;
1000                 else
1001                         fp = stdout;
1002                 if (expand_syslog_m(fmt, &newfmt) == -1) {
1003                         vfprintf(fp, fmt, v);
1004                 } else {
1005                         vfprintf(fp, newfmt, v);
1006                         free(newfmt);
1007                 }
1008                 fputs("\n", fp);
1009                 fflush(fp);
1010         } else {
1011                 vsyslog(pri, fmt, v);
1012         }
1013         va_end(v);
1014 }
1015
1016 int
1017 expand_syslog_m(const char *fmt, char **newfmt) {
1018         const char *str, *m;
1019         char *p, *np;
1020
1021         p = strdup("");
1022         str = fmt;
1023         while ((m = strstr(str, "%m")) != NULL) {
1024                 asprintf(&np, "%s%.*s%s", p, (int)(m - str),
1025                     str, strerror(errno));
1026                 free(p);
1027                 if (np == NULL) {
1028                         errno = ENOMEM;
1029                         return (-1);
1030                 }
1031                 p = np;
1032                 str = m + 2;
1033         }
1034         
1035         if (*str != '\0') {
1036                 asprintf(&np, "%s%s", p, str);
1037                 free(p);
1038                 if (np == NULL) {
1039                         errno = ENOMEM;
1040                         return (-1);
1041                 }
1042                 p = np;
1043         }
1044
1045         *newfmt = p;
1046         return (0);
1047 }