diff options
author | fjoe <fjoe@FreeBSD.org> | 2003-01-24 01:32:20 +0000 |
---|---|---|
committer | fjoe <fjoe@FreeBSD.org> | 2003-01-24 01:32:20 +0000 |
commit | fc2f60400f2eeb5b4d5322ee9d0bd0b218225fe4 (patch) | |
tree | ef3de707a3715f6bc27322be78dfbeaad1be3e98 | |
parent | 8a55a31618aea1ffbd4a75915958fdcb772c3236 (diff) | |
download | FreeBSD-src-fc2f60400f2eeb5b4d5322ee9d0bd0b218225fe4.zip FreeBSD-src-fc2f60400f2eeb5b4d5322ee9d0bd0b218225fe4.tar.gz |
- add support for IPX (tested with mount -t nwfs and mars_nwe),
IP fast forwarding, SIOCGIFADDR, setting hardware address (not currently
enabled in cm driver), multicasts (experimental)
- add ARC_MAX_DATA, use IF_HANDOFF, remove arc_sprintf() and some unused
variables
- if_simloop logic is made more similar to ethernet
- drop not ours packets early (if we are not in promiscous mode)
Submitted by: mark tinguely (partially)
-rw-r--r-- | sys/dev/cm/smc90cx6.c | 15 | ||||
-rw-r--r-- | sys/modules/arcnet/Makefile | 5 | ||||
-rw-r--r-- | sys/net/if.c | 2 | ||||
-rw-r--r-- | sys/net/if_arc.h | 5 | ||||
-rw-r--r-- | sys/net/if_arcsubr.c | 239 |
5 files changed, 173 insertions, 93 deletions
diff --git a/sys/dev/cm/smc90cx6.c b/sys/dev/cm/smc90cx6.c index 56f10b2..df4c3e7 100644 --- a/sys/dev/cm/smc90cx6.c +++ b/sys/dev/cm/smc90cx6.c @@ -44,7 +44,7 @@ /* #define CMSOFTCOPY */ #define CMRETRANSMIT /**/ -#undef CM_DEBUG +/* #define CM_DEBUG */ #include <sys/param.h> #include <sys/systm.h> @@ -346,7 +346,7 @@ cm_attach(sc, unit) #endif } - if_printf(ifp, "link addr 0x%02x(%d)\n", linkaddress, linkaddress); + if_printf(ifp, "link addr 0x%02x (%d)\n", linkaddress, linkaddress); return 0; } @@ -531,7 +531,7 @@ cm_start(ifp) if (m->m_len < 2) m = m_pullup(m, 2); #endif - cm_ram_ptr = buffer*512; + cm_ram_ptr = buffer * 512; if (m == 0) return; @@ -666,7 +666,7 @@ cm_srint(vsc) * (2*sizeof(ulong) - CM_HDRNEWLEN)), packet type dependent. */ - cm_ram_ptr = buffer*512; + cm_ram_ptr = buffer * 512; offset = GETMEM(cm_ram_ptr + 2); if (offset) len = 256 - offset; @@ -844,7 +844,7 @@ cmintr(arg) return; do { -#if defined(CM_DEBUG) && (CM_DEBUG>1) +#if defined(CM_DEBUG) && (CM_DEBUG > 1) if_printf(ifp, "intr: status 0x%02x, intmask 0x%02x\n", isr, sc->sc_intmask); #endif @@ -905,7 +905,7 @@ cmintr(arg) buffer = sc->sc_rx_act; /* look if buffer is marked invalid: */ - if (GETMEM(buffer*512) == 0) { + if (GETMEM(buffer * 512) == 0) { /* * invalid marked buffer (or illegally * configured sender) @@ -959,7 +959,7 @@ cmintr(arg) isr = GETREG(CMSTAT); maskedisr = isr & sc->sc_intmask; } while (maskedisr); -#if defined(CM_DEBUG) && (CM_DEBUG>1) +#if defined(CM_DEBUG) && (CM_DEBUG > 1) if_printf(ifp, "intr (exit): status 0x%02x, intmask 0x%02x\n", isr, sc->sc_intmask); #endif @@ -1008,6 +1008,7 @@ cm_ioctl(ifp, command, data) switch (command) { case SIOCSIFADDR: + case SIOCGIFADDR: case SIOCADDMULTI: case SIOCDELMULTI: case SIOCSIFMTU: diff --git a/sys/modules/arcnet/Makefile b/sys/modules/arcnet/Makefile index 9132566..ab1d961 100644 --- a/sys/modules/arcnet/Makefile +++ b/sys/modules/arcnet/Makefile @@ -4,7 +4,7 @@ KMOD= arcnet SRCS= if_arcsubr.c -SRCS+= opt_inet.h opt_inet6.h +SRCS+= opt_inet.h opt_inet6.h opt_ipx.h EXPORT_SYMS= arc_frag_init \ arc_frag_next \ @@ -19,4 +19,7 @@ EXPORT_SYMS= arc_frag_init \ opt_inet.h opt_inet6.h: echo "#define INET 1" > ${.TARGET} +opt_ipx.h: + echo "#define IPX 1" > ${.TARGET} + .include <bsd.kmod.mk> diff --git a/sys/net/if.c b/sys/net/if.c index 04f8f75..d9b3dad 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1950,6 +1950,8 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) case IFT_ISO88025: case IFT_L2VLAN: bcopy(lladdr, ((struct arpcom *)ifp->if_softc)->ac_enaddr, len); + /* FALLTHROUGH */ + case IFT_ARCNET: bcopy(lladdr, LLADDR(sdl), len); break; default: diff --git a/sys/net/if_arc.h b/sys/net/if_arc.h index 9f2da93..9af5dec 100644 --- a/sys/net/if_arc.h +++ b/sys/net/if_arc.h @@ -77,12 +77,12 @@ struct arc_header { #define ARC_HDRNEWLEN 6 #define ARC_HDRNEWLEN_EXC 10 -/* these lengths are data link layer length - 2*ARC_ADDR_LEN */ +/* these lengths are data link layer length - 2 * ARC_ADDR_LEN */ #define ARC_MIN_LEN 1 #define ARC_MIN_FORBID_LEN 254 #define ARC_MAX_FORBID_LEN 256 #define ARC_MAX_LEN 508 - +#define ARC_MAX_DATA 504 /* RFC 1051 */ #define ARCTYPE_IP_OLD 240 /* IP protocol */ @@ -134,7 +134,6 @@ extern int arc_ipmtu; /* XXX new ip only, no RFC 1051! */ void arc_ifattach(struct ifnet *, u_int8_t); void arc_ifdetach(struct ifnet *); void arc_storelladdr(struct ifnet *, u_int8_t); -char *arc_sprintf(u_int8_t *); int arc_isphds(int); void arc_input(struct ifnet *, struct mbuf *); int arc_output(struct ifnet *, struct mbuf *, diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index 0fffe8d..1fc68c3 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -40,6 +40,7 @@ */ #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_ipx.h" #include <sys/param.h> #include <sys/systm.h> @@ -73,16 +74,24 @@ #include <netinet6/nd6.h> #endif +#ifdef IPX +#include <netipx/ipx.h> +#include <netipx/ipx_if.h> +#endif + MODULE_VERSION(arcnet, 1); #define ARCNET_ALLOW_BROKEN_ARP static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); +static int arc_resolvemulti(struct ifnet *, struct sockaddr **, + struct sockaddr *); u_int8_t arcbroadcastaddr = 0; #define senderr(e) { error = (e); goto bad;} -#define SIN(s) ((struct sockaddr_in *)s) +#define SIN(s) ((struct sockaddr_in *)s) +#define SIPX(s) ((struct sockaddr_ipx *)s) /* * ARCnet output routine. @@ -96,23 +105,18 @@ arc_output(ifp, m, dst, rt0) struct sockaddr *dst; struct rtentry *rt0; { - struct mbuf *mcopy; struct rtentry *rt; struct arccom *ac; struct arc_header *ah; - struct arphdr *arph; int error; u_int8_t atype, adst; -#if __FreeBSD_version < 500000 - int s; -#endif + int loop_copy = 0; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) return(ENETDOWN); /* m, m1 aren't initialized yet */ error = 0; ac = (struct arccom *)ifp; - mcopy = NULL; if ((rt = rt0)) { if ((rt->rt_flags & RTF_UP) == 0) { @@ -151,10 +155,6 @@ arc_output(ifp, m, dst, rt0) else if (!arpresolve(ifp, rt, m, dst, &adst, rt0)) return 0; /* not resolved yet */ - /* If broadcasting on a simplex interface, loopback a copy */ - if ((m->m_flags & (M_BCAST|M_MCAST)) && - (ifp->if_flags & IFF_SIMPLEX)) - mcopy = m_copy(m, 0, (int)M_COPYALL); atype = (ifp->if_flags & IFF_LINK0) ? ARCTYPE_IP_OLD : ARCTYPE_IP; break; @@ -171,8 +171,17 @@ arc_output(ifp, m, dst, rt0) atype = ARCTYPE_INET6; break; #endif +#ifdef IPX + case AF_IPX: + adst = SIPX(dst)->sipx_addr.x_host.c_host[5]; + atype = ARCTYPE_IPX; + if (adst == 0xff) + adst = arcbroadcastaddr; + break; +#endif case AF_UNSPEC: + loop_copy = -1; ah = (struct arc_header *)dst->sa_data; adst = ah->arc_dhost; atype = ah->arc_type; @@ -188,9 +197,8 @@ arc_output(ifp, m, dst, rt0) * However, e.g., AmiTCP 3.0Beta used it... we make this * switchable for emergency cases. Not perfect, but... */ - arph = mtod(m, struct arphdr *); if (ifp->if_flags & IFF_LINK2) - arph->ar_pro = atype - 1; + mtod(m, struct arphdr *)->ar_pro = atype - 1; #endif } break; @@ -200,9 +208,6 @@ arc_output(ifp, m, dst, rt0) senderr(EAFNOSUPPORT); } - if (mcopy) - (void) if_simloop(ifp, mcopy, dst->sa_family, 0); - M_PREPEND(m, ARC_HDRLEN, M_NOWAIT); if (m == 0) senderr(ENOBUFS); @@ -211,31 +216,23 @@ arc_output(ifp, m, dst, rt0) ah->arc_dhost = adst; ah->arc_shost = *IF_LLADDR(ifp); - BPF_MTAP(ifp, m); + if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { + if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { + struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); -#if __FreeBSD_version < 500000 - s = splimp(); - - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(s); - senderr(ENOBUFS); + (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); + } else if (ah->arc_dhost == ah->arc_shost) { + (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); + return (0); /* XXX */ + } } - ifp->if_obytes += m->m_pkthdr.len; - IF_ENQUEUE(&ifp->if_snd, m); - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); - splx(s); -#else + + BPF_MTAP(ifp, m); + if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) { m = 0; senderr(ENOBUFS); } -#endif return (error); @@ -277,7 +274,7 @@ arc_frag_next(ifp) return m; ++ac->ac_seqid; /* make the seqid unique */ - tfrags = (m->m_pkthdr.len + 503) / 504; + tfrags = (m->m_pkthdr.len + ARC_MAX_DATA - 1) / ARC_MAX_DATA; ac->fsflag = 2 * tfrags - 3; ac->sflag = 0; ac->rsflag = ac->fsflag; @@ -292,7 +289,7 @@ arc_frag_next(ifp) /* split out next fragment and return it */ if (ac->sflag < ac->fsflag) { /* we CAN'T have short packets here */ - ac->curr_frag = m_split(m, 504, M_NOWAIT); + ac->curr_frag = m_split(m, ARC_MAX_DATA, M_NOWAIT); if (ac->curr_frag == 0) { m_freem(m); return 0; @@ -523,12 +520,6 @@ arc_input(ifp, m) struct arc_header *ah; struct ifqueue *inq; u_int8_t atype; -#ifdef INET - struct arphdr *arph; -#endif -#if __FreeBSD_version < 500000 - int s; -#endif if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); @@ -543,10 +534,17 @@ arc_input(ifp, m) BPF_MTAP(ifp, m); ah = mtod(m, struct arc_header *); + /* does this belong to us? */ + if ((ifp->if_flags & IFF_PROMISC) != 0 + && ah->arc_dhost != arcbroadcastaddr + && ah->arc_dhost != *IF_LLADDR(ifp)) { + m_freem(m); + return; + } ifp->if_ibytes += m->m_pkthdr.len; - if (arcbroadcastaddr == ah->arc_dhost) { + if (ah->arc_dhost == arcbroadcastaddr) { m->m_flags |= M_BCAST|M_MCAST; ifp->if_imcasts++; } @@ -556,12 +554,16 @@ arc_input(ifp, m) #ifdef INET case ARCTYPE_IP: m_adj(m, ARC_HDRNEWLEN); + if (ipflow_fastforward(m)) + return; schednetisr(NETISR_IP); inq = &ipintrq; break; case ARCTYPE_IP_OLD: m_adj(m, ARC_HDRLEN); + if (ipflow_fastforward(m)) + return; schednetisr(NETISR_IP); inq = &ipintrq; break; @@ -589,7 +591,6 @@ arc_input(ifp, m) m_adj(m, ARC_HDRLEN); schednetisr(NETISR_ARP); inq = &arpintrq; - arph = mtod(m, struct arphdr *); #ifdef ARCNET_ALLOW_BROKEN_ARP mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); #endif @@ -602,39 +603,19 @@ arc_input(ifp, m) inq = &ip6intrq; break; #endif +#ifdef IPX + case ARCTYPE_IPX: + m_adj(m, ARC_HDRNEWLEN); + schednetisr(NETISR_IPX); + inq = &ipxintrq; + break; +#endif default: m_freem(m); return; } -#if __FreeBSD_version < 500000 - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - } else - IF_ENQUEUE(inq, m); - splx(s); -#else IF_HANDOFF(inq, m, NULL); -#endif -} - -/* - * Convert Arcnet address to printable (loggable) representation. - */ -static char digits[] = "0123456789abcdef"; -char * -arc_sprintf(ap) - u_int8_t *ap; -{ - static char arcbuf[3]; - char *cp = arcbuf; - - *cp++ = digits[*ap >> 4]; - *cp++ = digits[*ap++ & 0xf]; - *cp = 0; - return (arcbuf); } /* @@ -665,6 +646,7 @@ arc_ifattach(ifp, lla) ifp->if_addrlen = 1; ifp->if_hdrlen = ARC_HDRLEN; ifp->if_mtu = 1500; + ifp->if_resolvemulti = arc_resolvemulti; if (ifp->if_baudrate == 0) ifp->if_baudrate = 2500000; #if __FreeBSD_version < 500000 @@ -722,12 +704,42 @@ arc_ioctl(ifp, command, data) arp_ifinit(ifp, ifa); break; #endif +#ifdef IPX + /* + * XXX This code is probably wrong + */ + case AF_IPX: + { + struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); + + if (ipx_nullhost(*ina)) + ina->x_host.c_host[5] = *IF_LLADDR(ifp); + else + arc_storelladdr(ifp, ina->x_host.c_host[5]); + + /* + * Set new address + */ + ifp->if_init(ifp->if_softc); + break; + } +#endif default: ifp->if_init(ifp->if_softc); break; } break; + case SIOCGIFADDR: + { + struct sockaddr *sa; + + sa = (struct sockaddr *) &ifr->ifr_data; + bcopy(IF_LLADDR(ifp), + (caddr_t) sa->sa_data, ARC_ADDR_LEN); + } + break; + case SIOCADDMULTI: case SIOCDELMULTI: if (ifr == NULL) @@ -757,19 +769,82 @@ arc_ioctl(ifp, command, data) else ifp->if_mtu = ifr->ifr_mtu; break; + } -#if 0 - case SIOCGIFADDR: - { - struct sockaddr *sa; + return (error); +} - sa = (struct sockaddr *) & ifr->ifr_data; - bcopy(IFP2AC(ifp)->ac_enaddr, - (caddr_t) sa->sa_data, ETHER_ADDR_LEN); +/* based on ether_resolvemulti() */ +int +arc_resolvemulti(ifp, llsa, sa) + struct ifnet *ifp; + struct sockaddr **llsa; + struct sockaddr *sa; +{ + struct sockaddr_dl *sdl; + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; +#endif + + switch(sa->sa_family) { + case AF_LINK: + /* + * No mapping needed. Just check that it's a valid MC address. + */ + sdl = (struct sockaddr_dl *)sa; + if (*LLADDR(sdl) != arcbroadcastaddr) + return EADDRNOTAVAIL; + *llsa = 0; + return 0; +#ifdef INET + case AF_INET: + sin = (struct sockaddr_in *)sa; + if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) + return EADDRNOTAVAIL; + MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, + M_ZERO); + sdl->sdl_len = sizeof *sdl; + sdl->sdl_family = AF_LINK; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = IFT_ARCNET; + sdl->sdl_alen = ARC_ADDR_LEN; + *LLADDR(sdl) = 0; + *llsa = (struct sockaddr *)sdl; + return 0; +#endif +#ifdef INET6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *)sa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + /* + * An IP6 address of 0 means listen to all + * of the Ethernet multicast address used for IP6. + * (This is used for multicast routers.) + */ + ifp->if_flags |= IFF_ALLMULTI; + *llsa = 0; + return 0; } - break; + if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + return EADDRNOTAVAIL; + MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, + M_ZERO); + sdl->sdl_len = sizeof *sdl; + sdl->sdl_family = AF_LINK; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = IFT_ARCNET; + sdl->sdl_alen = ARC_ADDR_LEN; + *LLADDR(sdl) = 0; + *llsa = (struct sockaddr *)sdl; + return 0; #endif - } - return (error); + default: + /* + * Well, the text isn't quite right, but it's the name + * that counts... + */ + return EAFNOSUPPORT; + } } |