📄 if_ppp.c
字号:
ppp_btom(sc) struct ppp_softc *sc;{ register struct mbuf *m, **mp; struct mbuf *top = sc->sc_m; /* * First check current mbuf. If we have more than a small mbuf, * return the whole cluster and set beginning of buffer to the * next mbuf. * Else, copy the current bytes into a small mbuf, attach the new * mbuf to the end of the chain and set beginning of buffer to the * current mbuf. */ if (sc->sc_mc->m_len > MHLEN) { sc->sc_m = sc->sc_mc->m_next; sc->sc_mc->m_next = NULL; } else { /* rather than waste a whole cluster on <= MHLEN bytes, alloc a small mbuf and copy to it */ MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return (NULL); bcopy(mtod(sc->sc_mc, caddr_t), mtod(m, caddr_t), sc->sc_mc->m_len); m->m_len = sc->sc_mc->m_len; for (mp = ⊤ *mp != sc->sc_mc; mp = &(*mp)->m_next) ; *mp = m; sc->sc_m = sc->sc_mc; } /* * Try to allocate enough extra mbufs to handle the next packet. */ if (pppgetm(sc) == 0) { m_freem(top); if (pppgetm(sc) == 0) { sc->sc_if.if_flags &= ~IFF_UP; microtime(&sc->sc_if.if_lastchange); } return (NULL); } return (top);}/* * 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)intppppktin(sc, m, ilen) struct ppp_softc *sc; struct mbuf *m; int ilen;{ struct ifqueue *inq; int s, xlen, proto, rv; struct ppp_header hdr; sc->sc_if.if_ipackets++; rv = 0; hdr = *mtod(m, struct ppp_header *); proto = ntohs(hdr.ph_protocol);#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); sc->sc_if.if_ierrors++; return 0; } m->m_data += PPP_HDRLEN; m->m_len -= PPP_HDRLEN; ilen -= PPP_HDRLEN; xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data), m->m_len, ilen, 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); 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 */ hdr.ph_protocol = htons(PPP_IP); *mtod(m, struct ppp_header *) = hdr; }#endif /* VJC */ /* get this packet as an mbuf chain */ if ((m = ppp_btom(sc)) == NULL) { sc->sc_if.if_ierrors++; return 0; } 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 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; schednetisr(NETISR_IP); 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); splx(s); return rv;}/* * tty interface receiver interrupt. */static unsigned paritytab[8] = { 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x96696996, 0x69969669};intpppinput(c, tp) int c; register struct tty *tp;{ register struct ppp_softc *sc; struct mbuf *m; int ilen; tk_nin++; sc = (struct ppp_softc *) tp->t_sc; if (sc == NULL || tp != (struct tty *) sc->sc_devp) return 0; ++sc->sc_bytesrcvd; if ((tp->t_state & TS_CONNECTED) == 0) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: no carrier\n", sc->sc_if.if_unit); goto flush; } if (c & TTY_ERRORMASK) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: line error %x\n", sc->sc_if.if_unit, c & TTY_ERRORMASK); goto flush; } c &= TTY_CHARMASK; 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. */ 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\n", sc->sc_if.if_unit); sc->sc_if.if_ierrors++; } else sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); return 0; } 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 0; } /* * 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--; m = sc->sc_m; if (sc->sc_flags & SC_LOG_INPKT) { printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen); pppdumpm(m, ilen); } if (ppppktin(sc, m, ilen)) { /* Put a placeholder byte in canq for ttselect()/ttnread(). */ putc(0, &tp->t_canq); ttwakeup(tp); } return 0; } if (sc->sc_flags & SC_FLUSH) { if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); return 0; } if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) return 0; 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 0; } /* * 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 */ m = sc->sc_m; m->m_len = 0; m->m_data = M_DATASTART(sc->sc_m) + HDROFF; 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) { sc->sc_mc = m = m->m_next; if (m == NULL) { printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit); goto flush; } 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 0; 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); } return 0;}/* * Process an ioctl request to interface. */intpppioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ struct proc *p = curproc; /* XXX */ register struct ppp_softc *sc = &ppp_softc[ifp->if_unit]; register struct ifaddr *ifa = (struct ifaddr *)data; register struct ifreq *ifr = (struct ifreq *)data; int s = splimp(), error = 0; switch (cmd) { 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_addr->sa_family != AF_INET) error = EAFNOSUPPORT; break; case SIOCSIFMTU: if (error = suser(p->p_ucred, &p->p_acflag)) return (error); if (ifr->ifr_mtu > PPP_MAXMTU) error = EINVAL; else { struct tty *tp; sc->sc_if.if_mtu = ifr->ifr_mtu; tp = (struct tty *) sc->sc_devp; if (tp != NULL) clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT, sc->sc_if.if_mtu + PPP_HIWAT); } break; case SIOCGIFMTU: ifr->ifr_mtu = sc->sc_if.if_mtu; break; case SIOCADDMULTI: case SIOCDELMULTI: switch(ifr->ifr_addr.sa_family) {#ifdef INET case AF_INET: break;#endif default: error = EAFNOSUPPORT; break; } 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 = (u_char *)m->m_data; 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);}PSEUDO_SET(pppattach, if_ppp);#endif /* NPPP > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -