X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=ultrix%2Fif_ppp.c;h=d93f5d3e8c6c8f407d8795911cff812d9b4a21cf;hp=f8d8058680c4662333244d190631801d3b89ae4a;hb=afc91a00dd17734d3076c083b18f2535b96d2133;hpb=cc9cdaef42f38bd22700c2bea8368afcd05b305d diff --git a/ultrix/if_ppp.c b/ultrix/if_ppp.c index f8d8058..d93f5d3 100644 --- a/ultrix/if_ppp.c +++ b/ultrix/if_ppp.c @@ -72,8 +72,9 @@ * Robert Olsson and Paul Mackerras. */ -/* $Id: if_ppp.c,v 1.2 1994/11/21 04:50:36 paulus Exp $ */ +/* $Id: if_ppp.c,v 1.13 1997/03/04 03:45:17 paulus Exp $ */ /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ +/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ #include "ppp.h" #if NPPP > 0 @@ -89,6 +90,7 @@ #include "../h/socket.h" #include "../h/ioctl.h" #include "../h/systm.h" +#include "../h/time.h" #include "../net/net/if.h" #include "../net/net/netisr.h" @@ -101,6 +103,10 @@ #include "../net/netinet/ip.h" #endif +#ifdef vax +#include "../machine/mtpr.h" +#endif + #ifdef VJC #include "slcompress.h" #endif @@ -114,16 +120,11 @@ #include "ppp-comp.h" #endif -void pppattach __P((void)); -int pppioctl __P((struct ppp_softc *sc, int cmd, caddr_t data, int flag, - struct proc *)); -int pppoutput __P((struct ifnet *ifp, struct mbuf *m0, - struct sockaddr *dst)); -int pppsioctl __P((struct ifnet *ifp, int cmd, caddr_t data)); -void pppintr __P((void)); - +static int pppsioctl(struct ifnet *, int, caddr_t); +static int pppoutput(struct ifnet *, struct mbuf *, struct sockaddr *); +static void ppp_requeue __P((struct ppp_softc *)); static void ppp_outpkt __P((struct ppp_softc *)); -static int ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd)); +static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd)); static void ppp_ccp_closed __P((struct ppp_softc *)); static void ppp_inproc __P((struct ppp_softc *, struct mbuf *)); static void pppdumpm __P((struct mbuf *m0)); @@ -161,13 +162,20 @@ static u_short interactive_ports[8] = { */ extern struct compressor ppp_bsd_compress; +extern struct compressor ppp_deflate; struct compressor *ppp_compressors[] = { +#if DO_BSD_COMPRESS &ppp_bsd_compress, +#endif +#if DO_DEFLATE + &ppp_deflate, +#endif NULL }; #endif /* PPP_COMPRESS */ + /* * Called from boot code to establish ppp interfaces. */ @@ -209,19 +217,23 @@ pppalloc(pid) for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) if (sc->sc_xfer == pid) { sc->sc_xfer = 0; - break; + return sc; } - if (nppp >= NPPP) - for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) - if (sc->sc_devp == NULL) - break; + for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) + if (sc->sc_devp == NULL) + break; if (nppp >= NPPP) return NULL; sc->sc_flags = 0; sc->sc_mru = PPP_MRU; + sc->sc_relinq = NULL; + bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats)); #ifdef VJC - sl_compress_init(&sc->sc_comp); + KM_ALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress), + KM_DEVBUF, KM_NOARG); + if (sc->sc_comp) + sl_compress_init(sc->sc_comp); #endif #ifdef PPP_COMPRESS sc->sc_xc_state = NULL; @@ -229,13 +241,15 @@ pppalloc(pid) #endif /* PPP_COMPRESS */ for (i = 0; i < NUM_NP; ++i) sc->sc_npmode[i] = NPMODE_ERROR; - sc->sc_if.if_flags |= IFF_RUNNING; + sc->sc_npqueue = NULL; + sc->sc_npqtail = &sc->sc_npqueue; + sc->sc_last_sent = sc->sc_last_recv = time.tv_sec; return sc; } /* - * Deallocate a ppp unit. + * Deallocate a ppp unit. Must be called at splnet or higher. */ void pppdealloc(sc) @@ -265,6 +279,10 @@ pppdealloc(sc) break; m_freem(m); } + while ((m = sc->sc_npqueue) != NULL) { + sc->sc_npqueue = m->m_act; + m_freem(m); + } if (sc->sc_togo != NULL) { m_freem(sc->sc_togo); sc->sc_togo = NULL; @@ -274,6 +292,12 @@ pppdealloc(sc) sc->sc_xc_state = NULL; sc->sc_rc_state = NULL; #endif /* PPP_COMPRESS */ +#ifdef VJC + if (sc->sc_comp != 0) { + KM_FREE(sc->sc_comp, KM_DEVBUF); + sc->sc_comp = 0; + } +#endif } /* @@ -286,11 +310,14 @@ pppioctl(sc, cmd, data, flag) int cmd, flag; { struct proc *p = u.u_procp; - int s, error, flags, mru, nb, npx; + int s, error, flags, mru, mtu, nb, npx; struct ppp_option_data *odp; struct compressor **cp; struct npioctl *npi; + time_t t; +#ifdef PPP_COMPRESS u_char ccp_option[CCP_MAX_OPTION_LENGTH]; +#endif switch (cmd) { case FIONREAD: @@ -310,8 +337,10 @@ pppioctl(sc, cmd, data, flag) return EPERM; flags = *(int *)data & SC_MASK; s = splnet(); +#ifdef PPP_COMPRESS if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) ppp_ccp_closed(sc); +#endif splimp(); sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; splx(s); @@ -329,13 +358,36 @@ pppioctl(sc, cmd, data, flag) *(int *)data = sc->sc_mru; break; + /* + * PPPIOC[GS]MTU are implemented here, instead of supporting + * SIOC[GS]IFMTU in pppsioctl, because under Ultrix, we can't get an + * interface ioctl through to the interface until it has an IP + * address set. + */ + case PPPIOCSMTU: + if (!suser()) + return EPERM; + mtu = *(int *) data; + if (mtu <= 0 || mtu > PPP_MAXMRU) + return EINVAL; + s = splimp(); + sc->sc_if.if_mtu = mtu; + splx(s); + break; + + case PPPIOCGMTU: + *(int *) data = sc->sc_if.if_mtu; + break; + #ifdef VJC case PPPIOCSMAXCID: if (!suser()) return EPERM; - s = splnet(); - sl_compress_setup(&sc->sc_comp, *(int *)data); - splx(s); + if (sc->sc_comp) { + s = splnet(); + sl_compress_setup(sc->sc_comp, *(int *)data); + splx(s); + } break; #endif @@ -353,7 +405,7 @@ pppioctl(sc, cmd, data, flag) nb = odp->length; if (nb > sizeof(ccp_option)) nb = sizeof(ccp_option); - if (error = copyin(odp->ptr, ccp_option, nb)) + if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) return (error); if (ccp_option[1] < 2) /* preliminary check on the length byte */ return (EINVAL); @@ -364,8 +416,8 @@ pppioctl(sc, cmd, data, flag) * a compressor or decompressor. */ error = 0; - s = splnet(); if (odp->transmit) { + s = splnet(); if (sc->sc_xc_state != NULL) (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); sc->sc_xcomp = *cp; @@ -378,7 +430,9 @@ pppioctl(sc, cmd, data, flag) } splimp(); sc->sc_flags &= ~SC_COMP_RUN; + splx(s); } else { + s = splnet(); if (sc->sc_rc_state != NULL) (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); sc->sc_rcomp = *cp; @@ -391,8 +445,8 @@ pppioctl(sc, cmd, data, flag) } splimp(); sc->sc_flags &= ~SC_DECOMP_RUN; + splx(s); } - splx(s); return (error); } if (sc->sc_flags & SC_DEBUG) @@ -418,15 +472,25 @@ pppioctl(sc, cmd, data, flag) if (!suser()) return EPERM; if (npi->mode != sc->sc_npmode[npx]) { - s = splimp(); + s = splnet(); sc->sc_npmode[npx] = npi->mode; - if (npi->mode != NPMODE_QUEUE) + if (npi->mode != NPMODE_QUEUE) { + ppp_requeue(sc); (*sc->sc_start)(sc); + } splx(s); } } break; + case PPPIOCGIDLE: + s = splnet(); + t = time.tv_sec; + ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; + ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; + splx(s); + break; + default: return (-1); } @@ -447,7 +511,9 @@ pppsioctl(ifp, cmd, data) register struct ifaddr *ifa = (struct ifaddr *)data; register struct ifreq *ifr = (struct ifreq *)data; struct ppp_stats *psp; +#ifdef PPP_COMPRESS struct ppp_comp_stats *pcp; +#endif int s = splimp(), error = 0; switch (cmd) { @@ -457,15 +523,21 @@ pppsioctl(ifp, cmd, data) break; case SIOCSIFADDR: - if (ifa->ifa_addr->sa_family != AF_INET) + if (ifa->ifa_addr.sa_family != AF_INET) error = EAFNOSUPPORT; break; case SIOCSIFDSTADDR: - if (ifa->ifa_addr->sa_family != AF_INET) + if (ifa->ifa_addr.sa_family != AF_INET) error = EAFNOSUPPORT; break; +/* + * Ioctls other than the above don't get through until the + * interface has its IP addresses set :-( + */ + +#if 0 case SIOCSIFMTU: if (!suser()) return EPERM; @@ -475,25 +547,23 @@ pppsioctl(ifp, cmd, data) case SIOCGIFMTU: ifr->ifr_mtu = sc->sc_if.if_mtu; break; +#endif case SIOCGPPPSTATS: psp = &((struct ifpppstatsreq *) data)->stats; bzero(psp, sizeof(*psp)); - psp->p.ppp_ibytes = sc->sc_bytesrcvd; - psp->p.ppp_ipackets = ifp->if_ipackets; - psp->p.ppp_ierrors = ifp->if_ierrors; - psp->p.ppp_obytes = sc->sc_bytessent; - psp->p.ppp_opackets = ifp->if_opackets; - psp->p.ppp_oerrors = ifp->if_oerrors; -#ifdef VJC - psp->vj.vjs_packets = sc->sc_comp.sls_packets; - psp->vj.vjs_compressed = sc->sc_comp.sls_compressed; - psp->vj.vjs_searches = sc->sc_comp.sls_searches; - psp->vj.vjs_misses = sc->sc_comp.sls_misses; - psp->vj.vjs_uncompressedin = sc->sc_comp.sls_uncompressedin; - psp->vj.vjs_compressedin = sc->sc_comp.sls_compressedin; - psp->vj.vjs_errorin = sc->sc_comp.sls_errorin; - psp->vj.vjs_tossed = sc->sc_comp.sls_tossed; + psp->p = sc->sc_stats; +#if defined(VJC) && !defined(SL_NO_STATS) + if (sc->sc_comp) { + psp->vj.vjs_packets = sc->sc_comp->sls_packets; + psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; + psp->vj.vjs_searches = sc->sc_comp->sls_searches; + psp->vj.vjs_misses = sc->sc_comp->sls_misses; + psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; + psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; + psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; + psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; + } #endif /* VJC */ break; @@ -526,24 +596,27 @@ pppoutput(ifp, m0, dst) struct sockaddr *dst; { 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; enum NPmode mode; + int len; + struct mbuf *m; if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 - || (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) { + || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { error = ENETDOWN; /* sort of */ goto bad; } /* * Compute PPP header. + * We use the m_context field of the mbuf to indicate whether + * the packet should go on the fast queue. */ - ifq = &ifp->if_snd; + m0->m_context = 0; switch (dst->sa_family) { #ifdef INET case AF_INET: @@ -551,7 +624,7 @@ pppoutput(ifp, m0, dst) control = PPP_UI; protocol = PPP_IP; mode = sc->sc_npmode[NP_IP]; - + /* * If this is a TCP packet to or from an "interactive" port, * put the packet on the fastq instead. @@ -559,7 +632,7 @@ pppoutput(ifp, m0, dst) 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; + m0->m_context = 1; } break; #endif @@ -611,11 +684,22 @@ pppoutput(ifp, m0, dst) *cp++ = protocol & 0xff; m0->m_len += PPP_HDRLEN; + len = 0; + for (m = m0; m != 0; m = m->m_next) + len += m->m_len; + if (sc->sc_flags & SC_LOG_OUTPKT) { printf("ppp%d output: ", ifp->if_unit); pppdumpm(m0); } + if ((protocol & 0x8000) == 0) { + /* + * Update the time we sent the most recent data packet. + */ + sc->sc_last_sent = time.tv_sec; + } + #if NBPFILTER > 0 /* * See if bpf wants to look at the packet. @@ -627,21 +711,26 @@ pppoutput(ifp, m0, dst) /* * Put the packet on the appropriate queue. */ - s = splimp(); /* splnet should be OK now */ - 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. - */ - if (mode == NPMODE_PASS) + s = splnet(); + if (mode == NPMODE_QUEUE) { + /* XXX we should limit the number of packets on this queue */ + *sc->sc_npqtail = m0; + m0->m_act = NULL; + sc->sc_npqtail = &m0->m_act; + } else { + ifq = m0->m_context? &sc->sc_fastq: &ifp->if_snd; + if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) { + IF_DROP(ifq); + splx(s); + sc->sc_if.if_oerrors++; + sc->sc_stats.ppp_oerrors++; + error = ENOBUFS; + goto bad; + } + IF_ENQUEUE(ifq, m0); (*sc->sc_start)(sc); + } + ifp->if_opackets++; splx(s); return (0); @@ -652,122 +741,98 @@ bad: } /* - * Get a packet to send. This procedure is intended to be called - * at spltty()/splimp(), so it takes little time. If there isn't - * a packet waiting to go out, it schedules a software interrupt - * to prepare a new packet; the device start routine gets called - * again when a packet is ready. + * After a change in the NPmode for some NP, move packets from the + * npqueue to the send queue or the fast queue as appropriate. + * Should be called at splnet. */ -struct mbuf * -ppp_dequeue(sc) +static void +ppp_requeue(sc) struct ppp_softc *sc; { - struct mbuf *m; + struct mbuf *m, **mpp; + struct ifqueue *ifq; + enum NPmode mode; - m = sc->sc_togo; - if (m) { - /* - * Had a packet waiting - send it. - */ - sc->sc_togo = NULL; - sc->sc_flags |= SC_TBUSY; - return m; + for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { + switch (PPP_PROTOCOL(mtod(m, u_char *))) { + case PPP_IP: + mode = sc->sc_npmode[NP_IP]; + break; + default: + mode = NPMODE_PASS; + } + + switch (mode) { + case NPMODE_PASS: + /* + * This packet can now go on one of the queues to be sent. + */ + *mpp = m->m_act; + m->m_act = NULL; + ifq = m->m_context? &sc->sc_fastq: &sc->sc_if.if_snd; + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + sc->sc_if.if_oerrors++; + sc->sc_stats.ppp_oerrors++; + } else + IF_ENQUEUE(ifq, m); + break; + + case NPMODE_DROP: + case NPMODE_ERROR: + *mpp = m->m_act; + m_freem(m); + break; + + case NPMODE_QUEUE: + mpp = &m->m_act; + break; + } } - /* - * Remember we wanted a packet and schedule a software interrupt. - */ - sc->sc_flags &= ~SC_TBUSY; - schednetisr(NETISR_PPP); - return NULL; + sc->sc_npqtail = mpp; } /* - * Software interrupt routine, called at splnet(). + * Transmitter has finished outputting some stuff; + * remember to call sc->sc_start later at splnet. */ void -pppintr() -{ +ppp_restart(sc) struct ppp_softc *sc; - int i, s; - struct mbuf *m; +{ + int s = splimp(); - sc = ppp_softc; - for (i = 0; i < NPPP; ++i, ++sc) { - if (!(sc->sc_flags & SC_TBUSY) && sc->sc_togo == NULL - && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) - ppp_outpkt(sc); - for (;;) { - IF_DEQUEUE(&sc->sc_rawq, m); - if (m == NULL) - break; - ppp_inproc(sc, m); - } - } + sc->sc_flags &= ~SC_TBUSY; + schednetisr(NETISR_PPP); + splx(s); } /* - * Grab another packet off a queue and apply VJ compression, - * packet compression, address/control and/or protocol compression - * if enabled. Should be called at splnet. + * Get a packet to send. This procedure is intended to be called at + * splnet, since it may involve time-consuming operations such as + * applying VJ compression, packet compression, address/control and/or + * protocol field compression to the packet. */ -static void -ppp_outpkt(sc) +struct mbuf * +ppp_dequeue(sc) struct ppp_softc *sc; { - int s; - struct mbuf *m, *mp, **mpp; + struct mbuf *m, *mp; u_char *cp; int address, control, protocol; - struct ifqueue *ifq; - enum NPmode mode; + int s; /* - * Scan through the send queues looking for a packet - * which can be sent: first the fast queue, then the normal queue. + * Grab a packet to send: first try the fast queue, then the + * normal queue. */ - ifq = &sc->sc_fastq; - for (;;) { - mpp = &ifq->ifq_head; - mp = NULL; - while ((m = *mpp) != NULL) { - switch (PPP_PROTOCOL(mtod(m, u_char *))) { - case PPP_IP: - mode = sc->sc_npmode[NP_IP]; - break; - default: - mode = NPMODE_PASS; - } - if (mode == NPMODE_PASS) - break; - switch (mode) { - case NPMODE_DROP: - case NPMODE_ERROR: - *mpp = m->m_nextpkt; - --ifq->ifq_len; - m_freem(m); - break; - case NPMODE_QUEUE: - mpp = &m->m_nextpkt; - mp = m; - break; - } - } - if (m != NULL) - break; - - if (ifq == &sc->sc_if.if_snd) - break; - /* Finished the fast queue; do the normal queue. */ - ifq = &sc->sc_if.if_snd; - } - + IF_DEQUEUE(&sc->sc_fastq, m); if (m == NULL) - return; + IF_DEQUEUE(&sc->sc_if.if_snd, m); + if (m == NULL) + return NULL; - if ((*mpp = m->m_nextpkt) == NULL) - ifq->ifq_tail = mp; - m->m_nextpkt = NULL; - --ifq->ifq_len; + ++sc->sc_stats.ppp_opackets; /* * Extract the ppp header of the new packet. @@ -779,12 +844,12 @@ ppp_outpkt(sc) protocol = PPP_PROTOCOL(cp); switch (protocol) { -#ifdef VJC case PPP_IP: +#ifdef VJC /* * If the packet is a TCP/IP packet, see if we can compress it. */ - if (sc->sc_flags & SC_COMP_TCP) { + if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { struct ip *ip; int type; @@ -798,7 +863,7 @@ ppp_outpkt(sc) } /* 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, + type = sl_compress_tcp(mp, ip, sc->sc_comp, !(sc->sc_flags & SC_NO_TCP_CCID)); switch (type) { case TYPE_UNCOMPRESSED_TCP: @@ -815,8 +880,8 @@ ppp_outpkt(sc) cp[3] = protocol; /* update protocol in PPP header */ } } - break; #endif /* VJC */ + break; #ifdef PPP_COMPRESS case PPP_CCP: @@ -828,20 +893,25 @@ ppp_outpkt(sc) #ifdef PPP_COMPRESS if (protocol != PPP_LCP && protocol != PPP_CCP && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { - struct mbuf *mcomp; + struct mbuf *mcomp = NULL; int slen, clen; slen = 0; for (mp = m; mp != NULL; mp = mp->m_next) slen += mp->m_len; clen = (*sc->sc_xcomp->compress) - (sc->sc_xc_state, &mcomp, m, slen, - (sc->sc_flags & SC_CCP_UP? sc->sc_if.if_mtu: 0)); + (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); if (mcomp != NULL) { - m_freem(m); - m = mcomp; - cp = mtod(m, u_char *); - protocol = cp[3]; + if (sc->sc_flags & SC_CCP_UP) { + /* Send the compressed packet instead of the original. */ + m_freem(m); + m = mcomp; + cp = mtod(m, u_char *); + protocol = cp[3]; + } else { + /* Can't transmit compressed packets until CCP is up. */ + m_freem(mcomp); + } } } #endif /* PPP_COMPRESS */ @@ -866,9 +936,38 @@ ppp_outpkt(sc) --m->m_len; } - s = splimp(); - sc->sc_togo = m; - (*sc->sc_start)(sc); + return m; +} + +/* + * Software interrupt routine, called at splnet. + */ +void +pppintr() +{ + struct ppp_softc *sc; + int i, s, s2; + struct mbuf *m; + + sc = ppp_softc; + s = splnet(); + for (i = 0; i < NPPP; ++i, ++sc) { + if (!(sc->sc_flags & SC_TBUSY) + && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) { + s2 = splimp(); + sc->sc_flags |= SC_TBUSY; + splx(s2); + (*sc->sc_start)(sc); + } + for (;;) { + s2 = splimp(); + IF_DEQUEUE(&sc->sc_rawq, m); + splx(s2); + if (m == NULL) + break; + ppp_inproc(sc, m); + } + } splx(s); } @@ -877,7 +976,7 @@ ppp_outpkt(sc) * Handle a CCP packet. `rcvd' is 1 if the packet was received, * 0 if it is about to be transmitted. */ -static int +static void ppp_ccp(sc, m, rcvd) struct ppp_softc *sc; struct mbuf *m; @@ -886,7 +985,6 @@ ppp_ccp(sc, m, rcvd) u_char *dp, *ep; struct mbuf *mp; int slen, s; - struct bsd_db *db; /* * Get a pointer to the data after the PPP header. @@ -933,7 +1031,7 @@ ppp_ccp(sc, m, rcvd) if (sc->sc_xc_state != NULL && (*sc->sc_xcomp->comp_init) (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, - sc->sc_if.if_unit, sc->sc_flags & SC_DEBUG)) { + sc->sc_if.if_unit, 0, sc->sc_flags & SC_DEBUG)) { s = splimp(); sc->sc_flags |= SC_COMP_RUN; splx(s); @@ -943,7 +1041,7 @@ ppp_ccp(sc, m, rcvd) if (sc->sc_rc_state != NULL && (*sc->sc_rcomp->decomp_init) (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, - sc->sc_if.if_unit, sc->sc_mru, + sc->sc_if.if_unit, 0, sc->sc_mru, sc->sc_flags & SC_DEBUG)) { s = splimp(); sc->sc_flags |= SC_DECOMP_RUN; @@ -994,24 +1092,25 @@ ppp_ccp_closed(sc) * 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. Should be called at splimp/spltty. + * were omitted. */ -#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */ - void ppppktin(sc, m, lost) struct ppp_softc *sc; struct mbuf *m; int lost; { - if (lost) - m->m_flags |= M_ERRMARK; + int s = splimp(); + + m->m_context = lost; IF_ENQUEUE(&sc->sc_rawq, m); schednetisr(NETISR_PPP); + splx(s); } /* * Process a received PPP packet, doing decompression as necessary. + * Should be called at splnet. */ #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ TYPE_UNCOMPRESSED_TCP) @@ -1021,17 +1120,21 @@ ppp_inproc(sc, m) struct ppp_softc *sc; struct mbuf *m; { + struct ifnet *ifp = &sc->sc_if; struct ifqueue *inq, *lock; int s, ilen, xlen, proto, rv; u_char *cp, adrs, ctrl; - struct mbuf *mp, *dmp, *pc; + struct mbuf *mp, *dmp = NULL, *pc; u_char *iphdr; u_int hlen; - sc->sc_if.if_ipackets++; + sc->sc_stats.ppp_ipackets++; if (sc->sc_flags & SC_LOG_INPKT) { - printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen); + ilen = 0; + for (mp = m; mp != NULL; mp = mp->m_next) + ilen += mp->m_len; + printf("ppp%d: got %d bytes\n", ifp->if_unit, ilen); pppdumpm(m); } @@ -1040,8 +1143,7 @@ ppp_inproc(sc, m) ctrl = PPP_CONTROL(cp); proto = PPP_PROTOCOL(cp); - if (m->m_flags & M_ERRMARK) { - m->m_flags &= ~M_ERRMARK; + if (m->m_context) { s = splimp(); sc->sc_flags |= SC_VJ_RESET; splx(s); @@ -1056,32 +1158,30 @@ ppp_inproc(sc, m) && !(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 (dmp != NULL) { + if (rv == DECOMP_OK) { m_freem(m); + if (dmp == NULL) { + /* no error, but no decompressed packet produced */ + return; + } m = dmp; cp = mtod(m, u_char *); proto = PPP_PROTOCOL(cp); } else { - /* pass the compressed packet up to pppd, which may take - CCP down or issue a Reset-Req. */ + /* + * An error has occurred in decompression. + * Pass the compressed packet up to pppd, which may take + * CCP down or issue a Reset-Req. + */ if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: decompress failed %d\n", sc->sc_if.if_unit, rv); + printf("ppp%d: decompress failed %d\n", ifp->if_unit, rv); s = splimp(); sc->sc_flags |= SC_VJ_RESET; - switch (rv) { - case DECOMP_OK: - /* no error, but no decompressed packet produced */ - splx(s); - m_freem(m); - return; - case DECOMP_ERROR: + if (rv == DECOMP_ERROR) sc->sc_flags |= SC_DC_ERROR; - break; - case DECOMP_FATALERROR: + else sc->sc_flags |= SC_DC_FERROR; - break; - } splx(s); } @@ -1105,7 +1205,8 @@ ppp_inproc(sc, m) * 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); + if (sc->sc_comp) + sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); s = splimp(); sc->sc_flags &= ~SC_VJ_RESET; splx(s); @@ -1115,17 +1216,17 @@ ppp_inproc(sc, m) * See if we have a VJ-compressed packet to uncompress. */ if (proto == PPP_VJC_COMP) { - if (sc->sc_flags & SC_REJ_COMP_TCP) + if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) goto bad; xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, - &sc->sc_comp, &iphdr, &hlen); + sc->sc_comp, &iphdr, &hlen); if (xlen <= 0) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: VJ uncompress failed on type comp\n", - sc->sc_if.if_unit); + ifp->if_unit); goto bad; } @@ -1135,7 +1236,7 @@ ppp_inproc(sc, m) goto bad; mp->m_len = 0; mp->m_next = NULL; - if (hlen + PPP_HDRLEN > MHLEN) { + if (hlen + PPP_HDRLEN > MLEN) { MCLGET(mp, pc); if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { m_freem(mp); @@ -1167,17 +1268,17 @@ ppp_inproc(sc, m) ilen += hlen - xlen; } else if (proto == PPP_VJC_UNCOMP) { - if (sc->sc_flags & SC_REJ_COMP_TCP) + if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) goto bad; xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, - &sc->sc_comp, &iphdr, &hlen); + sc->sc_comp, &iphdr, &hlen); if (xlen < 0) { if (sc->sc_flags & SC_DEBUG) printf("ppp%d: VJ uncompress failed on type uncomp\n", - sc->sc_if.if_unit); + ifp->if_unit); goto bad; } @@ -1193,26 +1294,34 @@ ppp_inproc(sc, m) if (ilen <= MLEN && M_IS_CLUSTER(m)) { MGET(mp, M_DONTWAIT, MT_DATA); if (mp != NULL) { - m_copydata(m, 0, ilen, mtod(mp, caddr_t)); + m_copydata(m, mtod(mp, caddr_t), ilen); m_freem(m); m = mp; m->m_len = ilen; } } + /* + * Record the time that we received this packet. + */ + if ((proto & 0x8000) == 0) { + sc->sc_last_recv = time.tv_sec; + } + #if NBPFILTER > 0 /* See if bpf wants to look at the packet. */ if (sc->sc_bpf) bpf_mtap(sc->sc_bpf, m); #endif + rv = 0; 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 + if ((ifp->if_flags & IFF_UP) == 0 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { /* interface is down - drop the packet. */ m_freem(m); @@ -1242,15 +1351,16 @@ ppp_inproc(sc, m) smp_lock(&lock->lk_ifqueue, LK_RETRY); if (IF_QFULL(inq)) { IF_DROP(inq); - /* XXX should we unlock here? */ + smp_unlock(&lock->lk_ifqueue); splx(s); if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: input queue full\n", sc->sc_if.if_unit); + printf("ppp%d: input queue full\n", ifp->if_unit); goto bad; } IF_ENQUEUEIF(inq, m, &sc->sc_if); smp_unlock(&lock->lk_ifqueue); splx(s); + ifp->if_ipackets++; if (rv) (*sc->sc_ctlp)(sc); @@ -1260,6 +1370,7 @@ ppp_inproc(sc, m) bad: m_freem(m); sc->sc_if.if_ierrors++; + sc->sc_stats.ppp_ierrors++; } #define MAX_DUMP_BYTES 128