BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / net / if_sl.c
index 0f51fc2..56ce96f 100644 (file)
@@ -30,7 +30,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)if_sl.c     8.1 (Berkeley) 6/10/93
+ *     @(#)if_sl.c     8.6 (Berkeley) 2/1/94
  */
 
 /*
  */
 
 /*
@@ -67,6 +67,8 @@
 #include "sl.h"
 #if NSL > 0
 
 #include "sl.h"
 #if NSL > 0
 
+#include "bpfilter.h"
+
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/mbuf.h>
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/mbuf.h>
@@ -97,6 +99,12 @@ Huh? Slip without inet?
 
 #include <net/slcompress.h>
 #include <net/if_slvar.h>
 
 #include <net/slcompress.h>
 #include <net/if_slvar.h>
+#include <net/slip.h>
+
+#if NBPFILTER > 0
+#include <sys/time.h>
+#include <net/bpf.h>
+#endif
 
 /*
  * SLMAX is a hard limit on input packet size.  To simplify the code
 
 /*
  * SLMAX is a hard limit on input packet size.  To simplify the code
@@ -138,7 +146,11 @@ Huh? Slip without inet?
  * time.  So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
  * at most 1% while maintaining good interactive response.
  */
  * time.  So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
  * at most 1% while maintaining good interactive response.
  */
-#define BUFOFFSET      128
+#if NBPFILTER > 0
+#define        BUFOFFSET       (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
+#else
+#define        BUFOFFSET       (128+sizeof(struct ifnet **))
+#endif
 #define        SLMAX           (MCLBYTES - BUFOFFSET)
 #define        SLBUFSIZE       (SLMAX + BUFOFFSET)
 #define        SLMTU           296
 #define        SLMAX           (MCLBYTES - BUFOFFSET)
 #define        SLBUFSIZE       (SLMAX + BUFOFFSET)
 #define        SLMTU           296
@@ -153,9 +165,9 @@ Huh? Slip without inet?
  *     if the IFF_DEBUG flag is on.
  */
 #define        ABT_ESC         '\033'  /* can't be t_intr - distant host must know it*/
  *     if the IFF_DEBUG flag is on.
  */
 #define        ABT_ESC         '\033'  /* can't be t_intr - distant host must know it*/
-#define ABT_IDLE       1       /* in seconds - idle before an escape */
-#define ABT_COUNT      3       /* count of escapes for abort */
-#define ABT_WINDOW     (ABT_COUNT*2+2) /* in seconds - time to count */
+#define        ABT_IDLE        1       /* in seconds - idle before an escape */
+#define        ABT_COUNT       3       /* count of escapes for abort */
+#define        ABT_WINDOW      (ABT_COUNT*2+2) /* in seconds - time to count */
 
 struct sl_softc sl_softc[NSL];
 
 
 struct sl_softc sl_softc[NSL];
 
@@ -164,8 +176,6 @@ struct sl_softc sl_softc[NSL];
 #define TRANS_FRAME_END                0xdc            /* transposed frame end */
 #define TRANS_FRAME_ESCAPE     0xdd            /* transposed frame esc */
 
 #define TRANS_FRAME_END                0xdc            /* transposed frame end */
 #define TRANS_FRAME_ESCAPE     0xdd            /* transposed frame esc */
 
-#define t_sc T_LINEP
-
 extern struct timeval time;
 
 static int slinit __P((struct sl_softc *));
 extern struct timeval time;
 
 static int slinit __P((struct sl_softc *));
@@ -193,6 +203,9 @@ slattach()
                sc->sc_if.if_snd.ifq_maxlen = 50;
                sc->sc_fastq.ifq_maxlen = 32;
                if_attach(&sc->sc_if);
                sc->sc_if.if_snd.ifq_maxlen = 50;
                sc->sc_fastq.ifq_maxlen = 32;
                if_attach(&sc->sc_if);
+#if NBPFILTER > 0
+               bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
+#endif
        }
 }
 
        }
 }
 
@@ -292,7 +305,6 @@ sltioctl(tp, cmd, data, flag)
        int flag;
 {
        struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
        int flag;
 {
        struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
-       int s;
 
        switch (cmd) {
        case SLIOCGUNIT:
 
        switch (cmd) {
        case SLIOCGUNIT:
@@ -307,6 +319,9 @@ sltioctl(tp, cmd, data, flag)
 
 /*
  * Queue a packet.  Start transmission if not active.
 
 /*
  * Queue a packet.  Start transmission if not active.
+ * Compression happens in slstart; if we do it here, IP TOS
+ * will cause us to not compress "background" packets, because
+ * ordering gets trashed.  It can be done for all packets in slstart.
  */
 int
 sloutput(ifp, m, dst, rtp)
  */
 int
 sloutput(ifp, m, dst, rtp)
@@ -318,7 +333,6 @@ sloutput(ifp, m, dst, rtp)
        register struct sl_softc *sc = &sl_softc[ifp->if_unit];
        register struct ip *ip;
        register struct ifqueue *ifq;
        register struct sl_softc *sc = &sl_softc[ifp->if_unit];
        register struct ip *ip;
        register struct ifqueue *ifq;
-       register int p;
        int s;
 
        /*
        int s;
 
        /*
@@ -337,33 +351,19 @@ sloutput(ifp, m, dst, rtp)
                m_freem(m);
                return (ENETDOWN);      /* sort of */
        }
                m_freem(m);
                return (ENETDOWN);      /* sort of */
        }
-       if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0) {
+       if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0 &&
+           (sc->sc_ttyp->t_cflag & CLOCAL) == 0) {
                m_freem(m);
                return (EHOSTUNREACH);
        }
        ifq = &sc->sc_if.if_snd;
        ip = mtod(m, struct ip *);
                m_freem(m);
                return (EHOSTUNREACH);
        }
        ifq = &sc->sc_if.if_snd;
        ip = mtod(m, struct ip *);
-       if (ip->ip_tos & IPTOS_LOWDELAY) {
-               ifq = &sc->sc_fastq;
-               p = 1;
-       } else
-               p = 0;
-       if (ip->ip_p == IPPROTO_TCP) {
-               if (sc->sc_if.if_flags & SC_COMPRESS) {
-                       /*
-                        * The last parameter turns off connection id
-                        * compression for background traffic:  Since
-                        * fastq traffic can jump ahead of the background
-                        * traffic, we don't know what order packets will
-                        * go on the line.
-                        */
-                       p = sl_compress_tcp(m, ip, &sc->sc_comp, p);
-                       *mtod(m, u_char *) |= p;
-               }
-       } else if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
+       if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
                m_freem(m);
                return (ENETRESET);             /* XXX ? */
        }
                m_freem(m);
                return (ENETRESET);             /* XXX ? */
        }
+       if (ip->ip_tos & IPTOS_LOWDELAY)
+               ifq = &sc->sc_fastq;
        s = splimp();
        if (IF_QFULL(ifq)) {
                IF_DROP(ifq);
        s = splimp();
        if (IF_QFULL(ifq)) {
                IF_DROP(ifq);
@@ -392,8 +392,13 @@ slstart(tp)
        register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
        register struct mbuf *m;
        register u_char *cp;
        register struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
        register struct mbuf *m;
        register u_char *cp;
+       register struct ip *ip;
        int s;
        struct mbuf *m2;
        int s;
        struct mbuf *m2;
+#if NBPFILTER > 0
+       u_char bpfbuf[SLMTU + SLIP_HDRLEN];
+       register int len;
+#endif
        extern int cfreecount;
 
        for (;;) {
        extern int cfreecount;
 
        for (;;) {
@@ -425,6 +430,53 @@ slstart(tp)
                splx(s);
                if (m == NULL)
                        return;
                splx(s);
                if (m == NULL)
                        return;
+
+               /*
+                * We do the header compression here rather than in sloutput
+                * because the packets will be out of order if we are using TOS
+                * queueing, and the connection id compression will get
+                * munged when this happens.
+                */
+#if NBPFILTER > 0
+               if (sc->sc_bpf) {
+                       /*
+                        * We need to save the TCP/IP header before it's
+                        * compressed.  To avoid complicated code, we just
+                        * copy the entire packet into a stack buffer (since
+                        * this is a serial line, packets should be short
+                        * and/or the copy should be negligible cost compared
+                        * to the packet transmission time).
+                        */
+                       register struct mbuf *m1 = m;
+                       register u_char *cp = bpfbuf + SLIP_HDRLEN;
+
+                       len = 0;
+                       do {
+                               register int mlen = m1->m_len;
+
+                               bcopy(mtod(m1, caddr_t), cp, mlen);
+                               cp += mlen;
+                               len += mlen;
+                       } while (m1 = m1->m_next);
+               }
+#endif
+               if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
+                       if (sc->sc_if.if_flags & SC_COMPRESS)
+                               *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
+                                   &sc->sc_comp, 1);
+               }
+#if NBPFILTER > 0
+               if (sc->sc_bpf) {
+                       /*
+                        * Put the SLIP pseudo-"link header" in place.  The
+                        * compressed header is now at the beginning of the
+                        * mbuf.
+                        */
+                       bpfbuf[SLX_DIR] = SLIPDIR_OUT;
+                       bcopy(mtod(m, caddr_t), &bpfbuf[SLX_CHDR], CHDR_LEN);
+                       bpf_tap(sc->sc_bpf, bpfbuf, len + SLIP_HDRLEN);
+               }
+#endif
                sc->sc_if.if_lastchange = time;
 
                /*
                sc->sc_if.if_lastchange = time;
 
                /*
@@ -472,7 +524,8 @@ slstart(tp)
                                         * Put n characters at once
                                         * into the tty output queue.
                                         */
                                         * Put n characters at once
                                         * into the tty output queue.
                                         */
-                                       if (b_to_q((char *)bp, cp - bp, &tp->t_outq))
+                                       if (b_to_q((char *)bp, cp - bp,
+                                           &tp->t_outq))
                                                break;
                                        sc->sc_if.if_obytes += cp - bp;
                                }
                                                break;
                                        sc->sc_if.if_obytes += cp - bp;
                                }
@@ -570,18 +623,23 @@ slinput(c, tp)
        register struct mbuf *m;
        register int len;
        int s;
        register struct mbuf *m;
        register int len;
        int s;
+#if NBPFILTER > 0
+       u_char chdr[CHDR_LEN];
+#endif
 
        tk_nin++;
        sc = (struct sl_softc *)tp->t_sc;
        if (sc == NULL)
                return;
 
        tk_nin++;
        sc = (struct sl_softc *)tp->t_sc;
        if (sc == NULL)
                return;
-       if (!(tp->t_state&TS_CARR_ON))  /* XXX */
+       if (c & TTY_ERRORMASK || ((tp->t_state & TS_CARR_ON) == 0 &&
+           (tp->t_cflag & CLOCAL) == 0)) {
+               sc->sc_flags |= SC_ERROR;
                return;
                return;
+       }
+       c &= TTY_CHARMASK;
 
        ++sc->sc_if.if_ibytes;
 
        ++sc->sc_if.if_ibytes;
-       c &= 0xff;                      /* XXX */
 
 
-#ifdef ABT_ESC
        if (sc->sc_if.if_flags & IFF_DEBUG) {
                if (c == ABT_ESC) {
                        /*
        if (sc->sc_if.if_flags & IFF_DEBUG) {
                if (c == ABT_ESC) {
                        /*
@@ -607,7 +665,6 @@ slinput(c, tp)
                        sc->sc_abortcount = 0;
                sc->sc_lasttime = time.tv_sec;
        }
                        sc->sc_abortcount = 0;
                sc->sc_lasttime = time.tv_sec;
        }
-#endif
 
        switch (c) {
 
 
        switch (c) {
 
@@ -626,11 +683,29 @@ slinput(c, tp)
                return;
 
        case FRAME_END:
                return;
 
        case FRAME_END:
+               if(sc->sc_flags & SC_ERROR) {
+                       sc->sc_flags &= ~SC_ERROR;
+                       goto newpack;
+               }
                len = sc->sc_mp - sc->sc_buf;
                if (len < 3)
                        /* less than min length packet - ignore */
                        goto newpack;
 
                len = sc->sc_mp - sc->sc_buf;
                if (len < 3)
                        /* less than min length packet - ignore */
                        goto newpack;
 
+#if NBPFILTER > 0
+               if (sc->sc_bpf) {
+                       /*
+                        * Save the compressed header, so we
+                        * can tack it on later.  Note that we
+                        * will end up copying garbage in some
+                        * cases but this is okay.  We remember
+                        * where the buffer started so we can
+                        * compute the new header length.
+                        */
+                       bcopy(sc->sc_buf, chdr, CHDR_LEN);
+               }
+#endif
+
                if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
                        if (c & 0x80)
                                c = TYPE_COMPRESSED_TCP;
                if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
                        if (c & 0x80)
                                c = TYPE_COMPRESSED_TCP;
@@ -658,6 +733,21 @@ slinput(c, tp)
                        } else
                                goto error;
                }
                        } else
                                goto error;
                }
+#if NBPFILTER > 0
+               if (sc->sc_bpf) {
+                       /*
+                        * Put the SLIP pseudo-"link header" in place.
+                        * We couldn't do this any earlier since
+                        * decompression probably moved the buffer
+                        * pointer.  Then, invoke BPF.
+                        */
+                       register u_char *hp = sc->sc_buf - SLIP_HDRLEN;
+
+                       hp[SLX_DIR] = SLIPDIR_IN;
+                       bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);
+                       bpf_tap(sc->sc_bpf, hp, len + SLIP_HDRLEN);
+               }
+#endif
                m = sl_btom(sc, len);
                if (m == NULL)
                        goto error;
                m = sl_btom(sc, len);
                if (m == NULL)
                        goto error;
@@ -682,6 +772,10 @@ slinput(c, tp)
                sc->sc_escape = 0;
                return;
        }
                sc->sc_escape = 0;
                return;
        }
+
+       /* can't put lower; would miss an extra frame */
+       sc->sc_flags |= SC_ERROR;
+
 error:
        sc->sc_if.if_ierrors++;
 newpack:
 error:
        sc->sc_if.if_ierrors++;
 newpack:
@@ -735,7 +829,6 @@ slioctl(ifp, cmd, data)
                        break;
                }
                break;
                        break;
                }
                break;
-#endif
 
        default:
                error = EINVAL;
 
        default:
                error = EINVAL;
@@ -743,3 +836,4 @@ slioctl(ifp, cmd, data)
        splx(s);
        return (error);
 }
        splx(s);
        return (error);
 }
+#endif