diff options
Diffstat (limited to 'sys/net/if_ppp.c')
-rw-r--r-- | sys/net/if_ppp.c | 108 |
1 files changed, 66 insertions, 42 deletions
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index efda46dbe54a..18beb9a345cd 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -70,7 +70,7 @@ */ /* - * $Id: if_ppp.c,v 1.7 1993/12/20 19:31:30 wollman Exp $ + * $Id: if_ppp.c,v 1.13 1994/05/30 03:37:47 ache Exp $ * From: if_ppp.c,v 1.22 1993/08/31 23:20:40 paulus Exp * From: if_ppp.c,v 1.21 1993/08/29 11:22:37 paulus Exp * From: if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp @@ -92,6 +92,7 @@ #include "kernel.h" #include "conf.h" #include "dkstat.h" +#include "pppdefs.h" #include "if.h" #include "if_types.h" @@ -117,11 +118,11 @@ #ifndef RB_LEN /* NetBSD, 4.3-Reno or similar */ #define CCOUNT(q) ((q)->c_cc) +#define TSA_HUP_OR_INPUT(tp) ((caddr_t)&tp->t_rawq) #else /* 386BSD, Jolitz-style ring buffers */ #define t_outq t_out -#define t_rawq t_raw #define t_canq t_can #define CCOUNT(q) (RB_LEN(q)) #endif @@ -249,7 +250,7 @@ pppopen(dev, tp) if (sc->sc_ttyp == NULL) break; if (nppp >= NPPP) - return ENXIO; + return (ENXIO); sc->sc_flags = 0; sc->sc_ilen = 0; @@ -344,33 +345,40 @@ pppread(tp, uio, flag) { register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; struct mbuf *m, *m0; - register int s; - int error = 0; + int s; + int error; - if ((tp->t_state & TS_CARR_ON)==0) - return (EIO); s = splimp(); - while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) { + for (;;) { + if (tp->t_line != PPPDISC) { + splx(s); + return (ENXIO); + } + if (!CAN_DO_IO(tp)) { + splx(s); + return (EIO); + } + if (sc->sc_inq.ifq_head != NULL) + break; if (tp->t_state & TS_ASYNC) { splx(s); return (EWOULDBLOCK); } - error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0); - if (error) - return error; - } - if (tp->t_line != PPPDISC) { - splx(s); - return (-1); + error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0); + if (error) { + splx(s); + return (error); + } } /* Pull place-holder byte out of canonical queue */ - getc(&tp->t_canq); + getc(tp->t_canq); /* Get the packet from the input queue */ IF_DEQUEUE(&sc->sc_inq, m0); splx(s); + error = 0; for (m = m0; m && uio->uio_resid; m = m->m_next) if (error = uiomove(mtod(m, u_char *), m->m_len, uio)) break; @@ -391,19 +399,33 @@ pppwrite(tp, uio, flag) struct mbuf *m, *m0, **mp; struct sockaddr dst; struct ppp_header *ph1, *ph2; - int len, error; + int len, error, s; - if ((tp->t_state & TS_CARR_ON)==0) - return (EIO); if (tp->t_line != PPPDISC) - return (EINVAL); + return (ENXIO); + + /* + * XXX the locking is probably too strong, and/or the order of checking + * for errors requires an inconvenient number of splx()'s. pppoutput() + * does its own locking, but we must hold at least an spltty() lock to + * preserve the validity of the test of TS_CARR_ON in CAN_DO_IO(). + */ + s = splimp(); + + if (!CAN_DO_IO(tp)) { + splx(s); + return (EIO); + } if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HEADER_LEN || - uio->uio_resid < PPP_HEADER_LEN) + uio->uio_resid < PPP_HEADER_LEN) { + splx(s); return (EMSGSIZE); + } for (mp = &m0; uio->uio_resid; mp = &m->m_next) { MGET(m, M_WAIT, MT_DATA); if ((*mp = m) == NULL) { m_freem(m0); + splx(s); return (ENOBUFS); } if (uio->uio_resid >= MCLBYTES / 2) @@ -411,6 +433,7 @@ pppwrite(tp, uio, flag) len = MIN(M_TRAILINGSPACE(m), uio->uio_resid); if (error = uiomove(mtod(m, u_char *), len, uio)) { m_freem(m0); + splx(s); return (error); } m->m_len = len; @@ -421,7 +444,9 @@ pppwrite(tp, uio, flag) *ph1 = *ph2; m0->m_data += PPP_HEADER_LEN; m0->m_len -= PPP_HEADER_LEN; - return (pppoutput(&sc->sc_if, m0, &dst, 0)); + error = pppoutput(&sc->sc_if, m0, &dst, 0); + splx(s); + return (error); } /* @@ -589,7 +614,7 @@ pppoutput(ifp, m0, dst, rt) error = ENETDOWN; /* sort of */ goto bad; } - if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0) { + if (!CAN_DO_IO(sc->sc_ttyp)) { error = EHOSTUNREACH; goto bad; } @@ -711,15 +736,14 @@ pppstart(tp) for (;;) { /* - * If there is more in the output queue, just send it now. + * Call output process whether or not there is any output. * We are being called in lieu of ttstart and must do what * it would. */ - if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) { - (*tp->t_oproc)(tp); - if (CCOUNT(&tp->t_outq) > PPP_HIWAT) - return; - } + (*tp->t_oproc)(tp); + if (CCOUNT(tp->t_outq) > PPP_HIWAT) + return; + /* * This happens briefly when the line shuts down. */ @@ -809,9 +833,9 @@ pppstart(tp) * will flush any accumulated garbage. We do this whenever * the line may have been idle for some time. */ - if (CCOUNT(&tp->t_outq) == 0) { + if (CCOUNT(tp->t_outq) == 0) { ++sc->sc_bytessent; - (void) putc(PPP_FLAG, &tp->t_outq); + (void) putc(PPP_FLAG, tp->t_outq); } /* Calculate the FCS for the first mbuf's worth. */ @@ -834,7 +858,7 @@ pppstart(tp) if (n) { #ifndef RB_LEN /* NetBSD (0.9 or later), 4.3-Reno or similar. */ - ndone = n - b_to_q(start, n, &tp->t_outq); + ndone = n - b_to_q(start, n, tp->t_outq); #else #ifdef NetBSD /* NetBSD with 2-byte ring buffer entries */ @@ -843,12 +867,12 @@ pppstart(tp) /* 386BSD, FreeBSD */ int cc, nleft; for (nleft = n; nleft > 0; nleft -= cc) { - if ((cc = RB_CONTIGPUT(&tp->t_out)) == 0) + if ((cc = RB_CONTIGPUT(tp->t_out)) == 0) break; cc = min (cc, nleft); - bcopy((char *)start + n - nleft, tp->t_out.rb_tl, cc); - tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out, - tp->t_out.rb_tl + cc); + bcopy((char *)start + n - nleft, tp->t_out->rb_tl, cc); + tp->t_out->rb_tl = RB_ROLLOVER(tp->t_out, + tp->t_out->rb_tl + cc); } ndone = n - nleft; #endif /* NetBSD */ @@ -866,10 +890,10 @@ pppstart(tp) * Put it out in a different form. */ if (len) { - if (putc(PPP_ESCAPE, &tp->t_outq)) + if (putc(PPP_ESCAPE, tp->t_outq)) break; - if (putc(*start ^ PPP_TRANS, &tp->t_outq)) { - (void) unputc(&tp->t_outq); + if (putc(*start ^ PPP_TRANS, tp->t_outq)) { + (void) unputc(tp->t_outq); break; } sc->sc_bytessent += 2; @@ -912,10 +936,10 @@ pppstart(tp) * don't all fit, back out. */ for (q = endseq; q < p; ++q) - if (putc(*q, &tp->t_outq)) { + if (putc(*q, tp->t_outq)) { done = 0; for (; q > endseq; --q) - unputc(&tp->t_outq); + unputc(tp->t_outq); break; } } @@ -1213,7 +1237,7 @@ pppinput(c, tp) * Some other protocol - place on input queue for read(). * Put a placeholder byte in canq for ttselect()/ttnread(). */ - putc(0, &tp->t_canq); + putc(0, tp->t_canq); ttwakeup(tp); inq = &sc->sc_inq; break; |