sys-rtems.c
来自「RTEMS (Real-Time Executive for Multiproc」· C语言 代码 · 共 1,339 行 · 第 1/3 页
C
1,339 行
/* * sys-bsd.c - System-dependent procedures for setting up * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.) * * Copyright (c) 1989 Carnegie Mellon University. * Copyright (c) 1995 The Australian National University. * 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 and The Australian National University. * The names of the Universities 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-rtems.c,v 1.4.4.1 2005/05/20 19:31:18 joel Exp $"#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <termios.h>#include <signal.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/param.h>#ifdef PPP_FILTER#include <net/bpf.h>#endif#include <net/if.h>#include <net/ppp_defs.h>#include <net/if_ppp.h>#include <net/route.h>#include <net/if_dl.h>#include <netinet/in.h>#if RTM_VERSION >= 3#include <sys/param.h>#if defined(NetBSD) && (NetBSD >= 199703)#include <netinet/if_inarp.h>#else /* NetBSD 1.2D or later */#include <netinet/if_ether.h>#endif#endif#include <rtems.h>#include <rtems/rtems_bsdnet.h>#include <rtems/termiostypes.h>extern int rtems_bsdnet_microseconds_per_tick;extern rtems_id rtems_pppd_taskid;#include "pppd.h"#include "fsm.h"#include "ipcp.h"static const char rcsid[] = RCSID;static int initdisc = -1; /* Initial TTY discipline for ppp_fd */static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */static int ppp_fd = -1; /* fd which is set to PPP discipline */static int rtm_seq;static int restore_term; /* 1 => we've munged the terminal */static struct termios inittermios; /* Initial TTY termios */static struct winsize wsinfo; /* Initial window size info */static int loop_slave = -1;static int loop_master;static unsigned char inbuf[512]; /* buffer for chars read from loopback */static int sockfd; /* socket for doing interface ioctls */static int if_is_up; /* the interface is currently up */static u_int32_t ifaddrs[2]; /* local and remote addresses we set */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 dodefaultroute __P((u_int32_t, int));static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *));/* * sys_init - System-dependent initialization. */voidsys_init(){ /* 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");}/* * 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 (ifaddrs[0] != 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(sockfd); if (loop_slave >= 0) { close(loop_slave); close(loop_master); }}/* * sys_check_options - check the options that the user specified */intsys_check_options(){ return 1;}/* * 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; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return 1; /* can't tell */ strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; close(s); return ok;}/* * establish_ppp - Turn the serial port into a ppp interface. */intestablish_ppp(fd) int fd;{ int taskid = (int)rtems_pppd_taskid; int pppdisc = PPPDISC; int x; if (demand) { /* * Demand mode - prime the old ppp device to relinquish the unit. */ if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) fatal("ioctl(transfer ppp unit): %m"); } /* * Save the old line discipline of fd, and set it to PPP. */ if (ioctl(fd, TIOCGETD, &initdisc) < 0) fatal("ioctl(TIOCGETD): %m"); if (ioctl(fd, TIOCSETD, &pppdisc) < 0) fatal("ioctl(TIOCSETD): %m"); /* set pppd taskid into the driver */ ioctl(fd, PPPIOCSTASK, &taskid); if (!demand) { /* * Find out which interface we were given. */ if (ioctl(fd, PPPIOCGUNIT, &pppifunit) < 0) fatal("ioctl(PPPIOCGUNIT): %m"); } else { /* * Check that we got the same unit again. */ if (ioctl(fd, PPPIOCGUNIT, &x) < 0) fatal("ioctl(PPPIOCGUNIT): %m"); if (x != pppifunit) fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x); x = TTYDISC; ioctl(loop_slave, TIOCSETD, &x); } ppp_fd = fd; /* * 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. */ 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;}/* * restore_loop - reattach the ppp unit to the loopback. */voidrestore_loop(){ int x; /* * Transfer the ppp interface back to the loopback. */ if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) fatal("ioctl(transfer ppp unit): %m"); x = PPPDISC; if (ioctl(loop_slave, TIOCSETD, &x) < 0) fatal("ioctl(TIOCSETD): %m"); /* * Check that we got the same unit again. */ if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) fatal("ioctl(PPPIOCGUNIT): %m"); if (x != pppifunit) fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x); ppp_fd = loop_slave;}/* * 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;{ int taskid = (int)0; /* clear pppd taskid from the driver */ ioctl(fd, PPPIOCSTASK, &taskid); /* 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; if (fd == ppp_fd) ppp_fd = -1;}/* * Check whether the link seems not to be 8-bit clean. */voidclean_check(){ int x; char *s; 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 = "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); } }}/* * 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. * * For *BSD, we assume that speed_t values numerically equal bits/second. */voidset_up_tty(fd, local) int fd, local;{ 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 && !local) { if (crtscts == 2) {#ifdef CDTRCTS tios.c_cflag |= CDTRCTS;#endif } else tios.c_cflag |= CRTSCTS; } else if (crtscts < 0) { tios.c_cflag &= ~CRTSCTS;#ifdef CDTRCTS tios.c_cflag &= ~CDTRCTS;#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 */ } if (inspeed) { cfsetospeed(&tios, inspeed); cfsetispeed(&tios, inspeed); } else { inspeed = cfgetospeed(&tios); /* * We can't proceed if the serial port speed is 0, * since that implies that the serial port is disabled. */ if (inspeed == 0) fatal("Baud rate for %s is 0; need explicit baud rate", devnam); } baud_rate = inspeed;/* if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { */ if (tcsetattr(fd, TCSADRAIN, &tios) < 0) { fatal("tcsetattr: %m"); } 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 (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) { */ if (tcsetattr(fd, TCSADRAIN, &inittermios) < 0) { if (errno != ENXIO) warn("tcsetattr: %m"); } 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?