📄 sys-linux.c
字号:
set_kdebugflag (kdebugflag); looped = 0; return ppp_fd; err_close: close(fd); err: return -1;}/******************************************************************** * * tty_disestablish_ppp - Restore the serial port to normal operation. * This shouldn't call die() because it's called from die(). */void tty_disestablish_ppp(int tty_fd){ if (!hungup) {/* * Flush the tty output buffer so that the TIOCSETD doesn't hang. */ if (tcflush(tty_fd, TCIOFLUSH) < 0) { warn("tcflush failed: %m"); goto flushfailed; }/* * Restore the previous line discipline */ if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) { if ( ! ok_error (errno)) error("ioctl(TIOCSETD, N_TTY): %m (line %d)", __LINE__); } if (ioctl(tty_fd, TIOCNXCL, 0) < 0) { if ( ! ok_error (errno)) warn("ioctl(TIOCNXCL): %m (line %d)", __LINE__); } /* Reset non-blocking mode on fd. */ if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) { if ( ! ok_error (errno)) warn("Couldn't restore device fd flags: %m"); } }flushfailed: initfdflags = -1; generic_disestablish_ppp(tty_fd);}/******************************************************************** * * generic_disestablish_ppp - Restore device components to normal * operation, and reconnect the ppp unit to the loopback if in demand * mode. This shouldn't call die() because it's called from die(). */void generic_disestablish_ppp(int dev_fd){ if (new_style_driver) { close(ppp_fd); ppp_fd = -1; if (demand) { modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC); looped = 1; } else if (!doing_multilink && ppp_dev_fd >= 0) { close(ppp_dev_fd); remove_fd(ppp_dev_fd); ppp_dev_fd = -1; } } else { /* old-style driver */ if (demand) set_ppp_fd(slave_fd); else ppp_dev_fd = -1; }}/* * make_ppp_unit - make a new ppp unit for ppp_dev_fd. * Assumes new_style_driver. */static int make_ppp_unit(){ int x, flags; if (ppp_dev_fd >= 0) { dbglog("in make_ppp_unit, already had /dev/ppp open?"); close(ppp_dev_fd); } ppp_dev_fd = open("/dev/ppp", O_RDWR); if (ppp_dev_fd < 0) fatal("Couldn't open /dev/ppp: %m"); flags = fcntl(ppp_dev_fd, F_GETFL); if (flags == -1 || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1) warn("Couldn't set /dev/ppp to nonblock: %m"); ifunit = req_unit; x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); if (x < 0 && req_unit >= 0 && errno == EEXIST) { warn("Couldn't allocate PPP unit %d as it is already in use", req_unit); ifunit = -1; x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); } if (x < 0) error("Couldn't create new ppp unit: %m"); return x;}/* * cfg_bundle - configure the existing bundle. * Used in demand mode. */void cfg_bundle(int mrru, int mtru, int rssn, int tssn){ if (!new_style_driver) return; /* set the mrru, mtu and flags */ if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0) error("Couldn't set MRRU: %m"); modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK, ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0) | (mrru? SC_MULTILINK: 0))); /* connect up the channel */ if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0) fatal("Couldn't attach to PPP unit %d: %m", ifunit); add_fd(ppp_dev_fd);}/* * make_new_bundle - create a new PPP unit (i.e. a bundle) * and connect our channel to it. This should only get called * if `multilink' was set at the time establish_ppp was called. * In demand mode this uses our existing bundle instead of making * a new one. */void make_new_bundle(int mrru, int mtru, int rssn, int tssn){ if (!new_style_driver) return; /* make us a ppp unit */ if (make_ppp_unit() < 0) die(1); /* set the mrru and flags */ cfg_bundle(mrru, mtru, rssn, tssn);}/* * bundle_attach - attach our link to a given PPP unit. * We assume the unit is controlled by another pppd. */int bundle_attach(int ifnum){ int master_fd; if (!new_style_driver) return -1; master_fd = open("/dev/ppp", O_RDWR); if (master_fd < 0) fatal("Couldn't open /dev/ppp: %m"); if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) { if (errno == ENXIO) { close(master_fd); return 0; /* doesn't still exist */ } fatal("Couldn't attach to interface unit %d: %m\n", ifnum); } if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0) fatal("Couldn't connect to interface unit %d: %m", ifnum); modify_flags(master_fd, 0, SC_MULTILINK); close(master_fd); ifunit = ifnum; return 1;}/* * destroy_bundle - tell the driver to destroy our bundle. */void destroy_bundle(void){ if (ppp_dev_fd >= 0) { close(ppp_dev_fd); remove_fd(ppp_dev_fd); ppp_dev_fd = -1; }}/******************************************************************** * * clean_check - Fetch the flags for the device and generate * appropriate error messages. */void clean_check(void){ int x; char *s; if (still_ppp()) { if (ioctl(ppp_fd, 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 = "all had bit 7 set to 1"; break; case SC_RCV_B7_1: s = "all had bit 7 set to 0"; break; case SC_RCV_EVNP: s = "all had odd parity"; break; case SC_RCV_ODDP: s = "all had even parity"; break; } if (s != NULL) { warn("Receive serial link is not 8-bit clean:"); warn("Problem: %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 B57600 { 57600, B57600 },#endif#ifdef B76800 { 76800, B76800 },#endif#ifdef B115200 { 115200, B115200 },#endif#ifdef EXTA { 19200, EXTA },#endif#ifdef EXTB { 38400, EXTB },#endif#ifdef B230400 { 230400, B230400 },#endif#ifdef B460800 { 460800, B460800 },#endif#ifdef B921600 { 921600, B921600 },#endif { 0, 0 }};/******************************************************************** * * Translate from bits/second to a speed_t. */static int translate_speed (int bps){ struct speed *speedp; if (bps != 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 int baud_rate_of (int speed){ struct speed *speedp; if (speed != 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. */void set_up_tty(int tty_fd, int local){ int speed; struct termios tios; setdtr(tty_fd, 1); if (tcgetattr(tty_fd, &tios) < 0) { if (!ok_error(errno)) fatal("tcgetattr: %m (line %d)", __LINE__); return; } if (!restore_term) inittermios = tios; tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); tios.c_cflag |= CS8 | CREAD | HUPCL; tios.c_iflag = IGNBRK | IGNPAR; tios.c_oflag = 0; tios.c_lflag = 0; tios.c_cc[VMIN] = 1; tios.c_cc[VTIME] = 0; if (local || !modem) tios.c_cflag ^= (CLOCAL | HUPCL); switch (crtscts) { case 1: tios.c_cflag |= CRTSCTS; break; case -2: tios.c_iflag |= IXON | IXOFF; tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ break; case -1: tios.c_cflag &= ~CRTSCTS; break; default: break; } speed = translate_speed(inspeed); if (speed) { cfsetospeed (&tios, speed); cfsetispeed (&tios, speed); }/* * We can't proceed if the serial port speed is B0, * since that implies that the serial port is disabled. */ else { speed = cfgetospeed(&tios); if (speed == B0) fatal("Baud rate for %s is 0; need explicit baud rate", devnam); } while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno)) if (errno != EINTR) fatal("tcsetattr: %m (line %d)", __LINE__); baud_rate = baud_rate_of(speed); restore_term = 1;}/******************************************************************** * * setdtr - control the DTR line on the serial port. * This is called from die(), so it shouldn't call die(). */void setdtr (int tty_fd, int on){ int modembits = TIOCM_DTR; ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);}/******************************************************************** * * restore_tty - restore the terminal to the saved settings. */void restore_tty (int tty_fd){ if (restore_term) { restore_term = 0;/* * Turn off echoing, because otherwise we can get into * a loop with the tty and the modem echoing to each other. * We presume we are the sole user of this tty device, so * when we close it, it will revert to its defaults anyway. */ if (!default_device) inittermios.c_lflag &= ~(ECHO | ECHONL); if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0) { if (! ok_error (errno)) warn("tcsetattr: %m (line %d)", __LINE__); } }}/******************************************************************** * * output - Output PPP packet. */void output (int unit, unsigned char *p, int len){ int fd = ppp_fd; int proto; dump_packet("sent", p, len); if (snoop_send_hook) snoop_send_hook(p, len); if (len < PPP_HDRLEN) return; if (new_style_driver) { p += 2; len -= 2; proto = (p[0] << 8) + p[1]; if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG)) fd = ppp_dev_fd; } if (write(fd, p, len) < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS || errno == ENXIO || errno == EIO || errno == EINTR) warn("write: warning: %m (%d)", errno); else error("write: %m (%d)", errno); }}/******************************************************************** * * wait_input - wait until there is data available, * for the length of time specified by *timo (indefinite * if timo is NULL). */void wait_input(struct timeval *timo){ fd_set ready, exc; int n; ready = in_fds; exc = in_fds; n = select(max_in_fd + 1, &ready, NULL, &exc, timo); if (n < 0 && errno != EINTR) fatal("select: %m");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -