📄 if_ppp.c
字号:
*/ ioctl(fd, FIONWRITE, (int) &count); if (count == 0) { ++sc->sc_bytessent; ch = PPP_FLAG; (void) write(fd, &ch, 1); } /* 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) { int cc, nleft; for (nleft = n; nleft > 0; nleft -= cc) { if ((cc = write(fd, (char *)start, n)) <= 0) break; if (cc > nleft) cc = nleft; } ndone = n - nleft; 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) { ch = PPP_ESCAPE; if (write(fd, &ch, 1) != 1) break; ch = *start ^ PPP_TRANS; if (write(fd, &ch, 1) != 1) 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; 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. */ write(fd, (char *)endseq, (int)p-(int)endseq); } if (!done) { m->m_data = (caddr_t)start; m->m_len = len; sc->sc_outm = m; break; /* can't do any more at the moment */ } /* Finished with this mbuf; free it and move on. */ m2 = m_free (m); 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; } }}/* * Allocate enough mbuf to handle current MRU. */static intpppgetm(sc) register struct ppp_softc *sc;{ struct mbuf *m, **mp; int len; int s; s = splimp(); mp = &sc->sc_m; for (len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){ if ((m = *mp) == NULL) { m = mHdrClGet (M_DONTWAIT, MT_DATA, len, FALSE); if (m == NULL) break; *mp = m; } len -= M_DATASIZE(m); mp = &m->m_next; } splx(s); return len <= 0;}/* * pppintr - PPP tty protocol hook routine */static intpppintr(unit, c) int unit; int c;{ register struct ppp_softc *sc = ppp_softc[unit]; TY_DEV * pTyDev; RING_ID ringId; if (ppp_softc[unit] == NULL) return FALSE; /* Set discard flag if this is a new packet and ring buffer full */ if ( sc->sc_qlen == 0 ) { pTyDev = (TY_DEV *) iosFdDevFind(sc->sc_fd); ringId = pTyDev->rdBuf; if (rngIsFull (ringId)) sc->sc_flags |= SC_DISCARD_PKT; else sc->sc_flags &= ~SC_DISCARD_PKT; } ++sc->sc_qlen; if (sc->sc_qlen > PPPBUFSIZE) { netJobAdd((FUNCPTR) ppp_tty_read, (int)unit, (int) sc, (int) sc->sc_qlen, 0, 0); sc->sc_qlen = 0; return (FALSE); } if (((ppp_if[unit]->lcp_fsm.state) != OPENED) && ((c & 0xff) == 'T')) { netJobAdd((FUNCPTR) ppp_tty_read, (int)unit, (int) sc, (int) sc->sc_qlen, 0, 0); return (FALSE); } if ((c & 0xff) == PPP_FLAG) { netJobAdd((FUNCPTR) ppp_tty_read, (int)unit, (int) sc, (int) sc->sc_qlen, 0, 0); sc->sc_qlen = 0; } return (FALSE);}/* * ppp_tty_read - read from ppp tty interface */static voidppp_tty_read(unit, sc, count) int unit; register struct ppp_softc *sc; register int count;{ register int i; register int num; char buf[PPPBUFSIZE + 2]; /* count should never be greater than PPPBUFSIZE+1 */ num = read(sc->sc_fd, buf, count); if (count > PPPBUFSIZE) { /* The received packet is greater than the MTU - Drop the packet */ sc->sc_if.if_ierrors++; return; } if ((ppp_if[unit]->lcp_fsm.state) != OPENED) { if (strncmp("CLIENT", buf, strlen("CLIENT") )==0) { sc->sc_qlen = 0; write(sc->sc_fd, "CLIENTSERVER", strlen("CLIENTSERVER")); return; } } if (sc->sc_flags & SC_DISCARD_PKT) { /* Packet discarded */ sc->sc_if.if_ierrors++; sc->sc_flags &= ~SC_DISCARD_PKT; return; } for (i = 0; i < num; i++) pppinput(sc, buf[i]);}/* * PPP packet input routine. * The caller has checked and removed the FCS. * The return value is 1 if the packet was put on sc->sc_inq, * 0 otherwise. */#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ TYPE_UNCOMPRESSED_TCP)/******************************************************************************** ppppktin - pass the packet to the appropriate stack LCP or IP* * This routine determines packet type and queues the mbuf to the appropriate* queue. This routine returns a value of 1 if the packet type is other than* PPP_IP.** NOMANUAL** RETURNS: 0/1*/static intppppktin(sc, m) struct ppp_softc *sc; struct mbuf *m;{ struct ifqueue *inq; int s, ilen, xlen, proto, rv; u_char *cp, adrs, ctrl; struct mbuf *mp; char buf[PPPBUFSIZE]; sc->sc_if.if_ipackets++; sc->sc_if.if_lastchange = tickGet (); /* record the last change */ rv = 0; cp = mtod(m, u_char *); adrs = cp[0]; ctrl = cp[1]; proto = (cp[2] << 8) + cp[3]; ilen = 0; for (mp = m; mp != NULL; mp = mp->m_next) ilen += mp->m_len;#ifdef VJC /* * See if we have a VJ-compressed packet to uncompress. */ if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) { char *pkttype = proto == PPP_VJC_COMP? "": "un"; if (sc->sc_flags & SC_REJ_COMP_TCP) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n", sc->sc_if.if_unit, pkttype, sc->sc_flags); m_freem(m); sc->sc_if.if_ierrors++; return 0; } if (proto == PPP_VJC_COMP && m->m_data - M_DATASTART(m) < MAX_HDR) { /* * We don't have room in the mbuf to decompress this packet. * XXX For now we just drop the packet. */ if (sc->sc_flags & SC_DEBUG) printf("ppp%d: no room to VJ-decompress packet\n", sc->sc_if.if_unit); m_freem(m); sc->sc_if.if_ierrors++; return 0; } m->m_data += PPP_HDRLEN; m->m_len -= PPP_HDRLEN; ilen -= PPP_HDRLEN; xlen = sl_uncompress_tcp((u_char **)(&m->m_data), m->m_len, COMPTYPE(proto), &sc->sc_comp); if (xlen == 0) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: sl_uncompress failed on type %scomp\n", sc->sc_if.if_unit, pkttype); m_freem(m); sc->sc_if.if_ierrors++; return 0; } /* adjust the first mbuf by the decompressed amt */ xlen += PPP_HDRLEN; m->m_len += xlen - ilen; ilen = xlen; m->m_data -= PPP_HDRLEN; proto = PPP_IP; /* put the ppp header back in place */ if (cp != mtod(m, u_char *)) { cp = mtod(m, u_char *); cp[0] = adrs; cp[1] = ctrl; cp[2] = 0; } cp[3] = PPP_IP; }#endif /* VJC */ /* * If the packet will fit in a header mbuf, don't waste a * whole cluster on it. */ m->m_pkthdr.len = ilen; m->m_pkthdr.rcvif = &sc->sc_if;#if NBPFILTER > 0 /* See if bpf wants to look at the packet. */ if (sc->sc_bpf) bpf_mtap(sc->sc_bpf, m);#endif /* call etherInputHookRtn here */ if (etherInputHookRtn != NULL) { FAST char *p = (char *) buf; for (mp = m; mp != NULL; p += mp->m_len, mp = mp->m_next) bcopy(mtod (mp, char *), p, mp->m_len); if ((*etherInputHookRtn) (&sc->sc_if, buf, ilen) != 0) { m_freem (m); /* free mbuf, not handed to the upperlayer */ return (OK); } } switch (proto) {#ifdef INET case PPP_IP: /* * IP packet - take off the ppp header and pass it up to IP. */ if ((sc->sc_if.if_flags & IFF_UP) == 0 || (sc->sc_flags & SC_ENABLE_IP) == 0) { /* interface is down - drop the packet. */ m_freem(m); return 0; } m->m_pkthdr.len -= PPP_HDRLEN; m->m_data += PPP_HDRLEN; m->m_len -= PPP_HDRLEN; inq = &ipintrq; break;#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 (IF_QFULL(inq)) { IF_DROP(inq); if (sc->sc_flags & SC_DEBUG) printf("ppp%d: queue full\n", sc->sc_if.if_unit); sc->sc_if.if_ierrors++; sc->sc_if.if_iqdrops++; m_freem(m); rv = 0; } else{ IF_ENQUEUE(inq, m); if (proto == PPP_IP) { sc->sc_iprcvd++; /* incr ip packets received */ ipintr(); } else kill(sc->sc_tid, SIGIO); /* give to alternate processing */ } splx(s); return rv;}/* * tty interface receiver interrupt. */static unsigned paritytab[8] = { 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x96696996, 0x69969669};static voidpppinput(sc, c) struct ppp_softc *sc; register int c;{ struct mbuf *m; int ilen; ++sc->sc_bytesrcvd; c &= 0xff; if (c & 0x80) sc->sc_flags |= SC_RCV_B7_1; else sc->sc_flags |= SC_RCV_B7_0; if (paritytab[c >> 5] & (1 << (c & 0x1F))) sc->sc_flags |= SC_RCV_ODDP; else sc->sc_flags |= SC_RCV_EVNP; if (sc->sc_flags & SC_LOG_RAWIN) ppplogchar(sc, c); if (c == PPP_FLAG) { ilen = sc->sc_ilen; sc->sc_ilen = 0; sc->sc_if.if_ibytes = sc->sc_bytesrcvd; if (sc->sc_rawin_count > 0) ppplogchar(sc, -1); /* * If SC_ESCAPED is set, then we've seen the packet * abort sequence "}~". */ if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED) || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {#ifdef VJC /* * If we've missed a packet, we must toss subsequent compressed * packets which don't have an explicit connection ID. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -