⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys-bsd.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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-bsd.c,v 1.46 1999/08/13 06:46:18 paulus Exp $"/*	$NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $	*/#endif/* * TODO: */#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 NetBSD1_2#include <util.h>#endif#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 */#ifdef __FreeBSD__#include <netinet/if_ether.h>#else#include <net/if_ether.h>#endif#endif#endif#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 char loop_name[20];static unsigned char inbuf[512]; /* buffer for chars read from loopback */static int sockfd;		/* socket for doing interface ioctls */static fd_set in_fds;		/* set of fds that wait_input waits for */static int max_in_fd;		/* highest fd set in in_fds */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");    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 (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(){#ifndef CDTRCTS    if (crtscts == 2) {	warn("DTR/CTS flow control is not supported on this system");	return 0;    }#endif    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;    extern char *no_ppp_msg;    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);    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.bsd\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 (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");    if (!demand) {	/*	 * Find out which interface we were given.	 */	if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 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 != ifunit)	    fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, 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 != ifunit)	fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, 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;{    /* 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)	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 (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;    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);}/* * get_pty - get a pty master/slave pair and chown the slave side * to the uid given.  Assumes slave_name points to >= 12 bytes of space. */intget_pty(master_fdp, slave_fdp, slave_name, uid)    int *master_fdp;    int *slave_fdp;    char *slave_name;    int uid;{    struct termios tios;    if (openpty(master_fdp, slave_fdp, slave_name, NULL, NULL) < 0)	return 0;    fchown(*slave_fdp, uid, -1);    fchmod(*slave_fdp, S_IRUSR | S_IWUSR);    if (tcgetattr(*slave_fdp, &tios) == 0) {	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);	tios.c_cflag |= CS8 | CREAD;	tios.c_iflag  = IGNPAR | CLOCAL;	tios.c_oflag  = 0;	tios.c_lflag  = 0;	if (tcsetattr(*slave_fdp, TCSAFLUSH, &tios) < 0)	    warn("couldn't set attributes on pty: %m");    } else	warn("couldn't get attributes on pty: %m");    return 1;}/* * open_ppp_loopback - open the device we use for getting * packets in demand mode, and connect it to a ppp interface. * Here we use a pty. */intopen_ppp_loopback(){    int flags;    struct termios tios;    int pppdisc = PPPDISC;    if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0)	fatal("No free pty for loopback");    SYSDEBUG(("using %s for loopback", loop_name));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -