Latest fixes from Nesheim@cornell
[unix-history] / usr / src / sys / vax / if / if_en.c
index 109e7a1..89fe9bd 100644 (file)
@@ -1,4 +1,10 @@
-/*     if_en.c 6.1     83/07/29        */
+/*
+ * Copyright (c) 1982 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *     @(#)if_en.c     6.8 (Berkeley) %G%
+ */
 
 #include "en.h"
 
 
 #include "en.h"
 
  */
 #include "../machine/pte.h"
 
  */
 #include "../machine/pte.h"
 
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/mbuf.h"
-#include "../h/buf.h"
-#include "../h/protosw.h"
-#include "../h/socket.h"
-#include "../h/vmmac.h"
-#include "../h/errno.h"
-#include "../h/ioctl.h"
+#include "param.h"
+#include "systm.h"
+#include "mbuf.h"
+#include "buf.h"
+#include "protosw.h"
+#include "socket.h"
+#include "vmmac.h"
+#include "errno.h"
+#include "ioctl.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 #include "../net/route.h"
 #include "../netinet/in.h"
 #include "../netinet/in_systm.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 #include "../net/route.h"
 #include "../netinet/in.h"
 #include "../netinet/in_systm.h"
+#include "../netinet/in_var.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
+#ifdef PUP
 #include "../netpup/pup.h"
 #include "../netpup/ether.h"
 #include "../netpup/pup.h"
 #include "../netpup/ether.h"
+#endif
 
 #include "../vax/cpu.h"
 #include "../vax/mtpr.h"
 
 #include "../vax/cpu.h"
 #include "../vax/mtpr.h"
-#include "../vaxif/if_en.h"
-#include "../vaxif/if_enreg.h"
-#include "../vaxif/if_uba.h"
+#include "if_en.h"
+#include "if_enreg.h"
+#include "if_uba.h"
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/ubavar.h"
 
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/ubavar.h"
 
@@ -52,7 +61,7 @@ int   eninit(),enoutput(),enreset(),enioctl();
  * If you need to byte swap IP's in the system, define
  * this and do a SIOCSIFFLAGS at boot time.
  */
  * If you need to byte swap IP's in the system, define
  * this and do a SIOCSIFFLAGS at boot time.
  */
-#define        ENF_SWABIPS     0x100
+#define        ENF_SWABIPS     0x1000
 #endif
 
 /*
 #endif
 
 /*
@@ -70,6 +79,7 @@ int   eninit(),enoutput(),enreset(),enioctl();
 struct en_softc {
        struct  ifnet es_if;            /* network-visible interface */
        struct  ifuba es_ifuba;         /* UNIBUS resources */
 struct en_softc {
        struct  ifnet es_if;            /* network-visible interface */
        struct  ifuba es_ifuba;         /* UNIBUS resources */
+       short   es_host;                /* hardware host number */
        short   es_delay;               /* current output delay */
        short   es_mask;                /* mask for current output delay */
        short   es_lastx;               /* host last transmitted to */
        short   es_delay;               /* current output delay */
        short   es_mask;                /* mask for current output delay */
        short   es_lastx;               /* host last transmitted to */
@@ -113,6 +123,7 @@ enattach(ui)
        es->es_if.if_unit = ui->ui_unit;
        es->es_if.if_name = "en";
        es->es_if.if_mtu = ENMTU;
        es->es_if.if_unit = ui->ui_unit;
        es->es_if.if_name = "en";
        es->es_if.if_mtu = ENMTU;
+       es->es_if.if_flags = IFF_BROADCAST;
        es->es_if.if_init = eninit;
        es->es_if.if_output = enoutput;
        es->es_if.if_ioctl = enioctl;
        es->es_if.if_init = eninit;
        es->es_if.if_output = enoutput;
        es->es_if.if_ioctl = enioctl;
@@ -152,10 +163,9 @@ eninit(unit)
        register struct en_softc *es = &en_softc[unit];
        register struct uba_device *ui = eninfo[unit];
        register struct endevice *addr;
        register struct en_softc *es = &en_softc[unit];
        register struct uba_device *ui = eninfo[unit];
        register struct endevice *addr;
-       struct sockaddr_in *sin = (struct sockaddr_in *)&es->es_if.if_addr;
        int s;
 
        int s;
 
-       if (in_netof(sin->sin_addr) == 0)
+       if (es->es_if.if_addrlist == (struct ifaddr *)0)
                return;
        if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
            sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 
                return;
        if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
            sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 
@@ -175,10 +185,9 @@ eninit(unit)
        addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
        addr->en_istat = EN_IEN|EN_GO;
        es->es_oactive = 1;
        addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
        addr->en_istat = EN_IEN|EN_GO;
        es->es_oactive = 1;
-       es->es_if.if_flags |= IFF_UP|IFF_RUNNING;
+       es->es_if.if_flags |= IFF_RUNNING;
        enxint(unit);
        splx(s);
        enxint(unit);
        splx(s);
-       if_rtinit(&es->es_if, RTF_UP);
 }
 
 int    enalldelay = 0;
 }
 
 int    enalldelay = 0;
@@ -200,6 +209,7 @@ enstart(dev)
        struct uba_device *ui = eninfo[unit];
        register struct en_softc *es = &en_softc[unit];
        register struct endevice *addr;
        struct uba_device *ui = eninfo[unit];
        register struct en_softc *es = &en_softc[unit];
        register struct endevice *addr;
+       register struct en_header *en;
        struct mbuf *m;
        int dest;
 
        struct mbuf *m;
        int dest;
 
@@ -216,7 +226,9 @@ enstart(dev)
                es->es_oactive = 0;
                return;
        }
                es->es_oactive = 0;
                return;
        }
-       dest = mtod(m, struct en_header *)->en_dhost;
+       en = mtod(m, struct en_header *);
+       dest = en->en_dhost;
+       en->en_shost = es->es_host;
        es->es_olen = if_wubaput(&es->es_ifuba, m);
 #ifdef ENF_SWABIPS
        /*
        es->es_olen = if_wubaput(&es->es_ifuba, m);
 #ifdef ENF_SWABIPS
        /*
@@ -228,8 +240,6 @@ enstart(dev)
         * Should swab everybody, but this is a kludge anyway.
         */
        if (es->es_if.if_flags & ENF_SWABIPS) {
         * Should swab everybody, but this is a kludge anyway.
         */
        if (es->es_if.if_flags & ENF_SWABIPS) {
-               register struct en_header *en;
-
                en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
                if (en->en_type == ENTYPE_IP)
                        enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
                en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
                if (en->en_type == ENTYPE_IP)
                        enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
@@ -362,7 +372,7 @@ enrint(unit)
        struct mbuf *m;
        int len; short resid;
        register struct ifqueue *inq;
        struct mbuf *m;
        int len; short resid;
        register struct ifqueue *inq;
-       int off;
+       int off, s;
 
        es->es_if.if_ipackets++;
 
 
        es->es_if.if_ipackets++;
 
@@ -451,11 +461,13 @@ enrint(unit)
                goto setup;
        }
 
                goto setup;
        }
 
+       s = splimp();
        if (IF_QFULL(inq)) {
                IF_DROP(inq);
                m_freem(m);
        } else
                IF_ENQUEUE(inq, m);
        if (IF_QFULL(inq)) {
                IF_DROP(inq);
                m_freem(m);
        } else
                IF_ENQUEUE(inq, m);
+       splx(s);
 
 setup:
        /*
 
 setup:
        /*
@@ -486,12 +498,19 @@ enoutput(ifp, m0, dst)
 
 #ifdef INET
        case AF_INET:
 
 #ifdef INET
        case AF_INET:
-               dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
-               if (in_lnaof(*((struct in_addr *)&dest)) >= 0x100) {
+               {
+               struct in_addr in;
+
+               in = ((struct sockaddr_in *)dst)->sin_addr;
+               if (in_broadcast(in))
+                       dest = EN_BROADCAST;
+               else
+                       dest = in_lnaof(in);
+               }
+               if (dest >= 0x100) {
                        error = EPERM;          /* ??? */
                        goto bad;
                }
                        error = EPERM;          /* ??? */
                        goto bad;
                }
-               dest = (dest >> 24) & 0xff;
                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                /* need per host negotiation */
                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                /* need per host negotiation */
                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
@@ -547,7 +566,7 @@ gottype:
         */
        if (m->m_off > MMAXOFF ||
            MMINOFF + sizeof (struct en_header) > m->m_off) {
         */
        if (m->m_off > MMAXOFF ||
            MMINOFF + sizeof (struct en_header) > m->m_off) {
-               m = m_get(M_DONTWAIT, MT_HEADER);
+               MGET(m, M_DONTWAIT, MT_HEADER);
                if (m == 0) {
                        error = ENOBUFS;
                        goto bad;
                if (m == 0) {
                        error = ENOBUFS;
                        goto bad;
@@ -560,7 +579,7 @@ gottype:
                m->m_len += sizeof (struct en_header);
        }
        en = mtod(m, struct en_header *);
                m->m_len += sizeof (struct en_header);
        }
        en = mtod(m, struct en_header *);
-       en->en_shost = ifp->if_host[0];
+       /* add en_shost later */
        en->en_dhost = dest;
        en->en_type = htons((u_short)type);
 
        en->en_dhost = dest;
        en->en_type = htons((u_short)type);
 
@@ -596,18 +615,28 @@ enioctl(ifp, cmd, data)
        int cmd;
        caddr_t data;
 {
        int cmd;
        caddr_t data;
 {
-       struct ifreq *ifr = (struct ifreq *)data;
+       register struct en_softc *es = ((struct en_softc *)ifp);
+       struct ifaddr *ifa = (struct ifaddr *) data;
        int s = splimp(), error = 0;
        int s = splimp(), error = 0;
+       struct endevice *enaddr;
 
        switch (cmd) {
 
        case SIOCSIFADDR:
 
        switch (cmd) {
 
        case SIOCSIFADDR:
-               if (ifp->if_flags & IFF_RUNNING)
-                       if_rtinit(ifp, -1);     /* delete previous route */
-               ensetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
-               if (ifp->if_flags & IFF_RUNNING)
-                       if_rtinit(ifp, RTF_UP);
-               else
+               enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
+               es->es_host = (~enaddr->en_addr) & 0xff;
+               /*
+                * Attempt to check agreement of protocol address
+                * and board address.
+                */
+               switch (ifa->ifa_addr.sa_family) {
+               case AF_INET:
+                       if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host)
+                               return (EADDRNOTAVAIL);
+                       break;
+               }
+               ifp->if_flags |= IFF_UP;
+               if ((ifp->if_flags & IFF_RUNNING) == 0)
                        eninit(ifp->if_unit);
                break;
 
                        eninit(ifp->if_unit);
                break;
 
@@ -618,37 +647,24 @@ enioctl(ifp, cmd, data)
        return (error);
 }
 
        return (error);
 }
 
-ensetaddr(ifp, sin)
-       register struct ifnet *ifp;
-       register struct sockaddr_in *sin;
-{
-       struct endevice *enaddr;
-
-       ifp->if_net = in_netof(sin->sin_addr);
-       enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
-       ifp->if_host[0] = (~enaddr->en_addr) & 0xff;
-       sin = (struct sockaddr_in *)&ifp->if_addr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]);
-       sin = (struct sockaddr_in *)&ifp->if_broadaddr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
-       ifp->if_flags |= IFF_BROADCAST;
-}
-
 #ifdef ENF_SWABIPS
 /*
  * Swab bytes
  * Jeffrey Mogul, Stanford
  */
 enswab(from, to, n)
 #ifdef ENF_SWABIPS
 /*
  * Swab bytes
  * Jeffrey Mogul, Stanford
  */
 enswab(from, to, n)
-       register caddr_t *from, *to;
+       register unsigned char *from, *to;
        register int n;
 {
        register unsigned long temp;
        register int n;
 {
        register unsigned long temp;
+
+       if ((n <= 0) || (n > 0xFFFF)) {
+               printf("enswab: bad len %d\n", n);
+               return;
+       }
        
        n >>= 1; n++;
        
        n >>= 1; n++;
-#define        STEP    temp = *from++,*to++ = *from++,*to++ = temp
+#define        STEP    {temp = *from++;*to++ = *from++;*to++ = temp;}
        /* round to multiple of 8 */
        while ((--n) & 07)
                STEP;
        /* round to multiple of 8 */
        while ((--n) & 07)
                STEP;