update from Ignatios Souvatzis
This commit is contained in:
parent
7d7d30315b
commit
d4f62dcb69
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_bah.c,v 1.7 1995/04/15 10:35:24 cgd Exp $ */
|
||||
/* $NetBSD: if_bah.c,v 1.8 1995/06/07 00:16:54 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Ignatios Souvatzis
|
||||
@ -172,7 +172,7 @@ struct bah_softc {
|
||||
|
||||
int bahmatch __P((struct device *, void *, void *));
|
||||
void bahattach __P((struct device *, struct device *, void *));
|
||||
void bah_ini __P((struct bah_softc *));
|
||||
void bah_init __P((struct bah_softc *));
|
||||
void bah_reset __P((struct bah_softc *));
|
||||
void bah_stop __P((struct bah_softc *));
|
||||
void bah_start __P((struct ifnet *));
|
||||
@ -766,7 +766,7 @@ bah_srint(sc, dummy)
|
||||
struct bah_softc *sc;
|
||||
void *dummy;
|
||||
{
|
||||
int buffer, buffer1, len, len1, amount, offset, s, i;
|
||||
int buffer, buffer1, len, len1, amount, offset, s, i, type;
|
||||
u_char __volatile *bah_ram_ptr;
|
||||
struct mbuf *m, *dst, *head;
|
||||
struct arc_header *ah;
|
||||
@ -816,25 +816,15 @@ bah_srint(sc, dummy)
|
||||
}
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_len = 0;
|
||||
|
||||
/*
|
||||
* Align so that IP packet will be longword aligned. Here we
|
||||
* assume that m_data of new packet is longword aligned.
|
||||
* When implementing RFC1201, we might have to change it to 2,
|
||||
* (2*sizeof(ulong) - ARC_HDRLEN - sizeof(splitflag) - sizeof(pckid))
|
||||
* possibly packet type dependent.
|
||||
* When implementing PHDS, we might have to change it to 2,
|
||||
* (2*sizeof(ulong) - ARC_HDRNEWLEN)), packet type dependent.
|
||||
*/
|
||||
|
||||
m->m_data += 1; /* sizeof(u_long) - ARC_HDRLEN */
|
||||
|
||||
head = m;
|
||||
|
||||
ah = mtod(head, struct arc_header *);
|
||||
bah_ram_ptr = sc->sc_base->buffers + buffer*512*2;
|
||||
|
||||
ah->arc_shost = bah_ram_ptr[0*2];
|
||||
ah->arc_dhost = bah_ram_ptr[1*2];
|
||||
offset = bah_ram_ptr[2*2];
|
||||
if (offset)
|
||||
len = 256 - offset;
|
||||
@ -842,9 +832,18 @@ bah_srint(sc, dummy)
|
||||
offset = bah_ram_ptr[3*2];
|
||||
len = 512 - offset;
|
||||
}
|
||||
m->m_pkthdr.len = len+2; /* whole packet length */
|
||||
m->m_len += 2; /* mbuf filled with ARCnet addresses */
|
||||
bah_ram_ptr += offset*2; /* ram buffer continues there */
|
||||
type = bah_ram_ptr[offset*2];
|
||||
m->m_data += 1 + arc_isphds(type);
|
||||
|
||||
head = m;
|
||||
ah = mtod(head, struct arc_header *);
|
||||
|
||||
ah->arc_shost = bah_ram_ptr[0*2];
|
||||
ah->arc_dhost = bah_ram_ptr[1*2];
|
||||
|
||||
m->m_pkthdr.len = len+2; /* whole packet length */
|
||||
m->m_len = 2; /* mbuf filled with ARCnet addresses */
|
||||
bah_ram_ptr += offset*2; /* ram buffer continues there */
|
||||
|
||||
while (len > 0) {
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_bahreg.h,v 1.3 1995/03/02 09:12:45 chopps Exp $ */
|
||||
/* $NetBSD: if_bahreg.h,v 1.4 1995/06/07 00:16:59 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Ignatios Souvatzis
|
||||
@ -48,16 +48,16 @@
|
||||
#define PRODUCT_2 9
|
||||
|
||||
struct a2060 {
|
||||
volatile u_char kick1;
|
||||
u_char pad1[16383];
|
||||
volatile u_char status; /* also intmask */
|
||||
u_char pad2;
|
||||
volatile u_char command;
|
||||
u_char pad3[16381];
|
||||
volatile u_char buffers[4096]; /* even bytes only */
|
||||
u_char pad4[12228];
|
||||
volatile u_char kick2;
|
||||
u_char pad5[16383];
|
||||
volatile u_int8_t kick1;
|
||||
u_int8_t pad1[16383];
|
||||
volatile u_int8_t status; /* also intmask */
|
||||
u_int8_t pad2;
|
||||
volatile u_int8_t command;
|
||||
u_int8_t pad3[16381];
|
||||
volatile u_int8_t buffers[4096]; /* even bytes only */
|
||||
u_int8_t pad4[12228];
|
||||
volatile u_int8_t kick2;
|
||||
u_int8_t pad5[16383];
|
||||
};
|
||||
|
||||
#define checkbyte buffers[0]
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: smc90cx6.c,v 1.7 1995/04/15 10:35:24 cgd Exp $ */
|
||||
/* $NetBSD: smc90cx6.c,v 1.8 1995/06/07 00:16:54 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Ignatios Souvatzis
|
||||
@ -172,7 +172,7 @@ struct bah_softc {
|
||||
|
||||
int bahmatch __P((struct device *, void *, void *));
|
||||
void bahattach __P((struct device *, struct device *, void *));
|
||||
void bah_ini __P((struct bah_softc *));
|
||||
void bah_init __P((struct bah_softc *));
|
||||
void bah_reset __P((struct bah_softc *));
|
||||
void bah_stop __P((struct bah_softc *));
|
||||
void bah_start __P((struct ifnet *));
|
||||
@ -766,7 +766,7 @@ bah_srint(sc, dummy)
|
||||
struct bah_softc *sc;
|
||||
void *dummy;
|
||||
{
|
||||
int buffer, buffer1, len, len1, amount, offset, s, i;
|
||||
int buffer, buffer1, len, len1, amount, offset, s, i, type;
|
||||
u_char __volatile *bah_ram_ptr;
|
||||
struct mbuf *m, *dst, *head;
|
||||
struct arc_header *ah;
|
||||
@ -816,25 +816,15 @@ bah_srint(sc, dummy)
|
||||
}
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_len = 0;
|
||||
|
||||
/*
|
||||
* Align so that IP packet will be longword aligned. Here we
|
||||
* assume that m_data of new packet is longword aligned.
|
||||
* When implementing RFC1201, we might have to change it to 2,
|
||||
* (2*sizeof(ulong) - ARC_HDRLEN - sizeof(splitflag) - sizeof(pckid))
|
||||
* possibly packet type dependent.
|
||||
* When implementing PHDS, we might have to change it to 2,
|
||||
* (2*sizeof(ulong) - ARC_HDRNEWLEN)), packet type dependent.
|
||||
*/
|
||||
|
||||
m->m_data += 1; /* sizeof(u_long) - ARC_HDRLEN */
|
||||
|
||||
head = m;
|
||||
|
||||
ah = mtod(head, struct arc_header *);
|
||||
bah_ram_ptr = sc->sc_base->buffers + buffer*512*2;
|
||||
|
||||
ah->arc_shost = bah_ram_ptr[0*2];
|
||||
ah->arc_dhost = bah_ram_ptr[1*2];
|
||||
offset = bah_ram_ptr[2*2];
|
||||
if (offset)
|
||||
len = 256 - offset;
|
||||
@ -842,9 +832,18 @@ bah_srint(sc, dummy)
|
||||
offset = bah_ram_ptr[3*2];
|
||||
len = 512 - offset;
|
||||
}
|
||||
m->m_pkthdr.len = len+2; /* whole packet length */
|
||||
m->m_len += 2; /* mbuf filled with ARCnet addresses */
|
||||
bah_ram_ptr += offset*2; /* ram buffer continues there */
|
||||
type = bah_ram_ptr[offset*2];
|
||||
m->m_data += 1 + arc_isphds(type);
|
||||
|
||||
head = m;
|
||||
ah = mtod(head, struct arc_header *);
|
||||
|
||||
ah->arc_shost = bah_ram_ptr[0*2];
|
||||
ah->arc_dhost = bah_ram_ptr[1*2];
|
||||
|
||||
m->m_pkthdr.len = len+2; /* whole packet length */
|
||||
m->m_len = 2; /* mbuf filled with ARCnet addresses */
|
||||
bah_ram_ptr += offset*2; /* ram buffer continues there */
|
||||
|
||||
while (len > 0) {
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: smc90cx6reg.h,v 1.3 1995/03/02 09:12:45 chopps Exp $ */
|
||||
/* $NetBSD: smc90cx6reg.h,v 1.4 1995/06/07 00:16:59 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Ignatios Souvatzis
|
||||
@ -48,16 +48,16 @@
|
||||
#define PRODUCT_2 9
|
||||
|
||||
struct a2060 {
|
||||
volatile u_char kick1;
|
||||
u_char pad1[16383];
|
||||
volatile u_char status; /* also intmask */
|
||||
u_char pad2;
|
||||
volatile u_char command;
|
||||
u_char pad3[16381];
|
||||
volatile u_char buffers[4096]; /* even bytes only */
|
||||
u_char pad4[12228];
|
||||
volatile u_char kick2;
|
||||
u_char pad5[16383];
|
||||
volatile u_int8_t kick1;
|
||||
u_int8_t pad1[16383];
|
||||
volatile u_int8_t status; /* also intmask */
|
||||
u_int8_t pad2;
|
||||
volatile u_int8_t command;
|
||||
u_int8_t pad3[16381];
|
||||
volatile u_int8_t buffers[4096]; /* even bytes only */
|
||||
u_int8_t pad4[12228];
|
||||
volatile u_int8_t kick2;
|
||||
u_int8_t pad5[16383];
|
||||
};
|
||||
|
||||
#define checkbyte buffers[0]
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_arc.h,v 1.4 1995/04/14 17:09:39 chopps Exp $ */
|
||||
/* $NetBSD: if_arc.h,v 1.5 1995/06/07 00:14:04 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
@ -41,7 +41,7 @@
|
||||
* don't know who uses this.
|
||||
*/
|
||||
struct arc_addr {
|
||||
u_char arc_addr_octet[1];
|
||||
u_int8_t arc_addr_octet[1];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -49,38 +49,75 @@ struct arc_addr {
|
||||
* as given to interface code.
|
||||
*/
|
||||
struct arc_header {
|
||||
u_char arc_shost;
|
||||
u_char arc_dhost;
|
||||
u_char arc_type;
|
||||
u_int8_t arc_shost;
|
||||
u_int8_t arc_dhost;
|
||||
u_int8_t arc_type;
|
||||
/*
|
||||
* only present for newstyle encoding with LL fragmentation.
|
||||
* Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
|
||||
*/
|
||||
u_int8_t arc_flag;
|
||||
u_int16_t arc_seqid;
|
||||
|
||||
/*
|
||||
* only present in exception packets (arc_flag == 0xff)
|
||||
*/
|
||||
u_int8_t arc_type2; /* same as arc_type */
|
||||
u_int8_t arc_flag2; /* real flag value */
|
||||
u_int16_t arc_seqid2; /* real seqid value */
|
||||
};
|
||||
|
||||
#define ARC_HDRLEN 3
|
||||
#define ARC_ADDR_LEN 1
|
||||
|
||||
#define ARC_HDRLEN 3
|
||||
#define ARC_HDRNEWLEN 6
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
/* RFC 1051 */
|
||||
#define ARCTYPE_IP_OLD 240 /* IP protocol */
|
||||
#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
|
||||
#define ARCTYPE_IP_OLD 240 /* IP protocol */
|
||||
#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
|
||||
|
||||
/* RFC 1201 */
|
||||
#define ARCTYPE_IP 212 /* IP protocol */
|
||||
#define ARCTYPE_ARP 213 /* address resolution protocol */
|
||||
#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
|
||||
#define ARCTYPE_IP 212 /* IP protocol */
|
||||
#define ARCTYPE_ARP 213 /* address resolution protocol */
|
||||
#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
|
||||
|
||||
#define ARCMTU 507
|
||||
#define ARCMIN 0
|
||||
#define ARCTYPE_ATALK 221 /* Appletalk */
|
||||
#define ARCTYPE_BANIAN 247 /* Banyan Vines */
|
||||
#define ARCTYPE_IPX 250 /* Novell IPX */
|
||||
|
||||
#define ARCMTU 507
|
||||
#define ARCMIN 0
|
||||
|
||||
struct arccom {
|
||||
struct ifnet ac_if; /* network-visible interface */
|
||||
u_char ac_anaddr; /* arcnet hardware address */
|
||||
/* only first byte used for arc */
|
||||
struct in_addr ac_ipaddr; /* copy of ip address- XXX */
|
||||
struct ifnet ac_if; /* network-visible interface */
|
||||
u_int8_t ac_anaddr; /* arcnet hardware address */
|
||||
struct in_addr ac_ipaddr; /* copy of ip address- XXX */
|
||||
|
||||
u_int16_t ac_seqid; /* seq. id used by PHDS encap. */
|
||||
|
||||
struct ac_frag {
|
||||
u_int8_t af_maxflag; /* from first packet */
|
||||
u_int8_t af_lastseen; /* last split flag seen */
|
||||
u_int16_t af_seqid;
|
||||
struct mbuf *af_packet;
|
||||
} ac_fragtab[256]; /* indexed by sender ll address */
|
||||
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
u_char arcbroadcastaddr;
|
||||
#ifdef _KERNEL
|
||||
u_int8_t arcbroadcastaddr;
|
||||
|
||||
void arc_ifattach __P((struct ifnet *));
|
||||
char *arc_sprintf __P((u_char *));
|
||||
void arc_input __P((struct ifnet *, struct mbuf *));
|
||||
int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *));
|
||||
void arc_ifattach __P((struct ifnet *));
|
||||
char *arc_sprintf __P((u_int8_t *));
|
||||
void arc_input __P((struct ifnet *, struct mbuf *));
|
||||
int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *));
|
||||
int arc_isphds __P((int));
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_arcsubr.c,v 1.3 1995/04/14 17:06:39 chopps Exp $ */
|
||||
/* $NetBSD: if_arcsubr.c,v 1.4 1995/06/07 00:13:52 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Ignatios Souvatzis
|
||||
@ -61,10 +61,27 @@
|
||||
#endif
|
||||
#include <netinet/if_arc.h>
|
||||
|
||||
u_char arcbroadcastaddr = 0;
|
||||
#ifndef ARC_PHDSMTU
|
||||
#define ARC_PHDSMTU 1500
|
||||
#endif
|
||||
|
||||
/* why isnt this in /sys/sys/mbuf.h?? */
|
||||
extern struct mbuf *m_split __P((struct mbuf *, int, int));
|
||||
static struct mbuf *arc_defrag __P((struct ifnet *, struct mbuf *));
|
||||
|
||||
/*
|
||||
* RC1201 requires us to have this configurable. We have it only per
|
||||
* machine at the moment... there is no generic "set mtu" ioctl, AFAICS.
|
||||
* Anyway, it is possible to binpatch this or set it per kernel config
|
||||
* option.
|
||||
*/
|
||||
#if ARC_PHDSMTU > 60480
|
||||
ERROR: The arc_phdsmtu is ARC_PHDSMTU, but must not exceed 60480.
|
||||
#endif
|
||||
u_int16_t arc_phdsmtu = ARC_PHDSMTU;
|
||||
u_int8_t arcbroadcastaddr = 0;
|
||||
|
||||
#define senderr(e) { error = (e); goto bad;}
|
||||
|
||||
#define SIN(s) ((struct sockaddr_in *)s)
|
||||
|
||||
/*
|
||||
@ -79,17 +96,24 @@ arc_output(ifp, m0, dst, rt0)
|
||||
struct sockaddr *dst;
|
||||
struct rtentry *rt0;
|
||||
{
|
||||
int s, error = 0;
|
||||
u_char atype, adst;
|
||||
register struct mbuf *m = m0;
|
||||
register struct rtentry *rt;
|
||||
struct mbuf *mcopy = (struct mbuf *)0;
|
||||
struct mbuf *m, *m1, *mcopy;
|
||||
struct rtentry *rt;
|
||||
struct arccom *ac;
|
||||
register struct arc_header *ah;
|
||||
int off, len = m->m_pkthdr.len;
|
||||
struct arccom *ac = (struct arccom *)ifp;
|
||||
int off, len;
|
||||
int s, error, newencoding;
|
||||
u_int8_t atype, adst;
|
||||
int tfrags, sflag, fsflag, rsflag;
|
||||
|
||||
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
|
||||
senderr(ENETDOWN);
|
||||
|
||||
error = newencoding = 0;
|
||||
ac = (struct arccom *)ifp;
|
||||
m = m0;
|
||||
len = m->m_pkthdr.len;
|
||||
mcopy = m1 = NULL;
|
||||
|
||||
ifp->if_lastchange = time;
|
||||
if (rt = rt0) {
|
||||
if ((rt->rt_flags & RTF_UP) == 0) {
|
||||
@ -113,8 +137,8 @@ arc_output(ifp, m0, dst, rt0)
|
||||
time.tv_sec < rt->rt_rmx.rmx_expire)
|
||||
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
|
||||
}
|
||||
switch (dst->sa_family) {
|
||||
|
||||
switch (dst->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
|
||||
@ -130,9 +154,16 @@ arc_output(ifp, m0, dst, rt0)
|
||||
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
|
||||
mcopy = m_copy(m, 0, (int)M_COPYALL);
|
||||
off = m->m_pkthdr.len - m->m_len;
|
||||
atype = ARCTYPE_IP_OLD;
|
||||
if (ifp->if_flags & IFF_LINK0) {
|
||||
atype = ARCTYPE_IP;
|
||||
newencoding = 1;
|
||||
} else {
|
||||
atype = ARCTYPE_IP_OLD;
|
||||
newencoding = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case AF_UNSPEC:
|
||||
ah = (struct arc_header *)dst->sa_data;
|
||||
adst = ah->arc_dhost;
|
||||
@ -145,9 +176,9 @@ arc_output(ifp, m0, dst, rt0)
|
||||
senderr(EAFNOSUPPORT);
|
||||
}
|
||||
|
||||
|
||||
if (mcopy)
|
||||
(void) looutput(ifp, mcopy, dst, rt);
|
||||
|
||||
/*
|
||||
* Add local net header. If no space in first mbuf,
|
||||
* allocate another.
|
||||
@ -157,37 +188,308 @@ arc_output(ifp, m0, dst, rt0)
|
||||
* the wire. At this point, it contains source, destination and
|
||||
* packet type.
|
||||
*/
|
||||
M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
ah = mtod(m, struct arc_header *);
|
||||
ah->arc_type = atype;
|
||||
ah->arc_dhost= adst;
|
||||
ah->arc_shost= ac->ac_anaddr;
|
||||
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);
|
||||
}
|
||||
IF_ENQUEUE(&ifp->if_snd, m);
|
||||
if ((ifp->if_flags & IFF_OACTIVE) == 0)
|
||||
(*ifp->if_start)(ifp);
|
||||
splx(s);
|
||||
if (newencoding) {
|
||||
++ac->ac_seqid; /* make the seqid unique */
|
||||
|
||||
tfrags = (len + 503) / 504;
|
||||
fsflag = 2*tfrags-3;
|
||||
sflag = 0;
|
||||
rsflag = fsflag;
|
||||
|
||||
while (sflag < fsflag) {
|
||||
/* we CAN'T have short packets here */
|
||||
m1 = m_split(m, 504, M_DONTWAIT);
|
||||
if (m1 == 0)
|
||||
senderr(ENOBUFS);
|
||||
|
||||
M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
m = m_pullup(m,ARC_HDRNEWLEN);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
|
||||
ah = mtod(m, struct arc_header *);
|
||||
ah->arc_type = atype;
|
||||
ah->arc_dhost = adst;
|
||||
ah->arc_shost = ac->ac_anaddr;
|
||||
ah->arc_flag = rsflag;
|
||||
ah->arc_seqid = ac->ac_seqid;
|
||||
|
||||
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);
|
||||
}
|
||||
IF_ENQUEUE(&ifp->if_snd, m);
|
||||
if ((ifp->if_flags & IFF_OACTIVE) == 0)
|
||||
(*ifp->if_start)(ifp);
|
||||
splx(s);
|
||||
|
||||
ifp->if_obytes += len + ARC_HDRLEN;
|
||||
/* we don't count the hardwares lenght bytes here */
|
||||
ifp->if_obytes += 504 + ARC_HDRNEWLEN;
|
||||
|
||||
m = m1;
|
||||
len -= 504;
|
||||
sflag += 2;
|
||||
rsflag = sflag;
|
||||
}
|
||||
m1 = NULL;
|
||||
|
||||
M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
m = m_pullup(m, ARC_HDRNEWLEN);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
|
||||
ah = mtod(m, struct arc_header *);
|
||||
ah->arc_type = atype;
|
||||
ah->arc_flag = sflag;
|
||||
ah->arc_seqid= ac->ac_seqid;
|
||||
|
||||
/* here we can have small, especially forbidden packets */
|
||||
|
||||
if ((len >= ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) &&
|
||||
(len <= ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) {
|
||||
|
||||
M_PREPEND(m, 4, M_DONTWAIT);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
|
||||
m = m_pullup(m, ARC_HDRNEWLEN);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
|
||||
ah = mtod(m, struct arc_header *);
|
||||
ah->arc_type = atype;
|
||||
ah->arc_flag = 0xFF;
|
||||
ah->arc_seqid= 0xFFFF;
|
||||
len += 4;
|
||||
}
|
||||
|
||||
ah->arc_dhost= adst;
|
||||
ah->arc_shost= ac->ac_anaddr;
|
||||
|
||||
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);
|
||||
}
|
||||
IF_ENQUEUE(&ifp->if_snd, m);
|
||||
if ((ifp->if_flags & IFF_OACTIVE) == 0)
|
||||
(*ifp->if_start)(ifp);
|
||||
splx(s);
|
||||
|
||||
ifp->if_obytes += len + ARC_HDRNEWLEN;
|
||||
|
||||
} else {
|
||||
M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
ah = mtod(m, struct arc_header *);
|
||||
ah->arc_type = atype;
|
||||
ah->arc_dhost= adst;
|
||||
ah->arc_shost= ac->ac_anaddr;
|
||||
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);
|
||||
}
|
||||
IF_ENQUEUE(&ifp->if_snd, m);
|
||||
if ((ifp->if_flags & IFF_OACTIVE) == 0)
|
||||
(*ifp->if_start)(ifp);
|
||||
splx(s);
|
||||
|
||||
ifp->if_obytes += len + ARC_HDRLEN;
|
||||
}
|
||||
return (error);
|
||||
|
||||
bad:
|
||||
if (m1)
|
||||
m_freem(m1);
|
||||
if (m)
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Defragmenter. Returns mbuf if last packet found, else
|
||||
* NULL. frees imcoming mbuf as necessary.
|
||||
*/
|
||||
|
||||
__inline struct mbuf *
|
||||
arc_defrag(ifp, m)
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m;
|
||||
{
|
||||
struct arc_header *ah, *ah1;
|
||||
struct arccom *ac;
|
||||
struct ac_frag *af;
|
||||
struct mbuf *m1;
|
||||
char *s;
|
||||
int newflen;
|
||||
u_char src,dst,typ;
|
||||
|
||||
ac = (struct arccom *)ifp;
|
||||
|
||||
m = m_pullup(m, ARC_HDRNEWLEN);
|
||||
if (m == NULL) {
|
||||
++ifp->if_ierrors;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ah = mtod(m, struct arc_header *);
|
||||
typ = ah->arc_type;
|
||||
|
||||
if (!arc_isphds(typ))
|
||||
return m;
|
||||
|
||||
src = ah->arc_shost;
|
||||
dst = ah->arc_dhost;
|
||||
|
||||
if (ah->arc_flag == 0xff) {
|
||||
m_adj(m, 4);
|
||||
|
||||
m = m_pullup(m, ARC_HDRNEWLEN);
|
||||
if (m == NULL) {
|
||||
++ifp->if_ierrors;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ah = mtod(m, struct arc_header *);
|
||||
ah->arc_shost = src;
|
||||
ah->arc_dhost = dst;
|
||||
ah->arc_type = typ;
|
||||
}
|
||||
|
||||
af = &ac->ac_fragtab[src];
|
||||
m1 = af->af_packet;
|
||||
s = "debug code error";
|
||||
|
||||
if (ah->arc_flag & 1) {
|
||||
/*
|
||||
* first fragment. We always initialize, which is
|
||||
* about the right thing to do, as we only want to
|
||||
* accept one fragmented packet per src at a time.
|
||||
*/
|
||||
if (m1 != NULL)
|
||||
m_freem(m1);
|
||||
|
||||
af->af_packet = m;
|
||||
m1 = m;
|
||||
af->af_maxflag = ah->arc_flag;
|
||||
af->af_lastseen = 0;
|
||||
af->af_seqid = ah->arc_seqid;
|
||||
|
||||
return NULL;
|
||||
/* notreached */
|
||||
} else {
|
||||
/* check for unfragmented packet */
|
||||
if (ah->arc_flag == 0)
|
||||
return m;
|
||||
|
||||
/* do we have a first packet from that src? */
|
||||
if (m1 == NULL) {
|
||||
s = "no first frag";
|
||||
goto outofseq;
|
||||
}
|
||||
|
||||
ah1 = mtod(m1, struct arc_header *);
|
||||
|
||||
if (ah->arc_seqid != ah1->arc_seqid) {
|
||||
s = "seqid differs";
|
||||
goto outofseq;
|
||||
}
|
||||
|
||||
if (ah->arc_type != ah1->arc_type) {
|
||||
s = "type differs";
|
||||
goto outofseq;
|
||||
}
|
||||
|
||||
if (ah->arc_dhost != ah1->arc_dhost) {
|
||||
s = "dest host differs";
|
||||
goto outofseq;
|
||||
}
|
||||
|
||||
/* typ, seqid and dst are ok here. */
|
||||
|
||||
if (ah->arc_flag == af->af_lastseen) {
|
||||
m_freem(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ah->arc_flag == af->af_lastseen + 2) {
|
||||
/* ok, this is next fragment */
|
||||
af->af_lastseen = ah->arc_flag;
|
||||
m_adj(m,ARC_HDRNEWLEN);
|
||||
|
||||
/*
|
||||
* m_cat might free the first mbuf (with pkthdr)
|
||||
* in 2nd chain; therefore:
|
||||
*/
|
||||
|
||||
newflen = m->m_pkthdr.len;
|
||||
|
||||
m_cat(m1,m);
|
||||
|
||||
m1->m_pkthdr.len += newflen;
|
||||
|
||||
/* is it the last one? */
|
||||
if (af->af_lastseen > af->af_maxflag) {
|
||||
af->af_packet = NULL;
|
||||
return(m1);
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
s = "other reason";
|
||||
/* if all else fails, it is out of sequence, too */
|
||||
}
|
||||
outofseq:
|
||||
if (m1) {
|
||||
m_freem(m1);
|
||||
af->af_packet = NULL;
|
||||
}
|
||||
|
||||
if (m)
|
||||
m_freem(m);
|
||||
|
||||
log(LOG_INFO,"%s%d: got out of seq. packet: %s\n",
|
||||
ifp->if_name, ifp->if_unit, s);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* return 1 if Packet Header Definition Standard, else 0.
|
||||
* For now: old IP, old ARP aren't obviously. Lacking correct information,
|
||||
* we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS.
|
||||
* (Apple and Novell corporations were involved, among others, in PHDS work).
|
||||
* Easiest is to assume that everybody else uses that, too.
|
||||
*/
|
||||
int
|
||||
arc_isphds(type)
|
||||
int type;
|
||||
{
|
||||
return ((type != ARCTYPE_IP_OLD &&
|
||||
type != ARCTYPE_ARP_OLD));
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a received Arcnet packet;
|
||||
* the packet is in the mbuf chain m with
|
||||
@ -200,14 +502,20 @@ arc_input(ifp, m)
|
||||
{
|
||||
register struct arc_header *ah;
|
||||
register struct ifqueue *inq;
|
||||
u_char atype;
|
||||
u_int8_t atype;
|
||||
int s;
|
||||
|
||||
if ((ifp->if_flags & IFF_UP) == 0) {
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
ah = mtod(m,struct arc_header *);
|
||||
|
||||
/* possibly defragment: */
|
||||
m = arc_defrag(ifp, m);
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
ah = mtod(m, struct arc_header *);
|
||||
|
||||
ifp->if_lastchange = time;
|
||||
ifp->if_ibytes += m->m_pkthdr.len;
|
||||
@ -220,6 +528,12 @@ arc_input(ifp, m)
|
||||
atype = ah->arc_type;
|
||||
switch (atype) {
|
||||
#ifdef INET
|
||||
case ARCTYPE_IP:
|
||||
m_adj(m,ARC_HDRNEWLEN);
|
||||
schednetisr(NETISR_IP);
|
||||
inq = &ipintrq;
|
||||
break;
|
||||
|
||||
case ARCTYPE_IP_OLD:
|
||||
m_adj(m,ARC_HDRLEN);
|
||||
schednetisr(NETISR_IP);
|
||||
@ -246,7 +560,7 @@ arc_input(ifp, m)
|
||||
static char digits[] = "0123456789abcdef";
|
||||
char *
|
||||
arc_sprintf(ap)
|
||||
register u_char *ap;
|
||||
register u_int8_t *ap;
|
||||
{
|
||||
static char arcbuf[3];
|
||||
register char *cp = arcbuf;
|
||||
@ -266,14 +580,22 @@ arc_ifattach(ifp)
|
||||
{
|
||||
register struct ifaddr *ifa;
|
||||
register struct sockaddr_dl *sdl;
|
||||
register struct arccom *ac;
|
||||
|
||||
ifp->if_type = IFT_ARCNET;
|
||||
ifp->if_addrlen = 1;
|
||||
ifp->if_hdrlen = ARC_HDRLEN;
|
||||
ifp->if_mtu = ARCMTU;
|
||||
if (((struct arccom *)ifp)->ac_anaddr == 0) {
|
||||
log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts.\n\
|
||||
Please change it and ifconfig %s%d down up\n",
|
||||
if (ifp->if_flags & IFF_LINK0 && arc_phdsmtu > 60480)
|
||||
log(LOG_ERR,
|
||||
"%s%d: arc_phdsmtu is %d, but must not exceed 60480",
|
||||
ifp->if_name, ifp->if_unit, arc_phdsmtu);
|
||||
|
||||
ifp->if_mtu = (ifp->if_flags & IFF_LINK0 ? arc_phdsmtu : ARCMTU);
|
||||
ac = (struct arccom *)ifp;
|
||||
ac->ac_seqid = (time.tv_sec) & 0xFFFF; /* try to make seqid unique */
|
||||
if (ac->ac_anaddr == 0) {
|
||||
/* XXX this message isn't entirely clear, to me -- cgd */
|
||||
log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts. Please change it and ifconfig %s%d down up\n",
|
||||
ifp->if_name,ifp->if_unit,ifp->if_name,ifp->if_unit);
|
||||
}
|
||||
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_arc.h,v 1.4 1995/04/14 17:09:39 chopps Exp $ */
|
||||
/* $NetBSD: if_arc.h,v 1.5 1995/06/07 00:14:04 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
@ -41,7 +41,7 @@
|
||||
* don't know who uses this.
|
||||
*/
|
||||
struct arc_addr {
|
||||
u_char arc_addr_octet[1];
|
||||
u_int8_t arc_addr_octet[1];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -49,38 +49,75 @@ struct arc_addr {
|
||||
* as given to interface code.
|
||||
*/
|
||||
struct arc_header {
|
||||
u_char arc_shost;
|
||||
u_char arc_dhost;
|
||||
u_char arc_type;
|
||||
u_int8_t arc_shost;
|
||||
u_int8_t arc_dhost;
|
||||
u_int8_t arc_type;
|
||||
/*
|
||||
* only present for newstyle encoding with LL fragmentation.
|
||||
* Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
|
||||
*/
|
||||
u_int8_t arc_flag;
|
||||
u_int16_t arc_seqid;
|
||||
|
||||
/*
|
||||
* only present in exception packets (arc_flag == 0xff)
|
||||
*/
|
||||
u_int8_t arc_type2; /* same as arc_type */
|
||||
u_int8_t arc_flag2; /* real flag value */
|
||||
u_int16_t arc_seqid2; /* real seqid value */
|
||||
};
|
||||
|
||||
#define ARC_HDRLEN 3
|
||||
#define ARC_ADDR_LEN 1
|
||||
|
||||
#define ARC_HDRLEN 3
|
||||
#define ARC_HDRNEWLEN 6
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
/* RFC 1051 */
|
||||
#define ARCTYPE_IP_OLD 240 /* IP protocol */
|
||||
#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
|
||||
#define ARCTYPE_IP_OLD 240 /* IP protocol */
|
||||
#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
|
||||
|
||||
/* RFC 1201 */
|
||||
#define ARCTYPE_IP 212 /* IP protocol */
|
||||
#define ARCTYPE_ARP 213 /* address resolution protocol */
|
||||
#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
|
||||
#define ARCTYPE_IP 212 /* IP protocol */
|
||||
#define ARCTYPE_ARP 213 /* address resolution protocol */
|
||||
#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
|
||||
|
||||
#define ARCMTU 507
|
||||
#define ARCMIN 0
|
||||
#define ARCTYPE_ATALK 221 /* Appletalk */
|
||||
#define ARCTYPE_BANIAN 247 /* Banyan Vines */
|
||||
#define ARCTYPE_IPX 250 /* Novell IPX */
|
||||
|
||||
#define ARCMTU 507
|
||||
#define ARCMIN 0
|
||||
|
||||
struct arccom {
|
||||
struct ifnet ac_if; /* network-visible interface */
|
||||
u_char ac_anaddr; /* arcnet hardware address */
|
||||
/* only first byte used for arc */
|
||||
struct in_addr ac_ipaddr; /* copy of ip address- XXX */
|
||||
struct ifnet ac_if; /* network-visible interface */
|
||||
u_int8_t ac_anaddr; /* arcnet hardware address */
|
||||
struct in_addr ac_ipaddr; /* copy of ip address- XXX */
|
||||
|
||||
u_int16_t ac_seqid; /* seq. id used by PHDS encap. */
|
||||
|
||||
struct ac_frag {
|
||||
u_int8_t af_maxflag; /* from first packet */
|
||||
u_int8_t af_lastseen; /* last split flag seen */
|
||||
u_int16_t af_seqid;
|
||||
struct mbuf *af_packet;
|
||||
} ac_fragtab[256]; /* indexed by sender ll address */
|
||||
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
u_char arcbroadcastaddr;
|
||||
#ifdef _KERNEL
|
||||
u_int8_t arcbroadcastaddr;
|
||||
|
||||
void arc_ifattach __P((struct ifnet *));
|
||||
char *arc_sprintf __P((u_char *));
|
||||
void arc_input __P((struct ifnet *, struct mbuf *));
|
||||
int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *));
|
||||
void arc_ifattach __P((struct ifnet *));
|
||||
char *arc_sprintf __P((u_int8_t *));
|
||||
void arc_input __P((struct ifnet *, struct mbuf *));
|
||||
int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *));
|
||||
int arc_isphds __P((int));
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user