* Paul Mackerras (paulus@cs.anu.edu.au).
*/
-/* $Id: if_ppp.c,v 1.2 1995/04/28 06:19:34 paulus Exp $ */
+/* $Id: if_ppp.c,v 1.14 1998/03/25 04:05:01 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
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/malloc.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/netisr.h>
#include <net/route.h>
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
#if INET
#include <netinet/in.h>
#include "bpfilter.h"
#if NBPFILTER > 0
-#include <sys/time.h>
#include <net/bpf.h>
#endif
#include <net/if_pppvar.h>
#include <machine/cpu.h>
+#define splsoftnet splnet
+
#ifndef NETISR_PPP
/* This definition should be moved to net/netisr.h */
#define NETISR_PPP 26 /* PPP software interrupt */
#include <net/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, struct rtentry *rtp));
-int pppsioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
-void pppintr __P((void));
-
+static int pppsioctl __P((struct ifnet *, int, caddr_t));
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));
*/
extern struct compressor ppp_bsd_compress;
+extern struct compressor ppp_deflate, ppp_deflate_draft;
struct compressor *ppp_compressors[8] = {
+#if DO_BSD_COMPRESS
&ppp_bsd_compress,
+#endif
+#if DO_DEFLATE
+ &ppp_deflate,
+ &ppp_deflate_draft,
+#endif
NULL
};
#endif /* PPP_COMPRESS */
sc->sc_if.if_name = "ppp";
sc->sc_if.if_unit = i++;
sc->sc_if.if_mtu = PPP_MTU;
- sc->sc_if.if_flags = IFF_POINTOPOINT;
+ sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
sc->sc_if.if_type = IFT_PPP;
sc->sc_if.if_hdrlen = PPP_HDRLEN;
sc->sc_if.if_ioctl = pppsioctl;
bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
#endif
}
- netisrs[NETISR_PPP] = ppp_intr;
+ netisrs[NETISR_PPP] = pppintr;
}
/*
sc->sc_flags = 0;
sc->sc_mru = PPP_MRU;
sc->sc_relinq = NULL;
+ bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
#ifdef VJC
- vj_compress_init(&sc->sc_comp, -1);
+ MALLOC(sc->sc_comp, struct vjcompress *, sizeof(struct vjcompress),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_comp)
+ vj_compress_init(sc->sc_comp, -1);
#endif
#ifdef PPP_COMPRESS
sc->sc_xc_state = NULL;
}
/*
- * Deallocate a ppp unit. Must be called at splnet or higher.
+ * Deallocate a ppp unit. Must be called at splsoftnet or higher.
*/
void
pppdealloc(sc)
sc->sc_xc_state = NULL;
sc->sc_rc_state = NULL;
#endif /* PPP_COMPRESS */
+#ifdef PPP_FILTER
+ if (sc->sc_pass_filt.bf_insns != 0) {
+ FREE(sc->sc_pass_filt.bf_insns, M_DEVBUF);
+ sc->sc_pass_filt.bf_insns = 0;
+ sc->sc_pass_filt.bf_len = 0;
+ }
+ if (sc->sc_active_filt.bf_insns != 0) {
+ FREE(sc->sc_active_filt.bf_insns, M_DEVBUF);
+ sc->sc_active_filt.bf_insns = 0;
+ sc->sc_active_filt.bf_len = 0;
+ }
+#endif /* PPP_FILTER */
+#ifdef VJC
+ if (sc->sc_comp != 0) {
+ FREE(sc->sc_comp, M_DEVBUF);
+ sc->sc_comp = 0;
+ }
+#endif
}
/*
int
pppioctl(sc, cmd, data, flag, p)
struct ppp_softc *sc;
+ int cmd;
caddr_t data;
- int cmd, flag;
+ int flag;
struct proc *p;
{
int s, error, flags, mru, nb, npx;
struct compressor **cp;
struct npioctl *npi;
time_t t;
+#ifdef PPP_FILTER
+ struct bpf_program *bp, *nbp;
+ struct bpf_insn *newcode, *oldcode;
+ int newcodelen;
+#endif /* PPP_FILTER */
#ifdef PPP_COMPRESS
u_char ccp_option[CCP_MAX_OPTION_LENGTH];
#endif
break;
case PPPIOCSFLAGS:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
flags = *(int *)data & SC_MASK;
- s = splnet();
+ s = splsoftnet();
#ifdef PPP_COMPRESS
if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
ppp_ccp_closed(sc);
break;
case PPPIOCSMRU:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
mru = *(int *)data;
if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
#ifdef VJC
case PPPIOCSMAXCID:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
- s = splnet();
- vj_compress_init(&sc->sc_comp, *(int *)data);
- splx(s);
+ if (sc->sc_comp) {
+ s = splsoftnet();
+ vj_compress_init(sc->sc_comp, *(int *)data);
+ splx(s);
+ }
break;
#endif
case PPPIOCXFERUNIT:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
sc->sc_xfer = p->p_pid;
break;
#ifdef PPP_COMPRESS
case PPPIOCSCOMPRESS:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
odp = (struct ppp_option_data *) data;
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);
* a compressor or decompressor.
*/
error = 0;
- s = splnet();
if (odp->transmit) {
+ s = splsoftnet();
if (sc->sc_xc_state != NULL)
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
sc->sc_xcomp = *cp;
}
splimp();
sc->sc_flags &= ~SC_COMP_RUN;
+ splx(s);
} else {
+ s = splsoftnet();
if (sc->sc_rc_state != NULL)
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
sc->sc_rcomp = *cp;
}
splimp();
sc->sc_flags &= ~SC_DECOMP_RUN;
+ splx(s);
}
- splx(s);
return (error);
}
if (sc->sc_flags & SC_DEBUG)
if (cmd == PPPIOCGNPMODE) {
npi->mode = sc->sc_npmode[npx];
} else {
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
if (npi->mode != sc->sc_npmode[npx]) {
- s = splimp();
+ s = splsoftnet();
sc->sc_npmode[npx] = npi->mode;
if (npi->mode != NPMODE_QUEUE) {
ppp_requeue(sc);
break;
case PPPIOCGIDLE:
- s = splimp();
+ s = splsoftnet();
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;
+#ifdef PPP_FILTER
+ case PPPIOCSPASS:
+ case PPPIOCSACTIVE:
+ nbp = (struct bpf_program *) data;
+ if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
+ return EINVAL;
+ newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
+ if (newcodelen != 0) {
+ MALLOC(newcode, struct bpf_insn *, newcodelen, M_DEVBUF, M_WAITOK);
+ if (newcode == 0) {
+ return EINVAL; /* or sumpin */
+ }
+ if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,
+ newcodelen)) != 0) {
+ FREE(newcode, M_DEVBUF);
+ return error;
+ }
+ if (!bpf_validate(newcode, nbp->bf_len)) {
+ FREE(newcode, M_DEVBUF);
+ return EINVAL;
+ }
+ } else
+ newcode = 0;
+ bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt;
+ oldcode = bp->bf_insns;
+ s = splimp();
+ bp->bf_len = nbp->bf_len;
+ bp->bf_insns = newcode;
+ splx(s);
+ if (oldcode != 0)
+ FREE(oldcode, M_DEVBUF);
+ break;
+#endif
+
default:
return (-1);
}
/*
* Process an ioctl request to the ppp network interface.
*/
-int
+static int
pppsioctl(ifp, cmd, data)
register struct ifnet *ifp;
int cmd;
break;
case SIOCSIFMTU:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
break;
sc->sc_if.if_mtu = ifr->ifr_mtu;
break;
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 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;
struct rtentry *rtp;
{
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;
}
*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) {
+#ifdef PPP_FILTER
+ /*
+ * Apply the pass and active filters to the packet,
+ * but only if it is a data packet.
+ */
+ *mtod(m0, u_char *) = 1; /* indicates outbound */
+ if (sc->sc_pass_filt.bf_insns != 0
+ && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,
+ len, 0) == 0) {
+ error = 0; /* drop this packet */
+ goto bad;
+ }
+
+ /*
+ * Update the time we sent the most recent packet.
+ */
+ if (sc->sc_active_filt.bf_insns == 0
+ || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0))
+ sc->sc_last_sent = time.tv_sec;
+
+ *mtod(m0, u_char *) = address;
+#else
+ /*
+ * Update the time we sent the most recent data packet.
+ */
+ sc->sc_last_sent = time.tv_sec;
+#endif /* PPP_FILTER */
+ }
+
#if NBPFILTER > 0
/*
* See if bpf wants to look at the packet.
/*
* Put the packet on the appropriate queue.
*/
- s = splimp(); /* splnet should be OK now */
+ s = splsoftnet();
if (mode == NPMODE_QUEUE) {
/* XXX we should limit the number of packets on this queue */
*sc->sc_npqtail = m0;
sc->sc_npqtail = &m0->m_nextpkt;
} else {
ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq: &ifp->if_snd;
- if (IF_QFULL(ifq)) {
+ 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_lastchange = time;
+ ifp->if_opackets++;
+ ifp->if_obytes += len;
splx(s);
return (0);
/*
* 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 splimp (actually splnet would probably suffice).
+ * Should be called at splsoftnet.
*/
static void
ppp_requeue(sc)
if (IF_QFULL(ifq)) {
IF_DROP(ifq);
sc->sc_if.if_oerrors++;
+ sc->sc_stats.ppp_oerrors++;
} else
IF_ENQUEUE(ifq, m);
break;
}
/*
- * 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.
+ * Transmitter has finished outputting some stuff;
+ * remember to call sc->sc_start later at splsoftnet.
*/
-struct mbuf *
-ppp_dequeue(sc)
+void
+ppp_restart(sc)
struct ppp_softc *sc;
{
- struct mbuf *m;
int s = splimp();
- m = sc->sc_togo;
- if (m) {
- /*
- * Had a packet waiting - send it.
- */
- sc->sc_togo = NULL;
- sc->sc_flags |= SC_TBUSY;
- splx(s);
- return m;
- }
- /*
- * Remember we wanted a packet and schedule a software interrupt.
- */
sc->sc_flags &= ~SC_TBUSY;
schednetisr(NETISR_PPP);
splx(s);
- return NULL;
}
/*
- * Software interrupt routine, called at splnet().
+ * Get a packet to send. This procedure is intended to be called at
+ * splsoftnet, since it may involve time-consuming operations such as
+ * applying VJ compression, packet compression, address/control and/or
+ * protocol field compression to the packet.
*/
-void
-pppintr()
-{
- struct ppp_softc *sc;
- int i, s;
- struct mbuf *m;
-
- s = splnet();
- 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);
- }
- }
- 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.
- */
-static void
-ppp_outpkt(sc)
+struct mbuf *
+ppp_dequeue(sc)
struct ppp_softc *sc;
{
- int s;
struct mbuf *m, *mp;
u_char *cp;
int address, control, protocol;
- enum NPmode mode;
/*
* Grab a packet to send: first try the fast queue, then the
if (m == NULL)
IF_DEQUEUE(&sc->sc_if.if_snd, m);
if (m == NULL)
- return;
+ return NULL;
+
+ ++sc->sc_stats.ppp_opackets;
/*
* Extract the ppp header of the new packet.
switch (protocol) {
case PPP_IP:
- /*
- * Update the time we sent the most recent packet.
- */
- sc->sc_last_sent = time.tv_sec;
-
#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;
}
/* this code assumes the IP/TCP header is in one non-shared mbuf */
if (ip->ip_p == IPPROTO_TCP) {
- type = vj_compress_tcp(mp, ip, &sc->sc_comp,
+ type = vj_compress_tcp(mp, ip, sc->sc_comp,
!(sc->sc_flags & SC_NO_TCP_CCID));
switch (type) {
case TYPE_UNCOMPRESSED_TCP:
#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 */
--m->m_len;
}
- s = splimp();
- sc->sc_togo = m;
- (*sc->sc_start)(sc);
+ return m;
+}
+
+/*
+ * Software interrupt routine, called at splsoftnet.
+ */
+void
+pppintr()
+{
+ struct ppp_softc *sc;
+ int i, s, s2;
+ struct mbuf *m;
+
+ sc = ppp_softc;
+ s = splsoftnet();
+ 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);
}
* 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;
slen = CCP_LENGTH(dp);
if (dp + slen > ep) {
if (sc->sc_flags & SC_DEBUG)
- printf("if_ppp/ccp: not enough data in mbuf (%x+%x > %x+%x)\n",
+ printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
dp, slen, mtod(mp, u_char *), mp->m_len);
return;
}
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);
/*
* Process a received PPP packet, doing decompression as necessary.
+ * Should be called at splsoftnet.
*/
#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
TYPE_UNCOMPRESSED_TCP)
struct ppp_softc *sc;
struct mbuf *m;
{
+ struct ifnet *ifp = &sc->sc_if;
struct ifqueue *inq;
int s, ilen, xlen, proto, rv;
u_char *cp, adrs, ctrl;
- struct mbuf *mp, *dmp;
+ struct mbuf *mp, *dmp = NULL;
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);
}
&& !(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);
}
* If we've missed a packet, we must toss subsequent compressed
* packets which don't have an explicit connection ID.
*/
- vj_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
+ if (sc->sc_comp)
+ vj_uncompress_tcp(NULL, 0, TYPE_ERROR, 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)
+ if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
goto bad;
xlen = vj_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;
}
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 = vj_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;
}
}
}
m->m_pkthdr.len = ilen;
- m->m_pkthdr.rcvif = &sc->sc_if;
+ m->m_pkthdr.rcvif = ifp;
+
+ if ((proto & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * See whether we want to pass this packet, and
+ * if it counts as link activity.
+ */
+ adrs = *mtod(m, u_char *); /* save address field */
+ *mtod(m, u_char *) = 0; /* indicate inbound */
+ if (sc->sc_pass_filt.bf_insns != 0
+ && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,
+ ilen, 0) == 0) {
+ /* drop this packet */
+ m_freem(m);
+ return;
+ }
+ if (sc->sc_active_filt.bf_insns == 0
+ || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m, ilen, 0))
+ sc->sc_last_recv = time.tv_sec;
+
+ *mtod(m, u_char *) = adrs;
+#else
+ /*
+ * Record the time that we received this packet.
+ */
+ sc->sc_last_recv = time.tv_sec;
+#endif /* PPP_FILTER */
+ }
#if NBPFILTER > 0
/* See if bpf wants to look at the packet. */
/*
* 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);
m->m_len -= PPP_HDRLEN;
schednetisr(NETISR_IP);
inq = &ipintrq;
- sc->sc_last_recv = time.tv_sec; /* update time of last pkt rcvd */
break;
#endif
IF_DROP(inq);
splx(s);
if (sc->sc_flags & SC_DEBUG)
- printf("ppp%d: input queue full\n", sc->sc_if.if_unit);
- sc->sc_if.if_iqdrops++;
+ printf("ppp%d: input queue full\n", ifp->if_unit);
+ ifp->if_iqdrops++;
goto bad;
}
IF_ENQUEUE(inq, m);
splx(s);
+ ifp->if_ipackets++;
+ ifp->if_ibytes += ilen;
+ ifp->if_lastchange = time;
if (rv)
(*sc->sc_ctlp)(sc);
bad:
m_freem(m);
sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
}
#define MAX_DUMP_BYTES 128