1 /* $OpenBSD: sys-bsd.c,v 1.15 2001/06/23 15:34:02 lebel Exp $ */ 2 3 /* 4 * sys-bsd.c - System-dependent procedures for setting up 5 * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.) 6 * 7 * Copyright (c) 1989 Carnegie Mellon University. 8 * Copyright (c) 1995 The Australian National University. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms are permitted 12 * provided that the above copyright notice and this paragraph are 13 * duplicated in all such forms and that any documentation, 14 * advertising materials, and other materials related to such 15 * distribution and use acknowledge that the software was developed 16 * by Carnegie Mellon University and The Australian National University. 17 * The names of the Universities may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 22 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 23 */ 24 25 #ifndef lint 26 #if 0 27 static char rcsid[] = "Id: sys-bsd.c,v 1.31 1998/04/02 12:04:19 paulus Exp $"; 28 #else 29 static char rcsid[] = "$OpenBSD: sys-bsd.c,v 1.15 2001/06/23 15:34:02 lebel Exp $"; 30 #endif 31 #endif 32 33 /* 34 * TODO: 35 */ 36 37 #include <stdio.h> 38 #include <syslog.h> 39 #include <string.h> 40 #include <stdlib.h> 41 #include <unistd.h> 42 #include <err.h> 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <termios.h> 46 #include <signal.h> 47 #include <util.h> 48 #include <sys/ioctl.h> 49 #include <sys/types.h> 50 #include <sys/socket.h> 51 #include <sys/time.h> 52 #include <sys/stat.h> 53 54 #ifdef PPP_FILTER 55 #include <net/bpf.h> 56 #endif 57 #include <net/if.h> 58 #include <net/ppp_defs.h> 59 #include <net/if_ppp.h> 60 #include <net/route.h> 61 #include <net/if_dl.h> 62 #include <netinet/in.h> 63 64 #if RTM_VERSION >= 3 65 #include <sys/param.h> 66 #if defined(NetBSD) && (NetBSD >= 199703) 67 #include <netinet/if_inarp.h> 68 #else /* NetBSD 1.2D or later */ 69 #if defined(__FreeBSD__) || defined(__OpenBSD__) 70 #include <netinet/if_ether.h> 71 #else 72 #include <net/if_ether.h> 73 #endif 74 #endif 75 #endif 76 77 #include "pppd.h" 78 #include "fsm.h" 79 #include "ipcp.h" 80 81 #ifdef IPX_CHANGE 82 #include <netipx/ipx.h> 83 #include <netipx/ipx_if.h> 84 #include "ipxcp.h" 85 #endif 86 87 #define ok_error(num) ((num)==EIO) 88 89 static int initdisc = -1; /* Initial TTY discipline for ppp_fd */ 90 static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */ 91 static int ppp_fd = -1; /* fd which is set to PPP discipline */ 92 static int rtm_seq; 93 94 static int restore_term; /* 1 => we've munged the terminal */ 95 static struct termios inittermios; /* Initial TTY termios */ 96 static struct winsize wsinfo; /* Initial window size info */ 97 98 static char *lock_file; /* name of lock file created */ 99 100 static int loop_slave = -1; 101 static int loop_master; 102 static char loop_name[20]; 103 104 static unsigned char inbuf[512]; /* buffer for chars read from loopback */ 105 106 static int sockfd; /* socket for doing interface ioctls */ 107 108 static int if_is_up; /* the interface is currently up */ 109 static u_int32_t ifaddrs[2]; /* local and remote addresses we set */ 110 static u_int32_t default_route_gateway; /* gateway addr for default route */ 111 static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */ 112 113 /* Prototypes for procedures local to this file. */ 114 static int dodefaultroute __P((u_int32_t, int)); 115 static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *)); 116 117 118 /* 119 * sys_init - System-dependent initialization. 120 */ 121 void 122 sys_init() 123 { 124 /* Get an internet socket for doing socket ioctl's on. */ 125 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 126 syslog(LOG_ERR, "Couldn't create IP socket: %m"); 127 die(1); 128 } 129 } 130 131 /* 132 * sys_cleanup - restore any system state we modified before exiting: 133 * mark the interface down, delete default route and/or proxy arp entry. 134 * This should call die() because it's called from die(). 135 */ 136 void 137 sys_cleanup() 138 { 139 struct ifreq ifr; 140 141 if (if_is_up) { 142 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 143 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0 144 && ((ifr.ifr_flags & IFF_UP) != 0)) { 145 ifr.ifr_flags &= ~IFF_UP; 146 ioctl(sockfd, SIOCSIFFLAGS, &ifr); 147 } 148 } 149 if (ifaddrs[0] != 0) 150 cifaddr(0, ifaddrs[0], ifaddrs[1]); 151 if (default_route_gateway) 152 cifdefaultroute(0, 0, default_route_gateway); 153 if (proxy_arp_addr) 154 cifproxyarp(0, proxy_arp_addr); 155 } 156 157 /* 158 * sys_close - Clean up in a child process before execing. 159 */ 160 void 161 sys_close() 162 { 163 close(sockfd); 164 if (loop_slave >= 0) { 165 close(loop_slave); 166 close(loop_master); 167 } 168 } 169 170 /* 171 * sys_check_options - check the options that the user specified 172 */ 173 void 174 sys_check_options() 175 { 176 } 177 178 /* 179 * ppp_available - check whether the system has any ppp interfaces 180 * (in fact we check whether we can do an ioctl on ppp0). 181 */ 182 int 183 ppp_available() 184 { 185 int s, ok; 186 struct ifreq ifr; 187 extern char *no_ppp_msg; 188 189 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 190 return 1; /* can't tell */ 191 192 strlcpy(ifr.ifr_name, "ppp0", sizeof(ifr.ifr_name)); 193 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; 194 close(s); 195 196 no_ppp_msg = "\ 197 This system lacks kernel support for PPP. To include PPP support\n\ 198 in the kernel, please add a line\n\ 199 \tpseudo-device ppp 1\n\ 200 to your kernel config file and build a new kernel.\n"; 201 return ok; 202 } 203 204 /* 205 * establish_ppp - Turn the serial port into a ppp interface. 206 */ 207 void 208 establish_ppp(fd) 209 int fd; 210 { 211 int pppdisc = PPPDISC; 212 int x; 213 214 if (demand) { 215 /* 216 * Demand mode - prime the old ppp device to relinquish the unit. 217 */ 218 if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) { 219 syslog(LOG_ERR, "ioctl(transfer ppp unit): %m"); 220 die(1); 221 } 222 } 223 224 /* 225 * Save the old line discipline of fd, and set it to PPP. 226 */ 227 if (ioctl(fd, TIOCGETD, &initdisc) < 0) { 228 syslog(LOG_ERR, "ioctl(TIOCGETD): %m"); 229 die(1); 230 } 231 if (ioctl(fd, TIOCSETD, &pppdisc) < 0) { 232 syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 233 die(1); 234 } 235 236 if (!demand) { 237 /* 238 * Find out which interface we were given. 239 */ 240 if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) { 241 syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); 242 die(1); 243 } 244 } else { 245 /* 246 * Check that we got the same unit again. 247 */ 248 if (ioctl(fd, PPPIOCGUNIT, &x) < 0) { 249 syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); 250 die(1); 251 } 252 if (x != ifunit) { 253 syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", 254 ifunit, x); 255 die(1); 256 } 257 x = TTYDISC; 258 ioctl(loop_slave, TIOCSETD, &x); 259 } 260 261 ppp_fd = fd; 262 263 /* 264 * Enable debug in the driver if requested. 265 */ 266 if (kdebugflag) { 267 if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 268 syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m"); 269 } else { 270 x |= (kdebugflag & 0xFF) * SC_DEBUG; 271 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 272 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m"); 273 } 274 } 275 276 /* 277 * Set device for non-blocking reads. 278 */ 279 if ((initfdflags = fcntl(fd, F_GETFL)) == -1 280 || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) { 281 syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m"); 282 } 283 } 284 285 /* 286 * restore_loop - reattach the ppp unit to the loopback. 287 */ 288 void 289 restore_loop() 290 { 291 int x; 292 293 /* 294 * Transfer the ppp interface back to the loopback. 295 */ 296 if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) { 297 syslog(LOG_ERR, "ioctl(transfer ppp unit): %m"); 298 die(1); 299 } 300 x = PPPDISC; 301 if (ioctl(loop_slave, TIOCSETD, &x) < 0) { 302 syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 303 die(1); 304 } 305 306 /* 307 * Check that we got the same unit again. 308 */ 309 if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) { 310 syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); 311 die(1); 312 } 313 if (x != ifunit) { 314 syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", 315 ifunit, x); 316 die(1); 317 } 318 ppp_fd = loop_slave; 319 } 320 321 #ifdef IPX_CHANGE 322 /* 323 * sipxfaddr - Config the interface IPX networknumber 324 */ 325 int 326 sipxfaddr(unit, network, node) 327 int unit; 328 u_int32_t network; 329 u_char * node; 330 { 331 int skfd; 332 int result = 1; 333 struct ifreq ifr; 334 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; 335 336 skfd = socket (AF_IPX, SOCK_DGRAM, 0); 337 if (skfd < 0) { 338 if (!ok_error (errno)) 339 syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno); 340 result = 0; 341 } else { 342 bzero (&ifr, sizeof(ifr)); 343 strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 344 345 sipx->sipx_len = sizeof(*sipx); 346 sipx->sipx_family = AF_IPX; 347 sipx->sipx_type = ETHERTYPE_II; 348 sipx->sipx_port = 0; 349 sipx->sipx_network = htonl (network); 350 memcpy (sipx->sipx_node, node, IPX_HOSTADDRLEN); 351 352 /* 353 * Set the IPX device 354 */ 355 if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) { 356 result = 0; 357 if (errno != EEXIST && !ok_error (errno)) { 358 syslog (LOG_DEBUG, 359 "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", 360 errno); 361 } else { 362 syslog (LOG_WARNING, 363 "ioctl(SIOCAIFADDR, CRTITF): Address already exists"); 364 } 365 } 366 close (skfd); 367 } 368 369 return result; 370 } 371 372 /* 373 * cipxfaddr - Clear the information for the IPX network. The IPX routes 374 * are removed and the device is no longer able to pass IPX 375 * frames. 376 */ 377 int 378 cipxfaddr(unit) 379 int unit; 380 { 381 int skfd; 382 int result = 1; 383 struct ifreq ifr; 384 struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; 385 386 skfd = socket (AF_IPX, SOCK_DGRAM, 0); 387 if (skfd < 0) { 388 if (! ok_error (errno)) 389 syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno); 390 result = 0; 391 } else { 392 bzero (&ifr, sizeof(ifr)); 393 strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 394 395 sipx->sipx_len = sizeof(*sipx); 396 sipx->sipx_family = AF_IPX; 397 sipx->sipx_type = ETHERTYPE_II; 398 399 /* 400 * Set the IPX device 401 */ 402 if (ioctl(skfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { 403 if (!ok_error (errno)) 404 syslog (LOG_INFO, 405 "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", 406 errno); 407 result = 0; 408 } 409 close (skfd); 410 } 411 412 return result; 413 } 414 #endif 415 416 /* 417 * disestablish_ppp - Restore the serial port to normal operation. 418 * This shouldn't call die() because it's called from die(). 419 */ 420 void 421 disestablish_ppp(fd) 422 int fd; 423 { 424 /* Reset non-blocking mode on fd. */ 425 if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0) 426 syslog(LOG_WARNING, "Couldn't restore device fd flags: %m"); 427 initfdflags = -1; 428 429 /* Restore old line discipline. */ 430 if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0) 431 syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 432 initdisc = -1; 433 434 if (fd == ppp_fd) 435 ppp_fd = -1; 436 } 437 438 /* 439 * Check whether the link seems not to be 8-bit clean. 440 */ 441 void 442 clean_check() 443 { 444 int x; 445 char *s; 446 447 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { 448 s = NULL; 449 switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { 450 case SC_RCV_B7_0: 451 s = "bit 7 set to 1"; 452 break; 453 case SC_RCV_B7_1: 454 s = "bit 7 set to 0"; 455 break; 456 case SC_RCV_EVNP: 457 s = "odd parity"; 458 break; 459 case SC_RCV_ODDP: 460 s = "even parity"; 461 break; 462 } 463 if (s != NULL) { 464 syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); 465 syslog(LOG_WARNING, "All received characters had %s", s); 466 } 467 } 468 } 469 470 /* 471 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, 472 * at the requested speed, etc. If `local' is true, set CLOCAL 473 * regardless of whether the modem option was specified. 474 * 475 * For *BSD, we assume that speed_t values numerically equal bits/second. 476 */ 477 void 478 set_up_tty(fd, local) 479 int fd, local; 480 { 481 struct termios tios; 482 483 if (tcgetattr(fd, &tios) < 0) { 484 syslog(LOG_ERR, "tcgetattr: %m"); 485 die(1); 486 } 487 488 if (!restore_term) { 489 inittermios = tios; 490 ioctl(fd, TIOCGWINSZ, &wsinfo); 491 } 492 493 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 494 if (crtscts > 0 && modem) 495 tios.c_cflag |= CRTSCTS; 496 else if (crtscts < 0) 497 tios.c_cflag &= ~CRTSCTS; 498 499 tios.c_cflag |= CS8 | CREAD | HUPCL; 500 if (local || !modem) 501 tios.c_cflag |= CLOCAL; 502 tios.c_iflag = IGNBRK | IGNPAR; 503 tios.c_oflag = 0; 504 tios.c_lflag = 0; 505 tios.c_cc[VMIN] = 1; 506 tios.c_cc[VTIME] = 0; 507 508 if (crtscts == -2) { 509 tios.c_iflag |= IXON | IXOFF; 510 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ 511 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ 512 } 513 514 if (inspeed) { 515 cfsetospeed(&tios, inspeed); 516 cfsetispeed(&tios, inspeed); 517 } else { 518 inspeed = cfgetospeed(&tios); 519 /* 520 * We can't proceed if the serial port speed is 0, 521 * since that implies that the serial port is disabled. 522 */ 523 if (inspeed == 0) { 524 syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate", 525 devnam); 526 die(1); 527 } 528 } 529 baud_rate = inspeed; 530 531 if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { 532 syslog(LOG_ERR, "tcsetattr: %m"); 533 die(1); 534 } 535 536 restore_term = 1; 537 } 538 539 /* 540 * restore_tty - restore the terminal to the saved settings. 541 */ 542 void 543 restore_tty(fd) 544 int fd; 545 { 546 if (restore_term) { 547 if (!default_device) { 548 /* 549 * Turn off echoing, because otherwise we can get into 550 * a loop with the tty and the modem echoing to each other. 551 * We presume we are the sole user of this tty device, so 552 * when we close it, it will revert to its defaults anyway. 553 */ 554 inittermios.c_lflag &= ~(ECHO | ECHONL); 555 } 556 if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) 557 if (errno != ENXIO) 558 syslog(LOG_WARNING, "tcsetattr: %m"); 559 ioctl(fd, TIOCSWINSZ, &wsinfo); 560 restore_term = 0; 561 } 562 } 563 564 /* 565 * setdtr - control the DTR line on the serial port. 566 * This is called from die(), so it shouldn't call die(). 567 */ 568 void 569 setdtr(fd, on) 570 int fd, on; 571 { 572 int modembits = TIOCM_DTR; 573 574 ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); 575 } 576 577 578 /* 579 * open_ppp_loopback - open the device we use for getting 580 * packets in demand mode, and connect it to a ppp interface. 581 * Here we use a pty. 582 */ 583 void 584 open_ppp_loopback() 585 { 586 int flags; 587 struct termios tios; 588 int pppdisc = PPPDISC; 589 590 if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) { 591 syslog(LOG_ERR, "No free pty for loopback"); 592 die(1); 593 } 594 SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name)); 595 596 if (tcgetattr(loop_slave, &tios) == 0) { 597 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); 598 tios.c_cflag |= CS8 | CREAD; 599 tios.c_iflag = IGNPAR; 600 tios.c_oflag = 0; 601 tios.c_lflag = 0; 602 if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0) 603 syslog(LOG_WARNING, "couldn't set attributes on loopback: %m"); 604 } 605 606 if ((flags = fcntl(loop_master, F_GETFL)) != -1) 607 if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1) 608 syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m"); 609 610 ppp_fd = loop_slave; 611 if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) { 612 syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 613 die(1); 614 } 615 616 /* 617 * Find out which interface we were given. 618 */ 619 if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) { 620 syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); 621 die(1); 622 } 623 624 /* 625 * Enable debug in the driver if requested. 626 */ 627 if (kdebugflag) { 628 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) { 629 syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m"); 630 } else { 631 flags |= (kdebugflag & 0xFF) * SC_DEBUG; 632 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0) 633 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m"); 634 } 635 } 636 637 } 638 639 640 /* 641 * output - Output PPP packet. 642 */ 643 void 644 output(unit, p, len) 645 int unit; 646 u_char *p; 647 int len; 648 { 649 if (debug) 650 log_packet(p, len, "sent ", LOG_DEBUG); 651 652 if (write(ttyfd, p, len) < 0) { 653 if (errno != EIO) 654 syslog(LOG_ERR, "write: %m"); 655 } 656 } 657 658 659 /* 660 * wait_input - wait until there is data available on ttyfd, 661 * for the length of time specified by *timo (indefinite 662 * if timo is NULL). 663 */ 664 void 665 wait_input(timo) 666 struct timeval *timo; 667 { 668 fd_set *fdsp = NULL; 669 int fdsn; 670 int n; 671 672 fdsn = howmany(ttyfd+1, NFDBITS) * sizeof(fd_mask); 673 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 674 err(1, "malloc"); 675 memset(fdsp, 0, fdsn); 676 FD_SET(ttyfd, fdsp); 677 678 n = select(ttyfd+1, fdsp, NULL, fdsp, timo); 679 if (n < 0 && errno != EINTR) { 680 syslog(LOG_ERR, "select: %m"); 681 free(fdsp); 682 die(1); 683 } 684 free(fdsp); 685 } 686 687 688 /* 689 * wait_loop_output - wait until there is data available on the 690 * loopback, for the length of time specified by *timo (indefinite 691 * if timo is NULL). 692 */ 693 void 694 wait_loop_output(timo) 695 struct timeval *timo; 696 { 697 fd_set *fdsp = NULL; 698 int fdsn; 699 int n; 700 701 fdsn = howmany(loop_master+1, NFDBITS) * sizeof(fd_mask); 702 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 703 err(1, "malloc"); 704 memset(fdsp, 0, fdsn); 705 FD_SET(loop_master, fdsp); 706 707 n = select(loop_master + 1, fdsp, NULL, fdsp, timo); 708 if (n < 0 && errno != EINTR) { 709 syslog(LOG_ERR, "select: %m"); 710 free(fdsp); 711 die(1); 712 } 713 free(fdsp); 714 } 715 716 717 /* 718 * wait_time - wait for a given length of time or until a 719 * signal is received. 720 */ 721 void 722 wait_time(timo) 723 struct timeval *timo; 724 { 725 int n; 726 727 n = select(0, NULL, NULL, NULL, timo); 728 if (n < 0 && errno != EINTR) { 729 syslog(LOG_ERR, "select: %m"); 730 die(1); 731 } 732 } 733 734 735 /* 736 * read_packet - get a PPP packet from the serial device. 737 */ 738 int 739 read_packet(buf) 740 u_char *buf; 741 { 742 int len; 743 744 if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) { 745 if (errno == EWOULDBLOCK || errno == EINTR) 746 return -1; 747 syslog(LOG_ERR, "read: %m"); 748 die(1); 749 } 750 return len; 751 } 752 753 754 /* 755 * get_loop_output - read characters from the loopback, form them 756 * into frames, and detect when we want to bring the real link up. 757 * Return value is 1 if we need to bring up the link, 0 otherwise. 758 */ 759 int 760 get_loop_output() 761 { 762 int rv = 0; 763 int n; 764 765 while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) { 766 if (loop_chars(inbuf, n)) 767 rv = 1; 768 } 769 770 if (n == 0) { 771 syslog(LOG_ERR, "eof on loopback"); 772 die(1); 773 } else if (errno != EWOULDBLOCK){ 774 syslog(LOG_ERR, "read from loopback: %m"); 775 die(1); 776 } 777 778 return rv; 779 } 780 781 782 /* 783 * ppp_send_config - configure the transmit characteristics of 784 * the ppp interface. 785 */ 786 void 787 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) 788 int unit, mtu; 789 u_int32_t asyncmap; 790 int pcomp, accomp; 791 { 792 u_int x; 793 struct ifreq ifr; 794 795 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 796 ifr.ifr_mtu = mtu; 797 if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) { 798 syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m"); 799 quit(); 800 } 801 802 if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { 803 syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m"); 804 quit(); 805 } 806 807 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 808 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); 809 quit(); 810 } 811 x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; 812 x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; 813 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { 814 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); 815 quit(); 816 } 817 } 818 819 820 /* 821 * ppp_set_xaccm - set the extended transmit ACCM for the interface. 822 */ 823 void 824 ppp_set_xaccm(unit, accm) 825 int unit; 826 ext_accm accm; 827 { 828 if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) 829 syslog(LOG_WARNING, "ioctl(set extended ACCM): %m"); 830 } 831 832 833 /* 834 * ppp_recv_config - configure the receive-side characteristics of 835 * the ppp interface. 836 */ 837 void 838 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) 839 int unit, mru; 840 u_int32_t asyncmap; 841 int pcomp, accomp; 842 { 843 int x; 844 845 if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { 846 syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m"); 847 quit(); 848 } 849 if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { 850 syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m"); 851 quit(); 852 } 853 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 854 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); 855 quit(); 856 } 857 x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; 858 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { 859 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); 860 quit(); 861 } 862 } 863 864 /* 865 * ccp_test - ask kernel whether a given compression method 866 * is acceptable for use. Returns 1 if the method and parameters 867 * are OK, 0 if the method is known but the parameters are not OK 868 * (e.g. code size should be reduced), or -1 if the method is unknown. 869 */ 870 int 871 ccp_test(unit, opt_ptr, opt_len, for_transmit) 872 int unit, opt_len, for_transmit; 873 u_char *opt_ptr; 874 { 875 struct ppp_option_data data; 876 877 data.ptr = opt_ptr; 878 data.length = opt_len; 879 data.transmit = for_transmit; 880 if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0) 881 return 1; 882 return (errno == ENOBUFS)? 0: -1; 883 } 884 885 /* 886 * ccp_flags_set - inform kernel about the current state of CCP. 887 */ 888 void 889 ccp_flags_set(unit, isopen, isup) 890 int unit, isopen, isup; 891 { 892 int x; 893 894 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 895 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); 896 return; 897 } 898 x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN; 899 x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP; 900 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) 901 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); 902 } 903 904 /* 905 * ccp_fatal_error - returns 1 if decompression was disabled as a 906 * result of an error detected after decompression of a packet, 907 * 0 otherwise. This is necessary because of patent nonsense. 908 */ 909 int 910 ccp_fatal_error(unit) 911 int unit; 912 { 913 int x; 914 915 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 916 syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m"); 917 return 0; 918 } 919 return x & SC_DC_FERROR; 920 } 921 922 /* 923 * get_idle_time - return how long the link has been idle. 924 */ 925 int 926 get_idle_time(u, ip) 927 int u; 928 struct ppp_idle *ip; 929 { 930 return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0; 931 } 932 933 934 #ifdef PPP_FILTER 935 /* 936 * set_filters - transfer the pass and active filters to the kernel. 937 */ 938 int 939 set_filters(pass, active) 940 struct bpf_program *pass, *active; 941 { 942 int ret = 1; 943 944 if (pass->bf_len > 0) { 945 if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) { 946 syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m"); 947 ret = 0; 948 } 949 } 950 if (active->bf_len > 0) { 951 if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) { 952 syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m"); 953 ret = 0; 954 } 955 } 956 return ret; 957 } 958 #endif 959 960 /* 961 * sifvjcomp - config tcp header compression 962 */ 963 int 964 sifvjcomp(u, vjcomp, cidcomp, maxcid) 965 int u, vjcomp, cidcomp, maxcid; 966 { 967 u_int x; 968 969 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { 970 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); 971 return 0; 972 } 973 x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP; 974 x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID; 975 if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { 976 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); 977 return 0; 978 } 979 if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { 980 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); 981 return 0; 982 } 983 return 1; 984 } 985 986 /* 987 * sifup - Config the interface up and enable IP packets to pass. 988 */ 989 int 990 sifup(u) 991 int u; 992 { 993 struct ifreq ifr; 994 995 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 996 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 997 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); 998 return 0; 999 } 1000 ifr.ifr_flags |= IFF_UP; 1001 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 1002 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); 1003 return 0; 1004 } 1005 if_is_up = 1; 1006 return 1; 1007 } 1008 1009 /* 1010 * sifnpmode - Set the mode for handling packets for a given NP. 1011 */ 1012 int 1013 sifnpmode(u, proto, mode) 1014 int u; 1015 int proto; 1016 enum NPmode mode; 1017 { 1018 struct npioctl npi; 1019 1020 npi.protocol = proto; 1021 npi.mode = mode; 1022 if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) { 1023 syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode); 1024 return 0; 1025 } 1026 return 1; 1027 } 1028 1029 /* 1030 * sifdown - Config the interface down and disable IP. 1031 */ 1032 int 1033 sifdown(u) 1034 int u; 1035 { 1036 struct ifreq ifr; 1037 int rv; 1038 struct npioctl npi; 1039 1040 rv = 1; 1041 npi.protocol = PPP_IP; 1042 npi.mode = NPMODE_ERROR; 1043 ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi); 1044 /* ignore errors, because ppp_fd might have been closed by now. */ 1045 1046 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1047 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { 1048 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); 1049 rv = 0; 1050 } else { 1051 ifr.ifr_flags &= ~IFF_UP; 1052 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { 1053 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); 1054 rv = 0; 1055 } else 1056 if_is_up = 0; 1057 } 1058 return rv; 1059 } 1060 1061 /* 1062 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, 1063 * if it exists. 1064 */ 1065 #define SET_SA_FAMILY(addr, family) \ 1066 BZERO((char *) &(addr), sizeof(addr)); \ 1067 addr.sa_family = (family); \ 1068 addr.sa_len = sizeof(addr); 1069 1070 /* 1071 * sifaddr - Config the interface IP addresses and netmask. 1072 */ 1073 int 1074 sifaddr(u, o, h, m) 1075 int u; 1076 u_int32_t o, h, m; 1077 { 1078 struct ifaliasreq ifra; 1079 struct ifreq ifr; 1080 1081 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); 1082 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); 1083 ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; 1084 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); 1085 ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; 1086 if (m != 0) { 1087 SET_SA_FAMILY(ifra.ifra_mask, AF_INET); 1088 ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; 1089 } else 1090 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); 1091 BZERO(&ifr, sizeof(ifr)); 1092 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1093 if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { 1094 if (errno != EADDRNOTAVAIL) 1095 syslog(LOG_WARNING, "Couldn't remove interface address: %m"); 1096 } 1097 if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { 1098 if (errno != EEXIST) { 1099 syslog(LOG_ERR, "Couldn't set interface address: %m"); 1100 return 0; 1101 } 1102 syslog(LOG_WARNING, 1103 "Couldn't set interface address: Address %s already exists", 1104 ip_ntoa(o)); 1105 } 1106 ifaddrs[0] = o; 1107 ifaddrs[1] = h; 1108 return 1; 1109 } 1110 1111 /* 1112 * cifaddr - Clear the interface IP addresses, and delete routes 1113 * through the interface if possible. 1114 */ 1115 int 1116 cifaddr(u, o, h) 1117 int u; 1118 u_int32_t o, h; 1119 { 1120 struct ifaliasreq ifra; 1121 1122 ifaddrs[0] = 0; 1123 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); 1124 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); 1125 ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; 1126 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); 1127 ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; 1128 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); 1129 if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) { 1130 if (errno != EADDRNOTAVAIL) 1131 syslog(LOG_WARNING, "Couldn't delete interface address: %m"); 1132 return 0; 1133 } 1134 return 1; 1135 } 1136 1137 /* 1138 * sifdefaultroute - assign a default route through the address given. 1139 */ 1140 int 1141 sifdefaultroute(u, l, g) 1142 int u; 1143 u_int32_t l, g; 1144 { 1145 return dodefaultroute(g, 's'); 1146 } 1147 1148 /* 1149 * cifdefaultroute - delete a default route through the address given. 1150 */ 1151 int 1152 cifdefaultroute(u, l, g) 1153 int u; 1154 u_int32_t l, g; 1155 { 1156 return dodefaultroute(g, 'c'); 1157 } 1158 1159 /* 1160 * dodefaultroute - talk to a routing socket to add/delete a default route. 1161 */ 1162 static int 1163 dodefaultroute(g, cmd) 1164 u_int32_t g; 1165 int cmd; 1166 { 1167 int routes; 1168 struct { 1169 struct rt_msghdr hdr; 1170 struct sockaddr_in dst; 1171 struct sockaddr_in gway; 1172 struct sockaddr_in mask; 1173 } rtmsg; 1174 1175 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 1176 syslog(LOG_ERR, "Couldn't %s default route: socket: %m", 1177 cmd=='s'? "add": "delete"); 1178 return 0; 1179 } 1180 1181 memset(&rtmsg, 0, sizeof(rtmsg)); 1182 rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE; 1183 rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY; 1184 rtmsg.hdr.rtm_version = RTM_VERSION; 1185 rtmsg.hdr.rtm_seq = ++rtm_seq; 1186 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 1187 rtmsg.dst.sin_len = sizeof(rtmsg.dst); 1188 rtmsg.dst.sin_family = AF_INET; 1189 rtmsg.gway.sin_len = sizeof(rtmsg.gway); 1190 rtmsg.gway.sin_family = AF_INET; 1191 rtmsg.gway.sin_addr.s_addr = g; 1192 rtmsg.mask.sin_len = sizeof(rtmsg.dst); 1193 rtmsg.mask.sin_family = AF_INET; 1194 1195 rtmsg.hdr.rtm_msglen = sizeof(rtmsg); 1196 if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) { 1197 syslog(LOG_ERR, "Couldn't %s default route: %m", 1198 cmd=='s'? "add": "delete"); 1199 close(routes); 1200 return 0; 1201 } 1202 1203 close(routes); 1204 default_route_gateway = (cmd == 's')? g: 0; 1205 return 1; 1206 } 1207 1208 #if RTM_VERSION >= 3 1209 1210 /* 1211 * sifproxyarp - Make a proxy ARP entry for the peer. 1212 */ 1213 static struct { 1214 struct rt_msghdr hdr; 1215 struct sockaddr_inarp dst; 1216 struct sockaddr_dl hwa; 1217 char extra[128]; 1218 } arpmsg; 1219 1220 static int arpmsg_valid; 1221 1222 int 1223 sifproxyarp(unit, hisaddr) 1224 int unit; 1225 u_int32_t hisaddr; 1226 { 1227 int routes; 1228 1229 /* 1230 * Get the hardware address of an interface on the same subnet 1231 * as our local address. 1232 */ 1233 memset(&arpmsg, 0, sizeof(arpmsg)); 1234 if (!get_ether_addr(hisaddr, &arpmsg.hwa)) { 1235 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); 1236 return 0; 1237 } 1238 1239 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 1240 syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m"); 1241 return 0; 1242 } 1243 1244 arpmsg.hdr.rtm_type = RTM_ADD; 1245 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; 1246 arpmsg.hdr.rtm_version = RTM_VERSION; 1247 arpmsg.hdr.rtm_seq = ++rtm_seq; 1248 arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 1249 arpmsg.hdr.rtm_inits = RTV_EXPIRE; 1250 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); 1251 arpmsg.dst.sin_family = AF_INET; 1252 arpmsg.dst.sin_addr.s_addr = hisaddr; 1253 arpmsg.dst.sin_other = SIN_PROXY; 1254 1255 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg 1256 + arpmsg.hwa.sdl_len; 1257 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 1258 syslog(LOG_ERR, "Couldn't add proxy arp entry: %m"); 1259 close(routes); 1260 return 0; 1261 } 1262 1263 close(routes); 1264 arpmsg_valid = 1; 1265 proxy_arp_addr = hisaddr; 1266 return 1; 1267 } 1268 1269 /* 1270 * cifproxyarp - Delete the proxy ARP entry for the peer. 1271 */ 1272 int 1273 cifproxyarp(unit, hisaddr) 1274 int unit; 1275 u_int32_t hisaddr; 1276 { 1277 int routes; 1278 1279 if (!arpmsg_valid) 1280 return 0; 1281 arpmsg_valid = 0; 1282 1283 arpmsg.hdr.rtm_type = RTM_DELETE; 1284 arpmsg.hdr.rtm_seq = ++rtm_seq; 1285 1286 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { 1287 syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m"); 1288 return 0; 1289 } 1290 1291 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { 1292 syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m"); 1293 close(routes); 1294 return 0; 1295 } 1296 1297 close(routes); 1298 proxy_arp_addr = 0; 1299 return 1; 1300 } 1301 1302 #else /* RTM_VERSION */ 1303 1304 /* 1305 * sifproxyarp - Make a proxy ARP entry for the peer. 1306 */ 1307 int 1308 sifproxyarp(unit, hisaddr) 1309 int unit; 1310 u_int32_t hisaddr; 1311 { 1312 struct arpreq arpreq; 1313 struct { 1314 struct sockaddr_dl sdl; 1315 char space[128]; 1316 } dls; 1317 1318 BZERO(&arpreq, sizeof(arpreq)); 1319 1320 /* 1321 * Get the hardware address of an interface on the same subnet 1322 * as our local address. 1323 */ 1324 if (!get_ether_addr(hisaddr, &dls.sdl)) { 1325 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); 1326 return 0; 1327 } 1328 1329 arpreq.arp_ha.sa_len = sizeof(struct sockaddr); 1330 arpreq.arp_ha.sa_family = AF_UNSPEC; 1331 BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen); 1332 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 1333 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 1334 arpreq.arp_flags = ATF_PERM | ATF_PUBL; 1335 if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) { 1336 syslog(LOG_ERR, "Couldn't add proxy arp entry: %m"); 1337 return 0; 1338 } 1339 1340 proxy_arp_addr = hisaddr; 1341 return 1; 1342 } 1343 1344 /* 1345 * cifproxyarp - Delete the proxy ARP entry for the peer. 1346 */ 1347 int 1348 cifproxyarp(unit, hisaddr) 1349 int unit; 1350 u_int32_t hisaddr; 1351 { 1352 struct arpreq arpreq; 1353 1354 BZERO(&arpreq, sizeof(arpreq)); 1355 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); 1356 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; 1357 if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) { 1358 syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m"); 1359 return 0; 1360 } 1361 proxy_arp_addr = 0; 1362 return 1; 1363 } 1364 #endif /* RTM_VERSION */ 1365 1366 1367 /* 1368 * get_ether_addr - get the hardware address of an interface on the 1369 * the same subnet as ipaddr. 1370 */ 1371 #define MAX_IFS 32 1372 1373 static int 1374 get_ether_addr(ipaddr, hwaddr) 1375 u_int32_t ipaddr; 1376 struct sockaddr_dl *hwaddr; 1377 { 1378 struct ifreq *ifr, *ifend, *ifp; 1379 u_int32_t ina, mask; 1380 struct sockaddr_dl *dla; 1381 struct ifreq ifreq; 1382 struct ifconf ifc; 1383 struct ifreq ifs[MAX_IFS]; 1384 1385 ifc.ifc_len = sizeof(ifs); 1386 ifc.ifc_req = ifs; 1387 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { 1388 syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m"); 1389 return 0; 1390 } 1391 1392 /* 1393 * Scan through looking for an interface with an Internet 1394 * address on the same subnet as `ipaddr'. 1395 */ 1396 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 1397 for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) 1398 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { 1399 if (ifr->ifr_addr.sa_family == AF_INET) { 1400 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 1401 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 1402 /* 1403 * Check that the interface is up, and not point-to-point 1404 * or loopback. 1405 */ 1406 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) 1407 continue; 1408 if ((ifreq.ifr_flags & 1409 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) 1410 != (IFF_UP|IFF_BROADCAST)) 1411 continue; 1412 /* 1413 * Get its netmask and check that it's on the right subnet. 1414 */ 1415 ifreq.ifr_addr = ifr->ifr_addr; 1416 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) 1417 continue; 1418 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; 1419 if ((ipaddr & mask) != (ina & mask)) 1420 continue; 1421 1422 break; 1423 } 1424 } 1425 1426 if (ifr >= ifend) 1427 return 0; 1428 syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name); 1429 1430 /* 1431 * Now scan through again looking for a link-level address 1432 * for this interface. 1433 */ 1434 ifp = ifr; 1435 for (ifr = ifc.ifc_req; ifr < ifend; ) { 1436 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 1437 && ifr->ifr_addr.sa_family == AF_LINK) { 1438 /* 1439 * Found the link-level address - copy it out 1440 */ 1441 dla = (struct sockaddr_dl *) &ifr->ifr_addr; 1442 BCOPY(dla, hwaddr, dla->sdl_len); 1443 return 1; 1444 } 1445 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); 1446 } 1447 1448 return 0; 1449 } 1450 1451 /* 1452 * Return user specified netmask, modified by any mask we might determine 1453 * for address `addr' (in network byte order). 1454 * Here we scan through the system's list of interfaces, looking for 1455 * any non-point-to-point interfaces which might appear to be on the same 1456 * network as `addr'. If we find any, we OR in their netmask to the 1457 * user-specified netmask. 1458 */ 1459 u_int32_t 1460 GetMask(addr) 1461 u_int32_t addr; 1462 { 1463 u_int32_t mask, nmask, ina; 1464 struct ifreq *ifr, *ifend, ifreq; 1465 struct ifconf ifc; 1466 struct ifreq ifs[MAX_IFS]; 1467 1468 addr = ntohl(addr); 1469 if (IN_CLASSA(addr)) /* determine network mask for address class */ 1470 nmask = IN_CLASSA_NET; 1471 else if (IN_CLASSB(addr)) 1472 nmask = IN_CLASSB_NET; 1473 else 1474 nmask = IN_CLASSC_NET; 1475 /* class D nets are disallowed by bad_ip_adrs */ 1476 mask = netmask | htonl(nmask); 1477 1478 /* 1479 * Scan through the system's network interfaces. 1480 */ 1481 ifc.ifc_len = sizeof(ifs); 1482 ifc.ifc_req = ifs; 1483 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { 1484 syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m"); 1485 return mask; 1486 } 1487 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 1488 for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) 1489 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { 1490 /* 1491 * Check the interface's internet address. 1492 */ 1493 if (ifr->ifr_addr.sa_family != AF_INET) 1494 continue; 1495 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 1496 if ((ntohl(ina) & nmask) != (addr & nmask)) 1497 continue; 1498 /* 1499 * Check that the interface is up, and not point-to-point or loopback. 1500 */ 1501 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 1502 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) 1503 continue; 1504 if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) 1505 != IFF_UP) 1506 continue; 1507 /* 1508 * Get its netmask and OR it into our mask. 1509 */ 1510 ifreq.ifr_addr = ifr->ifr_addr; 1511 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) 1512 continue; 1513 mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr; 1514 } 1515 1516 return mask; 1517 } 1518 1519 /* 1520 * Use the hostid as part of the random number seed. 1521 */ 1522 int 1523 get_host_seed() 1524 { 1525 return gethostid(); 1526 } 1527 1528 /* 1529 * lock - create a lock file for the named lock device 1530 */ 1531 #define LOCK_PREFIX "/var/spool/lock/LCK.." 1532 1533 int 1534 lock(dev) 1535 char *dev; 1536 { 1537 char hdb_lock_buffer[12]; 1538 int fd, pid, n; 1539 char *p; 1540 1541 if ((p = strrchr(dev, '/')) != NULL) 1542 dev = p + 1; 1543 lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1); 1544 if (lock_file == NULL) 1545 novm("lock file name"); 1546 strcat(strcpy(lock_file, LOCK_PREFIX), dev); 1547 1548 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 1549 if (errno == EEXIST 1550 && (fd = open(lock_file, O_RDONLY, 0)) >= 0) { 1551 /* Read the lock file to find out who has the device locked */ 1552 n = read(fd, hdb_lock_buffer, 11); 1553 if (n <= 0) { 1554 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file); 1555 close(fd); 1556 } else { 1557 hdb_lock_buffer[n] = 0; 1558 pid = atoi(hdb_lock_buffer); 1559 if (kill(pid, 0) == -1 && errno == ESRCH) { 1560 /* pid no longer exists - remove the lock file */ 1561 if (unlink(lock_file) == 0) { 1562 close(fd); 1563 syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)", 1564 dev, pid); 1565 continue; 1566 } else 1567 syslog(LOG_WARNING, "Couldn't remove stale lock on %s", 1568 dev); 1569 } else 1570 syslog(LOG_NOTICE, "Device %s is locked by pid %d", 1571 dev, pid); 1572 } 1573 close(fd); 1574 } else 1575 syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file); 1576 free(lock_file); 1577 lock_file = NULL; 1578 return -1; 1579 } 1580 1581 sprintf(hdb_lock_buffer, "%10d\n", getpid()); 1582 write(fd, hdb_lock_buffer, 11); 1583 1584 close(fd); 1585 return 0; 1586 } 1587 1588 /* 1589 * unlock - remove our lockfile 1590 */ 1591 void 1592 unlock() 1593 { 1594 if (lock_file) { 1595 unlink(lock_file); 1596 free(lock_file); 1597 lock_file = NULL; 1598 } 1599 } 1600