1 /* $OpenBSD: rarpd.c,v 1.52 2010/08/29 12:33:25 chl 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, bufsize, maxfd = 0; 388 fd_set *fdsp, *lfdsp; 389 u_char *buf, *bp, *ep; 390 struct if_info *ii; 391 392 if (iflist == 0) { 393 error(FATAL, "no interfaces"); 394 /* NOTREACHED */ 395 } 396 if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) { 397 error(FATAL, "BIOCGBLEN: %s", strerror(errno)); 398 /* NOTREACHED */ 399 } 400 buf = (u_char *) malloc((unsigned) bufsize); 401 if (buf == 0) { 402 error(FATAL, "malloc: %s", strerror(errno)); 403 /* NOTREACHED */ 404 } 405 /* 406 * Find the highest numbered file descriptor for select(). 407 * Initialize the set of descriptors to listen to. 408 */ 409 for (ii = iflist; ii; ii = ii->ii_next) 410 if (ii->ii_fd > maxfd) 411 maxfd = ii->ii_fd; 412 413 fdsn = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask); 414 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 415 error(FATAL, "malloc"); 416 if ((lfdsp = (fd_set *)malloc(fdsn)) == NULL) 417 error(FATAL, "malloc"); 418 419 memset(fdsp, 0, fdsn); 420 for (ii = iflist; ii; ii = ii->ii_next) 421 FD_SET(ii->ii_fd, fdsp); 422 423 while (1) { 424 memcpy(lfdsp, fdsp, fdsn); 425 if (select(maxfd + 1, lfdsp, (fd_set *) 0, 426 (fd_set *) 0, (struct timeval *) 0) < 0) { 427 error(FATAL, "select: %s", strerror(errno)); 428 /* NOTREACHED */ 429 } 430 for (ii = iflist; ii; ii = ii->ii_next) { 431 fd = ii->ii_fd; 432 if (!FD_ISSET(fd, lfdsp)) 433 continue; 434 again: 435 cc = read(fd, (char *) buf, bufsize); 436 /* Don't choke when we get ptraced */ 437 if (cc < 0 && errno == EINTR) 438 goto again; 439 /* Due to a SunOS bug, after 2^31 bytes, the file 440 * offset overflows and read fails with EINVAL. The 441 * lseek() to 0 will fix things. */ 442 if (cc < 0) { 443 if (errno == EINVAL && 444 (lseek(fd, (off_t)0, SEEK_CUR) + bufsize) < 0) { 445 (void) lseek(fd, (off_t)0, SEEK_SET); 446 goto again; 447 } 448 error(FATAL, "read: %s", strerror(errno)); 449 /* NOTREACHED */ 450 } 451 /* Loop through the packet(s) */ 452 #define bhp ((struct bpf_hdr *)bp) 453 bp = buf; 454 ep = bp + cc; 455 while (bp < ep) { 456 int caplen, hdrlen; 457 458 caplen = bhp->bh_caplen; 459 hdrlen = bhp->bh_hdrlen; 460 if (rarp_check(bp + hdrlen, caplen)) 461 rarp_process(ii, bp + hdrlen); 462 bp += BPF_WORDALIGN(hdrlen + caplen); 463 } 464 } 465 } 466 } 467 468 #ifndef TFTP_DIR 469 #define TFTP_DIR "/tftpboot" 470 #endif 471 472 /* 473 * True if this server can boot the host whose IP address is 'addr'. 474 * This check is made by looking in the tftp directory for the 475 * configuration file. 476 */ 477 int 478 rarp_bootable(u_int32_t addr) 479 { 480 struct dirent *dent; 481 char ipname[40]; 482 static DIR *dd = 0; 483 DIR *d; 484 485 (void) snprintf(ipname, sizeof ipname, "%08X", addr); 486 /* If directory is already open, rewind it. Otherwise, open it. */ 487 if ((d = dd)) 488 rewinddir(d); 489 else { 490 if (chdir(TFTP_DIR) == -1) { 491 error(FATAL, "chdir: %s", strerror(errno)); 492 /* NOTREACHED */ 493 } 494 d = opendir("."); 495 if (d == 0) { 496 error(FATAL, "opendir: %s", strerror(errno)); 497 /* NOTREACHED */ 498 } 499 dd = d; 500 } 501 while ((dent = readdir(d))) 502 if (strncmp(dent->d_name, ipname, 8) == 0) 503 return 1; 504 return 0; 505 } 506 507 508 /* 509 * Given a list of IP addresses, 'alist', return the first address that 510 * is on network 'net'; 'netmask' is a mask indicating the network portion 511 * of the address. 512 */ 513 static u_int32_t 514 choose_ipaddr(u_int32_t **alist, u_int32_t net, u_int32_t netmask) 515 { 516 for (; *alist; ++alist) { 517 if ((**alist & netmask) == net) 518 return **alist; 519 } 520 return 0; 521 } 522 /* 523 * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has 524 * already been checked for validity. The reply is overlaid on the request. 525 */ 526 void 527 rarp_process(struct if_info *ii, u_char *pkt) 528 { 529 char ename[MAXHOSTNAMELEN]; 530 u_int32_t target_ipaddr; 531 struct ether_header *ep; 532 struct ether_addr *ea; 533 struct hostent *hp; 534 struct in_addr in; 535 struct if_addr *ia; 536 537 ep = (struct ether_header *) pkt; 538 ea = (struct ether_addr *) &ep->ether_shost; 539 540 debug("%s", ether_ntoa(ea)); 541 if (ether_ntohost(ename, ea) != 0) { 542 debug("ether_ntohost failed"); 543 return; 544 } 545 if ((hp = gethostbyname(ename)) == 0) { 546 debug("gethostbyname (%s) failed", ename); 547 return; 548 } 549 550 /* Choose correct address from list. */ 551 if (hp->h_addrtype != AF_INET) { 552 error(FATAL, "cannot handle non IP addresses"); 553 /* NOTREACHED */ 554 } 555 for (target_ipaddr = 0, ia = ii->ii_addrs; ia; ia = ia->ia_next) { 556 target_ipaddr = choose_ipaddr((u_int32_t **) hp->h_addr_list, 557 ia->ia_ipaddr & ia->ia_netmask, ia->ia_netmask); 558 if (target_ipaddr) 559 break; 560 } 561 562 if (target_ipaddr == 0) { 563 for (ia = ii->ii_addrs; ia; ia = ia->ia_next) { 564 in.s_addr = ia->ia_ipaddr & ia->ia_netmask; 565 error(NONFATAL, "cannot find %s on net %s", 566 ename, inet_ntoa(in)); 567 } 568 return; 569 } 570 if (tflag == 0 || rarp_bootable(htonl(target_ipaddr))) 571 rarp_reply(ii, ia, ep, target_ipaddr, hp); 572 debug("reply sent"); 573 } 574 575 /* 576 * Lookup the ethernet address of the interface attached to the BPF 577 * file descriptor 'fd'; return it in 'eaddr'. 578 */ 579 void 580 lookup_addrs(char *ifname, struct if_info *p) 581 { 582 struct ifaddrs *ifap, *ifa; 583 struct sockaddr_dl *sdl; 584 u_char *eaddr = p->ii_eaddr; 585 struct if_addr *ia, **iap = &p->ii_addrs; 586 struct in_addr in; 587 int found = 0; 588 589 if (getifaddrs(&ifap) != 0) { 590 error(FATAL, "getifaddrs: %s", strerror(errno)); 591 /* NOTREACHED */ 592 } 593 594 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 595 if (strcmp(ifa->ifa_name, ifname)) 596 continue; 597 sdl = (struct sockaddr_dl *) ifa->ifa_addr; 598 if (sdl->sdl_family == AF_LINK && 599 sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6) { 600 memcpy((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6); 601 if (dflag) 602 fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n", 603 ifa->ifa_name, 604 eaddr[0], eaddr[1], eaddr[2], 605 eaddr[3], eaddr[4], eaddr[5]); 606 found = 1; 607 } else if (sdl->sdl_family == AF_INET) { 608 ia = malloc (sizeof (struct if_addr)); 609 if (ia == NULL) 610 error(FATAL, "lookup_addrs: malloc: %s", 611 strerror(errno)); 612 ia->ia_next = NULL; 613 ia->ia_ipaddr = 614 ((struct sockaddr_in *) ifa->ifa_addr)-> 615 sin_addr.s_addr; 616 ia->ia_netmask = 617 ((struct sockaddr_in *) ifa->ifa_netmask)-> 618 sin_addr.s_addr; 619 /* If SIOCGIFNETMASK didn't work, 620 figure out a mask from the IP 621 address class. */ 622 if (ia->ia_netmask == 0) 623 ia->ia_netmask = 624 ipaddrtonetmask(ia->ia_ipaddr); 625 if (dflag) { 626 in.s_addr = ia->ia_ipaddr; 627 fprintf(stderr, "\t%s\n", 628 inet_ntoa(in)); 629 } 630 *iap = ia; 631 iap = &ia->ia_next; 632 } 633 } 634 freeifaddrs(ifap); 635 if (!found) 636 error(FATAL, "lookup_addrs: Never saw interface `%s'!", ifname); 637 } 638 639 int arptab_set(u_char *eaddr, u_int32_t host); 640 641 /* 642 * Poke the kernel arp tables with the ethernet/ip address combinataion 643 * given. When processing a reply, we must do this so that the booting 644 * host (i.e. the guy running rarpd), won't try to ARP for the hardware 645 * address of the guy being booted (he cannot answer the ARP). 646 */ 647 void 648 update_arptab(u_char *ep, u_int32_t ipaddr) 649 { 650 #ifdef SIOCSARP 651 struct sockaddr_in *sin; 652 struct arpreq request; 653 u_int32_t host; 654 u_char *eaddr; 655 int s; 656 657 request.arp_flags = 0; 658 sin = (struct sockaddr_in *)&request.arp_pa; 659 sin->sin_family = AF_INET; 660 sin->sin_addr.s_addr = ipaddr; 661 request.arp_ha.sa_family = AF_UNSPEC; 662 /* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN, 663 because AF_UNSPEC is zero and the kernel assumes that a zero 664 sa_family means that the real sa_family value is in sa_len. */ 665 request.arp_ha.sa_len = 16; /* XXX */ 666 memcpy((char *) request.arp_ha.sa_data, (char *) ep, 6); 667 668 s = socket(AF_INET, SOCK_DGRAM, 0); 669 if (s < 0) { 670 error(NONFATAL, "socket: %s", strerror(errno)); 671 } else { 672 if (ioctl(s, SIOCSARP, (caddr_t)&request) < 0) 673 error(NONFATAL, "SIOCSARP: %s", strerror(errno)); 674 (void) close(s); 675 } 676 #else 677 if (arptab_set(ep, ipaddr) > 0) 678 syslog(LOG_ERR, "couldn't update arp table"); 679 #endif 680 } 681 /* 682 * Build a reverse ARP packet and sent it out on the interface. 683 * 'ep' points to a valid ARPOP_REVREQUEST. The ARPOP_REVREPLY is built 684 * on top of the request, then written to the network. 685 * 686 * RFC 903 defines the ether_arp fields as follows. The following comments 687 * are taken (more or less) straight from this document. 688 * 689 * ARPOP_REVREQUEST 690 * 691 * arp_sha is the hardware address of the sender of the packet. 692 * arp_spa is undefined. 693 * arp_tha is the 'target' hardware address. 694 * In the case where the sender wishes to determine his own 695 * protocol address, this, like arp_sha, will be the hardware 696 * address of the sender. 697 * arp_tpa is undefined. 698 * 699 * ARPOP_REVREPLY 700 * 701 * arp_sha is the hardware address of the responder (the sender of the 702 * reply packet). 703 * arp_spa is the protocol address of the responder (see the note below). 704 * arp_tha is the hardware address of the target, and should be the same as 705 * that which was given in the request. 706 * arp_tpa is the protocol address of the target, that is, the desired address. 707 * 708 * Note that the requirement that arp_spa be filled in with the responder's 709 * protocol is purely for convenience. For instance, if a system were to use 710 * both ARP and RARP, then the inclusion of the valid protocol-hardware 711 * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent 712 * ARP request. 713 */ 714 void 715 rarp_reply(struct if_info *ii, struct if_addr *ia, struct ether_header *ep, 716 u_int32_t ipaddr, struct hostent *hp) 717 { 718 struct ether_arp *ap = (struct ether_arp *) (ep + 1); 719 int len, n; 720 721 update_arptab((u_char *)&ap->arp_sha, ipaddr); 722 723 /* Build the rarp reply by modifying the rarp request in place. */ 724 ep->ether_type = htons(ETHERTYPE_REVARP); 725 ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER); 726 ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP); 727 ap->arp_op = htons(ARPOP_REVREPLY); 728 729 memcpy((char *) &ep->ether_dhost, (char *) &ap->arp_sha, 6); 730 memcpy((char *) &ep->ether_shost, (char *) ii->ii_eaddr, 6); 731 memcpy((char *) &ap->arp_sha, (char *) ii->ii_eaddr, 6); 732 733 memcpy((char *) ap->arp_tpa, (char *) &ipaddr, 4); 734 /* Target hardware is unchanged. */ 735 memcpy((char *) ap->arp_spa, (char *) &ia->ia_ipaddr, 4); 736 737 if (lflag) { 738 struct ether_addr ea; 739 740 memcpy(&ea.ether_addr_octet, &ap->arp_sha, 6); 741 syslog(LOG_INFO, "%s asked; %s replied", hp->h_name, 742 ether_ntoa(&ea)); 743 } 744 745 len = sizeof(*ep) + sizeof(*ap); 746 n = write(ii->ii_fd, (char *) ep, len); 747 if (n != len) 748 error(NONFATAL, "write: only %d of %d bytes written", n, len); 749 } 750 /* 751 * Get the netmask of an IP address. This routine is used if 752 * SIOCGIFNETMASK doesn't work. 753 */ 754 u_int32_t 755 ipaddrtonetmask(u_int32_t addr) 756 { 757 if (IN_CLASSA(addr)) 758 return IN_CLASSA_NET; 759 if (IN_CLASSB(addr)) 760 return IN_CLASSB_NET; 761 if (IN_CLASSC(addr)) 762 return IN_CLASSC_NET; 763 error(FATAL, "unknown IP address class: %08X", addr); 764 /* NOTREACHED */ 765 } 766 767 void 768 error(int fatal, const char *fmt,...) 769 { 770 va_list ap; 771 772 if (dflag) { 773 if (fatal) 774 (void) fprintf(stderr, "rarpd: error: "); 775 else 776 (void) fprintf(stderr, "rarpd: warning: "); 777 va_start(ap, fmt); 778 (void) vfprintf(stderr, fmt, ap); 779 va_end(ap); 780 (void) fprintf(stderr, "\n"); 781 } 782 va_start(ap, fmt); 783 vsyslog(LOG_ERR, fmt, ap); 784 va_end(ap); 785 if (fatal) 786 exit(1); 787 /* NOTREACHED */ 788 } 789 790 void 791 debug(const char *fmt,...) 792 { 793 va_list ap; 794 795 if (dflag) { 796 va_start(ap, fmt); 797 (void) fprintf(stderr, "rarpd: "); 798 (void) vfprintf(stderr, fmt, ap); 799 va_end(ap); 800 (void) fprintf(stderr, "\n"); 801 } 802 } 803