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