📄 sys-sunos4.c
字号:
/* * System-dependent procedures for pppd under SunOS 4. * * Copyright (c) 1994 The Australian National University. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted, provided that the above copyright * notice appears in all copies. This software is provided without any * warranty, express or implied. The Australian National University * makes no representations about the suitability of this software for * any purpose. * * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. */#define RCSID "$Id: sys-sunos4.c,v 1.26 2001/03/12 22:59:00 paulus Exp $"#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <termios.h>#include <signal.h>#include <malloc.h>#include <utmp.h>#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#include <sys/sockio.h>#include <sys/stream.h>#include <sys/stropts.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/poll.h>#include <net/if.h>#include <net/if_arp.h>#include <net/nit_if.h>#include <net/route.h>#include <net/ppp_defs.h>#include <net/pppio.h>#include <netinet/in.h>#include "pppd.h"#if defined(sun) && defined(sparc)#include <alloca.h>#ifndef __GNUC__extern void *alloca();#endif#endif /*sparc*/static const char rcsid[] = RCSID;static int pppfd;static int fdmuxid = -1;static int iffd;static int sockfd;static int restore_term;static struct termios inittermios;static struct winsize wsinfo; /* Initial window size info */static pid_t parent_pid; /* PID of our parent */extern u_char inpacket_buf[]; /* borrowed from main.c */#define MAX_POLLFDS 32static struct pollfd pollfds[MAX_POLLFDS];static int n_pollfds;static int link_mtu, link_mru;#define NMODULES 32static int tty_nmodules;static char tty_modules[NMODULES][FMNAMESZ+1];static int if_is_up; /* Interface has been marked up */static u_int32_t ifaddrs[2]; /* local and remote addresses */static u_int32_t default_route_gateway; /* Gateway for default route added */static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added *//* Prototypes for procedures local to this file. */static int translate_speed __P((int));static int baud_rate_of __P((int));static int get_ether_addr __P((u_int32_t, struct sockaddr *));static int strioctl __P((int, int, void *, int, int));/* * sys_init - System-dependent initialization. */voidsys_init(){ int x; /* Get an internet socket for doing socket ioctl's on. */ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) fatal("Couldn't create IP socket: %m"); /* * We may want to send a SIGHUP to the session leader associated * with our controlling terminal later. Because SunOS doesn't * have getsid(), we make do with sending the signal to our * parent process. */ parent_pid = getppid(); /* * Open the ppp device. */ pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0); if (pppfd < 0) fatal("Can't open /dev/ppp: %m"); if (kdebugflag) { x = PPPDBG_LOG + PPPDBG_DRIVER; strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0); } /* Assign a new PPA and get its unit number. */ if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) fatal("Can't create new PPP interface: %m"); /* * Open the ppp device again and push the if_ppp module on it. */ iffd = open("/dev/ppp", O_RDWR, 0); if (iffd < 0) fatal("Can't open /dev/ppp (2): %m"); if (kdebugflag) { x = PPPDBG_LOG + PPPDBG_DRIVER; strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0); } if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) fatal("Couldn't attach ppp interface to device: %m"); if (ioctl(iffd, I_PUSH, "if_ppp") < 0) fatal("Can't push ppp interface module: %m"); if (kdebugflag) { x = PPPDBG_LOG + PPPDBG_IF; strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0); } if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) fatal("Couldn't create ppp interface unit: %m"); x = PPP_IP; if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) fatal("Couldn't bind ppp interface to IP SAP: %m"); n_pollfds = 0;}/* * sys_cleanup - restore any system state we modified before exiting: * mark the interface down, delete default route and/or proxy arp entry. * This shouldn't call die() because it's called from die(). */voidsys_cleanup(){ if (if_is_up) sifdown(0); if (ifaddrs[0]) cifaddr(0, ifaddrs[0], ifaddrs[1]); if (default_route_gateway) cifdefaultroute(0, 0, default_route_gateway); if (proxy_arp_addr) cifproxyarp(0, proxy_arp_addr);}/* * sys_close - Clean up in a child process before execing. */voidsys_close(){ close(iffd); close(pppfd); close(sockfd);}/* * sys_check_options - check the options that the user specified */intsys_check_options(){ return 1;}#if 0/* * daemon - Detach us from controlling terminal session. */intdaemon(nochdir, noclose) int nochdir, noclose;{ int pid; if ((pid = fork()) < 0) return -1; if (pid != 0) exit(0); /* parent dies */ setsid(); if (!nochdir) chdir("/"); if (!noclose) { fclose(stdin); /* don't need stdin, stdout, stderr */ fclose(stdout); fclose(stderr); } return 0;}#endif/* * ppp_available - check whether the system has any ppp interfaces */intppp_available(){ struct stat buf; return stat("/dev/ppp", &buf) >= 0;}/* * tty_establish_ppp - Turn the serial port into a ppp interface. */inttty_establish_ppp(fd) int fd;{ int i; /* Pop any existing modules off the tty stream. */ for (i = 0;; ++i) if (ioctl(fd, I_LOOK, tty_modules[i]) < 0 || ioctl(fd, I_POP, 0) < 0) break; tty_nmodules = i; /* Push the async hdlc module and the compressor module. */ if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) fatal("Couldn't push PPP Async HDLC module: %m"); if (ioctl(fd, I_PUSH, "ppp_comp") < 0) error("Couldn't push PPP compression module: %m"); /* Link the serial port under the PPP multiplexor. */ if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) fatal("Can't link tty to PPP mux: %m"); return pppfd;}/* * disestablish_ppp - Restore the serial port to normal operation. * It attempts to reconstruct the stream with the previously popped * modules. This shouldn't call die() because it's called from die(). */voidtty_disestablish_ppp(fd) int fd;{ int i; if (fdmuxid >= 0) { if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) { if (!hungup) error("Can't unlink tty from PPP mux: %m"); } fdmuxid = -1; if (!hungup) { while (ioctl(fd, I_POP, 0) >= 0) ; for (i = tty_nmodules - 1; i >= 0; --i) if (ioctl(fd, I_PUSH, tty_modules[i]) < 0) error("Couldn't restore tty module %s: %m", tty_modules[i]); } if (hungup && default_device && parent_pid > 0) { /* * If we have received a hangup, we need to send a SIGHUP * to the terminal's controlling process. The reason is * that the original stream head for the terminal hasn't * seen the M_HANGUP message (it went up through the ppp * driver to the stream head for our fd to /dev/ppp). * Actually we send the signal to the process that invoked * pppd, since SunOS doesn't have getsid(). */ kill(parent_pid, SIGHUP); } }}/* * Check whether the link seems not to be 8-bit clean. */voidclean_check(){ int x; char *s; if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0) return; s = NULL; switch (~x) { case RCV_B7_0: s = "bit 7 set to 1"; break; case RCV_B7_1: s = "bit 7 set to 0"; break; case RCV_EVNP: s = "odd parity"; break; case RCV_ODDP: s = "even parity"; break; } if (s != NULL) { warn("Serial link is not 8-bit clean:"); warn("All received characters had %s", s); }}/* * List of valid speeds. */struct speed { int speed_int, speed_val;} speeds[] = {#ifdef B50 { 50, B50 },#endif#ifdef B75 { 75, B75 },#endif#ifdef B110 { 110, B110 },#endif#ifdef B134 { 134, B134 },#endif#ifdef B150 { 150, B150 },#endif#ifdef B200 { 200, B200 },#endif#ifdef B300 { 300, B300 },#endif#ifdef B600 { 600, B600 },#endif#ifdef B1200 { 1200, B1200 },#endif#ifdef B1800 { 1800, B1800 },#endif#ifdef B2000 { 2000, B2000 },#endif#ifdef B2400 { 2400, B2400 },#endif#ifdef B3600 { 3600, B3600 },#endif#ifdef B4800 { 4800, B4800 },#endif#ifdef B7200 { 7200, B7200 },#endif#ifdef B9600 { 9600, B9600 },#endif#ifdef B19200 { 19200, B19200 },#endif#ifdef B38400 { 38400, B38400 },#endif#ifdef EXTA { 19200, EXTA },#endif#ifdef EXTB { 38400, EXTB },#endif#ifdef B57600 { 57600, B57600 },#endif#ifdef B115200 { 115200, B115200 },#endif { 0, 0 }};/* * Translate from bits/second to a speed_t. */static inttranslate_speed(bps) int bps;{ struct speed *speedp; if (bps == 0) return 0; for (speedp = speeds; speedp->speed_int; speedp++) if (bps == speedp->speed_int) return speedp->speed_val; warn("speed %d not supported", bps); return 0;}/* * Translate from a speed_t to bits/second. */static intbaud_rate_of(speed) int speed;{ struct speed *speedp; if (speed == 0) return 0; for (speedp = speeds; speedp->speed_int; speedp++) if (speed == speedp->speed_val) return speedp->speed_int; return 0;}/* * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, * at the requested speed, etc. If `local' is true, set CLOCAL * regardless of whether the modem option was specified. */voidset_up_tty(fd, local) int fd, local;{ int speed; struct termios tios; if (tcgetattr(fd, &tios) < 0) fatal("tcgetattr: %m"); if (!restore_term) { inittermios = tios; ioctl(fd, TIOCGWINSZ, &wsinfo); } tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); if (crtscts > 0) tios.c_cflag |= CRTSCTS; else if (crtscts < 0) tios.c_cflag &= ~CRTSCTS; tios.c_cflag |= CS8 | CREAD | HUPCL; if (local || !modem) tios.c_cflag |= CLOCAL; tios.c_iflag = IGNBRK | IGNPAR; tios.c_oflag = 0; tios.c_lflag = 0; tios.c_cc[VMIN] = 1; tios.c_cc[VTIME] = 0; if (crtscts == -2) { tios.c_iflag |= IXON | IXOFF; tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ } speed = translate_speed(inspeed); if (speed) { cfsetospeed(&tios, speed); cfsetispeed(&tios, speed); } else { speed = cfgetospeed(&tios); /* * We can't proceed if the serial port speed is 0, * since that implies that the serial port is disabled. */ if (speed == B0) fatal("Baud rate for %s is 0; need explicit baud rate", devnam); } if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) fatal("tcsetattr: %m"); baud_rate = inspeed = baud_rate_of(speed); restore_term = 1;}/* * restore_tty - restore the terminal to the saved settings. */voidrestore_tty(fd) int fd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -