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

📄 if_ppp.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. * * Copyright (c) 1989 Carnegie Mellon 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.  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. * * Drew D. Perkins * Carnegie Mellon University * 4910 Forbes Ave. * Pittsburgh, PA 15213 * (412) 268-8576 * ddp@andrew.cmu.edu * * Based on: *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89 * * Copyright (c) 1987 Regents of the University of California. * 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 the University of California, Berkeley.  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. * * Serial Line interface * * Rick Adams * Center for Seismic Studies * 1300 N 17th Street, Suite 1450 * Arlington, Virginia 22209 * (703)276-7900 * rick@seismo.ARPA * seismo!rick * * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). * Converted to 4.3BSD Beta by Chris Torek. * Other changes made at Berkeley, based in part on code by Kirk Smith. * * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) * Added VJ tcp header compression; more unified ioctls * * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). * Cleaned up a lot of the mbuf-related code to fix bugs that * caused system crashes and packet corruption.  Changed pppstart * so that it doesn't just give up with a collision if the whole * packet doesn't fit in the output ring buffer. * * Added priority queueing for interactive IP packets, following * the model of if_sl.c, plus hooks for bpf. * Paul Mackerras (paulus@cs.anu.edu.au). *//* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */#include "ppp.h"#if NPPP > 0#define VJC#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/mbuf.h>#include <sys/buf.h>#include <sys/dkstat.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/tty.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/vnode.h>#include <sys/kernel.h>#include <net/if.h>#include <net/if_types.h>#include <net/netisr.h>#include <net/route.h>#if INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#endif#include "bpfilter.h"#if NBPFILTER > 0#include <sys/time.h>#include <net/bpf.h>#endif#ifdef VJC#include <net/pppcompress.h>#define HDROFF	MAX_HDR/* HDROFF should really be 128, but other parts of the system will   panic on TCP+IP headers bigger than MAX_HDR = MHLEN (100). */#else#define	HDROFF	(0)#endif#include <net/if_ppp.h>#include <machine/cpu.h>/* This is a FreeBSD-2.x kernel. */#define CCOUNT(q)	((q)->c_cc)#define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */#define	PPP_MAXMTU	16384	/* Largest MTU we allow */struct ppp_softc ppp_softc[NPPP];void	pppattach __P((void));int	pppopen __P((dev_t dev, struct tty *tp));int	pppclose __P((struct tty *tp, int flag));int	pppread __P((struct tty *tp, struct uio *uio, int flag));int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));int	ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,		       struct proc *));int	pppoutput __P((struct ifnet *, struct mbuf *,		       struct sockaddr *, struct rtentry *));int	pppinput __P((int c, struct tty *tp));int	pppioctl __P((struct ifnet *ifp, int cmd, caddr_t data));int	pppstart __P((struct tty *tp));static struct linesw pppdisc = {	pppopen, pppclose, pppread, pppwrite, ppptioctl,	pppinput, pppstart, ttymodem};extern struct	ppp_softc *pppalloc __P((pid_t pid));extern void	pppdealloc __P((struct ppp_softc *sc));extern struct	mbuf *ppp_dequeue __P((struct ppp_softc *sc));extern int	ppppktin __P((struct ppp_softc *sc, struct mbuf *m, int ilen));static int	pppasyncstart __P((struct ppp_softc *));static u_short	pppfcs __P((u_short fcs, u_char *cp, int len));static int	pppgetm __P((struct ppp_softc *sc));static struct	mbuf *ppp_btom __P((struct ppp_softc *sc));static void	pppdumpm __P((struct mbuf *m0, int pktlen));static void	pppdumpb __P((u_char *b, int l));static void	ppplogchar __P((struct ppp_softc *, int));/* * Some useful mbuf macros not in mbuf.h. */#define M_DATASTART(m)	\	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf : \	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)#define M_DATASIZE(m)	\	((m)->m_flags & M_EXT ? (m)->m_ext.ext_size : \	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)/* * The following disgusting hack gets around the problem that IP TOS * can't be set yet.  We want to put "interactive" traffic on a high * priority queue.  To decide if traffic is interactive, we check that * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. */static u_short interactive_ports[8] = {	0,	513,	0,	0,	0,	21,	0,	23,};#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))/* * Does c need to be escaped? */#define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))/* * Called from boot code to establish ppp interfaces. */voidpppattach(){    register struct ppp_softc *sc;    register int i = 0;    linesw[PPPDISC] = pppdisc;    for (sc = ppp_softc; i < NPPP; sc++) {	sc->sc_if.if_name = "ppp";	sc->sc_if.if_unit = i++;	sc->sc_if.if_mtu = PPP_MTU;	sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;	sc->sc_if.if_type = IFT_PPP;	sc->sc_if.if_hdrlen = PPP_HDRLEN;	sc->sc_if.if_ioctl = pppioctl;	sc->sc_if.if_output = pppoutput;	sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;	sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;	sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;	if_attach(&sc->sc_if);#if NBPFILTER > 0	bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);#endif    }}/* * Allocate a ppp interface unit and initialize it. */struct ppp_softc *pppalloc(pid)    pid_t pid;{    int nppp;    struct ppp_softc *sc;    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)	if (sc->sc_xfer == pid) {	    sc->sc_xfer = 0;	    break;	}    if (nppp >= NPPP)	for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)	    if (sc->sc_devp == NULL)		break;    if (nppp >= NPPP)	return NULL;    sc->sc_flags = 0;    sc->sc_mru = PPP_MRU;#ifdef VJC    sl_compress_init(&sc->sc_comp);#endif    sc->sc_if.if_flags |= IFF_RUNNING;    microtime(&sc->sc_if.if_lastchange);    return sc;}/* * Deallocate a ppp unit. */voidpppdealloc(sc)	struct ppp_softc *sc;{    struct mbuf *m;    if_down(&sc->sc_if);    sc->sc_devp = NULL;    sc->sc_xfer = 0;    for (;;) {	IF_DEQUEUE(&sc->sc_inq, m);	if (m == NULL)	    break;	m_freem(m);    }    for (;;) {	IF_DEQUEUE(&sc->sc_fastq, m);	if (m == NULL)	    break;	m_freem(m);    }    sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);    microtime(&sc->sc_if.if_lastchange);}/* * Line specific open routine for async tty devices. * Attach the given tty to the first available ppp unit. *//* ARGSUSED */intpppopen(dev, tp)    dev_t dev;    register struct tty *tp;{    struct proc *p = curproc;		/* XXX */    register struct ppp_softc *sc;    int error, s, i;    if (error = suser(p->p_ucred, &p->p_acflag))	return (error);    if (tp->t_line == PPPDISC) {	sc = (struct ppp_softc *) tp->t_sc;	if (sc != NULL && sc->sc_devp == (void *) tp)	    return (0);    }    if ((sc = pppalloc(p->p_pid)) == NULL)	return ENXIO;    if (sc->sc_outm != NULL) {	m_freem(sc->sc_outm);	sc->sc_outm = NULL;    }    if (pppgetm(sc) == 0) {	sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);	microtime(&sc->sc_if.if_lastchange);	return (ENOBUFS);    }    sc->sc_ilen = 0;    bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));    sc->sc_asyncmap[0] = 0xffffffff;    sc->sc_asyncmap[3] = 0x60000000;    sc->sc_rasyncmap = 0;    sc->sc_devp = (void *) tp;    sc->sc_start = pppasyncstart;    tp->t_sc = (caddr_t) sc;    ttyflush(tp, FREAD | FWRITE);    /*     * XXX we fudge t_canq to avoid providing pppselect() and FIONREAD.     * I hope one char is enough.  The following actually gives CBSIZE     * chars.     */    clist_alloc_cblocks(&tp->t_canq, 1, 1);    clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,			sc->sc_if.if_mtu + PPP_HIWAT);    clist_alloc_cblocks(&tp->t_rawq, 0, 0);    return (0);}/* * Line specific close routine. * Detach the tty from the ppp unit. * Mimics part of ttyclose(). */intpppclose(tp, flag)    struct tty *tp;    int flag;{    register struct ppp_softc *sc;    struct mbuf *m;    int s;    ttyflush(tp, FREAD | FWRITE);    s = splimp();		/* paranoid; splnet probably ok */    clist_free_cblocks(&tp->t_canq);    clist_free_cblocks(&tp->t_outq);    tp->t_line = 0;    sc = (struct ppp_softc *)tp->t_sc;    if (sc != NULL) {	tp->t_sc = NULL;	if (tp == (struct tty *) sc->sc_devp) {	    m_freem(sc->sc_outm);	    sc->sc_outm = NULL;	    m_freem(sc->sc_m);	    sc->sc_m = NULL;	    pppdealloc(sc);	}    }    splx(s);    return (0);			/* success */}/* * Line specific (tty) read routine. */intpppread(tp, uio, flag)    register struct tty *tp;    struct uio *uio;    int flag;{    register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;    struct mbuf *m, *m0;    register int s;    int error = 0;    if ((tp->t_state & TS_CONNECTED) == 0)	return 0;		/* end of file */    if (sc == NULL || tp != (struct tty *) sc->sc_devp)	return 0;    s = splimp();    while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {	    splx(s);	    return (EWOULDBLOCK);	}	error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);	if (error)	    return error;    }    if (tp->t_line != PPPDISC) {	splx(s);	return (-1);    }    /* Pull place-holder byte out of canonical queue */    getc(&tp->t_canq);    /* Get the packet from the input queue */    IF_DEQUEUE(&sc->sc_inq, m0);    splx(s);    for (m = m0; m && uio->uio_resid; m = m->m_next)	if (error = uiomove(mtod(m, u_char *), m->m_len, uio))	    break;    m_freem(m0);    return (error);}/* * Line specific (tty) write routine. */intpppwrite(tp, uio, flag)    register struct tty *tp;    struct uio *uio;    int flag;{    register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;    struct mbuf *m, *m0, **mp;    struct sockaddr dst;    struct ppp_header *ph1, *ph2;    int len, error;    if ((tp->t_state & TS_CONNECTED) == 0)	return 0;		/* wrote 0 bytes */    if (tp->t_line != PPPDISC)	return (EINVAL);    if (sc == NULL || tp != (struct tty *) sc->sc_devp)	return EIO;    if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||	uio->uio_resid < PPP_HDRLEN)	return (EMSGSIZE);    for (mp = &m0; uio->uio_resid; mp = &m->m_next) {	MGET(m, M_WAIT, MT_DATA);	if ((*mp = m) == NULL) {	    m_freem(m0);	    return (ENOBUFS);	}	m->m_len=0;	if (uio->uio_resid >= MCLBYTES / 2)	    MCLGET(m, M_DONTWAIT);	len = M_TRAILINGSPACE(m);	if (len > uio->uio_resid)	    len = uio->uio_resid;	if (error = uiomove(mtod(m, u_char *), len, uio)) {	    m_freem(m0);	    return (error);	}	m->m_len = len;    }    dst.sa_family = AF_UNSPEC;    ph1 = (struct ppp_header *) &dst.sa_data;    ph2 = mtod(m0, struct ppp_header *);    *ph1 = *ph2;    m0->m_data += PPP_HDRLEN;    m0->m_len -= PPP_HDRLEN;    return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));}/* * Line specific (tty) ioctl routine. * Provide a way to get the ppp unit number. * This discipline requires that tty device drivers call * the line specific l_ioctl routine from their ioctl routines. *//* ARGSUSED */intppptioctl(tp, cmd, data, flag, p)    struct tty *tp;    caddr_t data;    int cmd, flag;    struct proc *p;{    register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;    int s, error, flags, mru;    if (sc == NULL || tp != (struct tty *) sc->sc_devp)	return -1;    switch (cmd) {    case FIONREAD:	*(int *)data = sc->sc_inq.ifq_len;	break;    case PPPIOCGUNIT:	*(int *)data = sc->sc_if.if_unit;	break;    case PPPIOCGFLAGS:	*(u_int *)data = sc->sc_flags;	break;    case PPPIOCSFLAGS:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);	flags = *(int *)data & SC_MASK;	s = splimp();	sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;	splx(s);	break;    case PPPIOCSASYNCMAP:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);	sc->sc_asyncmap[0] = *(u_int *)data;	break;    case PPPIOCGASYNCMAP:	*(u_int *)data = sc->sc_asyncmap[0];	break;    case PPPIOCSRASYNCMAP:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);	sc->sc_rasyncmap = *(u_int *)data;	break;    case PPPIOCGRASYNCMAP:	*(u_int *)data = sc->sc_rasyncmap;	break;    case PPPIOCSXASYNCMAP:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */	break;    case PPPIOCGXASYNCMAP:	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));	break;    case PPPIOCSMRU:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);

⌨️ 快捷键说明

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