📄 sys-next.c
字号:
/* * sys-next.c - System-dependent procedures for setting up * PPP interfaces on NeXT 3.2/3.3 systems * * Copyright (c) 1989 Carnegie Mellon University. * Copyright (c) 1994 Philippe-Andre Prindeville. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#define RCSID "$Id: sys-NeXT.c,v 1.20 1999/08/13 06:46:17 paulus Exp $"#include <stdio.h>#include <termios.h>#include <utmp.h>#include <unistd.h>#include <stdlib.h>#include <libc.h>#include <strings.h>#include <sys/types.h>#include <sys/file.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/errno.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <net/if.h>#include <net/ppp_defs.h>#include <net/if_ppp.h>#include <netdb.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#if !(NS_TARGET >= 40)/* XXX get an error "duplicate member ip_v under 4.1 GAMMA */#include <netinet/ip.h>#endif /* NS_TARGET */#include <netinet/if_ether.h>#include <net/route.h>#include <netinet/in.h>#include <netinfo/ni.h>#include "pppd.h"static const char rcsid[] = RCSID;static int initdisc = -1; /* Initial TTY discipline */static int initfdflags = -1; /* Initial file descriptor flags for fd */static int ppp_fd = -1; /* fd which is set to PPP discipline */static int loop_slave = -1;static int loop_master;static char loop_name[20];static fd_set in_fds; /* set of fds that wait_input waits for */static int max_in_fd; /* highest fd set in in_fds */extern int errno;static int restore_term; /* 1 => we've munged the terminal */static struct termios inittermios; /* Initial TTY termios */static int sockfd; /* socket for doing interface ioctls */static int pppdev; /* +++ */#if defined(i386) && defined(HAS_BROKEN_IOCTL)#define ioctl myioctl#endifstatic int if_is_up; /* the interface is currently up */static u_int32_t default_route_gateway; /* gateway addr for default route */static u_int32_t proxy_arp_addr; /* remote addr for proxy arp *//* Prototypes for procedures local to this file. */static int translate_speed __P((int));static int baud_rate_of __P((int));static int dodefaultroute __P((u_int32_t, int));static int get_ether_addr __P((u_int32_t, struct sockaddr *));static int ether_by_host __P((char *, struct ether_addr *));/* * sys_init - System-dependent initialization. */voidsys_init(){ openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); setlogmask(LOG_UPTO(LOG_INFO)); /* 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"); if((pppdev = open("/dev/ppp0", O_RDWR, O_NONBLOCK)) == NULL) fatal("Couldn't open /dev/ppp0: %m"); FD_ZERO(&in_fds); max_in_fd = 0;}/* * sys_cleanup - restore any system state we modified before exiting: * mark the interface down, delete default route and/or proxy arp entry. * This should call die() because it's called from die(). */voidsys_cleanup(){ struct ifreq ifr; if (if_is_up) { strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0 && ((ifr.ifr_flags & IFF_UP) != 0)) { ifr.ifr_flags &= ~IFF_UP; ioctl(sockfd, SIOCSIFFLAGS, &ifr); } } if (default_route_gateway) cifdefaultroute(0, 0, default_route_gateway); if (proxy_arp_addr) cifproxyarp(0, proxy_arp_addr); close(pppdev);}/* * ppp_available - check whether the system has any ppp interfaces * (in fact we check whether we can do an ioctl on ppp0). */intppp_available(){ int s, ok; struct ifreq ifr; extern char *no_ppp_msg; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return 1; /* can't tell - maybe we're not root */ strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; close(s); no_ppp_msg = "\This system lacks kernel support for PPP. To include PPP support\n\in the kernel, please follow the steps detailed in the README.NeXT\n\file in the ppp-2.2 distribution.\n"; return ok;}/* * establish_ppp - Turn the serial port into a ppp interface. */intestablish_ppp(fd) int fd;{ int pppdisc = PPPDISC; int x; if (ioctl(fd, TIOCGETD, &initdisc) < 0) fatal("ioctl(TIOCGETD): %m"); if (ioctl(fd, TIOCSETD, &pppdisc) < 0) fatal("ioctl(establish TIOCSETD): %m"); /* * Find out which interface we were given. */ if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) fatal("ioctl(PPPIOCGUNIT): %m"); /* * Enable debug in the driver if requested. */ if (kdebugflag) { if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { warn("ioctl(PPPIOCGFLAGS): %m"); } else { x |= (kdebugflag & 0xFF) * SC_DEBUG; if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) warn("ioctl(PPPIOCSFLAGS): %m"); } } /* * Set device for non-blocking reads so PPPD can poll for * input from the kernel. */ if ((initfdflags = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) { warn("Couldn't set device to non-blocking mode: %m"); } return fd;}/* * disestablish_ppp - Restore the serial port to normal operation. * This shouldn't call die() because it's called from die(). */voiddisestablish_ppp(fd) int fd;{ /* Reset non-blocking mode on fd. */ if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0) warn("Couldn't restore device fd flags: %m"); initfdflags = -1; /* Restore old line discipline. */ if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0) error("ioctl(TIOCSETD): %m"); initdisc = -1;}/* * Check whether the link seems not to be 8-bit clean. */voidclean_check(){ int x; char *s; if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { s = NULL; switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { case SC_RCV_B7_0: s = "bit 7 set to 1"; break; case SC_RCV_B7_1: s = "bit 7 set to 0"; break; case SC_RCV_EVNP: s = "odd parity"; break; case SC_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 B14400 { 14400, B14400 },#endif#ifdef B28800 { 28800, B28800 },#endif#ifdef B43200 { 43200, B43200 },#endif#ifdef B57600 { 57600, B57600 },#endif/*#ifndef B115200#warning Defining B115200#define B115200 20#endif*/#ifdef B115200 { 115200, B115200 },#endif { 0, 0 }};/* * Translate from bits/second to a speed_t. */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, x, modembits; struct termios tios; if (tcgetattr(fd, &tios) < 0) fatal("tcgetattr: %m"); if (!restore_term) inittermios = tios; tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 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 B0, * 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 (modem) { modembits = TIOCM_RTS | TIOCM_CTS; if (ioctl(fd, (crtscts ? TIOCMBIS : TIOCMBIC), &modembits) < 0) error("ioctl: TIOCMBIS/BIC: %m"); } 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;{ if (restore_term) { if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) if (errno != ENXIO) warn("tcsetattr: %m"); restore_term = 0; }}/* * setdtr - control the DTR line on the serial port. * This is called from die(), so it shouldn't call die(). * * The write hack is to get NXFax to recognize that there is * activity on the port. Not using the write nukes * NXFax's capability to determine port usage. * */voidsetdtr(fd, on)int fd, on;{ int modembits = TIOCM_DTR; if (!on) { write(fd, " ", 1); sleep(1); }/* ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); */ ioctl(fd, (on? TIOCSDTR: TIOCCDTR), 0);}/* * output - Output PPP packet. */voidoutput(unit, p, len) int unit; u_char *p; int len;{ if (debug) dbglog("sent %P", p, len); if (write(ttyfd, p, len) < 0) { if (errno == EWOULDBLOCK || errno == ENOBUFS || errno == ENXIO || errno == EIO) { warn("write: warning: %m"); } else { fatal("write: %m"); } }}/* * wait_input - wait until there is data available, * for the length of time specified by *timo (indefinite * if timo is NULL). */voidwait_input(timo) struct timeval *timo;{ fd_set ready; int n; ready = in_fds; n = select(max_in_fd + 1, &ready, NULL, &ready, timo); if (n < 0 && errno != EINTR) fatal("select: %m");}/* * add_fd - add an fd to the set that wait_input waits for. */void add_fd(fd) int fd;{ FD_SET(fd, &in_fds); if (fd > max_in_fd) max_in_fd = fd;}/* * remove_fd - remove an fd from the set that wait_input waits for. */void remove_fd(fd) int fd;{ FD_CLR(fd, &in_fds);}/* * read_packet - get a PPP packet from the serial device. */intread_packet(buf) u_char *buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -