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

📄 if_ppp.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	mru = *(int *)data;	if (mru >= PPP_MRU && mru <= PPP_MAXMRU) {	    sc->sc_mru = mru;	    if (pppgetm(sc) == 0) {		error = ENOBUFS;		sc->sc_mru = PPP_MRU;		if (pppgetm(sc) == 0)		{		    sc->sc_if.if_flags &= ~IFF_UP;		    microtime(&sc->sc_if.if_lastchange);		}	    }	}	break;    case PPPIOCGMRU:	*(int *)data = sc->sc_mru;	break;#ifdef VJC    case PPPIOCSMAXCID:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);	sl_compress_setup(&sc->sc_comp, *(int *)data);	break;#endif    case PPPIOCXFERUNIT:	if (error = suser(p->p_ucred, &p->p_acflag))	    return (error);	sc->sc_xfer = p->p_pid;	break;    default:	return (-1);    }    return (0);}/* * FCS lookup table as calculated by genfcstab. */static u_short fcstab[256] = {	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78};/* * Calculate a new FCS given the current FCS and the new data. */static u_shortpppfcs(fcs, cp, len)    register u_short fcs;    register u_char *cp;    register int len;{    while (len--)	fcs = PPP_FCS(fcs, *cp++);    return (fcs);}/* * Queue a packet.  Start transmission if not active. * Packet is placed in Information field of PPP frame. */intpppoutput(ifp, m0, dst, rt)	struct ifnet *ifp;	struct mbuf *m0;	struct sockaddr *dst;	struct rtentry *rt;{    register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];    struct ppp_header *ph;    int protocol, address, control;    u_char *cp;    int s, error;    struct ip *ip;    struct ifqueue *ifq;    if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0	|| (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {	error = ENETDOWN;	/* sort of */	goto bad;    }    /*     * Compute PPP header.     */    address = PPP_ALLSTATIONS;    control = PPP_UI;    ifq = &ifp->if_snd;    switch (dst->sa_family) {#ifdef INET    case AF_INET:	protocol = PPP_IP;	if ((sc->sc_flags & SC_ENABLE_IP) == 0) {	    error = ENETDOWN;	    goto bad;	}	/*	 * If this is a TCP packet to or from an "interactive" port,	 * put the packet on the fastq instead.	 */	if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {	    register int p = ntohl(((int *)ip)[ip->ip_hl]);	    if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))		ifq = &sc->sc_fastq;	}      /*       * Most high-priority services set IPTOS_LOWDELAY.  This is a much more       * generic mechanism than specific port numbers.  This same mechanism       * is used by slip.       */      if (ip->ip_tos & IPTOS_LOWDELAY)          ifq = &sc->sc_fastq;	break;#endif#ifdef NS    case AF_NS:	protocol = PPP_XNS;	break;#endif    case AF_UNSPEC:	ph = (struct ppp_header *) dst->sa_data;	address = ph->ph_address;	control = ph->ph_control;	protocol = ntohs(ph->ph_protocol);	break;    default:	printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);	error = EAFNOSUPPORT;	goto bad;    }    /*     * Add PPP header.  If no space in first mbuf, allocate another.     * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)     */    if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {	m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);	if (m0 == 0) {	    error = ENOBUFS;	    goto bad;	}	m0->m_len = 0;    } else	m0->m_data -= PPP_HDRLEN;    cp = mtod(m0, u_char *);    *cp++ = address;    *cp++ = control;    *cp++ = protocol >> 8;    *cp++ = protocol & 0xff;    m0->m_len += PPP_HDRLEN;    if (sc->sc_flags & SC_LOG_OUTPKT) {	printf("ppp%d output: ", ifp->if_unit);	pppdumpm(m0, -1);    }#if NBPFILTER > 0    /* See if bpf wants to look at the packet. */    if (sc->sc_bpf)	bpf_mtap(sc->sc_bpf, m0);#endif    /*     * Put the packet on the appropriate queue.     */    s = splimp();    if (IF_QFULL(ifq)) {	IF_DROP(ifq);	splx(s);	sc->sc_if.if_oerrors++;	error = ENOBUFS;	goto bad;    }    IF_ENQUEUE(ifq, m0);    /*     * Tell the device to send it out.     */    (*sc->sc_start)(sc);    splx(s);    return (0);bad:    m_freem(m0);    return (error);}/* * Grab another packet off a queue and apply VJ compression, * address/control and/or protocol compression if appropriate. */struct mbuf *ppp_dequeue(sc)    struct ppp_softc *sc;{    int s;    struct mbuf *m;    u_char *cp;    int address, control, protocol;    s = splimp();    IF_DEQUEUE(&sc->sc_fastq, m);    if (m == NULL)	IF_DEQUEUE(&sc->sc_if.if_snd, m);    splx(s);    if (m == NULL)	return NULL;    /*     * Extract the ppp header of the new packet.     * The ppp header will be in one mbuf.     */    cp = mtod(m, u_char *);    address = cp[0];    control = cp[1];    protocol = (cp[2] << 8) + cp[3];#ifdef VJC    /*     * If the packet is a TCP/IP packet, see if we can compress it.     */    if (protocol == PPP_IP && sc->sc_flags & SC_COMP_TCP) {	struct ip *ip;	int type;	struct mbuf *mp;	mp = m;	ip = (struct ip *) (cp + PPP_HDRLEN);	if (mp->m_len <= PPP_HDRLEN) {	    mp = mp->m_next;	    ip = mtod(mp, struct ip *);	}	/* this code assumes the IP/TCP header is in one non-shared mbuf */	if (ip->ip_p == IPPROTO_TCP) {	    type = sl_compress_tcp(mp, ip, &sc->sc_comp,				   !(sc->sc_flags & SC_NO_TCP_CCID));	    switch (type) {	    case TYPE_UNCOMPRESSED_TCP:		protocol = PPP_VJC_UNCOMP;		break;	    case TYPE_COMPRESSED_TCP:		protocol = PPP_VJC_COMP;		cp = mtod(m, u_char *);		cp[0] = address;	/* header has moved */		cp[1] = control;		cp[2] = 0;		break;	    }	    cp[3] = protocol;	/* update protocol in PPP header */	}    }#endif	/* VJC */#ifdef BSD_COMP    if (protocol < PPP_COMP && (sc->sc_flags & SC_BSD_COMP)) {	slen = m_totallen(m0);	clen = pf_bsd_comp(sc->sc_bsd_db, cbuf, proto, m0, slen);    }#endif	/* BSD_COMP */    /*     * Compress the address/control and protocol, if possible.     */    if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&	control == PPP_UI && protocol != PPP_ALLSTATIONS &&	protocol != PPP_LCP) {	/* can compress address/control */	m->m_data += 2;	m->m_len -= 2;    }    if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {	/* can compress protocol */	if (mtod(m, u_char *) == cp) {	    cp[2] = cp[1];	/* move address/control up */	    cp[1] = cp[0];	}	++m->m_data;	--m->m_len;    }    return m;}/* * This gets called from pppoutput when a new packet is * put on a queue. */static intpppasyncstart(sc)    register struct ppp_softc *sc;{    register struct tty *tp = (struct tty *) sc->sc_devp;    pppstart(tp);    return 0;}/* * Start output on async tty interface.  Get another datagram * to send from the interface queue and start sending it. */intpppstart(tp)    register struct tty *tp;{    register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;    register struct mbuf *m;    register int len;    register u_char *start, *stop, *cp;    int n, s, ndone, done;    struct mbuf *m2;    if ((tp->t_state & TS_CONNECTED) == 0) {	/* sorry, I can't talk now */	return 0;    }    if (sc == NULL || tp != (struct tty *) sc->sc_devp) {	(*tp->t_oproc)(tp);	return 0;    }    for (;;) {	/*	 * Call output process whether or not there is any output.	 * We are being called in lieu of ttstart and must do what	 * it would.	 */	if (tp->t_oproc != NULL) {	    (*tp->t_oproc)(tp);	    if (CCOUNT(&tp->t_outq) > PPP_HIWAT)		return 0;	}	/*	 * See if we have an existing packet partly sent.	 * If not, get a new packet and start sending it.	 * We take packets on the priority queue ahead of those	 * on the normal queue.	 */	m = sc->sc_outm;	if (m == NULL) {	    /*	     * Get another packet to be sent	     */	    m = ppp_dequeue(sc);	    if (m == NULL)		return 0;	    /*	     * The extra PPP_FLAG will start up a new packet, and thus	     * will flush any accumulated garbage.  We do this whenever	     * the line may have been idle for some time.	     */	    if (CCOUNT(&tp->t_outq) == 0) {		++sc->sc_bytessent;		(void) putc(PPP_FLAG, &tp->t_outq);	    }	    /* Calculate the FCS for the first mbuf's worth. */	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);	}	for (;;) {	    start = mtod(m, u_char *);	    len = m->m_len;	    stop = start + len;	    while (len > 0) {		/*		 * Find out how many bytes in the string we can		 * handle without doing something special.		 */		for (cp = start; cp < stop; cp++)		    if (ESCAPE_P(*cp))			break;		n = cp - start;		if (n) {		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */		    ndone = n - b_to_q(start, n, &tp->t_outq);		    len -= ndone;		    start += ndone;		    sc->sc_bytessent += ndone;		    if (ndone < n)			break;	/* packet doesn't fit */		}		/*		 * If there are characters left in the mbuf,		 * the first one must be special..		 * Put it out in a different form.		 */		if (len) {		    if (putc(PPP_ESCAPE, &tp->t_outq))			break;		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {			(void) unputc(&tp->t_outq);			break;		    }		    sc->sc_bytessent += 2;		    start++;		    len--;		}	    }	    /*	     * If we didn't empty this mbuf, remember where we're up to.	     * If we emptied the last mbuf, try to add the FCS and closing	     * flag, and if we can't, leave sc_outm pointing to m, but with	     * m->m_len == 0, to remind us to output the FCS and flag later.	     */	    done = len == 0;	    if (done && m->m_next == NULL) {		u_char *p, *q;		int c;		u_char endseq[8];		/*		 * We may have to escape the bytes in the FCS.		 */		p = endseq;		c = ~sc->sc_outfcs & 0xFF;		if (ESCAPE_P(c)) {		    *p++ = PPP_ESCAPE;		    *p++ = c ^ PPP_TRANS;		} else		    *p++ = c;		c = (~sc->sc_outfcs >> 8) & 0xFF;		if (ESCAPE_P(c)) {		    *p++ = PPP_ESCAPE;		    *p++ = c ^ PPP_TRANS;		} else		    *p++ = c;		*p++ = PPP_FLAG;		/*		 * Try to output the FCS and flag.  If the bytes		 * don't all fit, back out.		 */		for (q = endseq; q < p; ++q)		    if (putc(*q, &tp->t_outq)) {			done = 0;			for (; q > endseq; --q)			    unputc(&tp->t_outq);			break;		    }	    }	    if (!done) {		m->m_data = start;		m->m_len = len;		sc->sc_outm = m;		if (tp->t_oproc != NULL)		    (*tp->t_oproc)(tp);		return 0;	/* can't do any more at the moment */	    }	    /* Finished with this mbuf; free it and move on. */	    MFREE(m, m2);	    if (m2 == NULL)		break;	    m = m2;	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);	}	/* Finished a packet */	sc->sc_outm = NULL;	sc->sc_bytessent++;	/* account for closing flag */	sc->sc_if.if_opackets++;	sc->sc_if.if_obytes = sc->sc_bytessent;    }    return 0;}/* * Allocate enough mbuf to handle current MRU. */static intpppgetm(sc)    register struct ppp_softc *sc;{    struct mbuf *m, **mp;    int len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN;    int s;    s = splimp();    for (mp = &sc->sc_m; (m = *mp) != NULL; mp = &m->m_next)	if ((len -= M_DATASIZE(m)) <= 0) {	    splx(s);	    return (1);	}    for (;; mp = &m->m_next) {	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == 0) {	    m_freem(sc->sc_m);	    sc->sc_m = NULL;	    splx(s);	    printf("ppp%d: can't allocate mbuf\n", sc->sc_if.if_unit);	    return (0);	}	*mp = m;	MCLGET(m, M_DONTWAIT);	if ((len -= M_DATASIZE(m)) <= 0) {	    splx(s);	    return (1);	}    }}/* * Copy mbuf chain.  Would like to use m_copy(), but we need a real copy * of the data, not just copies of pointers to the data. */static struct mbuf *

⌨️ 快捷键说明

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