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