📄 if_ppp.c
字号:
* 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. */ sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);#endif if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){ if (sc->sc_flags & SC_DEBUG) printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit, sc->sc_fcs); sc->sc_if.if_ierrors++; } else sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); return; } if (ilen < PPP_HDRLEN + PPP_FCSLEN) { if (ilen) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen); sc->sc_if.if_ierrors++; } return; } /* * Remove FCS trailer. Somewhat painful... */ ilen -= 2; if (--sc->sc_mc->m_len == 0) { for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next) ; sc->sc_mc = m; } sc->sc_mc->m_len--; /* excise this mbuf chain */ m = sc->sc_m; sc->sc_m = sc->sc_mc->m_next; sc->sc_mc->m_next = NULL; if (sc->sc_flags & SC_LOG_INPKT) { printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen); pppdumpm(m, ilen); } ppppktin(sc, m); /* handover packet to upper layer */ pppgetm(sc); return; } if (sc->sc_flags & SC_FLUSH) { if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); return; } if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) return; if (sc->sc_flags & SC_ESCAPED) { sc->sc_flags &= ~SC_ESCAPED; c ^= PPP_TRANS; } else if (c == PPP_ESCAPE) { sc->sc_flags |= SC_ESCAPED; return; } /* * Initialize buffer on first octet received. * First octet could be address or protocol (when compressing * address/control). * Second octet is control. * Third octet is first or second (when compressing protocol) * octet of protocol. * Fourth octet is second octet of protocol. */ if (sc->sc_ilen == 0) { /* reset the first input mbuf */ if (sc->sc_m == NULL) { pppgetm(sc); if (sc->sc_m == NULL) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit); goto flush; } } m = sc->sc_m; m->m_len = 0; m->m_data = M_DATASTART(sc->sc_m); if (M_DATASIZE(sc->sc_m) >= HDROFF + PPP_HDRLEN) m->m_data += HDROFF; /* allow room for VJ decompression */ sc->sc_mc = m; sc->sc_mp = mtod(m, char *); sc->sc_fcs = PPP_INITFCS; if (c != PPP_ALLSTATIONS) { if (sc->sc_flags & SC_REJ_COMP_AC) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: garbage received: 0x%x (need 0xFF)\n", sc->sc_if.if_unit, c); goto flush; } *sc->sc_mp++ = PPP_ALLSTATIONS; *sc->sc_mp++ = PPP_UI; sc->sc_ilen += 2; m->m_len += 2; } } if (sc->sc_ilen == 1 && c != PPP_UI) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: missing UI (0x3), got 0x%x\n", sc->sc_if.if_unit, c); goto flush; } if (sc->sc_ilen == 2 && (c & 1) == 1) { /* a compressed protocol */ *sc->sc_mp++ = 0; sc->sc_ilen++; sc->sc_mc->m_len++; } if (sc->sc_ilen == 3 && (c & 1) == 0) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit, (sc->sc_mp[-1] << 8) + c); goto flush; } /* packet beyond configured mru? */ if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: packet too big\n", sc->sc_if.if_unit); goto flush; } /* is this mbuf full? */ m = sc->sc_mc; if (M_TRAILINGSPACE(m) <= 0) { if (m->m_next == NULL) { pppgetm(sc); if (m->m_next == NULL) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit); goto flush; } } sc->sc_mc = m = m->m_next; m->m_len = 0; m->m_data = M_DATASTART(m); sc->sc_mp = mtod(m, char *); } ++m->m_len; *sc->sc_mp++ = c; sc->sc_fcs = PPP_FCS(sc->sc_fcs, c); return; flush: if (!(sc->sc_flags & SC_FLUSH)) { sc->sc_if.if_ierrors++; sc->sc_flags |= SC_FLUSH; if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); }}/* * Process an ioctl request to interface. */static intpppioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ register struct ppp_softc *sc = ppp_softc[ifp->if_unit]; register struct ifaddr *ifa = (struct ifaddr *)data; register struct ifreq *ifr = (struct ifreq *)data; register M2_NETDRVCNFG *pm2DrvCnfg = (M2_NETDRVCNFG *)data; register M2_NETDRVCNTRS *pm2DrvCntr = (M2_NETDRVCNTRS *)data; int s = splimp(), error = 0; switch (cmd) { case SIOCGIFFLAGS: *(short *)data = ifp->if_flags; break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_RUNNING) == 0) ifp->if_flags &= ~IFF_UP; break; case SIOCSIFADDR: if (ifa->ifa_addr->sa_family != AF_INET) error = EAFNOSUPPORT; break; case SIOCSIFDSTADDR: if (ifa->ifa_dstaddr->sa_family != AF_INET) error = EAFNOSUPPORT; break; case SIOCSIFMTU: sc->sc_if.if_mtu = ifr->ifr_mtu; break; case SIOCGIFMTU: ifr->ifr_mtu = sc->sc_if.if_mtu; break; case SIOCADDMULTI: case SIOCDELMULTI: if (ifr == 0) { error = EAFNOSUPPORT; break; } switch(ifr->ifr_addr.sa_family) {#ifdef INET case AF_INET: break;#endif default: error = EAFNOSUPPORT; break; } break; case SIOCGMIB2CNFG: pm2DrvCnfg->ifType = M2_ifType_ppp; /* ppp type */ pm2DrvCnfg->ifSpecific.idLength = 0; /* use default */ break; case SIOCGMIB2CNTRS: /* fill in counters */ pm2DrvCntr->ifInOctets = sc->sc_bytesrcvd; pm2DrvCntr->ifInNUcastPkts = 0; pm2DrvCntr->ifInDiscards = 0; pm2DrvCntr->ifInUnknownProtos = ppp_if[ppp_unit]->unknownProto; pm2DrvCntr->ifOutOctets = sc->sc_bytessent; pm2DrvCntr->ifOutNUcastPkts = 0; pm2DrvCntr->ifOutDiscards = 0; if ((pm2DrvCntr->ifSpeed = ppp_if[ppp_unit]->baud_rate) == 0) pm2DrvCntr->ifSpeed = 9600; /* nominal default */ break; default: error = EINVAL; } splx(s); return (error);}#define MAX_DUMP_BYTES 128static voidpppdumpm(m0, pktlen) struct mbuf *m0; int pktlen;{ char buf [3*MAX_DUMP_BYTES+4]; char *bp = buf; struct mbuf *m; static char digits [] = "0123456789abcdef"; for (m = m0; m && pktlen; m = m->m_next) { int l = m->m_len; u_char *rptr = mtod(m, u_char *); if (pktlen > 0) { if (l > pktlen) l = pktlen; pktlen -= l; } while (l--) { if (bp > buf + sizeof(buf) - 4) goto done; *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ *bp++ = digits[*rptr++ & 0xf]; } if (m->m_next) { if (bp > buf + sizeof(buf) - 3) goto done; *bp++ = '|'; } else *bp++ = ' '; }done: if (m && pktlen) *bp++ = '>'; *bp = 0; printf("%s\n", buf);}static voidppplogchar(sc, c) struct ppp_softc *sc; int c;{ if (c >= 0) sc->sc_rawin[sc->sc_rawin_count++] = c; if (sc->sc_rawin_count >= sizeof(sc->sc_rawin) || (c < 0 && sc->sc_rawin_count > 0)) { printf("ppp%d input: ", sc->sc_if.if_unit); pppdumpb(sc->sc_rawin, sc->sc_rawin_count); sc->sc_rawin_count = 0; }}static voidpppdumpb(b, l) u_char *b; int l;{ char buf [3*MAX_DUMP_BYTES+4]; char *bp = buf; static char digits[] = "0123456789abcdef"; while (l--) { if (bp >= buf + sizeof (buf) - 3) { *bp++ = '>'; break; } *bp++ = digits [*b >> 4]; /* convert byte to ascii hex */ *bp++ = digits [*b++ & 0xf]; *bp++ = ' '; } *bp = 0; printf("%s\n", buf);}/* * Flush write output on the interface. */static voidppp_wrt_flush(sc) register struct ppp_softc *sc;{ register struct mbuf *m; register int len; register u_char *start, *stop, *cp; int n, ndone, done; struct mbuf *m2; int count, fd; char ch; fd = sc->sc_fd; for (;;) { /* * 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) break; /* * 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. */ 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++; }}#endif /* NPPP > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -