summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorfjoe <fjoe@FreeBSD.org>2003-01-24 01:32:20 +0000
committerfjoe <fjoe@FreeBSD.org>2003-01-24 01:32:20 +0000
commitfc2f60400f2eeb5b4d5322ee9d0bd0b218225fe4 (patch)
treeef3de707a3715f6bc27322be78dfbeaad1be3e98 /sys
parent8a55a31618aea1ffbd4a75915958fdcb772c3236 (diff)
downloadFreeBSD-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)
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/cm/smc90cx6.c15
-rw-r--r--sys/modules/arcnet/Makefile5
-rw-r--r--sys/net/if.c2
-rw-r--r--sys/net/if_arc.h5
-rw-r--r--sys/net/if_arcsubr.c239
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;
+ }
}
OpenPOWER on IntegriCloud