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