* Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
*/
-/* $Id: if_ppp.c,v 1.6 1995/05/01 01:39:03 paulus Exp $ */
+/* $Id: if_ppp.c,v 1.9 1995/10/27 03:59:42 paulus Exp $ */
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
#include "ppp.h"
#endif
void pppattach __P((void));
-int pppioctl __P((struct ppp_softc *sc, int cmd, caddr_t data, int flag,
- struct proc *));
+int pppioctl __P((struct ppp_softc *sc, int cmd, caddr_t data, int flag));
int pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
struct sockaddr *dst));
int pppsioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
sc->sc_npmode[i] = NPMODE_ERROR;
sc->sc_npqueue = NULL;
sc->sc_npqtail = &sc->sc_npqueue;
+ sc->sc_last_sent = sc->sc_last_recv = time.tv_sec;
return sc;
}
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:
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);
if (!suser())
return EPERM;
mtu = *(int *) data;
- if (mtu < PPP_MRU || mtu > PPP_MAXMRU)
+ if (mtu <= 0 || mtu > PPP_MAXMRU)
return EINVAL;
s = splimp();
sc->sc_if.if_mtu = mtu;
* 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;
}
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;
}
splimp();
sc->sc_flags &= ~SC_DECOMP_RUN;
+ splx(s);
}
- splx(s);
return (error);
}
if (sc->sc_flags & SC_DEBUG)
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) {
ppp_requeue(sc);
}
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);
}
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) {
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.
/*
* Put the packet on the appropriate queue.
*/
- s = splimp(); /* splnet should be OK now */
+ s = splnet();
if (mode == NPMODE_QUEUE) {
/* XXX we should limit the number of packets on this queue */
*sc->sc_npqtail = m0;
sc->sc_npqtail = &m0->m_act;
} else {
ifq = m0->m_context? &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++;
/*
* 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 splnet.
*/
static void
ppp_requeue(sc)
}
/*
- * 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.
+ * Get a packet to send. This procedure is intended to be called at
+ * spltty or 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.
*/
struct mbuf *
ppp_dequeue(sc)
}
/*
- * Software interrupt routine, called at splnet().
+ * Software interrupt routine, called at splnet.
*/
void
pppintr()
&& (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head))
ppp_outpkt(sc);
for (;;) {
+ s = splimp();
IF_DEQUEUE(&sc->sc_rawq, m);
+ splx(s);
if (m == NULL)
break;
ppp_inproc(sc, m);
protocol = PPP_PROTOCOL(cp);
switch (protocol) {
-#ifdef VJC
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.
*/
cp[3] = protocol; /* update protocol in PPP header */
}
}
- break;
#endif /* VJC */
+ break;
#ifdef PPP_COMPRESS
case PPP_CCP:
--m->m_len;
}
- s = splimp();
sc->sc_togo = m;
(*sc->sc_start)(sc);
- splx(s);
}
#ifdef PPP_COMPRESS
u_char *dp, *ep;
struct mbuf *mp;
int slen, s;
- struct bsd_db *db;
/*
* Get a pointer to the data after the PPP header.
/*
* 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)
sc->sc_if.if_ipackets++;
if (sc->sc_flags & SC_LOG_INPKT) {
+ ilen = 0;
+ for (mp = m; mp != NULL; mp = mp->m_next)
+ ilen += mp->m_len;
printf("ppp%d: got %d bytes\n", sc->sc_if.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);
- s = splimp();
+ s = splhigh();
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);
}
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
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);