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