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