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

📄 if_ppp.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 3 页
字号:
    struct ppp_softc *sc;{    int s;    NETBUF_T m;    u_char *cp;    int address, control, protocol;#if NS_TARGET >= 40    struct timeval tv_time;#endif    /*     * Grab a packet to send: first try the fast queue, then the     * normal queue.     */    m = nbq_dequeue(&sc->sc_fastq);    if (m == NULL)	m = nbq_dequeue(&sc->sc_slowq);    if (m == NULL)	return;    /*     * Extract the ppp header of the new packet.     * The ppp header will be in one netbuf.     */    cp = mtod(m, u_char *);    address = PPP_ADDRESS(cp);    control = PPP_CONTROL(cp);    protocol = PPP_PROTOCOL(cp);#if NS_TARGET >= 40	ns_time_to_timeval(clock_value(System), &tv_time);#endif /* NS_TARGET */    switch (protocol) {    case PPP_IP:	/*	 * Update the time we sent the most recent packet.	 */#if NS_TARGET >= 40	sc->sc_last_sent = tv_time.tv_sec;#else        sc->sc_last_sent = time.tv_sec;#endif /* NS_TARGET */#ifdef VJC	/*	 * If the packet is a TCP/IP packet, see if we can compress it.	 */	if (sc->sc_flags & SC_COMP_TCP) {	    struct ip *ip;	    int type;	    u_char *vjhdr;	    ip = (struct ip *) (cp + PPP_HDRLEN);	    /* this code assumes the IP/TCP header is in one netbuf */	    if (ip->ip_p == IPPROTO_TCP) {		type = vj_compress_tcp(ip, NB_SIZE(m) - PPP_HDRLEN,				       &sc->sc_comp,				       !(sc->sc_flags & SC_NO_TCP_CCID), &vjhdr);		switch (type) {		case TYPE_UNCOMPRESSED_TCP:		    protocol = PPP_VJC_UNCOMP;		    break;		case TYPE_COMPRESSED_TCP:		    NB_SHRINK_TOP(m, vjhdr - (u_char *) ip);		    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 */	break;#ifdef PPP_COMPRESS    case PPP_CCP:	ppp_ccp(sc, m, 0);	break;#endif	/* PPP_COMPRESS */    }#ifdef PPP_COMPRESS    if (protocol != PPP_LCP && protocol != PPP_CCP	&& sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {	NETBUF_T mcomp;	int slen, clen;	slen = NB_SIZE(m);	clen = (*sc->sc_xcomp->compress)	    (sc->sc_xc_state, &mcomp, m, slen,	     sc->sc_flags & SC_CCP_UP? if_mtu(sc->sc_if): 0);	if (mcomp && (NB_SIZE(mcomp) >= slen))	    IOLog("BSD Warning... packet growth: Orig=%d New=%d.\n",		  slen, NB_SIZE(mcomp));	if (mcomp != NULL) {	    NB_FREE(m);	    m = mcomp;	    cp = mtod(m, u_char *);	    protocol = cp[3];	}    }#endif	/* PPP_COMPRESS */    /*     * 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 */	NB_SHRINK_TOP(m, 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];	}	NB_SHRINK_TOP(m, 1);    }    s = splimp();    nbq_enqueue(&sc->sc_compq, m);    (*sc->sc_start)(sc);    splx(s);}#ifdef PPP_COMPRESS/* * Handle a CCP packet.  `rcvd' is 1 if the packet was received, * 0 if it is about to be transmitted. */static voidppp_ccp(sc, m, rcvd)    struct ppp_softc *sc;    NETBUF_T m;    int rcvd;{    u_char *dp, *ep;    int slen, s;    /*     * Get a pointer to the data after the PPP header.     */    dp = mtod(m, u_char *) + PPP_HDRLEN;    ep = mtod(m, u_char *) + NB_SIZE(m);    if (dp + CCP_HDRLEN > ep)	return;    slen = CCP_LENGTH(dp);    if (dp + slen > ep) {	IOLogDbg("ppp%d: ccp: not enough data in netbuf (%x+%x > %x+%x)\n",		 if_unit(sc->sc_if), dp, slen, mtod(m, u_char *), NB_SIZE(m));	return;    }    switch (CCP_CODE(dp)) {    case CCP_CONFREQ:    case CCP_TERMREQ:    case CCP_TERMACK:	/* CCP must be going down - disable compression */	if (sc->sc_flags & SC_CCP_UP) {	    s = splimp();	    sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);	    splx(s);	}	break;    case CCP_CONFACK:	if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)	    && slen >= CCP_HDRLEN + CCP_OPT_MINLEN	    && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {	    if (!rcvd) {		/* we're agreeing to send compressed packets. */		if (sc->sc_xc_state != NULL		    && (*sc->sc_xcomp->comp_init)			(sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,			 if_unit(sc->sc_if), 0, sc->sc_flags & SC_DEBUG)) {		    s = splimp();		    sc->sc_flags |= SC_COMP_RUN;		    splx(s);		}	    } else {		/* peer is agreeing to send compressed packets. */		if (sc->sc_rc_state != NULL		    && (*sc->sc_rcomp->decomp_init)			(sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,			 if_unit(sc->sc_if),#ifdef VJC			 VJ_HDRLEN +#endif			 0, sc->sc_mru, sc->sc_flags & SC_DEBUG)) {		    s = splimp();		    sc->sc_flags |= SC_DECOMP_RUN;		    sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);		    splx(s);		}	    }	}	break;    case CCP_RESETACK:	if (sc->sc_flags & SC_CCP_UP) {	    if (!rcvd) {		if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {		    (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);		    nbq_flush(&sc->sc_compq);  /* Flush pre-compressed packets */		  }	    } else {		if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {		    (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);		    s = splimp();		    sc->sc_flags &= ~SC_DC_ERROR;		    splx(s);		}	    }	}	break;    }}/* * CCP is down; free (de)compressor state if necessary. */static voidppp_ccp_closed(sc)    struct ppp_softc *sc;{    if (sc->sc_xc_state) {	(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);	sc->sc_xc_state = NULL;    }    if (sc->sc_rc_state) {	(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);	sc->sc_rc_state = NULL;    }}#endif /* PPP_COMPRESS *//* * PPP packet input routine. * The caller has checked and removed the FCS and has inserted * the address/control bytes and the protocol high byte if they * were omitted. */voidppppktin(sc, m, lost)    struct ppp_softc *sc;    NETBUF_T m;    int lost;{  int error, s = splimp();    NB_SET_MARK(m,(lost ? M_ERRMARK : 0));    /* XXX - we should check for the raw queue overflowing... */  nbq_enqueue(&sc->sc_rawq, m);  if (!sc->sc_decompsched)    {      if ((error = pppsched(pppintr_decomp, sc)) == KERN_SUCCESS)	sc->sc_decompsched = 1;      else	IOLogDbg("ppp%d: decompression callout failed returning %d\n",		 if_unit(sc->sc_if), error);    }    splx(s);}/* * Process a received PPP packet, doing decompression as necessary. */#define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \			 TYPE_UNCOMPRESSED_TCP)static voidppp_inproc(sc, m)    struct ppp_softc *sc;    NETBUF_T m;{    struct nb_queue *inq;    int s, ilen, xlen, proto, rv;    mark_t flags;    u_char *cp, adrs, ctrl;    NETBUF_T dmp;    u_char *iphdr;    u_int hlen;#if NS_TARGET >= 40    struct timeval tv_time;#endif /* NS_TARGET */    incr_cnt(sc->sc_if, if_ipackets);    NB_GET_MARK(m,&flags);    if (sc->sc_flags & SC_LOG_INPKT) {	IOLog("ppp%d: got %d bytes\n", if_unit(sc->sc_if), NB_SIZE(m));	pppdumpm(m);    }    cp = mtod(m, u_char *);    adrs = PPP_ADDRESS(cp);    ctrl = PPP_CONTROL(cp);    proto = PPP_PROTOCOL(cp);    if (flags & M_ERRMARK) {	s = splimp();	sc->sc_flags |= SC_VJ_RESET;	splx(s);    }#ifdef PPP_COMPRESS    /*     * Decompress this packet if necessary, update the receiver's     * dictionary, or take appropriate action on a CCP packet.     */    if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)	&& !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {	/* decompress this packet */	rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);	if (rv == DECOMP_OK){	  NB_FREE(m);	  if (dmp == NULL){	    /* No error, but no decompressed packet returned */	    return;	  }	    m = dmp;	    cp = mtod(m, u_char *);	    proto = PPP_PROTOCOL(cp);	} else {	    /*	     * An error has occurred in decompression.	     * Pass the compressed packet up to pppd, which may take	     * CCP down or issue a Reset-Req.	     */	    IOLogDbg("ppp%d: decompress failed %d\n", if_unit(sc->sc_if), rv);	    s = splimp();	    sc->sc_flags |= SC_VJ_RESET;	    if (rv == DECOMP_ERROR)	      sc->sc_flags |= SC_DC_ERROR;	    else	      sc->sc_flags |= SC_DC_FERROR;	    splx(s);	}    } else {	if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN))	  {	    (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);	}	if (proto == PPP_CCP) {	    ppp_ccp(sc, m, 1);	}    }#endif    ilen = NB_SIZE(m);#ifdef VJC    if (sc->sc_flags & SC_VJ_RESET) {	/*	 * If we've missed a packet, we must toss subsequent compressed	 * packets which don't have an explicit connection ID.	 *//*	IOLog("SC_VJ_RESET was set!\n"); */	vj_uncompress_err(&sc->sc_comp);	s = splimp();	sc->sc_flags &= ~SC_VJ_RESET;	splx(s);    }    /*     * See if we have a VJ-compressed packet to uncompress.     */    if (proto == PPP_VJC_COMP) {	if (sc->sc_flags & SC_REJ_COMP_TCP)	    goto bad;	xlen = vj_uncompress_tcp(cp + PPP_HDRLEN, ilen - PPP_HDRLEN,				 ilen - PPP_HDRLEN,				 &sc->sc_comp, &iphdr, &hlen);	if (xlen <= 0) {/*   IOLogDbg("ppp%d: VJ uncompress failed on type comp\n", 			if_unit(sc->sc_if));*/	    goto bad;	}	/*	 * Write the IP/TCP header back into the datagram.	 * The pointers point to the stored copy in the VJ	 * compression table.	 */   	NB_GROW_TOP(m, hlen - xlen);	NB_WRITE(m, PPP_HDRLEN, hlen, iphdr);	cp = mtod(m, u_char *);#ifdef TCP_CHECKSUM    {#define getip_hl(base)	((base).ip_hl)      u_short mytcpcksum (struct ip *pip);      struct tcphdr *ptcp;      struct ip *iphdr;      u_short thecksum;      u_long hlen;      iphdr = (struct ip*) (cp + PPP_HDRLEN);      hlen = getip_hl(*iphdr) << 2;  /* Length is in words */      ptcp = (struct tcphdr *)&((u_char *)iphdr)[hlen];      thecksum = (u_short)mytcpcksum(iphdr);      if(ptcp->th_sum != thecksum)	{#ifdef NEWVJ_RESYNC	  set_newvj_error_mode();#endif	  IOLog("NEWVJ: Warning... TCP checksum failed Received=%u, Calculated=%u)\n",		(ptcp->th_sum)&0xffff, thecksum&0xffff);	}    }	    	    #endif	cp[0] = adrs;	cp[1] = ctrl;	cp[2] = 0;	cp[3] = PPP_IP;	proto = PPP_IP;	ilen += hlen - xlen;    } else if (proto == PPP_VJC_UNCOMP) {	if (sc->sc_flags & SC_REJ_COMP_TCP)	    goto bad;	vj_uncompress_uncomp(cp + PPP_HDRLEN, ilen-PPP_HDRLEN, &sc->sc_comp);	proto = PPP_IP;	cp[3] = PPP_IP;    }#endif /* VJC */    rv = 0;    switch (proto) {#ifdef INET    case PPP_IP:	/*	 * IP packet - take off the ppp header and pass it up to IP.	 */	if ((if_flags(sc->sc_if) & IFF_UP) == 0	    || sc->sc_npmode[NP_IP] != NPMODE_PASS) {	    /* interface is down - drop the packet. */	    NB_FREE(m);	    IOLogDbg("ppp%d: IP packed dropped (NPmode)\n", if_unit(sc->sc_if));	    return;	}	NB_SHRINK_TOP(m, PPP_HDRLEN);	inet_queue(sc->sc_if, NB_TO_nb(m));#if NS_TARGET >= 40	/*  I am assuming the time is different here than above. */	ns_time_to_timeval(clock_value(System), &tv_time);	sc->sc_last_recv = tv_time.tv_sec; /* update time of last pkt rcvd */#else	sc->sc_last_recv = time.tv_sec; /* update time of last pkt rcvd */#endif	return;#endif    default:	/*	 * Some other protocol - place on input queue for read().	 */	inq = &sc->sc_inq;	rv = 1;	break;    }    /*     * Put the packet on the appropriate input queue.     */    s = splimp();    if (nbq_full(inq)) {	nbq_drop(inq);	splx(s);	IOLog("ppp%d: input queue full\n", if_unit(sc->sc_if));	goto bad;    }    nbq_enqueue(inq, m);    splx(s);    if (rv)	(*sc->sc_ctlp)(sc);    return; bad:    NB_FREE(m);    incr_cnt(sc->sc_if, if_ierrors);}#define MAX_DUMP_BYTES	128static voidpppdumpm(m0)    NETBUF_T m0;{    char buf[3*MAX_DUMP_BYTES+4];    char *bp = buf;    static char digits[] = "0123456789abcdef";    int l = NB_SIZE(m0);    u_char *rptr = mtod(m0, u_char *);    while (l--) {	if (bp > buf + sizeof(buf) - 4)	    goto done;	*bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */	*bp++ = digits[*rptr++ & 0xf];    }    *bp++ = ' ';done:    if (l)	*bp++ = '>';    *bp = 0;    IOLog("%s\n", buf);}

⌨️ 快捷键说明

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