From ee4a642ef6b80d885c32696c0683d0239112d08d Mon Sep 17 00:00:00 2001 From: Paul Richards Date: Sat, 19 Jun 1993 08:24:14 +0000 Subject: [PATCH] Added bpf support to if_is.c (Isolan driver) --- sys/i386/isa/if_is.c | 609 +++++++++++++++++++++++++++---------------- 1 file changed, 390 insertions(+), 219 deletions(-) diff --git a/sys/i386/isa/if_is.c b/sys/i386/isa/if_is.c index 3dfcb15d8551..e08da3bf1b2a 100644 --- a/sys/i386/isa/if_is.c +++ b/sys/i386/isa/if_is.c @@ -1,39 +1,3 @@ -/*- - * Copyright (c) 1990, 1991 William F. Jolitz. - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * 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. - * - * 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_is.c - */ - /* * Isolan AT 4141-0 Ethernet driver * Isolink 4110 @@ -42,22 +6,30 @@ * */ +/* TODO + +1) Add bpf and multicast support +2) Use better allocation of memory to card +3) Advertise for more packets until all transmit buffers are full +4) Add more of the timers/coutner e.g. arpcom.opackets etc. +*/ + #include "is.h" #if NIS > 0 +#include "bpfilter.h" + #include "param.h" -#include "systm.h" -#include "mbuf.h" -#include "buf.h" -#include "protosw.h" -#include "socket.h" -#include "ioctl.h" #include "errno.h" +#include "ioctl.h" +#include "mbuf.h" +#include "socket.h" #include "syslog.h" #include "net/if.h" +#include "net/if_dl.h" +#include "net/if_types.h" #include "net/netisr.h" -#include "net/route.h" #ifdef INET #include "netinet/in.h" @@ -72,36 +44,33 @@ #include "netns/ns_if.h" #endif +#if NBPFILTER > 0 +#include "net/bpf.h" +#include "net/bpfdesc.h" +#endif + #include "i386/isa/isa_device.h" #include "i386/isa/if_isreg.h" #include "i386/isa/icu.h" #include "vm/vm.h" -/* Function prototypes */ -int isprobe(), isattach(); -int isioctl(),isinit(),isstart(); -struct isa_driver isdriver = { - isprobe, isattach, "is", -}; - - -struct mbuf *isget(); #define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1518 +#define ETHER_ADDR_LEN 6 + /* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, - * is_if, which the routing code uses to locate the interface. + * arpcom.ac_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */ struct is_softc { - struct arpcom ns_ac; /* Ethernet common part */ -#define is_if ns_ac.ac_if /* network-visible interface */ -#define is_addr ns_ac.ac_enaddr /* hardware Ethernet address */ + struct arpcom arpcom; /* Ethernet common part */ int iobase; /* IO base address of card */ struct mds *rd; struct mds *td; @@ -110,10 +79,27 @@ struct is_softc { int last_rd; int last_td; int no_td; + caddr_t bpf; /* BPF "magic cookie" */ + } is_softc[NIS] ; struct init_block init_block[NIS]; +/* Function prototypes */ +int is_probe(),is_attach(),is_watchdog(); +int is_ioctl(),is_init(),is_start(); + +static inline void is_rint(int unit); +static inline void isread(struct is_softc*, char*, int); + +struct mbuf *isget(); + +struct isa_driver isdriver = { + is_probe, + is_attach, + "is" +}; + iswrcsr(unit,port,val) int unit; u_short port; @@ -137,15 +123,14 @@ u_short isrdcsr(unit,port) return(inw(iobase+RDP)); } -isprobe(isdev) - struct isa_device *isdev; +is_probe(isa_dev) + struct isa_device *isa_dev; { int val,i,s; - int unit = isdev->id_unit ; + int unit = isa_dev->id_unit ; register struct is_softc *is = &is_softc[unit]; - is->iobase = isdev->id_iobase; - s = splimp(); + is->iobase = isa_dev->id_iobase; /* Stop the lance chip, put it known state */ iswrcsr(unit,0,STOP); @@ -160,9 +145,9 @@ isprobe(isdev) iswrcsr(unit,3, 0); /* Extract board address */ - for(i=0; i < 6; i++) is->is_addr[i] = inb(is->iobase+(i*2)); + for(i=0;iarpcom.ac_enaddr[i]=inb(is->iobase+(i*2)); - splx(s); return (1); } @@ -171,13 +156,15 @@ isprobe(isdev) /* * Reset of interface. */ -isreset(unit, uban) - int unit, uban; +int is_reset(int unit) { + int s; if (unit >= NIS) return; + s = splnet(); printf("is%d: reset\n", unit); - isinit(unit); + is_init(unit); + s = splx(); } /* @@ -185,28 +172,71 @@ isreset(unit, uban) * record. System will initialize the interface when it is ready * to accept packets. We get the ethernet address here. */ -isattach(isdev) - struct isa_device *isdev; +int is_attach(isa_dev) + struct isa_device *isa_dev; { - int unit = isdev->id_unit; - register struct is_softc *is = &is_softc[unit]; - register struct ifnet *ifp = &is->is_if; + int unit = isa_dev->id_unit; + struct is_softc *is = &is_softc[unit]; + struct ifnet *ifp = &is->arpcom.ac_if; + struct ifaddr *ifa; + struct sockaddr_dl *sdl; + - /* Set up DMA */ - isa_dmacascade(isdev->id_drq); ifp->if_unit = unit; ifp->if_name = isdriver.name ; ifp->if_mtu = ETHERMTU; - printf (" ethernet address %s", ether_sprintf(is->is_addr)) ; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; - ifp->if_init = isinit; + ifp->if_init = is_init; ifp->if_output = ether_output; - ifp->if_start = isstart; - ifp->if_ioctl = isioctl; - ifp->if_reset = isreset; - ifp->if_watchdog = 0; + ifp->if_start = is_start; + ifp->if_ioctl = is_ioctl; + ifp->if_reset = is_reset; + ifp->if_watchdog = is_watchdog; + + /* Set up DMA */ + isa_dmacascade(isa_dev->id_drq); + if_attach(ifp); + +#if NBPFILTER > 0 + bpfattach(&is->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + +/* + * Search down the ifa address list looking for the AF_LINK type +entry + */ + ifa = ifp->if_addrlist; + while ((ifa != 0) && (ifa->ifa_addr != 0) && + (ifa->ifa_addr->sa_family != AF_LINK)) + ifa = ifa->ifa_next; + + /* + * If we find an AF_LINK type entry, we will fill + * in the hardware address for this interface. + */ + if ((ifa != 0) && (ifa->ifa_addr != 0)) { + /* + * Fill in the link level address for this interface + */ + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + sdl->sdl_type = IFT_ETHER; + sdl->sdl_alen = ETHER_ADDR_LEN; + sdl->sdl_slen = 0; + bcopy(is->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN); + } + + printf (" ethernet address %s", ether_sprintf(is->arpcom.ac_enaddr)) ; +} + +int +is_watchdog(unit) + int unit; +{ + log(LOG_ERR, "is%d: device timeout\n", unit); + + is_reset(unit); } @@ -235,13 +265,7 @@ static u_char lance_mem[NIS][MAXMEM]; init_block[unit].mode = 0; - /* Get ethernet address */ - for (i=0; i<6; i++) - init_block[unit].padr[i] = is_softc[unit].is_addr[i]; - /* Clear multicast address for now */ - for (i=0; i<8; i++) - init_block[unit].ladrf[i] = 0; init_block[unit].rdra = kvtop(is->rd); init_block[unit].rlen = ((kvtop(is->rd) >> 16) & 0xff) | (RLEN<<13); @@ -277,18 +301,19 @@ static u_char lance_mem[NIS][MAXMEM]; * Initialization of interface; set up initialization block * and transmit/receive descriptor rings. */ -isinit(unit) +is_init(unit) int unit; { register struct is_softc *is = &is_softc[unit]; - struct ifnet *ifp = &is->is_if; + struct ifnet *ifp = &is->arpcom.ac_if; int s; register i; + /* Address not known */ if (ifp->if_addrlist == (struct ifaddr *)0) return; + s = splnet(); is->last_rd = is->last_td = is->no_td = 0; - s = splimp(); /* Set up lance's memory area */ init_mem(unit); @@ -296,6 +321,20 @@ isinit(unit) /* Stop Lance to get access to other registers */ iswrcsr(unit,0,STOP); + /* Get ethernet address */ + for (i=0; iarpcom.ac_enaddr[i]; + +#if NBPFILTER > 0 + /* + * Initialize multicast address hashing registers to accept + * all multicasts (only used when in promiscuous mode) + */ + for (i = 0; i < 8; ++i) + init_block[unit].ladrf[i] = 0xff; +#endif + + /* I wish I knew what this was */ iswrcsr(unit,3,0); @@ -314,13 +353,15 @@ isinit(unit) if (isrdcsr(unit,0)&IDON) { /* Start lance */ iswrcsr(unit,0,STRT|IDON|INEA); - is->is_if.if_flags |= IFF_RUNNING; - isstart(ifp); + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + is_start(ifp); } else printf("Isolink card failed to initialise\n"); - splx(s); + (void) splx(s); } /* @@ -329,7 +370,7 @@ isinit(unit) * and map it to the interface before starting the output. * called only at splimp or interrupt level. */ -isstart(ifp) +is_start(ifp) struct ifnet *ifp; { int unit = ifp->if_unit; @@ -341,7 +382,7 @@ isstart(ifp) struct mds *cdm; - if ((is->is_if.if_flags & IFF_RUNNING) == 0) + if ((is->arpcom.ac_if.if_flags & IFF_RUNNING) == 0) return; do { @@ -349,7 +390,7 @@ isstart(ifp) if (cdm->flags&OWN) return; - IF_DEQUEUE(&is->is_if.if_snd, m); + IF_DEQUEUE(&is->arpcom.ac_if.if_snd, m); if (m == 0) return; @@ -365,6 +406,72 @@ isstart(ifp) buffer += m->m_len; len += m->m_len; } +#if NBPFILTER > 0 + if (is->bpf) { + u_short etype; + int off, datasize, resid; + struct ether_header *eh; + struct trailer_header { + u_short ether_type; + u_short ether_residual; + } trailer_header; + char ether_packet[ETHER_MAX_LEN]; + char *ep; + + ep = ether_packet; + + /* + * We handle trailers below: + * Copy ether header first, then residual data, + * then data. Put all this in a temporary buffer + * 'ether_packet' and send off to bpf. Since the + * system has generated this packet, we assume + * that all of the offsets in the packet are + * correct; if they're not, the system will almost + * certainly crash in m_copydata. + * We make no assumptions about how the data is + * arranged in the mbuf chain (i.e. how much + * data is in each mbuf, if mbuf clusters are + * used, etc.), which is why we use m_copydata + * to get the ether header rather than assume + * that this is located in the first mbuf. + */ + /* copy ether header */ + m_copydata(m0, 0, sizeof(struct ether_header), ep); + eh = (struct ether_header *) ep; + ep += sizeof(struct ether_header); + etype = ntohs(eh->ether_type); + if (etype >= ETHERTYPE_TRAIL && + etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { + datasize = ((etype - ETHERTYPE_TRAIL) << 9); + off = datasize + sizeof(struct ether_header); + + /* copy trailer_header into a data structure */ + m_copydata(m0, off, sizeof(struct trailer_header), + &trailer_header.ether_type); + + /* copy residual data */ + resid = trailer_header.ether_residual - + sizeof(struct trailer_header); + resid = ntohs(resid); + m_copydata(m0, off+sizeof(struct trailer_header), + resid, ep); + ep += resid; + + /* copy data */ + m_copydata(m0, sizeof(struct ether_header), + datasize, ep); + ep += datasize; + + /* restore original ether packet type */ + eh->ether_type = trailer_header.ether_type; + + bpf_tap(is->bpf, ether_packet, ep - ether_packet); + } else + bpf_mtap(is->bpf, m0); + } +#endif + m_freem(m0); len = MAX(len,ETHER_MIN_LEN); @@ -385,7 +492,7 @@ isstart(ifp) is->last_td=0; }while(++is->no_td < NTBUF); is->no_td = NTBUF; - is->is_if.if_flags |= IFF_OACTIVE; + is->arpcom.ac_if.if_flags |= IFF_OACTIVE; #if ISDEBUG >4 printf("no_td = %x, last_td = %x\n",is->no_td, is->last_td); #endif @@ -415,19 +522,23 @@ isintr(unit) } if (!(isr&RXON)) { printf("!(isr&RXON)\n"); - isreset(unit); + is_reset(unit); return(1); } if (!(isr&TXON)) { printf("!(isr&TXON)\n"); - isreset(unit); + is_reset(unit); return(1); } if (isr&RINT) { - isrint(unit); + /* reset watchdog timer */ + is->arpcom.ac_if.if_timer = 0; + is_rint(unit); } if (isr&TINT) { + /* reset watchdog timer */ + is->arpcom.ac_if.if_timer = 0; iswrcsr(unit,0,TINT|INEA); istint(unit); } @@ -438,7 +549,7 @@ istint(unit) int unit; { struct is_softc *is = &is_softc[unit]; - register struct ifnet *ifp = &is->is_if; + register struct ifnet *ifp = &is->arpcom.ac_if; int i,loopcount=0; struct mds *cdm; @@ -455,17 +566,17 @@ istint(unit) return; } loopcount++; - is->is_if.if_flags &= ~IFF_OACTIVE; + is->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; }while(--is->no_td > 0); - isstart(ifp); + is_start(ifp); } #define NEXTRDS \ if (++rmd == NRBUF) rmd=0, cdm=is->rd; else ++cdm -isrint(unit) - int unit; +/* only called from one place, so may as well integrate */ +static inline void is_rint(int unit) { register struct is_softc *is=&is_softc[unit]; register int rmd = is->last_rd; @@ -503,7 +614,7 @@ isrint(unit) is->last_rd = rmd; printf("is%d:Chained buffer\n",unit); if ((cdm->flags & (OWN|ERR|STP|ENP)) != ENP) { - isreset(unit); + is_reset(unit); return; } }else @@ -522,53 +633,78 @@ isrint(unit) #endif } /* while */ is->last_rd = rmd; -} /* isrint */ +} /* is_rint */ + /* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */ -isread(is, buf, len) - register struct is_softc *is; - char *buf; - int len; +static inline void isread(struct is_softc *is, char *buf, int len) { - register struct ether_header *eh; - struct mbuf *m; - int off, resid; - register struct ifqueue *inq; + register struct ether_header *eh; + struct mbuf *m; + int off, resid; + register struct ifqueue *inq; - /* - * Deal with trailer protocol: if type is trailer type - * get true type from first 16-bit word past data. - * Remember that type was trailer by setting off. - */ - eh = (struct ether_header *)buf; - eh->ether_type = ntohs((u_short)eh->ether_type); - len = len - sizeof(struct ether_header) - 4; -#define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) - if (eh->ether_type >= ETHERTYPE_TRAIL && - eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { - off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; - if (off >= ETHERMTU) return; /* sanity */ - eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *)); - resid = ntohs(*(nedataaddr(eh, off+2, u_short *))); - if (off + resid > len) return; /* sanity */ - len = off + resid; - } else off = 0; + /* + * Deal with trailer protocol: if type is trailer type + * get true type from first 16-bit word past data. + * Remember that type was trailer by setting off. + */ + eh = (struct ether_header *)buf; + eh->ether_type = ntohs((u_short)eh->ether_type); + len = len - sizeof(struct ether_header) - 4; +#define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) + if (eh->ether_type >= ETHERTYPE_TRAIL && + eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { + off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; + if (off >= ETHERMTU) return; /* sanity */ + eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *)); + resid = ntohs(*(nedataaddr(eh, off+2, u_short *))); + if (off + resid > len) return; /* sanity */ + len = off + resid; + } else off = 0; - if (len == 0) return; + if (len == 0) return; - /* - * Pull packet off interface. Off is nonzero if packet - * has trailing header; neget will then force this header - * information to be at the front, but we still have to drop - * the type and length which are at the front of any trailer data. - */ - m = isget(buf, len, off, &is->is_if); - if (m == 0) return; + /* + * Pull packet off interface. Off is nonzero if packet + * has trailing header; neget will then force this header + * information to be at the front, but we still have to drop + * the type and length which are at the front of any trailer data. + */ + m = isget(buf, len, off, &is->arpcom.ac_if); + if (m == 0) return; +#if NBPFILTER > 0 + /* + * Check if there's a BPF listener on this interface. + * If so, hand off the raw packet to bpf. + */ + if (is->bpf) { + bpf_mtap(is->bpf, m); - ether_input(&is->is_if, eh, m); + /* + * Note that the interface cannot be in promiscuous mode if + * there are no BPF listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + * + * XXX This test does not support multicasts. + */ + if ((is->arpcom.ac_if.if_flags & IFF_PROMISC) && + bcmp(eh->ether_dhost, is->arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0 && + bcmp(eh->ether_dhost, etherbroadcastaddr, + sizeof(eh->ether_dhost)) != 0) { + + m_freem(m); + return; + } + } +#endif + + + ether_input(&is->arpcom.ac_if, eh, m); } /* @@ -586,76 +722,76 @@ isread(is, buf, len) */ struct mbuf * isget(buf, totlen, off0, ifp) - caddr_t buf; - int totlen, off0; - struct ifnet *ifp; + caddr_t buf; + int totlen, off0; + struct ifnet *ifp; { - struct mbuf *top, **mp, *m, *p; - int off = off0, len; - register caddr_t cp = buf; - char *epkt; + struct mbuf *top, **mp, *m, *p; + int off = off0, len; + register caddr_t cp = buf; + char *epkt; - buf += sizeof(struct ether_header); - cp = buf; - epkt = cp + totlen; + buf += sizeof(struct ether_header); + cp = buf; + epkt = cp + totlen; - if (off) { - cp += off + 2 * sizeof(u_short); - totlen -= 2 * sizeof(u_short); - } + if (off) { + cp += off + 2 * sizeof(u_short); + totlen -= 2 * sizeof(u_short); + } - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) - return (0); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = totlen; - m->m_len = MHLEN; - - top = 0; - mp = ⊤ - while (totlen > 0) { - if (top) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) { - m_freem(top); - return (0); - } - m->m_len = MLEN; - } - len = min(totlen, epkt - cp); - if (len >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if (m->m_flags & M_EXT) - m->m_len = len = min(len, MCLBYTES); - else - len = m->m_len; - } else { - /* - * Place initial small packet/header at end of mbuf. - */ - if (len < m->m_len) { - if (top == 0 && len + max_linkhdr <= m->m_len) - m->m_data += max_linkhdr; - m->m_len = len; - } else - len = m->m_len; - } - bcopy(cp, mtod(m, caddr_t), (unsigned)len); - cp += len; - *mp = m; - mp = &m->m_next; - totlen -= len; - if (cp == epkt) - cp = buf; - } - return (top); + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return (0); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; + top = 0; + mp = ⊤ + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return (0); + } + m->m_len = MLEN; + } + len = min(totlen, epkt - cp); + if (len >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = len = min(len, MCLBYTES); + else + len = m->m_len; + } else { + /* + * Place initial small packet/header at end of mbuf. + */ + if (len < m->m_len) { + if (top == 0 && len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; + } + bcopy(cp, mtod(m, caddr_t), (unsigned)len); + cp += len; + *mp = m; + mp = &m->m_next; + totlen -= len; + if (cp == epkt) + cp = buf; + } + return (top); } + /* * Process an ioctl request. */ -isioctl(ifp, cmd, data) +is_ioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data; @@ -664,8 +800,9 @@ isioctl(ifp, cmd, data) int unit = ifp->if_unit; struct is_softc *is = &is_softc[unit]; struct ifreq *ifr = (struct ifreq *)data; - int s = splimp(), error = 0; + int s, error = 0; + s = splnet(); switch (cmd) { @@ -675,60 +812,94 @@ isioctl(ifp, cmd, data) switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: - isinit(ifp->if_unit); /* before arpwhohas */ + is_init(ifp->if_unit); /* before arpwhohas */ + /* + * See if another station has *our* IP address. + * i.e.: There is an address conflict! If a + * conflict exists, a message is sent to the + * console. + */ ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; #endif #ifdef NS + /* + * XXX - This code is probably wrong + */ case AF_NS: { - register struct is_addr *ina = &(IA_SNS(ifa)->sns_addr); + register struct arpcom.ac_enaddr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) - ina->x_host = *(union ns_host *)(is->is_addr); + ina->x_host = *(union ns_host *)(is->arpcom.ac_enaddr); else { /* - * The manual says we can't change the address - * while the receiver is armed, - * so reset everything */ - ifp->if_flags &= ~IFF_RUNNING; bcopy((caddr_t)ina->x_host.c_host, - (caddr_t)is->is_addr, sizeof(is->is_addr)); + (caddr_t)is->arpcom.ac_enaddr, sizeof(is->arpcom.ac_enaddr)); } - isinit(ifp->if_unit); /* does ne_setaddr() */ + /* + * Set new address + */ + is_init(ifp->if_unit); break; } #endif default: - isinit(ifp->if_unit); + is_init(ifp->if_unit); break; } break; case SIOCSIFFLAGS: + /* + * If interface is marked down and it is running, then stop it + */ if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { - ifp->if_flags &= ~IFF_RUNNING; iswrcsr(unit,0,STOP); - } else if (ifp->if_flags & IFF_UP && - (ifp->if_flags & IFF_RUNNING) == 0) - isinit(ifp->if_unit); + ifp->if_flags &= ~IFF_RUNNING; + } else { + /* + * If interface is marked up and it is stopped, then start it + */ + if ((ifp->if_flags & IFF_UP) && + (ifp->if_flags & IFF_RUNNING) == 0) + is_init(ifp->if_unit); + } +#if NBPFILTER > 0 + if (ifp->if_flags & IFF_PROMISC) { + /* + * Set promiscuous mode on interface. + * XXX - for multicasts to work, we would need to + * write 1's in all bits of multicast + * hashing array. For now we assume that + * this was done in is_init(). + */ + init_block[unit].mode = PROM; + } else + /* + * XXX - for multicasts to work, we would need to + * rewrite the multicast hashing array with the + * proper hash (would have been destroyed above). + */ + { /* Don't know about this */}; +#endif break; #ifdef notdef case SIOCGHWADDR: - bcopy((caddr_t)is->is_addr, (caddr_t) &ifr->ifr_data, - sizeof(is->is_addr)); + bcopy((caddr_t)is->arpcom.ac_enaddr, (caddr_t) &ifr->ifr_data, + sizeof(is->arpcom.ac_enaddr)); break; #endif default: error = EINVAL; } - splx(s); + (void) splx(s); return (error); }