BSD 4_4 release
[unix-history] / usr / src / sys / net / if_sl.c
index 92b6203..0f51fc2 100644 (file)
@@ -1,20 +1,36 @@
 /*
 /*
- * Copyright (c) 1987, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1987, 1989, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)if_sl.c     7.19 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * 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
  */
 
 /*
  */
 
 /*
  * interrupts and network activity; thus, splimp must be >= spltty.
  */
 
  * interrupts and network activity; thus, splimp must be >= spltty.
  */
 
-/* $Header: if_sl.c,v 1.7 89/05/31 02:24:52 van Exp $ */
-/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
-
 #include "sl.h"
 #if NSL > 0
 
 #include "sl.h"
 #if NSL > 0
 
-#include "param.h"
-#include "dir.h"
-#include "user.h"
-#include "mbuf.h"
-#include "buf.h"
-#include "dk.h"
-#include "socket.h"
-#include "ioctl.h"
-#include "file.h"
-#include "tty.h"
-#include "kernel.h"
-#include "conf.h"
-#include "errno.h"
-
-#include "if.h"
-#include "if_types.h"
-#include "netisr.h"
-#include "route.h"
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/dkstat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
 #if INET
 #if INET
-#include "../netinet/in.h"
-#include "../netinet/in_systm.h"
-#include "../netinet/in_var.h"
-#include "../netinet/ip.h"
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#else
+Huh? Slip without inet?
 #endif
 
 #endif
 
-#include "machine/mtpr.h"
-
-#include "slcompress.h"
-#include "if_slvar.h"
+#include <net/slcompress.h>
+#include <net/if_slvar.h>
 
 /*
  * 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
  * SLIP ABORT ESCAPE MECHANISM:
  *     (inspired by HAYES modem escape arrangement)
  *     1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
  * SLIP ABORT ESCAPE MECHANISM:
  *     (inspired by HAYES modem escape arrangement)
  *     1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
- *     signals a "soft" exit from slip mode by usermode process
+ *     within window time signals a "soft" exit from slip mode by remote end
+ *     if the IFF_DEBUG flag is on.
  */
  */
-
 #define        ABT_ESC         '\033'  /* can't be t_intr - distant host must know it*/
 #define        ABT_ESC         '\033'  /* can't be t_intr - distant host must know it*/
-#define ABT_WAIT       1       /* in seconds - idle before an escape & after */
-#define ABT_RECYCLE    (5*2+2) /* in seconds - time window processing abort */
-
-#define ABT_SOFT       3       /* count of escapes */
-
-/*
- * The following disgusting hack gets around the problem that IP TOS
- * can't be set yet.  We want to put "interactive" traffic on a high
- * priority queue.  To decide if traffic is interactive, we check that
- * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
- */
-static u_short interactive_ports[8] = {
-       0,      513,    0,      0,
-       0,      21,     0,      23,
-};
-#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
+#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];
 
@@ -165,12 +166,15 @@ struct sl_softc sl_softc[NSL];
 
 #define t_sc T_LINEP
 
 
 #define t_sc T_LINEP
 
-int sloutput(), slioctl(), ttrstrt();
 extern struct timeval time;
 
 extern struct timeval time;
 
+static int slinit __P((struct sl_softc *));
+static struct mbuf *sl_btom __P((struct sl_softc *, int));
+
 /*
  * Called from boot code to establish sl interfaces.
  */
 /*
  * Called from boot code to establish sl interfaces.
  */
+void
 slattach()
 {
        register struct sl_softc *sc;
 slattach()
 {
        register struct sl_softc *sc;
@@ -178,9 +182,11 @@ slattach()
 
        for (sc = sl_softc; i < NSL; sc++) {
                sc->sc_if.if_name = "sl";
 
        for (sc = sl_softc; i < NSL; sc++) {
                sc->sc_if.if_name = "sl";
+               sc->sc_if.if_next = NULL;
                sc->sc_if.if_unit = i++;
                sc->sc_if.if_mtu = SLMTU;
                sc->sc_if.if_unit = i++;
                sc->sc_if.if_mtu = SLMTU;
-               sc->sc_if.if_flags = IFF_POINTOPOINT;
+               sc->sc_if.if_flags =
+                   IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST;
                sc->sc_if.if_type = IFT_SLIP;
                sc->sc_if.if_ioctl = slioctl;
                sc->sc_if.if_output = sloutput;
                sc->sc_if.if_type = IFT_SLIP;
                sc->sc_if.if_ioctl = slioctl;
                sc->sc_if.if_output = sloutput;
@@ -217,15 +223,17 @@ slinit(sc)
  * Attach the given tty to the first available sl unit.
  */
 /* ARGSUSED */
  * Attach the given tty to the first available sl unit.
  */
 /* ARGSUSED */
+int
 slopen(dev, tp)
        dev_t dev;
        register struct tty *tp;
 {
 slopen(dev, tp)
        dev_t dev;
        register struct tty *tp;
 {
+       struct proc *p = curproc;               /* XXX */
        register struct sl_softc *sc;
        register int nsl;
        int error;
 
        register struct sl_softc *sc;
        register int nsl;
        int error;
 
-       if (error = suser(u.u_cred, &u.u_acflag))
+       if (error = suser(p->p_ucred, &p->p_acflag))
                return (error);
 
        if (tp->t_line == SLIPDISC)
                return (error);
 
        if (tp->t_line == SLIPDISC)
@@ -247,8 +255,8 @@ slopen(dev, tp)
 /*
  * Line specific close routine.
  * Detach the tty from the sl unit.
 /*
  * Line specific close routine.
  * Detach the tty from the sl unit.
- * Mimics part of ttyclose().
  */
  */
+void
 slclose(tp)
        struct tty *tp;
 {
 slclose(tp)
        struct tty *tp;
 {
@@ -276,31 +284,21 @@ slclose(tp)
  * Provide a way to get the sl unit number.
  */
 /* ARGSUSED */
  * Provide a way to get the sl unit number.
  */
 /* ARGSUSED */
+int
 sltioctl(tp, cmd, data, flag)
        struct tty *tp;
 sltioctl(tp, cmd, data, flag)
        struct tty *tp;
+       int cmd;
        caddr_t data;
        caddr_t data;
+       int flag;
 {
        struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
        int s;
 
        switch (cmd) {
 {
        struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
        int s;
 
        switch (cmd) {
-       case TIOCGETD:                          /* XXX */
-       case SLIOGUNIT:
+       case SLIOCGUNIT:
                *(int *)data = sc->sc_if.if_unit;
                break;
 
                *(int *)data = sc->sc_if.if_unit;
                break;
 
-       case SLIOCGFLAGS:
-               *(int *)data = sc->sc_flags;
-               break;
-
-       case SLIOCSFLAGS:
-#define        SC_MASK 0xffff
-               s = splimp();
-               sc->sc_flags =
-                   (sc->sc_flags &~ SC_MASK) | ((*(int *)data) & SC_MASK);
-               splx(s);
-               break;
-
        default:
                return (-1);
        }
        default:
                return (-1);
        }
@@ -310,14 +308,17 @@ sltioctl(tp, cmd, data, flag)
 /*
  * Queue a packet.  Start transmission if not active.
  */
 /*
  * Queue a packet.  Start transmission if not active.
  */
-sloutput(ifp, m, dst)
+int
+sloutput(ifp, m, dst, rtp)
        struct ifnet *ifp;
        register struct mbuf *m;
        struct sockaddr *dst;
        struct ifnet *ifp;
        register struct mbuf *m;
        struct sockaddr *dst;
+       struct rtentry *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;
 
        /*
@@ -328,6 +329,7 @@ sloutput(ifp, m, dst)
                printf("sl%d: af%d not supported\n", sc->sc_if.if_unit,
                        dst->sa_family);
                m_freem(m);
                printf("sl%d: af%d not supported\n", sc->sc_if.if_unit,
                        dst->sa_family);
                m_freem(m);
+               sc->sc_if.if_noproto++;
                return (EAFNOSUPPORT);
        }
 
                return (EAFNOSUPPORT);
        }
 
@@ -340,16 +342,14 @@ sloutput(ifp, m, dst)
                return (EHOSTUNREACH);
        }
        ifq = &sc->sc_if.if_snd;
                return (EHOSTUNREACH);
        }
        ifq = &sc->sc_if.if_snd;
-       if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
-               register int p = ((int *)ip)[ip->ip_hl];
-
-               if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16)) {
-                       ifq = &sc->sc_fastq;
-                       p = 1;
-               } else
-                       p = 0;
-
-               if (sc->sc_flags & SC_COMPRESS) {
+       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
                        /*
                         * The last parameter turns off connection id
                         * compression for background traffic:  Since
@@ -360,9 +360,9 @@ sloutput(ifp, m, dst)
                        p = sl_compress_tcp(m, ip, &sc->sc_comp, p);
                        *mtod(m, u_char *) |= p;
                }
                        p = sl_compress_tcp(m, ip, &sc->sc_comp, p);
                        *mtod(m, u_char *) |= p;
                }
-       } else if (sc->sc_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
+       } else if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
                m_freem(m);
                m_freem(m);
-               return (0);
+               return (ENETRESET);             /* XXX ? */
        }
        s = splimp();
        if (IF_QFULL(ifq)) {
        }
        s = splimp();
        if (IF_QFULL(ifq)) {
@@ -385,6 +385,7 @@ sloutput(ifp, m, dst)
  * to send from the interface queue and map it to
  * the interface before starting output.
  */
  * to send from the interface queue and map it to
  * the interface before starting output.
  */
+void
 slstart(tp)
        register struct tty *tp;
 {
 slstart(tp)
        register struct tty *tp;
 {
@@ -417,12 +418,15 @@ slstart(tp)
                 */
                s = splimp();
                IF_DEQUEUE(&sc->sc_fastq, m);
                 */
                s = splimp();
                IF_DEQUEUE(&sc->sc_fastq, m);
-               if (m == NULL)
+               if (m)
+                       sc->sc_if.if_omcasts++;         /* XXX */
+               else
                        IF_DEQUEUE(&sc->sc_if.if_snd, m);
                splx(s);
                if (m == NULL)
                        return;
                sc->sc_if.if_lastchange = time;
                        IF_DEQUEUE(&sc->sc_if.if_snd, m);
                splx(s);
                if (m == NULL)
                        return;
                sc->sc_if.if_lastchange = time;
+
                /*
                 * If system is getting low on clists, just flush our
                 * output queue (if the stuff was important, it'll get
                /*
                 * If system is getting low on clists, just flush our
                 * output queue (if the stuff was important, it'll get
@@ -433,14 +437,13 @@ slstart(tp)
                        sc->sc_if.if_collisions++;
                        continue;
                }
                        sc->sc_if.if_collisions++;
                        continue;
                }
-
                /*
                 * The extra FRAME_END will start up a new packet, and thus
                 * will flush any accumulated garbage.  We do this whenever
                 * the line may have been idle for some time.
                 */
                if (tp->t_outq.c_cc == 0) {
                /*
                 * The extra FRAME_END will start up a new packet, and thus
                 * will flush any accumulated garbage.  We do this whenever
                 * the line may have been idle for some time.
                 */
                if (tp->t_outq.c_cc == 0) {
-                       ++sc->sc_bytessent;
+                       ++sc->sc_if.if_obytes;
                        (void) putc(FRAME_END, &tp->t_outq);
                }
 
                        (void) putc(FRAME_END, &tp->t_outq);
                }
 
@@ -471,7 +474,7 @@ slstart(tp)
                                         */
                                        if (b_to_q((char *)bp, cp - bp, &tp->t_outq))
                                                break;
                                         */
                                        if (b_to_q((char *)bp, cp - bp, &tp->t_outq))
                                                break;
-                                       sc->sc_bytessent += cp - bp;
+                                       sc->sc_if.if_obytes += cp - bp;
                                }
                                /*
                                 * If there are characters left in the mbuf,
                                }
                                /*
                                 * If there are characters left in the mbuf,
@@ -487,7 +490,7 @@ slstart(tp)
                                                (void) unputc(&tp->t_outq);
                                                break;
                                        }
                                                (void) unputc(&tp->t_outq);
                                                break;
                                        }
-                                       sc->sc_bytessent += 2;
+                                       sc->sc_if.if_obytes += 2;
                                }
                        }
                        MFREE(m, m2);
                                }
                        }
                        MFREE(m, m2);
@@ -506,10 +509,9 @@ slstart(tp)
                        (void) putc(FRAME_END, &tp->t_outq);
                        sc->sc_if.if_collisions++;
                } else {
                        (void) putc(FRAME_END, &tp->t_outq);
                        sc->sc_if.if_collisions++;
                } else {
-                       ++sc->sc_bytessent;
+                       ++sc->sc_if.if_obytes;
                        sc->sc_if.if_opackets++;
                }
                        sc->sc_if.if_opackets++;
                }
-               sc->sc_if.if_obytes = sc->sc_bytessent;
        }
 }
 
        }
 }
 
@@ -559,6 +561,7 @@ sl_btom(sc, len)
 /*
  * tty interface receiver interrupt.
  */
 /*
  * tty interface receiver interrupt.
  */
+void
 slinput(c, tp)
        register int c;
        register struct tty *tp;
 slinput(c, tp)
        register int c;
        register struct tty *tp;
@@ -575,33 +578,33 @@ slinput(c, tp)
        if (!(tp->t_state&TS_CARR_ON))  /* XXX */
                return;
 
        if (!(tp->t_state&TS_CARR_ON))  /* XXX */
                return;
 
-       ++sc->sc_bytesrcvd;
        ++sc->sc_if.if_ibytes;
        c &= 0xff;                      /* XXX */
 
 #ifdef ABT_ESC
        ++sc->sc_if.if_ibytes;
        c &= 0xff;                      /* XXX */
 
 #ifdef ABT_ESC
-       if (sc->sc_flags & SC_ABORT) {
-               /* if we see an abort after "idle" time, count it */
-               if (c == ABT_ESC && time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
-                       sc->sc_abortcount++;
-                       /* record when the first abort escape arrived */
-                       if (sc->sc_abortcount == 1)
-                               sc->sc_starttime = time.tv_sec;
-               }
-               /*
-                * if we have an abort, see that we have not run out of time,
-                * or that we have an "idle" time after the complete escape
-                * sequence
-                */
-               if (sc->sc_abortcount) {
-                       if (time.tv_sec >= sc->sc_starttime + ABT_RECYCLE)
+       if (sc->sc_if.if_flags & IFF_DEBUG) {
+               if (c == ABT_ESC) {
+                       /*
+                        * If we have a previous abort, see whether
+                        * this one is within the time limit.
+                        */
+                       if (sc->sc_abortcount &&
+                           time.tv_sec >= sc->sc_starttime + ABT_WINDOW)
                                sc->sc_abortcount = 0;
                                sc->sc_abortcount = 0;
-                       if (sc->sc_abortcount >= ABT_SOFT &&
-                           time.tv_sec >= sc->sc_lasttime + ABT_WAIT) {
-                               slclose(tp);
-                               return;
+                       /*
+                        * If we see an abort after "idle" time, count it;
+                        * record when the first abort escape arrived.
+                        */
+                       if (time.tv_sec >= sc->sc_lasttime + ABT_IDLE) {
+                               if (++sc->sc_abortcount == 1)
+                                       sc->sc_starttime = time.tv_sec;
+                               if (sc->sc_abortcount >= ABT_COUNT) {
+                                       slclose(tp);
+                                       return;
+                               }
                        }
                        }
-               }
+               } else
+                       sc->sc_abortcount = 0;
                sc->sc_lasttime = time.tv_sec;
        }
 #endif
                sc->sc_lasttime = time.tv_sec;
        }
 #endif
@@ -640,18 +643,18 @@ slinput(c, tp)
                         * it's a reasonable packet, decompress it and then
                         * enable compression.  Otherwise, drop it.
                         */
                         * it's a reasonable packet, decompress it and then
                         * enable compression.  Otherwise, drop it.
                         */
-                       if (sc->sc_flags & SC_COMPRESS) {
+                       if (sc->sc_if.if_flags & SC_COMPRESS) {
                                len = sl_uncompress_tcp(&sc->sc_buf, len,
                                                        (u_int)c, &sc->sc_comp);
                                if (len <= 0)
                                        goto error;
                                len = sl_uncompress_tcp(&sc->sc_buf, len,
                                                        (u_int)c, &sc->sc_comp);
                                if (len <= 0)
                                        goto error;
-                       } else if ((sc->sc_flags & SC_AUTOCOMP) &&
+                       } else if ((sc->sc_if.if_flags & SC_AUTOCOMP) &&
                            c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
                                len = sl_uncompress_tcp(&sc->sc_buf, len,
                                                        (u_int)c, &sc->sc_comp);
                                if (len <= 0)
                                        goto error;
                            c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
                                len = sl_uncompress_tcp(&sc->sc_buf, len,
                                                        (u_int)c, &sc->sc_comp);
                                if (len <= 0)
                                        goto error;
-                               sc->sc_flags |= SC_COMPRESS;
+                               sc->sc_if.if_flags |= SC_COMPRESS;
                        } else
                                goto error;
                }
                        } else
                                goto error;
                }
@@ -689,13 +692,15 @@ newpack:
 /*
  * Process an ioctl request.
  */
 /*
  * Process an ioctl request.
  */
+int
 slioctl(ifp, cmd, data)
        register struct ifnet *ifp;
        int cmd;
        caddr_t data;
 {
        register struct ifaddr *ifa = (struct ifaddr *)data;
 slioctl(ifp, cmd, data)
        register struct ifnet *ifp;
        int cmd;
        caddr_t data;
 {
        register struct ifaddr *ifa = (struct ifaddr *)data;
-       int s = splimp(), error = 0;
+       register struct ifreq *ifr;
+       register int s = splimp(), error = 0;
 
        switch (cmd) {
 
 
        switch (cmd) {
 
@@ -711,10 +716,30 @@ slioctl(ifp, cmd, data)
                        error = EAFNOSUPPORT;
                break;
 
                        error = EAFNOSUPPORT;
                break;
 
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               ifr = (struct ifreq *)data;
+               if (ifr == 0) {
+                       error = EAFNOSUPPORT;           /* XXX */
+                       break;
+               }
+               switch (ifr->ifr_addr.sa_family) {
+
+#ifdef INET
+               case AF_INET:
+                       break;
+#endif
+
+               default:
+                       error = EAFNOSUPPORT;
+                       break;
+               }
+               break;
+#endif
+
        default:
                error = EINVAL;
        }
        splx(s);
        return (error);
 }
        default:
                error = EINVAL;
        }
        splx(s);
        return (error);
 }
-#endif