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