MULTICAST is now standard
[unix-history] / usr / src / sys / net / if_sl.c
index 43d0c41..dae3c25 100644 (file)
@@ -1,10 +1,10 @@
 /*
 /*
- * Copyright (c) 1987, 1989 Regents of the University of California.
+ * Copyright (c) 1987, 1989, 1992 Regents of the University of California.
  * All rights reserved.
  *
  * %sccs.include.redist.c%
  *
  * All rights reserved.
  *
  * %sccs.include.redist.c%
  *
- *     @(#)if_sl.c     7.22 (Berkeley) %G%
+ *     @(#)if_sl.c     7.31 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
  * 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 "proc.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 "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
 
 #else
 Huh? Slip without inet?
 #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
@@ -125,26 +123,13 @@ Huh? Slip without inet?
  * 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];
 
@@ -168,9 +153,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;
@@ -269,7 +256,9 @@ slclose(tp)
 /* ARGSUSED */
 sltioctl(tp, cmd, data, flag)
        struct tty *tp;
 /* ARGSUSED */
 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;
 {
        struct sl_softc *sc = (struct sl_softc *)tp->t_sc;
        int s;
@@ -279,18 +268,6 @@ sltioctl(tp, cmd, data, flag)
                *(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);
        }
@@ -308,6 +285,7 @@ sloutput(ifp, m, dst)
        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;
 
        /*
@@ -318,6 +296,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);
        }
 
@@ -330,16 +309,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
@@ -350,9 +327,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)) {
@@ -407,12 +384,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
@@ -423,14 +403,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);
                }
 
@@ -461,7 +440,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,
@@ -477,7 +456,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);
@@ -496,10 +475,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;
        }
 }
 
        }
 }
 
@@ -565,33 +543,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
@@ -630,18 +608,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;
                }
@@ -685,7 +663,8 @@ slioctl(ifp, cmd, data)
        caddr_t data;
 {
        register struct ifaddr *ifa = (struct ifaddr *)data;
        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) {
 
@@ -701,10 +680,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