1/* 2 * System-dependent procedures for pppd under SunOS 4. 3 * 4 * Copyright (c) 1994 The Australian National University. 5 * All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software and its 8 * documentation is hereby granted, provided that the above copyright 9 * notice appears in all copies. This software is provided without any 10 * warranty, express or implied. The Australian National University 11 * makes no representations about the suitability of this software for 12 * any purpose. 13 * 14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 18 * OF SUCH DAMAGE. 19 * 20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 25 * OR MODIFICATIONS. 26 */ 27 28#define RCSID "$Id: sys-sunos4.c,v 1.1.1.1 2008/10/15 03:30:13 james26_jang Exp $" 29 30#include <stdio.h> 31#include <stddef.h> 32#include <stdlib.h> 33#include <string.h> 34#include <ctype.h> 35#include <errno.h> 36#include <fcntl.h> 37#include <unistd.h> 38#include <termios.h> 39#include <signal.h> 40#include <malloc.h> 41#include <utmp.h> 42#include <sys/types.h> 43#include <sys/param.h> 44#include <sys/socket.h> 45#include <sys/sockio.h> 46#include <sys/stream.h> 47#include <sys/stropts.h> 48#include <sys/stat.h> 49#include <sys/time.h> 50#include <sys/poll.h> 51#include <net/if.h> 52#include <net/if_arp.h> 53#include <net/nit_if.h> 54#include <net/route.h> 55#include <net/ppp_defs.h> 56#include <net/pppio.h> 57#include <netinet/in.h> 58 59#include "pppd.h" 60 61#if defined(sun) && defined(sparc) 62#include <alloca.h> 63#ifndef __GNUC__ 64extern void *alloca(); 65#endif 66#endif /*sparc*/ 67 68static const char rcsid[] = RCSID; 69 70static int pppfd; 71static int fdmuxid = -1; 72static int iffd; 73static int sockfd; 74 75static int restore_term; 76static struct termios inittermios; 77static struct winsize wsinfo; /* Initial window size info */ 78static pid_t parent_pid; /* PID of our parent */ 79 80extern u_char inpacket_buf[]; /* borrowed from main.c */ 81 82#define MAX_POLLFDS 32 83static struct pollfd pollfds[MAX_POLLFDS]; 84static int n_pollfds; 85 86static int link_mtu, link_mru; 87 88#define NMODULES 32 89static int tty_nmodules; 90static char tty_modules[NMODULES][FMNAMESZ+1]; 91 92static int if_is_up; /* Interface has been marked up */ 93static u_int32_t ifaddrs[2]; /* local and remote addresses */ 94static u_int32_t default_route_gateway; /* Gateway for default route added */ 95static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ 96 97/* Prototypes for procedures local to this file. */ 98static int translate_speed __P((int)); 99static int baud_rate_of __P((int)); 100static int get_ether_addr __P((u_int32_t, struct sockaddr *)); 101static int strioctl __P((int, int, void *, int, int)); 102 103 104/* 105 * sys_init - System-dependent initialization. 106 */ 107void 108sys_init() 109{ 110 int x; 111 112 /* Get an internet socket for doing socket ioctl's on. */ 113 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 114 fatal("Couldn't create IP socket: %m"); 115 116 /* 117 * We may want to send a SIGHUP to the session leader associated 118 * with our controlling terminal later. Because SunOS doesn't 119 * have getsid(), we make do with sending the signal to our 120 * parent process. 121 */ 122 parent_pid = getppid(); 123 124 /* 125 * Open the ppp device. 126 */ 127 pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0); 128 if (pppfd < 0) 129 fatal("Can't open /dev/ppp: %m"); 130 if (kdebugflag) { 131 x = PPPDBG_LOG + PPPDBG_DRIVER; 132 strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0); 133 } 134 135 /* Assign a new PPA and get its unit number. */ 136 if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) 137 fatal("Can't create new PPP interface: %m"); 138 139 /* 140 * Open the ppp device again and push the if_ppp module on it. 141 */ 142 iffd = open("/dev/ppp", O_RDWR, 0); 143 if (iffd < 0) 144 fatal("Can't open /dev/ppp (2): %m"); 145 if (kdebugflag) { 146 x = PPPDBG_LOG + PPPDBG_DRIVER; 147 strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0); 148 } 149 if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) 150 fatal("Couldn't attach ppp interface to device: %m"); 151 if (ioctl(iffd, I_PUSH, "if_ppp") < 0) 152 fatal("Can't push ppp interface module: %m"); 153 if (kdebugflag) { 154 x = PPPDBG_LOG + PPPDBG_IF; 155 strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0); 156 } 157 if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) 158 fatal("Couldn't create ppp interface unit: %m"); 159 x = PPP_IP; 160 if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) 161 fatal("Couldn't bind ppp interface to IP SAP: %m"); 162 163 n_pollfds = 0; 164} 165 166/* 167 * sys_cleanup - restore any system state we modified before exiting: 168 * mark the interface down, delete default route and/or proxy arp entry. 169 * This shouldn't call die() because it's called from die(). 170 */ 171void 172sys_cleanup() 173{ 174 if (if_is_up) 175 sifdown(0); 176 if (ifaddrs[0]) 177 cifaddr(0, ifaddrs[0], ifaddrs[1]); 178 if (default_route_gateway) 179 cifdefaultroute(0, 0, default_route_gateway); 180 if (proxy_arp_addr) 181 cifproxyarp(0, proxy_arp_addr); 182} 183 184/* 185 * sys_close - Clean up in a child process before execing. 186 */ 187void 188sys_close() 189{ 190 close(iffd); 191 close(pppfd); 192 close(sockfd); 193} 194 195/* 196 * sys_check_options - check the options that the user specified 197 */ 198int 199sys_check_options() 200{ 201 return 1; 202} 203 204 205/* 206 * ppp_available - check whether the system has any ppp interfaces 207 */ 208int 209ppp_available() 210{ 211 struct stat buf; 212 213 return stat("/dev/ppp", &buf) >= 0; 214} 215 216/* 217 * tty_establish_ppp - Turn the serial port into a ppp interface. 218 */ 219int 220tty_establish_ppp(fd) 221 int fd; 222{ 223 int i; 224 225 /* Pop any existing modules off the tty stream. */ 226 for (i = 0;; ++i) 227 if (ioctl(fd, I_LOOK, tty_modules[i]) < 0 228 || ioctl(fd, I_POP, 0) < 0) 229 break; 230 tty_nmodules = i; 231 232 /* Push the async hdlc module and the compressor module. */ 233 if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) 234 fatal("Couldn't push PPP Async HDLC module: %m"); 235 if (ioctl(fd, I_PUSH, "ppp_comp") < 0) 236 error("Couldn't push PPP compression module: %m"); 237 238 /* Link the serial port under the PPP multiplexor. */ 239 if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) 240 fatal("Can't link tty to PPP mux: %m"); 241 242 return pppfd; 243} 244 245/* 246 * disestablish_ppp - Restore the serial port to normal operation. 247 * It attempts to reconstruct the stream with the previously popped 248 * modules. This shouldn't call die() because it's called from die(). 249 */ 250void 251tty_disestablish_ppp(fd) 252 int fd; 253{ 254 int i; 255 256 if (fdmuxid >= 0) { 257 if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) { 258 if (!hungup) 259 error("Can't unlink tty from PPP mux: %m"); 260 } 261 fdmuxid = -1; 262 263 if (!hungup) { 264 while (ioctl(fd, I_POP, 0) >= 0) 265 ; 266 for (i = tty_nmodules - 1; i >= 0; --i) 267 if (ioctl(fd, I_PUSH, tty_modules[i]) < 0) 268 error("Couldn't restore tty module %s: %m", 269 tty_modules[i]); 270 } 271 if (hungup && default_device && parent_pid > 0) { 272 /* 273 * If we have received a hangup, we need to send a SIGHUP 274 * to the terminal's controlling process. The reason is 275 * that the original stream head for the terminal hasn't 276 * seen the M_HANGUP message (it went up through the ppp 277 * driver to the stream head for our fd to /dev/ppp). 278 * Actually we send the signal to the process that invoked 279 * pppd, since SunOS doesn't have getsid(). 280 */ 281 kill(parent_pid, SIGHUP); 282 } 283 } 284} 285 286/* 287 * Check whether the link seems not to be 8-bit clean. 288 */ 289void 290clean_check() 291{ 292 int x; 293 char *s; 294 295 if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0) 296 return; 297 s = NULL; 298 switch (~x) { 299 case RCV_B7_0: 300 s = "bit 7 set to 1"; 301 break; 302 case RCV_B7_1: 303 s = "bit 7 set to 0"; 304 break; 305 case RCV_EVNP: 306 s = "odd parity"; 307 break; 308 case RCV_ODDP: 309 s = "even parity"; 310 break; 311 } 312 if (s != NULL) { 313 warn("Serial link is not 8-bit clean:"); 314 warn("All received characters had %s", s); 315 } 316} 317 318/* 319 * List of valid speeds. 320 */ 321struct speed { 322 int speed_int, speed_val; 323} speeds[] = { 324#ifdef B50 325 { 50, B50 }, 326#endif 327#ifdef B75 328 { 75, B75 }, 329#endif 330#ifdef B110 331 { 110, B110 }, 332#endif 333#ifdef B134 334 { 134, B134 }, 335#endif 336#ifdef B150 337 { 150, B150 }, 338#endif 339#ifdef B200 340 { 200, B200 }, 341#endif 342#ifdef B300 343 { 300, B300 }, 344#endif 345#ifdef B600 346 { 600, B600 }, 347#endif 348#ifdef B1200 349 { 1200, B1200 }, 350#endif 351#ifdef B1800 352 { 1800, B1800 }, 353#endif 354#ifdef B2000 355 { 2000, B2000 }, 356#endif 357#ifdef B2400 358 { 2400, B2400 }, 359#endif 360#ifdef B3600 361 { 3600, B3600 }, 362#endif 363#ifdef B4800 364 { 4800, B4800 }, 365#endif 366#ifdef B7200 367 { 7200, B7200 }, 368#endif 369#ifdef B9600 370 { 9600, B9600 }, 371#endif 372#ifdef B19200 373 { 19200, B19200 }, 374#endif 375#ifdef B38400 376 { 38400, B38400 }, 377#endif 378#ifdef EXTA 379 { 19200, EXTA }, 380#endif 381#ifdef EXTB 382 { 38400, EXTB }, 383#endif 384#ifdef B57600 385 { 57600, B57600 }, 386#endif 387#ifdef B115200 388 { 115200, B115200 }, 389#endif 390 { 0, 0 } 391}; 392 393/* 394 * Translate from bits/second to a speed_t. 395 */ 396static int 397translate_speed(bps) 398 int bps; 399{ 400 struct speed *speedp; 401 402 if (bps == 0) 403 return 0; 404 for (speedp = speeds; speedp->speed_int; speedp++) 405 if (bps == speedp->speed_int) 406 return speedp->speed_val; 407 warn("speed %d not supported", bps); 408 return 0; 409} 410 411/* 412 * Translate from a speed_t to bits/second. 413 */ 414static int 415baud_rate_of(speed) 416 int speed; 417{ 418 struct speed *speedp; 419 420 if (speed == 0) 421 return 0; 422 for (speedp = speeds; speedp->speed_int; speedp++) 423 if (speed == speedp->speed_val) 424 return speedp->speed_int; 425 return 0; 426} 427 428/* 429 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, 430 * at the requested speed, etc. If `local' is true, set CLOCAL 431 * regardless of whether the modem option was specified. 432 */ 433void 434set_up_tty(fd, local) 435 int fd, local; 436{ 437 int speed; 438 struct termios tios; 439 440 if (tcgetattr(fd, &tios) < 0) 441 fatal("tcgetattr: %m"); 442 443 if (!restore_term) { 444 inittermios = tios; 445 ioctl(fd, TIOCGWINSZ, &wsinfo); 446 } 447 448 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 449 if (crtscts > 0) 450 tios.c_cflag |= CRTSCTS; 451 else if (crtscts < 0) 452 tios.c_cflag &= ~CRTSCTS; 453 454 tios.c_cflag |= CS8 | CREAD | HUPCL; 455 if (local || !modem) 456 tios.c_cflag |= CLOCAL; 457 tios.c_iflag = IGNBRK | IGNPAR; 458 tios.c_oflag = 0; 459 tios.c_lflag = 0; 460 tios.c_cc[VMIN] = 1; 461 tios.c_cc[VTIME] = 0; 462 463 if (crtscts == -2) { 464 tios.c_iflag |= IXON | IXOFF; 465 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ 466 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ 467 } 468 469 speed = translate_speed(inspeed); 470 if (speed) { 471 cfsetospeed(&tios, speed); 472 cfsetispeed(&tios, speed); 473 } else { 474 speed = cfgetospeed(&tios); 475 /* 476 * We can't proceed if the serial port speed is 0, 477 * since that implies that the serial port is disabled. 478 */ 479 if (speed == B0) 480 fatal("Baud rate for %s is 0; need explicit baud rate", devnam); 481 } 482 483 if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) 484 fatal("tcsetattr: %m"); 485 486 baud_rate = inspeed = baud_rate_of(speed); 487 restore_term = 1; 488} 489 490/* 491 * restore_tty - restore the terminal to the saved settings. 492 */ 493void 494restore_tty(fd) 495 int fd; 496{ 497 if (restore_term) { 498 if (!default_device) { 499 /* 500 * Turn off echoing, because otherwise we can get into 501 * a loop with the tty and the modem echoing to each other. 502 * We presume we are the sole user of this tty device, so 503 * when we close it, it will revert to its defaults anyway. 504 */ 505 inittermios.c_lflag &= ~(ECHO | ECHONL); 506 } 507 if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) 508 if (!hungup && errno != ENXIO) 509 warn("tcsetattr: %m"); 510 ioctl(fd, TIOCSWINSZ, &wsinfo); 511 restore_term = 0; 512 } 513} 514 515/* 516 * setdtr - control the DTR line on the serial port. 517 * This is called from die(), so it shouldn't call die(). 518 */ 519void 520setdtr(fd, on) 521int fd, on; 522{ 523 int modembits = TIOCM_DTR; 524 525 ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); 526} 527 528/* 529 * open_loopback - open the device we use for getting packets 530 * in demand mode. Under SunOS, we use our existing fd 531 * to the ppp driver. 532 */ 533int 534open_ppp_loopback() 535{ 536 return pppfd; 537} 538 539/* 540 * output - Output PPP packet. 541 */ 542void 543output(unit, p, len) 544 int unit; 545 u_char *p; 546 int len; 547{ 548 struct strbuf data; 549 int retries; 550 struct pollfd pfd; 551 552 if (debug) 553 dbglog("sent %P", p, len); 554 555 data.len = len; 556 data.buf = (caddr_t) p; 557 retries = 4; 558 while (putmsg(pppfd, NULL, &data, 0) < 0) { 559 if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) { 560 if (errno != ENXIO) 561 error("Couldn't send packet: %m"); 562 break; 563 } 564 pfd.fd = pppfd; 565 pfd.events = POLLOUT; 566 poll(&pfd, 1, 250); /* wait for up to 0.25 seconds */ 567 } 568} 569 570 571/* 572 * wait_input - wait until there is data available, 573 * for the length of time specified by *timo (indefinite 574 * if timo is NULL). 575 */ 576void 577wait_input(timo) 578 struct timeval *timo; 579{ 580 int t; 581 582 t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000; 583 if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR) { 584 if (errno != EAGAIN) 585 fatal("poll: %m"); 586 /* we can get EAGAIN on a heavily loaded system, 587 * just wait a short time and try again. */ 588 usleep(50000); 589 } 590} 591 592/* 593 * add_fd - add an fd to the set that wait_input waits for. 594 */ 595void add_fd(fd) 596 int fd; 597{ 598 int n; 599 600 for (n = 0; n < n_pollfds; ++n) 601 if (pollfds[n].fd == fd) 602 return; 603 if (n_pollfds < MAX_POLLFDS) { 604 pollfds[n_pollfds].fd = fd; 605 pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP; 606 ++n_pollfds; 607 } else 608 error("Too many inputs!"); 609} 610 611/* 612 * remove_fd - remove an fd from the set that wait_input waits for. 613 */ 614void remove_fd(fd) 615 int fd; 616{ 617 int n; 618 619 for (n = 0; n < n_pollfds; ++n) { 620 if (pollfds[n].fd == fd) { 621 while (++n < n_pollfds) 622 pollfds[n-1] = pollfds[n]; 623 --n_pollfds; 624 break; 625 } 626 } 627} 628 629 630/* 631 * read_packet - get a PPP packet from the serial device. 632 */ 633int 634read_packet(buf) 635 u_char *buf; 636{ 637 struct strbuf ctrl, data; 638 int flags, len; 639 unsigned char ctrlbuf[64]; 640 641 for (;;) { 642 data.maxlen = PPP_MRU + PPP_HDRLEN; 643 data.buf = (caddr_t) buf; 644 ctrl.maxlen = sizeof(ctrlbuf); 645 ctrl.buf = (caddr_t) ctrlbuf; 646 flags = 0; 647 len = getmsg(pppfd, &ctrl, &data, &flags); 648 if (len < 0) { 649 if (errno == EAGAIN || errno == EINTR) 650 return -1; 651 fatal("Error reading packet: %m"); 652 } 653 654 if (ctrl.len <= 0) 655 return data.len; 656 657 /* 658 * Got a M_PROTO or M_PCPROTO message. Huh? 659 */ 660 if (debug) 661 dbglog("got ctrl msg len=%d", ctrl.len); 662 663 } 664} 665 666/* 667 * get_loop_output - get outgoing packets from the ppp device, 668 * and detect when we want to bring the real link up. 669 * Return value is 1 if we need to bring up the link, 0 otherwise. 670 */ 671int 672get_loop_output() 673{ 674 int len; 675 int rv = 0; 676 677 while ((len = read_packet(inpacket_buf)) > 0) { 678 if (loop_frame(inpacket_buf, len)) 679 rv = 1; 680 } 681 return rv; 682} 683 684/* 685 * ppp_send_config - configure the transmit characteristics of 686 * the ppp interface. 687 */ 688void 689ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) 690 int unit, mtu; 691 u_int32_t asyncmap; 692 int pcomp, accomp; 693{ 694 int cf[2]; 695 struct ifreq ifr; 696 697 link_mtu = mtu; 698 if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) { 699 if (hungup && errno == ENXIO) 700 return; 701 error("Couldn't set MTU: %m"); 702 } 703 if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) { 704 error("Couldn't set transmit ACCM: %m"); 705 } 706 cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0); 707 cf[1] = COMP_PROT | COMP_AC; 708 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) { 709 error("Couldn't set prot/AC compression: %m"); 710 } 711 712 /* set mtu for ip as well */ 713 memset(&ifr, 0, sizeof(ifr)); 714 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 715 ifr.ifr_metric = link_mtu; 716 if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) { 717 error("Couldn't set IP MTU: %m"); 718 } 719} 720 721/* 722 * ppp_set_xaccm - set the extended transmit ACCM for the interface. 723 */ 724void 725ppp_set_xaccm(unit, accm) 726 int unit; 727 ext_accm accm; 728{ 729 if (strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) { 730 if (!hungup || errno != ENXIO) 731 warn("Couldn't set extended ACCM: %m"); 732 } 733} 734 735/* 736 * ppp_recv_config - configure the receive-side characteristics of 737 * the ppp interface. 738 */ 739void 740ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) 741 int unit, mru; 742 u_int32_t asyncmap; 743 int pcomp, accomp; 744{ 745 int cf[2]; 746 747 link_mru = mru; 748 if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) { 749 if (hungup && errno == ENXIO) 750 return; 751 error("Couldn't set MRU: %m"); 752 } 753 if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) { 754 error("Couldn't set receive ACCM: %m"); 755 } 756 cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0); 757 cf[1] = DECOMP_PROT | DECOMP_AC; 758 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) { 759 error("Couldn't set prot/AC decompression: %m"); 760 } 761} 762 763/* 764 * ccp_test - ask kernel whether a given compression method 765 * is acceptable for use. 766 */ 767int 768ccp_test(unit, opt_ptr, opt_len, for_transmit) 769 int unit, opt_len, for_transmit; 770 u_char *opt_ptr; 771{ 772 if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP), 773 opt_ptr, opt_len, 0) >= 0) 774 return 1; 775 return (errno == ENOSR)? 0: -1; 776} 777 778/* 779 * ccp_flags_set - inform kernel about the current state of CCP. 780 */ 781void 782ccp_flags_set(unit, isopen, isup) 783 int unit, isopen, isup; 784{ 785 int cf[2]; 786 787 cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0); 788 cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR; 789 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) { 790 if (!hungup || errno != ENXIO) 791 error("Couldn't set kernel CCP state: %m"); 792 } 793} 794 795/* 796 * get_idle_time - return how long the link has been idle. 797 */ 798int 799get_idle_time(u, ip) 800 int u; 801 struct ppp_idle *ip; 802{ 803 return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0; 804} 805 806/* 807 * get_ppp_stats - return statistics for the link. 808 */ 809int 810get_ppp_stats(u, stats) 811 int u; 812 struct pppd_stats *stats; 813{ 814 struct ppp_stats s; 815 816 if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) { 817 error("Couldn't get link statistics: %m"); 818 return 0; 819 } 820 stats->bytes_in = s.p.ppp_ibytes; 821 stats->bytes_out = s.p.ppp_obytes; 822 return 1; 823} 824 825 826/* 827 * ccp_fatal_error - returns 1 if decompression was disabled as a 828 * result of an error detected after decompression of a packet, 829 * 0 otherwise. This is necessary because of patent nonsense. 830 */ 831int 832ccp_fatal_error(unit) 833 int unit; 834{ 835 int cf[2]; 836 837 cf[0] = cf[1] = 0; 838 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) { 839 if (errno != ENXIO && errno != EINVAL) 840 error("Couldn't get compression flags: %m"); 841 return 0; 842 } 843 return cf[0] & CCP_FATALERROR; 844} 845 846/* 847 * sifvjcomp - config tcp header compression 848 */ 849int 850sifvjcomp(u, vjcomp, xcidcomp, xmaxcid) 851 int u, vjcomp, xcidcomp, xmaxcid; 852{ 853 int cf[2]; 854 char maxcid[2]; 855 856 if (vjcomp) { 857 maxcid[0] = xcidcomp; 858 maxcid[1] = 15; 859 if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) { 860 error("Couldn't initialize VJ compression: %m"); 861 } 862 } 863 864 cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0) 865 + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0); 866 cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID; 867 if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) { 868 if (vjcomp) 869 error("Couldn't enable VJ compression: %m"); 870 } 871 872 return 1; 873} 874 875/* 876 * sifup - Config the interface up and enable IP packets to pass. 877 */ 878int 879sifup(u) 880 int u; 881{ 882 struct ifreq ifr; 883 884 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 885 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 886 error("Couldn't mark interface up (get): %m"); 887 return 0; 888 } 889 ifr.ifr_flags |= IFF_UP; 890 if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { 891 error("Couldn't mark interface up (set): %m"); 892 return 0; 893 } 894 if_is_up = 1; 895 return 1; 896} 897 898/* 899 * sifdown - Config the interface down and disable IP. 900 */ 901int 902sifdown(u) 903 int u; 904{ 905 struct ifreq ifr; 906 907 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 908 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 909 error("Couldn't mark interface down (get): %m"); 910 return 0; 911 } 912 if ((ifr.ifr_flags & IFF_UP) != 0) { 913 ifr.ifr_flags &= ~IFF_UP; 914 if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { 915 error("Couldn't mark interface down (set): %m"); 916 return 0; 917 } 918 } 919 if_is_up = 0; 920 return 1; 921} 922 923/* 924 * sifnpmode - Set the mode for handling packets for a given NP. 925 */ 926int 927sifnpmode(u, proto, mode) 928 int u; 929 int proto; 930 enum NPmode mode; 931{ 932 int npi[2]; 933 934 npi[0] = proto; 935 npi[1] = (int) mode; 936 if (strioctl(pppfd, PPPIO_NPMODE, npi, 2 * sizeof(int), 0) < 0) { 937 error("ioctl(set NP %d mode to %d): %m", proto, mode); 938 return 0; 939 } 940 return 1; 941} 942 943#define INET_ADDR(x) (((struct sockaddr_in *) &(x))->sin_addr.s_addr) 944 945/* 946 * sifaddr - Config the interface IP addresses and netmask. 947 */ 948int 949sifaddr(u, o, h, m) 950 int u; 951 u_int32_t o, h, m; 952{ 953 struct ifreq ifr; 954 955 memset(&ifr, 0, sizeof(ifr)); 956 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 957 ifr.ifr_addr.sa_family = AF_INET; 958 INET_ADDR(ifr.ifr_addr) = m; 959 if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { 960 error("Couldn't set IP netmask: %m"); 961 } 962 ifr.ifr_addr.sa_family = AF_INET; 963 INET_ADDR(ifr.ifr_addr) = o; 964 if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { 965 error("Couldn't set local IP address: %m"); 966 } 967 ifr.ifr_dstaddr.sa_family = AF_INET; 968 INET_ADDR(ifr.ifr_dstaddr) = h; 969 if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) { 970 error("Couldn't set remote IP address: %m"); 971 } 972 ifaddrs[0] = o; 973 ifaddrs[1] = h; 974 975 return 1; 976} 977 978/* 979 * cifaddr - Clear the interface IP addresses, and delete routes 980 * through the interface if possible. 981 */ 982int 983cifaddr(u, o, h) 984 int u; 985 u_int32_t o, h; 986{ 987 struct rtentry rt; 988 989 bzero(&rt, sizeof(rt)); 990 rt.rt_dst.sa_family = AF_INET; 991 INET_ADDR(rt.rt_dst) = h; 992 rt.rt_gateway.sa_family = AF_INET; 993 INET_ADDR(rt.rt_gateway) = o; 994 rt.rt_flags = RTF_HOST; 995 if (ioctl(sockfd, SIOCDELRT, &rt) < 0) 996 error("Couldn't delete route through interface: %m"); 997 ifaddrs[0] = 0; 998 return 1; 999} 1000 1001/* 1002 * sifdefaultroute - assign a default route through the address given. 1003 */ 1004int 1005sifdefaultroute(u, l, g) 1006 int u; 1007 u_int32_t l, g; 1008{ 1009 struct rtentry rt; 1010 1011 bzero(&rt, sizeof(rt)); 1012 rt.rt_dst.sa_family = AF_INET; 1013 INET_ADDR(rt.rt_dst) = 0; 1014 rt.rt_gateway.sa_family = AF_INET; 1015 INET_ADDR(rt.rt_gateway) = g; 1016 rt.rt_flags = RTF_GATEWAY; 1017 1018 if (ioctl(sockfd, SIOCADDRT, &rt) < 0) { 1019 error("Can't add default route: %m"); 1020 return 0; 1021 } 1022 1023 default_route_gateway = g; 1024 return 1; 1025} 1026 1027/* 1028 * cifdefaultroute - delete a default route through the address given. 1029 */ 1030int 1031cifdefaultroute(u, l, g) 1032 int u; 1033 u_int32_t l, g; 1034{ 1035 struct rtentry rt; 1036 1037 bzero(&rt, sizeof(rt)); 1038 rt.rt_dst.sa_family = AF_INET; 1039 INET_ADDR(rt.rt_dst) = 0; 1040 rt.rt_gateway.sa_family = AF_INET; 1041 INET_ADDR(rt.rt_gateway) = g; 1042 rt.rt_flags = RTF_GATEWAY; 1043 1044 if (ioctl(sockfd, SIOCDELRT, &rt) < 0) { 1045 error("Can't delete default route: %m"); 1046 return 0; 1047 } 1048 1049 default_route_gateway = 0; 1050 return 1; 1051} 1052 1053/* 1054 * sifproxyarp - Make a proxy ARP entry for the peer. 1055 */ 1056int 1057sifproxyarp(unit, hisaddr) 1058 int unit; 1059 u_int32_t hisaddr; 1060{ 1061 struct arpreq arpreq; 1062 1063 bzero(&arpreq, sizeof(arpreq)); 1064 if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) 1065 return 0; 1066 1067 arpreq.arp_pa.sa_family = AF_INET; 1068 INET_ADDR(arpreq.arp_pa) = hisaddr; 1069 arpreq.arp_flags = ATF_PERM | ATF_PUBL; 1070 if (ioctl(sockfd, SIOCSARP, (caddr_t) &arpreq) < 0) { 1071 error("Couldn't set proxy ARP entry: %m"); 1072 return 0; 1073 } 1074 1075 proxy_arp_addr = hisaddr; 1076 return 1; 1077} 1078 1079/* 1080 * cifproxyarp - Delete the proxy ARP entry for the peer. 1081 */ 1082int 1083cifproxyarp(unit, hisaddr) 1084 int unit; 1085 u_int32_t hisaddr; 1086{ 1087 struct arpreq arpreq; 1088 1089 bzero(&arpreq, sizeof(arpreq)); 1090 arpreq.arp_pa.sa_family = AF_INET; 1091 INET_ADDR(arpreq.arp_pa) = hisaddr; 1092 if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) { 1093 error("Couldn't delete proxy ARP entry: %m"); 1094 return 0; 1095 } 1096 1097 proxy_arp_addr = 0; 1098 return 1; 1099} 1100 1101/* 1102 * get_ether_addr - get the hardware address of an interface on the 1103 * the same subnet as ipaddr. 1104 */ 1105#define MAX_IFS 32 1106 1107static int 1108get_ether_addr(ipaddr, hwaddr) 1109 u_int32_t ipaddr; 1110 struct sockaddr *hwaddr; 1111{ 1112 struct ifreq *ifr, *ifend; 1113 u_int32_t ina, mask; 1114 struct ifreq ifreq; 1115 struct ifconf ifc; 1116 struct ifreq ifs[MAX_IFS]; 1117 int nit_fd; 1118 1119 ifc.ifc_len = sizeof(ifs); 1120 ifc.ifc_req = ifs; 1121 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { 1122 error("ioctl(SIOCGIFCONF): %m"); 1123 return 0; 1124 } 1125 1126 /* 1127 * Scan through looking for an interface with an Internet 1128 * address on the same subnet as `ipaddr'. 1129 */ 1130 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 1131 for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) 1132 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) { 1133 if (ifr->ifr_addr.sa_family == AF_INET) { 1134 1135 /* 1136 * Check that the interface is up, and not point-to-point 1137 * or loopback. 1138 */ 1139 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 1140 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) 1141 continue; 1142 if ((ifreq.ifr_flags & 1143 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) 1144 != (IFF_UP|IFF_BROADCAST)) 1145 continue; 1146 1147 /* 1148 * Get its netmask and check that it's on the right subnet. 1149 */ 1150 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) 1151 continue; 1152 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; 1153 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; 1154 if ((ipaddr & mask) != (ina & mask)) 1155 continue; 1156 1157 break; 1158 } 1159 } 1160 1161 if (ifr >= ifend) 1162 return 0; 1163 info("found interface %s for proxy arp", ifr->ifr_name); 1164 1165 /* 1166 * Grab the physical address for this interface. 1167 */ 1168 if ((nit_fd = open("/dev/nit", O_RDONLY)) < 0) { 1169 error("Couldn't open /dev/nit: %m"); 1170 return 0; 1171 } 1172 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 1173 if (ioctl(nit_fd, NIOCBIND, &ifreq) < 0 1174 || ioctl(nit_fd, SIOCGIFADDR, &ifreq) < 0) { 1175 error("Couldn't get hardware address for %s: %m", 1176 ifreq.ifr_name); 1177 close(nit_fd); 1178 return 0; 1179 } 1180 1181 hwaddr->sa_family = AF_UNSPEC; 1182 memcpy(hwaddr->sa_data, ifreq.ifr_addr.sa_data, 6); 1183 close(nit_fd); 1184 return 1; 1185} 1186 1187/* 1188 * have_route_to - determine if the system has any route to 1189 * a given IP address. 1190 * For demand mode to work properly, we have to ignore routes 1191 * through our own interface. 1192 */ 1193int have_route_to(addr) 1194 u_int32_t addr; 1195{ 1196 return -1; 1197} 1198 1199#define WTMPFILE "/usr/adm/wtmp" 1200 1201void 1202logwtmp(line, name, host) 1203 const char *line, *name, *host; 1204{ 1205 int fd; 1206 struct stat buf; 1207 struct utmp ut; 1208 1209 if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0) 1210 return; 1211 if (!fstat(fd, &buf)) { 1212 strncpy(ut.ut_line, line, sizeof(ut.ut_line)); 1213 strncpy(ut.ut_name, name, sizeof(ut.ut_name)); 1214 strncpy(ut.ut_host, host, sizeof(ut.ut_host)); 1215 (void)time(&ut.ut_time); 1216 if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp)) 1217 (void)ftruncate(fd, buf.st_size); 1218 } 1219 close(fd); 1220} 1221 1222/* 1223 * Return user specified netmask, modified by any mask we might determine 1224 * for address `addr' (in network byte order). 1225 * Here we scan through the system's list of interfaces, looking for 1226 * any non-point-to-point interfaces which might appear to be on the same 1227 * network as `addr'. If we find any, we OR in their netmask to the 1228 * user-specified netmask. 1229 */ 1230u_int32_t 1231GetMask(addr) 1232 u_int32_t addr; 1233{ 1234 u_int32_t mask, nmask, ina; 1235 struct ifreq *ifr, *ifend, ifreq; 1236 struct ifconf ifc; 1237 1238 addr = ntohl(addr); 1239 if (IN_CLASSA(addr)) /* determine network mask for address class */ 1240 nmask = IN_CLASSA_NET; 1241 else if (IN_CLASSB(addr)) 1242 nmask = IN_CLASSB_NET; 1243 else 1244 nmask = IN_CLASSC_NET; 1245 /* class D nets are disallowed by bad_ip_adrs */ 1246 mask = netmask | htonl(nmask); 1247 1248 /* 1249 * Scan through the system's network interfaces. 1250 */ 1251 ifc.ifc_len = MAX_IFS * sizeof(struct ifreq); 1252 ifc.ifc_req = alloca(ifc.ifc_len); 1253 if (ifc.ifc_req == 0) 1254 return mask; 1255 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { 1256 warn("Couldn't get system interface list: %m"); 1257 return mask; 1258 } 1259 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 1260 for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) { 1261 /* 1262 * Check the interface's internet address. 1263 */ 1264 if (ifr->ifr_addr.sa_family != AF_INET) 1265 continue; 1266 ina = INET_ADDR(ifr->ifr_addr); 1267 if ((ntohl(ina) & nmask) != (addr & nmask)) 1268 continue; 1269 /* 1270 * Check that the interface is up, and not point-to-point or loopback. 1271 */ 1272 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); 1273 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) 1274 continue; 1275 if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) 1276 != IFF_UP) 1277 continue; 1278 /* 1279 * Get its netmask and OR it into our mask. 1280 */ 1281 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) 1282 continue; 1283 mask |= INET_ADDR(ifreq.ifr_addr); 1284 } 1285 1286 return mask; 1287} 1288 1289static int 1290strioctl(fd, cmd, ptr, ilen, olen) 1291 int fd, cmd, ilen, olen; 1292 void *ptr; 1293{ 1294 struct strioctl str; 1295 1296 str.ic_cmd = cmd; 1297 str.ic_timout = 0; 1298 str.ic_len = ilen; 1299 str.ic_dp = ptr; 1300 if (ioctl(fd, I_STR, &str) == -1) 1301 return -1; 1302 if (str.ic_len != olen) 1303 dbglog("strioctl: expected %d bytes, got %d for cmd %x\n", 1304 olen, str.ic_len, cmd); 1305 return 0; 1306} 1307 1308/* 1309 * Use the hostid as part of the random number seed. 1310 */ 1311int 1312get_host_seed() 1313{ 1314 return gethostid(); 1315} 1316 1317 1318/* 1319 * get_pty - get a pty master/slave pair and chown the slave side 1320 * to the uid given. Assumes slave_name points to >= 12 bytes of space. 1321 */ 1322int 1323get_pty(master_fdp, slave_fdp, slave_name, uid) 1324 int *master_fdp; 1325 int *slave_fdp; 1326 char *slave_name; 1327 int uid; 1328{ 1329 int i, mfd, sfd; 1330 char pty_name[12]; 1331 struct termios tios; 1332 1333 sfd = -1; 1334 for (i = 0; i < 64; ++i) { 1335 slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x", 1336 'p' + i / 16, i % 16); 1337 mfd = open(pty_name, O_RDWR, 0); 1338 if (mfd >= 0) { 1339 pty_name[5] = 't'; 1340 sfd = open(pty_name, O_RDWR | O_NOCTTY, 0); 1341 if (sfd >= 0) 1342 break; 1343 close(mfd); 1344 } 1345 } 1346 if (sfd < 0) 1347 return 0; 1348 1349 strlcpy(slave_name, pty_name, 12); 1350 *master_fdp = mfd; 1351 *slave_fdp = sfd; 1352 fchown(sfd, uid, -1); 1353 fchmod(sfd, S_IRUSR | S_IWUSR); 1354 if (tcgetattr(sfd, &tios) == 0) { 1355 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); 1356 tios.c_cflag |= CS8 | CREAD; 1357 tios.c_iflag = IGNPAR | CLOCAL; 1358 tios.c_oflag = 0; 1359 tios.c_lflag = 0; 1360 if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0) 1361 warn("couldn't set attributes on pty: %m"); 1362 } else 1363 warn("couldn't get attributes on pty: %m"); 1364 1365 return 1; 1366} 1367 1368/* 1369 * SunOS doesn't have strtoul :-( 1370 */ 1371unsigned long 1372strtoul(str, ptr, base) 1373 char *str, **ptr; 1374 int base; 1375{ 1376 return (unsigned long) strtol(str, ptr, base); 1377} 1378 1379/* 1380 * Or strerror :-( 1381 */ 1382extern char *sys_errlist[]; 1383extern int sys_nerr; 1384 1385char * 1386strerror(n) 1387 int n; 1388{ 1389 static char unknown[32]; 1390 1391 if (n > 0 && n < sys_nerr) 1392 return sys_errlist[n]; 1393 slprintf(unknown, sizeof(unknown), "Error %d", n); 1394 return unknown; 1395} 1396