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