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