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