📄 sys-solaris.c
字号:
#endif#ifdef B38400 { 38400, B38400 },#endif#ifdef EXTA { 19200, EXTA },#endif#ifdef EXTB { 38400, EXTB },#endif#ifdef B57600 { 57600, B57600 },#endif#ifdef B76800 { 76800, B76800 },#endif#ifdef B115200 { 115200, B115200 },#endif#ifdef B153600 { 153600, B153600 },#endif#ifdef B230400 { 230400, B230400 },#endif#ifdef B307200 { 307200, B307200 },#endif#ifdef B460800 { 460800, B460800 },#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 !defined (CRTSCTS) struct termiox tiox;#endif if (!sync_serial && tcgetattr(fd, &tios) < 0) fatal("tcgetattr: %m");#ifndef CRTSCTS termiox_ok = 1; if (!sync_serial && ioctl (fd, TCGETX, &tiox) < 0) { termiox_ok = 0; if (errno != ENOTTY) error("TCGETX: %m"); }#endif if (!restore_term) { inittermios = tios;#ifndef CRTSCTS inittermiox = tiox;#endif if (!sync_serial) ioctl(fd, TIOCGWINSZ, &wsinfo); } tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);#ifdef CRTSCTS if (crtscts > 0) tios.c_cflag |= CRTSCTS; else if (crtscts < 0) tios.c_cflag &= ~CRTSCTS;#else if (crtscts != 0 && !termiox_ok) { error("Can't set RTS/CTS flow control"); } else if (crtscts > 0) { tiox.x_hflag |= RTSXOFF|CTSXON; } else if (crtscts < 0) { tiox.x_hflag &= ~(RTSXOFF|CTSXON); }#endif 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) && !sync_serial) fatal("Baud rate for %s is 0; need explicit baud rate", devnam); } if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &tios) < 0) fatal("tcsetattr: %m");#ifndef CRTSCTS if (!sync_serial && termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){ error("TCSETXF: %m"); }#endif baud_rate = inspeed = baud_rate_of(speed); if (!sync_serial) restore_term = 1;}/* * restore_tty - restore the terminal to the saved settings. */voidrestore_tty(fd) int fd;{ if (restore_term) { if (!default_device) { /* * 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. */ inittermios.c_lflag &= ~(ECHO | ECHONL); } if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) if (!hungup && errno != ENXIO) warn("tcsetattr: %m");#ifndef CRTSCTS if (!sync_serial && ioctl (fd, TCSETXF, &inittermiox) < 0){ if (!hungup && errno != ENXIO) error("TCSETXF: %m"); }#endif if (!sync_serial) ioctl(fd, TIOCSWINSZ, &wsinfo); restore_term = 0; }}/* * setdtr - control the DTR line on the serial port. * This is called from die(), so it shouldn't call die(). */voidsetdtr(fd, on)int fd, on;{ int modembits = TIOCM_DTR; ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);}/* * open_loopback - open the device we use for getting packets * in demand mode. Under Solaris 2, we use our existing fd * to the ppp driver. */intopen_ppp_loopback(){ return pppfd;}/* * output - Output PPP packet. */voidoutput(unit, p, len) int unit; u_char *p; int len;{ struct strbuf data; int retries; struct pollfd pfd; dump_packet("sent", p, len); if (snoop_send_hook) snoop_send_hook(p, len); data.len = len; data.buf = (caddr_t) p; retries = 4; while (putmsg(pppfd, NULL, &data, 0) < 0) { if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) { if (errno != ENXIO) error("Couldn't send packet: %m"); break; } pfd.fd = pppfd; pfd.events = POLLOUT; poll(&pfd, 1, 250); /* wait for up to 0.25 seconds */ }}/* * 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;{ int t; t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000; if (poll(pollfds, n_pollfds, t) < 0 && errno != EINTR) fatal("poll: %m");}/* * add_fd - add an fd to the set that wait_input waits for. */void add_fd(fd) int fd;{ int n; for (n = 0; n < n_pollfds; ++n) if (pollfds[n].fd == fd) return; if (n_pollfds < MAX_POLLFDS) { pollfds[n_pollfds].fd = fd; pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP; ++n_pollfds; } else error("Too many inputs!");}/* * remove_fd - remove an fd from the set that wait_input waits for. */void remove_fd(fd) int fd;{ int n; for (n = 0; n < n_pollfds; ++n) { if (pollfds[n].fd == fd) { while (++n < n_pollfds) pollfds[n-1] = pollfds[n]; --n_pollfds; break; } }}#if 0/* * wait_loop_output - wait until there is data available on the * loopback, for the length of time specified by *timo (indefinite * if timo is NULL). */voidwait_loop_output(timo) struct timeval *timo;{ wait_input(timo);}/* * wait_time - wait for a given length of time or until a * signal is received. */voidwait_time(timo) struct timeval *timo;{ int n; n = select(0, NULL, NULL, NULL, timo); if (n < 0 && errno != EINTR) fatal("select: %m");}#endif/* * read_packet - get a PPP packet from the serial device. */intread_packet(buf) u_char *buf;{ struct strbuf ctrl, data; int flags, len; unsigned char ctrlbuf[sizeof(union DL_primitives) + 64]; for (;;) { data.maxlen = PPP_MRU + PPP_HDRLEN; data.buf = (caddr_t) buf; ctrl.maxlen = sizeof(ctrlbuf); ctrl.buf = (caddr_t) ctrlbuf; flags = 0; len = getmsg(pppfd, &ctrl, &data, &flags); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return -1; fatal("Error reading packet: %m"); } if (ctrl.len <= 0) return data.len; /* * Got a M_PROTO or M_PCPROTO message. Interpret it * as a DLPI primitive?? */ if (debug) dbglog("got dlpi prim 0x%x, len=%d", ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len); }}/* * get_loop_output - get outgoing packets from the ppp device, * and detect when we want to bring the real link up. * Return value is 1 if we need to bring up the link, 0 otherwise. */intget_loop_output(){ int len; int rv = 0; while ((len = read_packet(inpacket_buf)) > 0) { if (loop_frame(inpacket_buf, len)) rv = 1; } return rv;}/* * netif_set_mtu - set the MTU on the PPP network interface. */voidnetif_set_mtu(unit, mtu) int unit, mtu;{ struct ifreq ifr;#if defined(INET6) && defined(SOL2) struct lifreq lifr; int fd;#endif /* defined(INET6) && defined(SOL2) */ memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ifr.ifr_metric = link_mtu; if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) { error("Couldn't set IP MTU (%s): %m", ifr.ifr_name); }#if defined(INET6) && defined(SOL2) fd = socket(AF_INET6, SOCK_DGRAM, 0); if (fd < 0) error("Couldn't open IPv6 socket: %m"); memset(&lifr, 0, sizeof(lifr)); strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name)); lifr.lifr_mtu = link_mtu; if (ioctl(fd, SIOCSLIFMTU, &lifr) < 0) { close(fd); error("Couldn't set IPv6 MTU (%s): %m", ifr.ifr_name); } close(fd);#endif /* defined(INET6) && defined(SOL2) */}/* * tty_send_config - configure the transmit characteristics of * the ppp interface. */voidtty_send_config(mtu, asyncmap, pcomp, accomp) int mtu; u_int32_t asyncmap; int pcomp, accomp;{ int cf[2]; link_mtu = mtu; if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) { if (hungup && errno == ENXIO) { ++error_count; return; } error("Couldn't set MTU: %m"); } if (fdmuxid >= 0) { if (!sync_serial) { if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) error("Couldn't set transmit ACCM: %m"); } cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0); cf[1] = COMP_PROT | COMP_AC; if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) error("Couldn't set prot/AC compression: %m"); }}/* * tty_set_xaccm - set the extended transmit ACCM for the interface. */voidtty_set_xaccm(accm) ext_accm accm;{ if (sync_serial) return; if (fdmuxid >= 0 && strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) { if (!hungup || errno != ENXIO) warn("Couldn't set extended ACCM: %m"); }}/* * tty_recv_config - configure the receive-side characteristics of * the ppp interface. */voidtty_recv_config(mru, asyncmap, pcomp, accomp) int mru; u_int32_t asyncmap; int pcomp, accomp;{ int cf[2]; link_mru = mru; if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) { if (hungup && errno == ENXIO) { ++error_count; return; } error("Couldn't set MRU: %m"); } if (fdmuxid >= 0) { if (!sync_serial) { if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) error("Couldn't set receive ACCM: %m"); } cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0); cf[1] = DECOMP_PROT | DECOMP_AC; if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) error("Couldn't set prot/AC decompression: %m"); }}/* * ccp_test - ask kernel whether a given compression method * is acceptable for use. */intccp_test(unit, opt_ptr, opt_len, for_transmit) int unit, opt_len, for_transmit; u_char *opt_ptr;{ if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP), opt_ptr, opt_len, 0) >= 0) return 1; return (errno == ENOSR)? 0: -1;}/* * ccp_flags_set - inform kernel about the current state of CCP. */voidccp_flags_set(unit, isopen, isup) int unit, isopen, isup;{ int cf[2]; cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0); cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR; if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) { if (!hungup || errno != ENXIO) error("Couldn't set kernel CCP state: %m"); }}/* * get_idle_time - return how long the link has been idle. */intget_idle_time(u, ip) int u; struct ppp_idle *ip;{ return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -