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