summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authormycroft <mycroft@NetBSD.org>1994-05-13 06:01:27 +0000
committermycroft <mycroft@NetBSD.org>1994-05-13 06:01:27 +0000
commitd361acde189f4a167b7b6ec02287134e657f4eae (patch)
tree7bf8797a3a2b365a1ec7662c749ee5d882569858 /sys
parent9d020030acb40952b5263c6813b0cd1cf8968258 (diff)
Update to 4.4-Lite networking code, with a few local changes.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/sys_socket.c3
-rw-r--r--sys/kern/uipc_domain.c44
-rw-r--r--sys/kern/uipc_mbuf.c160
-rw-r--r--sys/kern/uipc_proto.c12
-rw-r--r--sys/kern/uipc_socket.c61
-rw-r--r--sys/kern/uipc_socket2.c3
-rw-r--r--sys/net/bpf.c561
-rw-r--r--sys/net/bpf.h36
-rw-r--r--sys/net/bpf_filter.c15
-rw-r--r--sys/net/bpfdesc.h25
-rw-r--r--sys/net/if.c175
-rw-r--r--sys/net/if.h212
-rw-r--r--sys/net/if_arp.h32
-rw-r--r--sys/net/if_dl.h13
-rw-r--r--sys/net/if_ethersubr.c410
-rw-r--r--sys/net/if_llc.h84
-rw-r--r--sys/net/if_loop.c53
17 files changed, 1224 insertions, 675 deletions
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 1cfc7c266f7..634738ba7e9 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)sys_socket.c 8.1 (Berkeley) 6/10/93
- * $Id: sys_socket.c,v 1.9 1994/05/11 10:27:22 mycroft Exp $
+ * $Id: sys_socket.c,v 1.10 1994/05/13 06:01:27 mycroft Exp $
*/
#include <sys/param.h>
@@ -43,7 +43,6 @@
#include <sys/socketvar.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/select.h>
#include <net/if.h>
#include <net/route.h>
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index d96b026a311..0345b84e099 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1993
+ * 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
@@ -30,32 +30,31 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)uipc_domain.c 7.9 (Berkeley) 3/4/91
- * $Id: uipc_domain.c,v 1.10 1994/05/07 00:46:28 cgd Exp $
+ * from: @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93
+ * $Id: uipc_domain.c,v 1.11 1994/05/13 06:01:30 mycroft Exp $
*/
-#include <sys/cdefs.h>
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/time.h>
#include <sys/kernel.h>
+#include <sys/systm.h>
#include <sys/proc.h>
#include <vm/vm.h>
#include <sys/sysctl.h>
+void pffasttimo __P((void *));
+void pfslowtimo __P((void *));
+
#define ADDDOMAIN(x) { \
extern struct domain __CONCAT(x,domain); \
__CONCAT(x,domain.dom_next) = domains; \
domains = &__CONCAT(x,domain); \
}
-void pffasttimo __P((void *));
-void pfslowtimo __P((void *));
-
void
domaininit()
{
@@ -75,16 +74,16 @@ domaininit()
#ifdef ISO
ADDDOMAIN(iso);
#endif
-#ifdef RMP
- ADDDOMAIN(rmp);
-#endif
#ifdef CCITT
ADDDOMAIN(ccitt);
#endif
-#ifdef IMP
+#ifdef notdef /* XXXX */
+#include "imp.h"
+#if NIMP > 0
ADDDOMAIN(imp);
#endif
#endif
+#endif
for (dp = domains; dp; dp = dp->dom_next) {
if (dp->dom_init)
@@ -146,6 +145,7 @@ found:
return (maybe);
}
+int
net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
int *name;
u_int namelen;
@@ -166,6 +166,20 @@ net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
*/
if (namelen < 3)
return (EISDIR); /* overloaded */
+ family = name[0];
+ protocol = name[1];
+
+ if (family == 0)
+ return (0);
+ for (dp = domains; dp; dp = dp->dom_next)
+ if (dp->dom_family == family)
+ goto found;
+ return (ENOPROTOOPT);
+found:
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+ if (pr->pr_protocol == protocol && pr->pr_sysctl)
+ return ((*pr->pr_sysctl)(name + 2, namelen - 2,
+ oldp, oldlenp, newp, newlen));
return (ENOPROTOOPT);
}
@@ -180,10 +194,9 @@ pfctlinput(cmd, sa)
for (dp = domains; dp; dp = dp->dom_next)
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_ctlinput)
- (*pr->pr_ctlinput)(cmd, sa, (caddr_t) 0);
+ (*pr->pr_ctlinput)(cmd, sa, (caddr_t)0);
}
-/* ARGSUSED */
void
pfslowtimo(arg)
void *arg;
@@ -198,7 +211,6 @@ pfslowtimo(arg)
timeout(pfslowtimo, NULL, hz/2);
}
-/* ARGSUSED */
void
pffasttimo(arg)
void *arg;
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 0c660b7acc7..2f5aef7c6f0 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1982, 1986, 1988, 1991 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1988, 1991, 1993
+ * 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
@@ -30,14 +30,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)uipc_mbuf.c 7.19 (Berkeley) 4/20/91
- * $Id: uipc_mbuf.c,v 1.8 1994/04/14 21:34:17 deraadt Exp $
+ * from: @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
+ * $Id: uipc_mbuf.c,v 1.9 1994/05/13 06:01:32 mycroft Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/malloc.h>
+#include <sys/map.h>
#define MBTYPES
#include <sys/mbuf.h>
#include <sys/kernel.h>
@@ -46,7 +47,6 @@
#include <sys/protosw.h>
#include <vm/vm.h>
-#include <vm/vm_kern.h>
extern vm_map_t mb_map;
struct mbuf *mbutl;
@@ -79,11 +79,12 @@ bad:
/* ARGSUSED */
m_clalloc(ncl, nowait)
register int ncl;
+ int nowait;
{
- int npg, mbx;
+ static int logged;
register caddr_t p;
register int i;
- static int logged;
+ int npg;
npg = ncl * CLSIZE;
p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait);
@@ -200,6 +201,7 @@ m_free(m)
return (n);
}
+void
m_freem(m)
register struct mbuf *m;
{
@@ -222,13 +224,13 @@ m_freem(m)
* copy junk along.
*/
struct mbuf *
-m_prepend(m, len, nowait)
+m_prepend(m, len, how)
register struct mbuf *m;
- int len, nowait;
+ int len, how;
{
struct mbuf *mn;
- MGET(mn, nowait, m->m_type);
+ MGET(mn, how, m->m_type);
if (mn == (struct mbuf *)NULL) {
m_freem(m);
return ((struct mbuf *)NULL);
@@ -295,7 +297,7 @@ m_copym(m, off0, len, wait)
n->m_pkthdr.len = len;
copyhdr = 0;
}
- n->m_len = MIN(len, m->m_len - off);
+ n->m_len = min(len, m->m_len - off);
if (m->m_flags & M_EXT) {
n->m_data = m->m_data + off;
mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
@@ -344,7 +346,7 @@ m_copydata(m, off, len, cp)
while (len > 0) {
if (m == 0)
panic("m_copydata");
- count = MIN(m->m_len - off, len);
+ count = min(m->m_len - off, len);
bcopy(mtod(m, caddr_t) + off, cp, count);
len -= count;
cp += count;
@@ -519,3 +521,137 @@ bad:
MPFail++;
return (0);
}
+
+/*
+ * Partition an mbuf chain in two pieces, returning the tail --
+ * all but the first len0 bytes. In case of failure, it returns NULL and
+ * attempts to restore the chain to its original state.
+ */
+struct mbuf *
+m_split(m0, len0, wait)
+ register struct mbuf *m0;
+ int len0, wait;
+{
+ register struct mbuf *m, *n;
+ unsigned len = len0, remain;
+
+ for (m = m0; m && len > m->m_len; m = m->m_next)
+ len -= m->m_len;
+ if (m == 0)
+ return (0);
+ remain = m->m_len - len;
+ if (m0->m_flags & M_PKTHDR) {
+ MGETHDR(n, wait, m0->m_type);
+ if (n == 0)
+ return (0);
+ n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
+ n->m_pkthdr.len = m0->m_pkthdr.len - len0;
+ m0->m_pkthdr.len = len0;
+ if (m->m_flags & M_EXT)
+ goto extpacket;
+ if (remain > MHLEN) {
+ /* m can't be the lead packet */
+ MH_ALIGN(n, 0);
+ n->m_next = m_split(m, len, wait);
+ if (n->m_next == 0) {
+ (void) m_free(n);
+ return (0);
+ } else
+ return (n);
+ } else
+ MH_ALIGN(n, remain);
+ } else if (remain == 0) {
+ n = m->m_next;
+ m->m_next = 0;
+ return (n);
+ } else {
+ MGET(n, wait, m->m_type);
+ if (n == 0)
+ return (0);
+ M_ALIGN(n, remain);
+ }
+extpacket:
+ if (m->m_flags & M_EXT) {
+ n->m_flags |= M_EXT;
+ n->m_ext = m->m_ext;
+ mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
+ m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
+ n->m_data = m->m_data + len;
+ } else {
+ bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
+ }
+ n->m_len = remain;
+ m->m_len = len;
+ n->m_next = m->m_next;
+ m->m_next = 0;
+ return (n);
+}
+/*
+ * Routine to copy from device local memory into mbufs.
+ */
+struct mbuf *
+m_devget(buf, totlen, off0, ifp, copy)
+ char *buf;
+ int totlen, off0;
+ struct ifnet *ifp;
+ void (*copy)();
+{
+ register struct mbuf *m;
+ struct mbuf *top = 0, **mp = &top;
+ register int off = off0, len;
+ register char *cp;
+ char *epkt;
+
+ cp = buf;
+ epkt = cp + totlen;
+ 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;
+
+ 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;
+ }
+ if (copy)
+ copy(cp, mtod(m, caddr_t), (unsigned)len);
+ else
+ 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);
+}
diff --git a/sys/kern/uipc_proto.c b/sys/kern/uipc_proto.c
index 7fa130d2163..7880710a087 100644
--- a/sys/kern/uipc_proto.c
+++ b/sys/kern/uipc_proto.c
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1982, 1986 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1993
+ * 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
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)uipc_proto.c 7.6 (Berkeley) 5/9/91
- * $Id: uipc_proto.c,v 1.3 1993/12/18 04:22:26 mycroft Exp $
+ * from: @(#)uipc_proto.c 8.1 (Berkeley) 6/10/93
+ * $Id: uipc_proto.c,v 1.4 1994/05/13 06:01:34 mycroft Exp $
*/
#include <sys/param.h>
@@ -44,8 +44,8 @@
* Definitions of protocols supported in the UNIX domain.
*/
-int uipc_usrreq();
-int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput();
+int uipc_usrreq(), raw_usrreq();
+void raw_init(), raw_input(), raw_ctlinput();
extern struct domain unixdomain; /* or at least forward */
struct protosw unixsw[] = {
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 6d1cb5a539f..528a763157d 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993
+ * 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
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)uipc_socket.c 7.28 (Berkeley) 5/4/91
- * $Id: uipc_socket.c,v 1.14 1994/05/04 11:24:06 mycroft Exp $
+ * from: @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94
+ * $Id: uipc_socket.c,v 1.15 1994/05/13 06:01:37 mycroft Exp $
*/
#include <sys/param.h>
@@ -71,7 +71,7 @@ socreate(dom, aso, type, proto)
prp = pffindproto(dom, proto, type);
else
prp = pffindtype(dom, type);
- if (!prp || !prp->pr_usrreq)
+ if (prp == 0 || prp->pr_usrreq == 0)
return (EPROTONOSUPPORT);
if (prp->pr_type != type)
return (EPROTOTYPE);
@@ -299,6 +299,7 @@ bad:
return (error);
}
+#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
/*
* Send on a socket.
* If send must go all at once and message is larger than
@@ -325,7 +326,7 @@ sosend(so, addr, uio, top, control, flags)
struct mbuf *control;
int flags;
{
- struct proc *p = curproc; /* XXX */
+ struct proc *p = curproc; /* XXX */
struct mbuf **mp;
register struct mbuf *m;
register long space, len, resid;
@@ -354,7 +355,7 @@ sosend(so, addr, uio, top, control, flags)
#define snderr(errno) { error = errno; splx(s); goto release; }
restart:
- if (error = sblock(&so->so_snd))
+ if (error = sblock(&so->so_snd, SBLOCKWAIT(flags)))
goto out;
do {
s = splnet();
@@ -408,15 +409,25 @@ restart:
MGET(m, M_WAIT, MT_DATA);
mlen = MLEN;
}
- if (resid >= MINCLSIZE) {
+ if (resid >= MINCLSIZE && space >= MCLBYTES) {
MCLGET(m, M_WAIT);
if ((m->m_flags & M_EXT) == 0)
goto nopages;
mlen = MCLBYTES;
- len = min(min(mlen, resid), space);
+#ifdef MAPPED_MBUFS
+ len = min(MCLBYTES, resid);
+#else
+ if (atomic && top == 0) {
+ len = min(MCLBYTES - max_hdr, resid);
+ m->m_data += max_hdr;
+ } else
+ len = min(MCLBYTES, resid);
+#endif
+ space -= MCLBYTES;
} else {
nopages:
len = min(min(mlen, resid), space);
+ space -= len;
/*
* For datagram protocols, leave room
* for protocol headers in first mbuf.
@@ -424,7 +435,6 @@ nopages:
if (atomic && top == 0 && len < mlen)
MH_ALIGN(m, len);
}
- space -= len;
error = uiomove(mtod(m, caddr_t), (int)len, uio);
resid = uio->uio_resid;
m->m_len = len;
@@ -492,7 +502,6 @@ soreceive(so, paddr, uio, mp0, controlp, flagsp)
struct mbuf **controlp;
int *flagsp;
{
- struct proc *p = curproc; /* XXX */
register struct mbuf *m, **mp;
register int flags, len, error, s, offset;
struct protosw *pr = so->so_proto;
@@ -532,7 +541,7 @@ bad:
(struct mbuf *)0, (struct mbuf *)0);
restart:
- if (error = sblock(&so->so_rcv))
+ if (error = sblock(&so->so_rcv, SBLOCKWAIT(flags)))
return (error);
s = splnet();
@@ -540,14 +549,16 @@ restart:
/*
* If we have less data than requested, block awaiting more
* (subject to any timeout) if:
- * 1. the current count is less than the low water mark, or
+ * 1. the current count is less than the low water mark,
* 2. MSG_WAITALL is set, and it is possible to do the entire
- * receive operation at once if we block (resid <= hiwat).
+ * receive operation at once if we block (resid <= hiwat), or
+ * 3. MSG_DONTWAIT is not set.
* If MSG_WAITALL is set but resid is larger than the receive buffer,
* we have to do the receive in sections, and thus risk returning
* a short count if a timeout or signal occurs after we start.
*/
- while (m == 0 || so->so_rcv.sb_cc < uio->uio_resid &&
+ if (m == 0 || ((flags & MSG_DONTWAIT) == 0 &&
+ so->so_rcv.sb_cc < uio->uio_resid) &&
(so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0) {
@@ -557,7 +568,7 @@ restart:
#endif
if (so->so_error) {
if (m)
- break;
+ goto dontblock;
error = so->so_error;
if ((flags & MSG_PEEK) == 0)
so->so_error = 0;
@@ -565,7 +576,7 @@ restart:
}
if (so->so_state & SS_CANTRCVMORE) {
if (m)
- break;
+ goto dontblock;
else
goto release;
}
@@ -581,7 +592,7 @@ restart:
}
if (uio->uio_resid == 0)
goto release;
- if (so->so_state & SS_NBIO) {
+ if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
error = EWOULDBLOCK;
goto release;
}
@@ -593,7 +604,10 @@ restart:
goto restart;
}
dontblock:
- p->p_stats->p_ru.ru_msgrcv++;
+#ifdef notyet /* XXXX */
+ if (uio->uio_procp)
+ uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
+#endif
nextrecord = m->m_nextpkt;
if (pr->pr_flags & PR_ADDR) {
#ifdef DIAGNOSTIC
@@ -806,7 +820,7 @@ sorflush(so)
struct sockbuf asb;
sb->sb_flags |= SB_NOINTR;
- (void) sblock(sb);
+ (void) sblock(sb, M_WAITOK);
s = splimp();
socantrcvmore(so);
sbunlock(sb);
@@ -849,6 +863,7 @@ sosetopt(so, level, optname, m0)
case SO_USELOOPBACK:
case SO_BROADCAST:
case SO_REUSEADDR:
+ case SO_REUSEPORT:
case SO_OOBINLINE:
if (m == NULL || m->m_len < sizeof (int)) {
error = EINVAL;
@@ -922,6 +937,11 @@ sosetopt(so, level, optname, m0)
error = ENOPROTOOPT;
break;
}
+ if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
+ (void) ((*so->so_proto->pr_ctloutput)
+ (PRCO_SETOPT, so, level, optname, &m0));
+ m = NULL; /* freed by protocol */
+ }
}
bad:
if (m)
@@ -961,6 +981,7 @@ sogetopt(so, level, optname, mp)
case SO_DEBUG:
case SO_KEEPALIVE:
case SO_REUSEADDR:
+ case SO_REUSEPORT:
case SO_BROADCAST:
case SO_OOBINLINE:
*mtod(m, int *) = so->so_options & optname;
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index f0ecb914058..63ed94c289d 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
- * $Id: uipc_socket2.c,v 1.7 1994/05/04 11:04:58 mycroft Exp $
+ * $Id: uipc_socket2.c,v 1.8 1994/05/13 06:01:40 mycroft Exp $
*/
#include <sys/param.h>
@@ -40,7 +40,6 @@
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/malloc.h>
-#include <sys/select.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 5ebec8ef1ae..796474feafb 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1,10 +1,10 @@
-/*-
- * Copyright (c) 1991-1993 The Regents of the University of California.
- * All rights reserved.
+/*
+ * Copyright (c) 1990, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
- * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,27 +35,32 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)bpf.c 7.4 (Berkeley) 6/17/91
- *
- * from: Header: bpf.c,v 1.3 93/12/11 02:52:18 mccanne Exp
- * $Id: bpf.c,v 1.11 1994/01/25 06:10:08 deraadt Exp $
+ * from: @(#)bpf.c 8.2 (Berkeley) 3/28/94
+ * $Id: bpf.c,v 1.12 1994/05/13 06:02:14 mycroft Exp $
*/
#include "bpfilter.h"
-#if (NBPFILTER > 0)
+#ifndef __GNUC__
+#define inline
+#else
+#define inline __inline
+#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/buf.h>
+#include <sys/time.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <sys/map.h>
-#include <sys/select.h>
#include <sys/file.h>
+#if defined(sparc) && BSD < 199103
+#include <sys/stream.h>
+#endif
#include <sys/tty.h>
#include <sys/uio.h>
@@ -67,16 +72,27 @@
#include <net/bpfdesc.h>
#include <sys/errno.h>
-#include <sys/kernel.h>
-#include <sys/vnode.h>
-#include "sl.h"
-#include "ppp.h"
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <sys/kernel.h>
-#ifndef BPF_BUFSIZE
-#define BPF_BUFSIZE NBPG
+/*
+ * Older BSDs don't have kernel malloc.
+ */
+#if BSD < 199103
+extern bcopy();
+static caddr_t bpf_alloc();
+#include <net/bpf_compat.h>
+#define BPF_BUFSIZE (MCLBYTES-8)
+#define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio)
+#else
+#define BPF_BUFSIZE 4096
+#define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio)
#endif
+#define PRINET 26 /* interruptible */
+
/*
* The default read buffer size is patchable.
*/
@@ -86,20 +102,136 @@ int bpf_bufsize = BPF_BUFSIZE;
* bpf_iflist is the list of interfaces; each corresponds to an ifnet
* bpf_dtab holds the descriptors, indexed by minor device #
*/
-struct bpf_if *bpf_iflist;
+struct bpf_if *bpf_iflist;
struct bpf_d bpf_dtab[NBPFILTER];
-static void bpf_ifname();
-static void catchpacket();
-static void bpf_freed();
-static int bpf_setif();
-static int bpf_allocbufs();
-
+#if BSD >= 199207 || NetBSD0_9 >= 2
+/*
+ * bpfilterattach() is called at boot time in new systems. We do
+ * nothing here since old systems will not call this.
+ */
+/* ARGSUSED */
void
bpfilterattach(n)
int n;
{
}
+#endif
+
+static int bpf_allocbufs __P((struct bpf_d *));
+static int bpf_allocbufs __P((struct bpf_d *));
+static void bpf_freed __P((struct bpf_d *));
+static void bpf_freed __P((struct bpf_d *));
+static void bpf_ifname __P((struct ifnet *, struct ifreq *));
+static void bpf_ifname __P((struct ifnet *, struct ifreq *));
+static void bpf_mcopy __P((const void *, void *, u_int));
+static int bpf_movein __P((struct uio *, int,
+ struct mbuf **, struct sockaddr *, int *));
+static int bpf_setif __P((struct bpf_d *, struct ifreq *));
+static int bpf_setif __P((struct bpf_d *, struct ifreq *));
+static inline void
+ bpf_wakeup __P((struct bpf_d *));
+static void catchpacket __P((struct bpf_d *, u_char *, u_int,
+ u_int, void (*)(const void *, void *, u_int)));
+static void reset_d __P((struct bpf_d *));
+
+static int
+bpf_movein(uio, linktype, mp, sockp, datlen)
+ register struct uio *uio;
+ int linktype, *datlen;
+ register struct mbuf **mp;
+ register struct sockaddr *sockp;
+{
+ struct mbuf *m;
+ int error;
+ int len;
+ int hlen;
+
+ /*
+ * Build a sockaddr based on the data link layer type.
+ * We do this at this level because the ethernet header
+ * is copied directly into the data field of the sockaddr.
+ * In the case of SLIP, there is no header and the packet
+ * is forwarded as is.
+ * Also, we are careful to leave room at the front of the mbuf
+ * for the link level header.
+ */
+ switch (linktype) {
+
+ case DLT_SLIP:
+ sockp->sa_family = AF_INET;
+ hlen = 0;
+ break;
+
+ case DLT_PPP:
+ sockp->sa_family = AF_UNSPEC;
+ hlen = 0;
+ break;
+
+ case DLT_EN10MB:
+ sockp->sa_family = AF_UNSPEC;
+ /* XXX Would MAXLINKHDR be better? */
+ hlen = sizeof(struct ether_header);
+ break;
+
+ case DLT_FDDI:
+ sockp->sa_family = AF_UNSPEC;
+ /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
+ hlen = 24;
+ break;
+
+ case DLT_NULL:
+ sockp->sa_family = AF_UNSPEC;
+ hlen = 0;
+ break;
+
+ default:
+ return (EIO);
+ }
+
+ len = uio->uio_resid;
+ *datlen = len - hlen;
+ if ((unsigned)len > MCLBYTES)
+ return (EIO);
+
+ MGET(m, M_WAIT, MT_DATA);
+ if (m == 0)
+ return (ENOBUFS);
+ if (len > MLEN) {
+#if BSD >= 199103
+ MCLGET(m, M_WAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+#else
+ MCLGET(m);
+ if (m->m_len != MCLBYTES) {
+#endif
+ error = ENOBUFS;
+ goto bad;
+ }
+ }
+ m->m_len = len;
+ *mp = m;
+ /*
+ * Make room for link header.
+ */
+ if (hlen != 0) {
+ m->m_len -= hlen;
+#if BSD >= 199103
+ m->m_data += hlen; /* XXX */
+#else
+ m->m_off += hlen;
+#endif
+ error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio);
+ if (error)
+ goto bad;
+ }
+ error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio);
+ if (!error)
+ return (0);
+ bad:
+ m_freem(m);
+ return (error);
+}
/*
* Attach file to the bpf interface, i.e. make d listen on bp.
@@ -165,7 +297,7 @@ bpf_detachd(d)
/*
- * Mark a descriptor free by making it point to itself.
+ * Mark a descriptor free by making it point to itself.
* This is probably cheaper than marking with a constant since
* the address should be in a register anyway.
*/
@@ -184,7 +316,7 @@ bpfopen(dev, flag)
int flag;
{
register struct bpf_d *d;
-
+
if (minor(dev) >= NBPFILTER)
return (ENXIO);
/*
@@ -225,8 +357,47 @@ bpfclose(dev, flag)
}
/*
+ * Support for SunOS, which does not have tsleep.
+ */
+#if BSD < 199103
+static
+bpf_timeout(arg)
+ caddr_t arg;
+{
+ struct bpf_d *d = (struct bpf_d *)arg;
+ d->bd_timedout = 1;
+ wakeup(arg);
+}
+
+#define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan)
+
+int
+bpf_sleep(d)
+ register struct bpf_d *d;
+{
+ register int rto = d->bd_rtout;
+ register int st;
+
+ if (rto != 0) {
+ d->bd_timedout = 0;
+ timeout(bpf_timeout, (caddr_t)d, rto);
+ }
+ st = sleep((caddr_t)d, PRINET|PCATCH);
+ if (rto != 0) {
+ if (d->bd_timedout == 0)
+ untimeout(bpf_timeout, (caddr_t)d);
+ else if (st == 0)
+ return EWOULDBLOCK;
+ }
+ return (st != 0) ? EINTR : 0;
+}
+#else
+#define BPF_SLEEP tsleep
+#endif
+
+/*
* Rotate the packet buffers in descriptor d. Move the store buffer
- * into the hold slot, and the free buffer into the store slot.
+ * into the hold slot, and the free buffer into the store slot.
* Zero the length of the new store buffer.
*/
#define ROTATE_BUFFERS(d) \
@@ -234,22 +405,21 @@ bpfclose(dev, flag)
(d)->bd_hlen = (d)->bd_slen; \
(d)->bd_sbuf = (d)->bd_fbuf; \
(d)->bd_slen = 0; \
- (d)->bd_fbuf = 0;
+ (d)->bd_fbuf = 0;
/*
* bpfread - read next chunk of packets from buffers
*/
int
-bpfread(dev, uio, ioflag)
+bpfread(dev, uio)
dev_t dev;
register struct uio *uio;
- int ioflag;
{
register struct bpf_d *d = &bpf_dtab[minor(dev)];
int error;
int s;
/*
- * Restrict application to use a buffer the same size as
+ * Restrict application to use a buffer the same size as
* as kernel buffers.
*/
if (uio->uio_resid != d->bd_bufsize)
@@ -262,14 +432,6 @@ bpfread(dev, uio, ioflag)
* have arrived to fill the store buffer.
*/
while (d->bd_hbuf == 0) {
- if (ioflag & IO_NDELAY) {
- if (d->bd_slen == 0) {
- splx(s);
- return (EWOULDBLOCK);
- }
- ROTATE_BUFFERS(d);
- break;
- }
if (d->bd_immediate && d->bd_slen != 0) {
/*
* A packet(s) either arrived since the previous
@@ -279,64 +441,65 @@ bpfread(dev, uio, ioflag)
ROTATE_BUFFERS(d);
break;
}
- error = tsleep((caddr_t)d, PWAIT | PCATCH, "bpf", d->bd_rtout);
- if (error != 0) {
- if (error == EWOULDBLOCK) {
+ error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf",
+ d->bd_rtout);
+ if (error == EINTR || error == ERESTART) {
+ splx(s);
+ return (error);
+ }
+ if (error == EWOULDBLOCK) {
+ /*
+ * On a timeout, return what's in the buffer,
+ * which may be nothing. If there is something
+ * in the store buffer, we can rotate the buffers.
+ */
+ if (d->bd_hbuf)
/*
- * On a timeout, return what's in the buffer,
- * which may be nothing. If there is something
- * in the store buffer, we can do a rotation.
+ * We filled up the buffer in between
+ * getting the timeout and arriving
+ * here, so we don't need to rotate.
*/
- if (d->bd_hbuf)
- /*
- * We filled up the buffer in between
- * getting the timeout and arriving
- * here, so we don't need to rotate.
- */
- break;
-
- if (d->bd_slen == 0) {
- splx(s);
- return (0);
- }
- ROTATE_BUFFERS(d);
break;
+
+ if (d->bd_slen == 0) {
+ splx(s);
+ return (0);
}
- splx(s);
- return (error);
+ ROTATE_BUFFERS(d);
+ break;
}
}
/*
* At this point, we know we have something in the hold slot.
*/
splx(s);
-
- /*
+
+ /*
* Move data from hold buffer into user space.
* We know the entire buffer is transferred since
* we checked above that the read buffer is bpf_bufsize bytes.
*/
- error = uiomove(d->bd_hbuf, d->bd_hlen, uio);
+ error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio);
s = splimp();
d->bd_fbuf = d->bd_hbuf;
d->bd_hbuf = 0;
d->bd_hlen = 0;
splx(s);
-
+
return (error);
}
/*
- * If there are processes sleeping on this descriptor, wake them up.
+ * If there are processes sleeping on this descriptor, wake them up.
*/
static inline void
bpf_wakeup(d)
register struct bpf_d *d;
{
wakeup((caddr_t)d);
-#if (BSD > 199103) || defined(__NetBSD__)
+#if BSD >= 199103
selwakeup(&d->bd_sel);
/* XXX */
d->bd_sel.si_pid = 0;
@@ -354,113 +517,37 @@ bpfwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
- register struct bpf_if *bp = bpf_dtab[minor(dev)].bd_bif;
- register struct ifnet *ifp;
- register struct mbuf *m;
- register u_int len, hlen;
- register int error, s;
- struct sockaddr dst;
+ register struct bpf_d *d = &bpf_dtab[minor(dev)];
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int error, s;
+ static struct sockaddr dst;
+ int datlen;
- if (bp == 0)
+ if (d->bd_bif == 0)
return (ENXIO);
- /*
- * Build a sockaddr based on the data link layer type.
- * The AF_UNSPEC kludge allows us to hand the link level
- * header to the driver via the sockaddr. This isn't
- * very clean. It would be better if AF_UNSPEC meant that
- * the driver shouldn't bother with encapsulation (i.e., the
- * link header is already in the mbuf). The code here is
- * structured this way, then things are kludged back before
- * calling if_output.
- *
- * NOTE: When adding new link layers make sure the driver supports
- * AF_UNSPEC and that the link header can fit in the sa_data
- * field of a sockaddr.
- */
- switch (bp->bif_dlt) {
-
-#if NSL > 0
- case DLT_SLIP:
- dst.sa_family = AF_INET;
- hlen = 0;
- break;
-#endif
-
-#if NPPP > 0
- case DLT_PPP:
- dst.sa_family = AF_UNSPEC;
- hlen = 0;
- break;
-#endif
-
- case DLT_EN10MB:
- dst.sa_family = AF_UNSPEC;
- hlen = 14;
- break;
-
- case DLT_FDDI:
- dst.sa_family = AF_UNSPEC;
- /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
- hlen = 24;
- break;
+ ifp = d->bd_bif->bif_ifp;
- case DLT_NULL:
- dst.sa_family = AF_UNSPEC;
- hlen = 0;
- break;
+ if (uio->uio_resid == 0)
+ return (0);
- default:
- return (EIO);
- }
- ifp = bp->bif_ifp;
- len = uio->uio_resid;
- /*
- * If we didn't get enough for the link level header, or we
- * exceed the interface's mtu, return an error.
- */
- if (len < hlen || len - hlen > ifp->if_mtu)
- return (EMSGSIZE);
+ error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen);
+ if (error)
+ return (error);
- /*
- * XXX Avoid complicated buffer chaining ---
- * bail if it won't fit in a single mbuf.
- */
- if (len > MCLBYTES)
+ if (datlen > ifp->if_mtu)
return (EMSGSIZE);
- MGETHDR(m, M_WAIT, MT_DATA);
- if (m == 0)
- return (ENOBUFS);
- if (len > MLEN) {
- MCLGET(m, M_WAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_freem(m);
- return (ENOBUFS);
- }
- }
- /*
- * Move the whole packet, including the data link header,
- * into the mbuf. Then, copy the link header back out of the
- * packet into the sockaddr. Finally, strip the link header
- * from the front of the mbuf.
- */
- error = uiomove(mtod(m, caddr_t), len, uio);
- if (error) {
- m_freem(m);
- return (error);
- }
- if (hlen > 0) {
- bcopy(mtod(m, caddr_t), dst.sa_data, hlen);
- m->m_data += hlen;
- len -= hlen;
- }
- m->m_pkthdr.len = m->m_len = len;
s = splnet();
+#if BSD >= 199103
error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0);
+#else
+ error = (*ifp->if_output)(ifp, m, &dst);
+#endif
splx(s);
/*
- * The driver frees the mbuf.
+ * The driver frees the mbuf.
*/
return (error);
}
@@ -517,20 +604,16 @@ bpfioctl(dev, cmd, addr, flag)
error = EINVAL;
break;
- case FIONBIO:
- case FIOASYNC:
- break;
-
/*
* Check for read packet available.
*/
case FIONREAD:
{
int n;
-
+
s = splimp();
n = d->bd_slen;
- if (d->bd_hbuf)
+ if (d->bd_hbuf)
n += d->bd_hlen;
splx(s);
@@ -546,7 +629,7 @@ bpfioctl(dev, cmd, addr, flag)
error = EINVAL;
else {
ifp = d->bd_bif->bif_ifp;
- error = (*ifp->if_ioctl)(ifp, cmd, addr);
+ error = (*ifp->if_ioctl)(ifp, cmd, addr);
}
break;
}
@@ -562,6 +645,9 @@ bpfioctl(dev, cmd, addr, flag)
* Set buffer length.
*/
case BIOCSBLEN:
+#if BSD < 199103
+ error = EINVAL;
+#else
if (d->bd_bif != 0)
error = EINVAL;
else {
@@ -573,12 +659,13 @@ bpfioctl(dev, cmd, addr, flag)
*(u_int *)addr = size = BPF_MINBUFSIZE;
d->bd_bufsize = size;
}
+#endif
break;
/*
* Set link layer read filter.
*/
- case BIOCSETF:
+ case BIOCSETF:
error = bpf_setf(d, (struct bpf_program *)addr);
break;
@@ -641,7 +728,7 @@ bpfioctl(dev, cmd, addr, flag)
/*
* Set read timeout.
*/
- case BIOCSRTIMEOUT:
+ case BIOCSRTIMEOUT:
{
struct timeval *tv = (struct timeval *)addr;
u_long msec;
@@ -659,7 +746,7 @@ bpfioctl(dev, cmd, addr, flag)
/*
* Get read timeout.
*/
- case BIOCGRTIMEOUT:
+ case BIOCGRTIMEOUT:
{
struct timeval *tv = (struct timeval *)addr;
u_long msec = d->bd_rtout;
@@ -696,12 +783,12 @@ bpfioctl(dev, cmd, addr, flag)
bv->bv_major = BPF_MAJOR_VERSION;
bv->bv_minor = BPF_MINOR_VERSION;
break;
- }
+ }
}
return (error);
}
-/*
+/*
* Set d's packet filter program to fp. If this file already has a filter,
* free it and replace it. Returns EINVAL for bogus requests.
*/
@@ -732,8 +819,6 @@ bpf_setf(d, fp)
size = flen * sizeof(*fp->bf_insns);
fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
- if (fcode == 0)
- return (ENOMEM);
if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
bpf_validate(fcode, (int)flen)) {
s = splimp();
@@ -765,7 +850,7 @@ bpf_setif(d, ifr)
/*
* Separate string into name part and unit number. Put a null
- * byte at the end of the name part, and compute the number.
+ * byte at the end of the name part, and compute the number.
* If the a unit number is unspecified, the default is 0,
* as initialized above. XXX This should be common code.
*/
@@ -787,7 +872,7 @@ bpf_setif(d, ifr)
for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
struct ifnet *ifp = bp->bif_ifp;
- if (ifp == 0 || unit != ifp->if_unit
+ if (ifp == 0 || unit != ifp->if_unit
|| strcmp(ifp->if_name, ifr->ifr_name) != 0)
continue;
/*
@@ -808,7 +893,7 @@ bpf_setif(d, ifr)
s = splimp();
if (bp != d->bd_bif) {
if (d->bd_bif)
- /*
+ /*
* Detach if attached to something else.
*/
bpf_detachd(d);
@@ -843,28 +928,43 @@ bpf_ifname(ifp, ifr)
}
/*
+ * The new select interface passes down the proc pointer; the old select
+ * stubs had to grab it out of the user struct. This glue allows either case.
+ */
+#if BSD >= 199103
+#define bpf_select bpfselect
+#else
+int
+bpfselect(dev, rw)
+ register dev_t dev;
+ int rw;
+{
+ return (bpf_select(dev, rw, u.u_procp));
+}
+#endif
+
+/*
* Support for select() system call
- * Inspired by the code in tty.c for the same purpose.
*
* Return true iff the specific operation will not block indefinitely.
* Otherwise, return false but make a note that a selwakeup() must be done.
*/
int
-bpfselect(dev, rw, p)
+bpf_select(dev, rw, p)
register dev_t dev;
int rw;
struct proc *p;
{
register struct bpf_d *d;
register int s;
-
+
if (rw != FREAD)
return (0);
/*
* An imitation of the FIONREAD ioctl code.
*/
d = &bpf_dtab[minor(dev)];
-
+
s = splimp();
if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) {
/*
@@ -873,23 +973,22 @@ bpfselect(dev, rw, p)
splx(s);
return (1);
}
+#if BSD >= 199103
+ selrecord(p, &d->bd_sel);
+#else
/*
* No data ready. If there's already a select() waiting on this
- * minor device then this is a collision. This shouldn't happen
+ * minor device then this is a collision. This shouldn't happen
* because minors really should not be shared, but if a process
* forks while one of these is open, it is possible that both
* processes could select on the same descriptor.
*/
-#if defined(__NetBSD__)
- selrecord(p, &d->bd_sel);
-#else
if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait)
d->bd_selcoll = 1;
else
d->bd_selproc = p;
-
#endif
- splx(s);
+ splx(s);
return (0);
}
@@ -908,7 +1007,6 @@ bpf_tap(arg, pkt, pktlen)
struct bpf_if *bp;
register struct bpf_d *d;
register u_int slen;
-
/*
* Note that the ipl does not have to be raised at this point.
* The only problem that could arise here is that if two different
@@ -928,18 +1026,21 @@ bpf_tap(arg, pkt, pktlen)
* from m_copydata in sys/uipc_mbuf.c.
*/
static void
-bpf_mcopy(src, dst, len)
- u_char *src;
- u_char *dst;
- register int len;
+bpf_mcopy(src_arg, dst_arg, len)
+ const void *src_arg;
+ void *dst_arg;
+ register u_int len;
{
- register struct mbuf *m = (struct mbuf *)src;
- register unsigned count;
+ register const struct mbuf *m;
+ register u_int count;
+ u_char *dst;
+ m = src_arg;
+ dst = dst_arg;
while (len > 0) {
if (m == 0)
panic("bpf_mcopy");
- count = MIN(m->m_len, len);
+ count = min(m->m_len, len);
bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
m = m->m_next;
dst += count;
@@ -985,7 +1086,7 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn)
register struct bpf_d *d;
register u_char *pkt;
register u_int pktlen, snaplen;
- register void (*cpfn)();
+ register void (*cpfn) __P((const void *, void *, u_int));
{
register struct bpf_hdr *hp;
register int totlen, curlen;
@@ -996,7 +1097,7 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn)
* much. Otherwise, transfer the whole packet (unless
* we hit the buffer size limit).
*/
- totlen = hdrlen + MIN(snaplen, pktlen);
+ totlen = hdrlen + min(snaplen, pktlen);
if (totlen > d->bd_bufsize)
totlen = d->bd_bufsize;
@@ -1011,8 +1112,8 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn)
* pending reads.
*/
if (d->bd_fbuf == 0) {
- /*
- * We haven't completed the previous read yet,
+ /*
+ * We haven't completed the previous read yet,
* so drop the packet.
*/
++d->bd_dcount;
@@ -1022,7 +1123,7 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn)
bpf_wakeup(d);
curlen = 0;
}
- else if (d->bd_immediate)
+ else if (d->bd_immediate)
/*
* Immediate mode is set. A packet arrived so any
* reads should be woken up.
@@ -1033,7 +1134,13 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn)
* Append the bpf header.
*/
hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
+#if BSD >= 199103
microtime(&hp->bh_tstamp);
+#elif defined(sun)
+ uniqtime(&hp->bh_tstamp);
+#else
+ hp->bh_tstamp = time;
+#endif
hp->bh_datalen = pktlen;
hp->bh_hdrlen = hdrlen;
/*
@@ -1043,7 +1150,7 @@ catchpacket(d, pkt, pktlen, snaplen, cpfn)
d->bd_slen = curlen + totlen;
}
-/*
+/*
* Initialize all nonzero fields of a descriptor.
*/
static int
@@ -1103,12 +1210,17 @@ bpfattach(driverp, ifp, dlt, hdrlen)
{
struct bpf_if *bp;
int i;
+#if BSD < 199103
+ static struct bpf_if bpf_ifs[NBPFILTER];
+ static int bpfifno;
+ bp = (bpfifno < NBPFILTER) ? &bpf_ifs[bpfifno++] : 0;
+#else
bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
- if (bp == 0) {
- printf("bpf: no buffers in attach");
- return;
- }
+#endif
+ if (bp == 0)
+ panic("bpfattach");
+
bp->bif_dlist = 0;
bp->bif_driverp = (struct bpf_if **)driverp;
bp->bif_ifp = ifp;
@@ -1121,8 +1233,8 @@ bpfattach(driverp, ifp, dlt, hdrlen)
/*
* Compute the length of the bpf header. This is not necessarily
- * equal to SIZEOF_BPF_HDR because we want to insert spacing such
- * that the network layer header begins on a longword boundary (for
+ * equal to SIZEOF_BPF_HDR because we want to insert spacing such
+ * that the network layer header begins on a longword boundary (for
* performance reasons and to alleviate alignment restrictions).
*/
bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
@@ -1139,6 +1251,7 @@ bpfattach(driverp, ifp, dlt, hdrlen)
#endif
}
+#if BSD >= 199103
/* XXX This routine belongs in net/if.c. */
/*
* Set/clear promiscuous mode on interface ifp based on the truth value
@@ -1152,7 +1265,7 @@ ifpromisc(ifp, pswitch)
int pswitch;
{
struct ifreq ifr;
- /*
+ /*
* If the device is not configured up, we cannot put it in
* promiscuous mode.
*/
@@ -1171,5 +1284,35 @@ ifpromisc(ifp, pswitch)
ifr.ifr_flags = ifp->if_flags;
return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
}
+#endif
+
+#if BSD < 199103
+/*
+ * Allocate some memory for bpf. This is temporary SunOS support, and
+ * is admittedly a hack.
+ * If resources unavaiable, return 0.
+ */
+static caddr_t
+bpf_alloc(size, canwait)
+ register int size;
+ register int canwait;
+{
+ register struct mbuf *m;
+
+ if ((unsigned)size > (MCLBYTES-8))
+ return 0;
-#endif (NBPFILTER > 0)
+ MGET(m, canwait, MT_DATA);
+ if (m == 0)
+ return 0;
+ if ((unsigned)size > (MLEN-8)) {
+ MCLGET(m);
+ if (m->m_len != MCLBYTES) {
+ m_freem(m);
+ return 0;
+ }
+ }
+ *mtod(m, struct mbuf **) = m;
+ return mtod(m, caddr_t) + 8;
+}
+#endif
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index c8160808f18..f4494f34a4f 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -1,10 +1,10 @@
-/*-
- * Copyright (c) 1990-1991 The Regents of the University of California.
- * All rights reserved.
+/*
+ * Copyright (c) 1990, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
- * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
@@ -17,8 +17,8 @@
* 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.
+ * 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.
@@ -35,13 +35,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)bpf.h 7.1 (Berkeley) 5/7/91
- * $Id: bpf.h,v 1.4 1993/05/20 03:05:50 cgd Exp $
+ * from: @(#)bpf.h 8.1 (Berkeley) 6/10/93
+ * $Id: bpf.h,v 1.5 1994/05/13 06:02:19 mycroft Exp $
*/
-#ifndef _NET_BPF_H_
-#define _NET_BPF_H_
-
/*
* Alignment macros. BPF_WORDALIGN rounds up to the next
* even multiple of BPF_ALIGNMENT.
@@ -233,10 +230,18 @@ struct bpf_insn {
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
#ifdef KERNEL
-extern u_int bpf_filter();
-extern void bpfattach();
-extern void bpf_tap();
-extern void bpf_mtap();
+int bpf_validate __P((struct bpf_insn *, int));
+int bpfopen __P((dev_t, int));
+int bpfclose __P((dev_t, int));
+int bpfread __P((dev_t, struct uio *));
+int bpfwrite __P((dev_t, struct uio *));
+int bpfioctl __P((dev_t, int, caddr_t, int));
+int bpf_select __P((dev_t, int, struct proc *));
+void bpf_tap __P((caddr_t, u_char *, u_int));
+void bpf_mtap __P((caddr_t, struct mbuf *));
+void bpfattach __P((caddr_t *, struct ifnet *, u_int, u_int));
+void bpfilterattach __P((int));
+u_int bpf_filter __P((struct bpf_insn *, u_char *, u_int, u_int));
#endif
/*
@@ -244,4 +249,3 @@ extern void bpf_mtap();
*/
#define BPF_MEMWORDS 16
-#endif /* !_NET_BPF_H_ */
diff --git a/sys/net/bpf_filter.c b/sys/net/bpf_filter.c
index 767145d28a5..0fbb1aeaaa0 100644
--- a/sys/net/bpf_filter.c
+++ b/sys/net/bpf_filter.c
@@ -1,10 +1,10 @@
-/*-
- * Copyright (c) 1990-1991 The Regents of the University of California.
- * All rights reserved.
+/*
+ * Copyright (c) 1990, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
- * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,16 +35,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)bpf_filter.c 7.2 (Berkeley) 5/14/91
- * $Id: bpf_filter.c,v 1.4 1993/12/18 00:40:51 mycroft Exp $
+ * from: @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93
+ * $Id: bpf_filter.c,v 1.5 1994/05/13 06:02:22 mycroft Exp $
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <net/bpf.h>
-
#ifdef sun
#include <netinet/in.h>
#endif
@@ -161,6 +159,7 @@ m_xhalf(m, k, err)
}
#endif
+#include <net/bpf.h>
/*
* Execute the filter program starting at pc on the packet p
* wirelen is the length of the original packet
diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h
index f6108d9cc08..6f414589e23 100644
--- a/sys/net/bpfdesc.h
+++ b/sys/net/bpfdesc.h
@@ -1,10 +1,10 @@
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
+/*
+ * Copyright (c) 1990, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
- * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,14 +35,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)bpfdesc.h 7.1 (Berkeley) 5/7/91
- * $Id: bpfdesc.h,v 1.7 1993/11/23 04:51:29 cgd Exp $
+ * from: @(#)bpfdesc.h 8.1 (Berkeley) 6/10/93
+ * $Id: bpfdesc.h,v 1.8 1994/05/13 06:02:24 mycroft Exp $
*/
-#ifndef _NET_BPFDESC_H_
-#define _NET_BPFDESC_H_
-
-#include "select.h"
+#include <sys/select.h>
/*
* Descriptor associated with each open bpf file.
@@ -75,11 +72,11 @@ struct bpf_d {
u_char bd_promisc; /* true if listening promiscuously */
u_char bd_state; /* idle, waiting, or timed out */
u_char bd_immediate; /* true to return on packet arrival */
-#if (BSD <= 199103) && !defined(__NetBSD__)
+#if BSD < 199103
u_char bd_selcoll; /* true if selects collide */
int bd_timedout;
struct proc * bd_selproc; /* process that last selected us */
-#else /* BSD > 199103 */
+#else
u_char bd_pad; /* explicit alignment */
struct selinfo bd_sel; /* bsd select info */
#endif
@@ -97,4 +94,6 @@ struct bpf_if {
struct ifnet *bif_ifp; /* correspoding interface */
};
-#endif /* !_NET_BPFDESC_H_ */
+#ifdef KERNEL
+int bpf_setf __P((struct bpf_d *, struct bpf_program *));
+#endif
diff --git a/sys/net/if.c b/sys/net/if.c
index 7287ef4c148..e0b3ed515ef 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1980, 1986 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1980, 1986, 1993
+ * 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
@@ -30,30 +30,26 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if.c 7.14 (Berkeley) 4/20/91
- * $Id: if.c,v 1.14 1994/05/05 09:33:21 mycroft Exp $
+ * from: @(#)if.c 8.3 (Berkeley) 1/4/94
+ * $Id: if.c,v 1.15 1994/05/13 06:02:26 mycroft Exp $
*/
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
-#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
-#include <net/route.h>
-
-#include "ether.h"
int ifqmaxlen = IFQ_MAXLEN;
-
-void if_slowtimo __P((void *));
+void if_slowtimo __P((void *arg));
/*
* Network interface utility routines.
@@ -61,7 +57,6 @@ void if_slowtimo __P((void *));
* Routines with ifa_ifwith* names take sockaddr *'s as
* parameters.
*/
-
void
ifinit()
{
@@ -77,6 +72,7 @@ ifinit()
/*
* Call each interface on a Unibus reset.
*/
+void
ifubareset(uban)
int uban;
{
@@ -90,23 +86,24 @@ ifubareset(uban)
int if_index = 0;
struct ifaddr **ifnet_addrs;
-static char *sprint_d();
+static char *sprint_d __P((u_int, char *, int));
/*
* Attach an interface to the
* list of "active" interfaces.
*/
+void
if_attach(ifp)
struct ifnet *ifp;
{
unsigned socksize, ifasize;
- int namelen, unitlen;
+ int namelen, unitlen, masklen;
char workbuf[12], *unitname;
register struct ifnet **p = &ifnet;
register struct sockaddr_dl *sdl;
register struct ifaddr *ifa;
static int if_indexlim = 8;
- extern link_rtrequest(), ether_output();
+ extern void link_rtrequest();
while (*p)
p = &((*p)->if_next);
@@ -122,14 +119,6 @@ if_attach(ifp)
}
ifnet_addrs = q;
}
-#if defined(INET) && NETHER > 0
- /* XXX -- Temporary fix before changing 10 ethernet drivers */
- if (ifp->if_output == ether_output) {
- ifp->if_type = IFT_ETHER;
- ifp->if_addrlen = 6;
- ifp->if_hdrlen = 14;
- }
-#endif
/*
* create a Link Level name for this device
*/
@@ -137,8 +126,9 @@ if_attach(ifp)
namelen = strlen(ifp->if_name);
unitlen = strlen(unitname);
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
- socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
- unitlen + namelen + ifp->if_addrlen;
+ masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
+ unitlen + namelen;
+ socksize = masklen + ifp->if_addrlen;
#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
socksize = ROUNDUP(socksize);
if (socksize < sizeof(*sdl))
@@ -147,25 +137,26 @@ if_attach(ifp)
ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
if (ifa == 0)
return;
- ifnet_addrs[if_index - 1] = ifa;
bzero((caddr_t)ifa, ifasize);
sdl = (struct sockaddr_dl *)(ifa + 1);
- ifa->ifa_addr = (struct sockaddr *)sdl;
- ifa->ifa_ifp = ifp;
sdl->sdl_len = socksize;
sdl->sdl_family = AF_LINK;
bcopy(ifp->if_name, sdl->sdl_data, namelen);
bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
sdl->sdl_nlen = (namelen += unitlen);
sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = ifp->if_type;
+ ifnet_addrs[if_index - 1] = ifa;
+ ifa->ifa_ifp = ifp;
+ ifa->ifa_next = ifp->if_addrlist;
+ ifa->ifa_rtrequest = link_rtrequest;
+ ifp->if_addrlist = ifa;
+ ifa->ifa_addr = (struct sockaddr *)sdl;
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
ifa->ifa_netmask = (struct sockaddr *)sdl;
- sdl->sdl_len = socksize - ifp->if_addrlen;
+ sdl->sdl_len = masklen;
while (namelen != 0)
sdl->sdl_data[--namelen] = 0xff;
- ifa->ifa_next = ifp->if_addrlist;
- ifa->ifa_rtrequest = link_rtrequest;
- ifp->if_addrlist = ifa;
}
/*
* Locate an interface based on a complete address.
@@ -216,7 +207,7 @@ ifa_ifwithdstaddr(addr)
/*
* Find an interface on a specific network. If many, choice
- * is first found.
+ * is most specific found.
*/
struct ifaddr *
ifa_ifwithnet(addr)
@@ -224,32 +215,36 @@ ifa_ifwithnet(addr)
{
register struct ifnet *ifp;
register struct ifaddr *ifa;
+ struct ifaddr *ifa_maybe = 0;
u_int af = addr->sa_family;
+ char *addr_data = addr->sa_data, *cplim;
- if (af >= AF_MAX)
- return (0);
if (af == AF_LINK) {
register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
if (sdl->sdl_index && sdl->sdl_index <= if_index)
return (ifnet_addrs[sdl->sdl_index - 1]);
}
for (ifp = ifnet; ifp; ifp = ifp->if_next)
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
- register char *cp, *cp2, *cp3;
- register char *cplim;
- if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
- continue;
- cp = addr->sa_data;
- cp2 = ifa->ifa_addr->sa_data;
- cp3 = ifa->ifa_netmask->sa_data;
- cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
- for (; cp3 < cplim; cp3++)
- if ((*cp++ ^ *cp2++) & *cp3)
- break;
- if (cp3 == cplim)
- return (ifa);
- }
- return ((struct ifaddr *)0);
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ register char *cp, *cp2, *cp3;
+
+ if (ifa->ifa_addr->sa_family != af ||
+ ifa->ifa_netmask == 0)
+ next: continue;
+ cp = addr_data;
+ cp2 = ifa->ifa_addr->sa_data;
+ cp3 = ifa->ifa_netmask->sa_data;
+ cplim = (char *)ifa->ifa_netmask +
+ ifa->ifa_netmask->sa_len;
+ while (cp3 < cplim)
+ if ((*cp++ ^ *cp2++) & *cp3++)
+ goto next;
+ if (ifa_maybe == 0 ||
+ rn_refines((caddr_t)ifa->ifa_netmask,
+ (caddr_t)ifa_maybe->ifa_netmask))
+ ifa_maybe = ifa;
+ }
+ return (ifa_maybe);
}
/*
@@ -309,24 +304,30 @@ ifaof_ifpforaddr(addr, ifp)
return (ifa_maybe);
}
+#include <net/route.h>
+
/*
* Default action when installing a route with a Link Level gateway.
* Lookup an appropriate real ifa to point to.
* This should be moved to /sys/net/link.c eventually.
*/
+void
link_rtrequest(cmd, rt, sa)
-register struct rtentry *rt;
-struct sockaddr *sa;
+ int cmd;
+ register struct rtentry *rt;
+ struct sockaddr *sa;
{
register struct ifaddr *ifa;
struct sockaddr *dst;
- struct ifnet *ifp, *oldifnet = ifnet;
+ struct ifnet *ifp;
if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
return;
if (ifa = ifaof_ifpforaddr(dst, ifp)) {
+ IFAFREE(rt->rt_ifa);
rt->rt_ifa = ifa;
+ ifa->ifa_refcnt++;
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
ifa->ifa_rtrequest(cmd, rt, sa);
}
@@ -337,6 +338,7 @@ struct sockaddr *sa;
* the transition.
* NOTE: must be called at splnet or eqivalent.
*/
+void
if_down(ifp)
register struct ifnet *ifp;
{
@@ -346,11 +348,33 @@ if_down(ifp)
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
if_qflush(&ifp->if_snd);
+ rt_ifmsg(ifp);
+}
+
+/*
+ * Mark an interface up and notify protocols of
+ * the transition.
+ * NOTE: must be called at splnet or equivalent.
+ */
+void
+if_up(ifp)
+ register struct ifnet *ifp;
+{
+ register struct ifaddr *ifa;
+
+ ifp->if_flags |= IFF_UP;
+#ifdef notyet
+ /* this has no effect on IP, and will kill all ISO connections XXX */
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+ pfctlinput(PRC_IFUP, ifa->ifa_addr);
+#endif
+ rt_ifmsg(ifp);
}
/*
* Flush an interface queue.
*/
+void
if_qflush(ifq)
register struct ifqueue *ifq;
{
@@ -371,7 +395,6 @@ if_qflush(ifq)
* from softclock, we decrement timers (if set) and
* call the appropriate interface routine on expiration.
*/
-/* ARGSUSED */
void
if_slowtimo(arg)
void *arg;
@@ -432,6 +455,7 @@ ifunit(name)
/*
* Interface ioctls.
*/
+int
ifioctl(so, cmd, data, p)
struct socket *so;
int cmd;
@@ -447,17 +471,6 @@ ifioctl(so, cmd, data, p)
case SIOCGIFCONF:
case OSIOCGIFCONF:
return (ifconf(cmd, data));
-
-#if defined(INET) && NETHER > 0
- case SIOCSARP:
- case SIOCDARP:
- if (error = suser(p->p_ucred, &p->p_acflag))
- return (error);
- /* FALL THROUGH */
- case SIOCGARP:
- case OSIOCGARP:
- return (arpioctl(cmd, data));
-#endif
}
ifr = (struct ifreq *)data;
ifp = ifunit(ifr->ifr_name);
@@ -473,14 +486,6 @@ ifioctl(so, cmd, data, p)
ifr->ifr_metric = ifp->if_metric;
break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (error = suser(p->p_ucred, &p->p_acflag))
- return (error);
- if (! ifp->if_ioctl) /* BUG:: 10NOV93 CMAEDA */
- return (EOPNOTSUPP);
- return ((*ifp->if_ioctl)(ifp, cmd, data));
-
case SIOCSIFFLAGS:
if (error = suser(p->p_ucred, &p->p_acflag))
return (error);
@@ -489,6 +494,11 @@ ifioctl(so, cmd, data, p)
if_down(ifp);
splx(s);
}
+ if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
+ int s = splimp();
+ if_up(ifp);
+ splx(s);
+ }
ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
(ifr->ifr_flags &~ IFF_CANTCHANGE);
if (ifp->if_ioctl)
@@ -501,14 +511,13 @@ ifioctl(so, cmd, data, p)
ifp->if_metric = ifr->ifr_metric;
break;
- case SIOCSIFMTU:
- case SIOCGIFMTU:
- case SIOCSIFASYNCMAP:
- case SIOCGIFASYNCMAP:
- if (!ifp->if_ioctl)
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (error = suser(p->p_ucred, &p->p_acflag))
+ return (error);
+ if (ifp->if_ioctl == 0)
return (EOPNOTSUPP);
return ((*ifp->if_ioctl)(ifp, cmd, data));
- break;
default:
if (so->so_proto == 0)
@@ -578,6 +587,7 @@ ifioctl(so, cmd, data, p)
* other information.
*/
/*ARGSUSED*/
+int
ifconf(cmd, data)
int cmd;
caddr_t data;
@@ -592,13 +602,14 @@ ifconf(cmd, data)
ifrp = ifc->ifc_req;
ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
- bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
+ strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2);
for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
- ;
+ continue;
*cp++ = '0' + ifp->if_unit; *cp = '\0';
if ((ifa = ifp->if_addrlist) == 0) {
bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
- error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
+ error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
+ sizeof(ifr));
if (error)
break;
space -= sizeof (ifr), ifrp++;
diff --git a/sys/net/if.h b/sys/net/if.h
index ba18fb9165f..27b862cf479 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * 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
@@ -30,13 +30,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if.h 7.11 (Berkeley) 3/19/91
- * $Id: if.h,v 1.8 1994/02/16 20:12:50 mycroft Exp $
+ * from: @(#)if.h 8.1 (Berkeley) 6/10/93
+ * $Id: if.h,v 1.9 1994/05/13 06:02:29 mycroft Exp $
*/
-#ifndef _NET_IF_H_
-#define _NET_IF_H_
-
/*
* Structures defining a network interface, providing a packet
* transport mechanism (ala level 0 of the PUP protocols).
@@ -45,8 +42,8 @@
* length, and provides higher level routines with input datagrams
* received from its medium.
*
- * Output occurs when the routine if_output is called, with three parameters:
- * (*ifp->if_output)(ifp, m, dst)
+ * Output occurs when the routine if_output is called, with four parameters:
+ * (*ifp->if_output)(ifp, m, dst, rt)
* Here m is the mbuf chain to be sent and dst is the destination address.
* The output routine encapsulates the supplied datagram if necessary,
* and then transmits it on its medium.
@@ -64,20 +61,61 @@
/* XXX fast fix for SNMP, going away soon */
#include <sys/time.h>
+struct mbuf;
+struct proc;
+struct rtentry;
+struct socket;
+struct ether_header;
+
/*
* Structure defining a queue for a network interface.
*
* (Would like to call this struct ``if'', but C isn't PL/1.)
*/
-
struct ifnet {
char *if_name; /* name, e.g. ``en'' or ``lo'' */
+ struct ifnet *if_next; /* all struct ifnets are chained */
+ struct ifaddr *if_addrlist; /* linked list of addresses per if */
+ int if_pcount; /* number of promiscuous listeners */
+ caddr_t if_bpf; /* packet filter structure */
+ u_short if_index; /* numeric abbreviation for this if */
short if_unit; /* sub-unit for lower level driver */
- short if_mtu; /* maximum transmission unit */
- short if_flags; /* up/down, broadcast, etc. */
short if_timer; /* time 'til if_watchdog called */
- int if_metric; /* routing metric (external only) */
- struct ifaddr *if_addrlist; /* linked list of addresses per if */
+ short if_flags; /* up/down, broadcast, etc. */
+ struct if_data {
+/* generic interface information */
+ u_char ifi_type; /* ethernet, tokenring, etc. */
+ u_char ifi_addrlen; /* media address length */
+ u_char ifi_hdrlen; /* media header length */
+ u_long ifi_mtu; /* maximum transmission unit */
+ u_long ifi_metric; /* routing metric (external only) */
+ u_long ifi_baudrate; /* linespeed */
+/* volatile statistics */
+ u_long ifi_ipackets; /* packets received on interface */
+ u_long ifi_ierrors; /* input errors on interface */
+ u_long ifi_opackets; /* packets sent on interface */
+ u_long ifi_oerrors; /* output errors on interface */
+ u_long ifi_collisions; /* collisions on csma interfaces */
+ u_long ifi_ibytes; /* total number of octets received */
+ u_long ifi_obytes; /* total number of octets sent */
+ u_long ifi_imcasts; /* packets received via multicast */
+ u_long ifi_omcasts; /* packets sent via multicast */
+ u_long ifi_iqdrops; /* dropped on input, this interface */
+ u_long ifi_noproto; /* destined for unsupported protocol */
+ struct timeval ifi_lastchange;/* last updated */
+ } if_data;
+/* procedure handles */
+ int (*if_output) /* output routine (enqueue) */
+ __P((struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct rtentry *));
+ int (*if_start) /* initiate output routine */
+ __P((struct ifnet *));
+ int (*if_ioctl) /* ioctl routine */
+ __P((struct ifnet *, int, caddr_t));
+ int (*if_reset) /* XXX bus reset routine */
+ __P((int));
+ int (*if_watchdog) /* timer routine */
+ __P((int));
struct ifqueue {
struct mbuf *ifq_head;
struct mbuf *ifq_tail;
@@ -85,35 +123,25 @@ struct ifnet {
int ifq_maxlen;
int ifq_drops;
} if_snd; /* output queue */
-/* procedure handles */
- int (*if_output)(); /* output routine (enqueue) */
- int (*if_start)(); /* initiate output routine */
- int (*if_ioctl)(); /* ioctl routine */
- int (*if_reset)(); /* bus reset routine */
- int (*if_watchdog)(); /* timer routine */
-/* generic interface statistics */
- int if_ipackets; /* packets received on interface */
- int if_ierrors; /* input errors on interface */
- int if_opackets; /* packets sent on interface */
- int if_oerrors; /* output errors on interface */
- int if_collisions; /* collisions on csma interfaces */
-/* end statistics */
- struct ifnet *if_next;
- u_char if_type; /* ethernet, tokenring, etc */
- u_char if_addrlen; /* media address length */
- u_char if_hdrlen; /* media header length */
- u_char if_index; /* numeric abbreviation for this if */
-/* more statistics here to avoid recompiling netstat */
- struct timeval if_lastchange; /* last updated */
- int if_ibytes; /* total number of octets received */
- int if_obytes; /* total number of octets sent */
- int if_imcasts; /* packets received via multicast */
- int if_omcasts; /* packets sent via multicast */
- int if_iqdrops; /* dropped on input, this interface */
- int if_noproto; /* destined for unsupported protocol */
- int if_baudrate; /* linespeed */
- int if_pcount; /* number of promiscuous listeners */
};
+#define if_mtu if_data.ifi_mtu
+#define if_type if_data.ifi_type
+#define if_addrlen if_data.ifi_addrlen
+#define if_hdrlen if_data.ifi_hdrlen
+#define if_metric if_data.ifi_metric
+#define if_baudrate if_data.ifi_baudrate
+#define if_ipackets if_data.ifi_ipackets
+#define if_ierrors if_data.ifi_ierrors
+#define if_opackets if_data.ifi_opackets
+#define if_oerrors if_data.ifi_oerrors
+#define if_collisions if_data.ifi_collisions
+#define if_ibytes if_data.ifi_ibytes
+#define if_obytes if_data.ifi_obytes
+#define if_imcasts if_data.ifi_imcasts
+#define if_omcasts if_data.ifi_omcasts
+#define if_iqdrops if_data.ifi_iqdrops
+#define if_noproto if_data.ifi_noproto
+#define if_lastchange if_data.ifi_lastchange
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
@@ -123,7 +151,6 @@ struct ifnet {
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* resources allocated */
#define IFF_NOARP 0x80 /* no address resolution protocol */
-/* next two not supported now, but reserved: */
#define IFF_PROMISC 0x100 /* receive all packets */
#define IFF_ALLMULTI 0x200 /* receive all multicast packets */
#define IFF_OACTIVE 0x400 /* transmission in progress */
@@ -131,12 +158,12 @@ struct ifnet {
#define IFF_LINK0 0x1000 /* per link layer defined bit */
#define IFF_LINK1 0x2000 /* per link layer defined bit */
#define IFF_LINK2 0x4000 /* per link layer defined bit */
-#define IFF_MULTICAST 0x8000 /* supports multicast */
+#define IFF_MULTICAST 0x8000 /* supports multicast */
/* flags set internally only: */
-#define IFF_CANTCHANGE \
- (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE| \
- IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
+#define IFF_CANTCHANGE \
+ (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
+ IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
/*
* Output queues (ifp->if_snd) and internetwork datagram level (pup level 1)
@@ -188,12 +215,41 @@ struct ifaddr {
struct sockaddr *ifa_netmask; /* used to determine subnet */
struct ifnet *ifa_ifp; /* back-pointer to interface */
struct ifaddr *ifa_next; /* next address for interface */
- int (*ifa_rtrequest)(); /* check or clean routes (+ or -)'d */
- struct rtentry *ifa_rt; /* ??? for ROUTETOIF */
+ void (*ifa_rtrequest)(); /* check or clean routes (+ or -)'d */
u_short ifa_flags; /* mostly rt_flags for cloning */
- u_short ifa_llinfolen; /* extra to malloc for link info */
+ short ifa_refcnt; /* count of references */
+ int ifa_metric; /* cost of going out this interface */
+};
+#define IFA_ROUTE RTF_UP /* route installed */
+
+/*
+ * Message format for use in obtaining information about interfaces
+ * from sysctl and the routing socket.
+ */
+struct if_msghdr {
+ u_short ifm_msglen; /* to skip over non-understood messages */
+ u_char ifm_version; /* future binary compatability */
+ u_char ifm_type; /* message type */
+ int ifm_addrs; /* like rtm_addrs */
+ int ifm_flags; /* value of if_flags */
+ u_short ifm_index; /* index for associated ifp */
+ struct if_data ifm_data;/* statistics and other data about if */
};
-#define IFA_ROUTE RTF_UP /* route installed */
+
+/*
+ * Message format for use in obtaining information about interface addresses
+ * from sysctl and the routing socket.
+ */
+struct ifa_msghdr {
+ u_short ifam_msglen; /* to skip over non-understood messages */
+ u_char ifam_version; /* future binary compatability */
+ u_char ifam_type; /* message type */
+ int ifam_addrs; /* like rtm_addrs */
+ int ifam_flags; /* value of ifa_flags */
+ u_short ifam_index; /* index for associated ifp */
+ int ifam_metric; /* value of ifa_metric */
+};
+
/*
* Interface request structure used for socket
* ioctl's. All interface ioctl's must have parameter
@@ -242,14 +298,50 @@ struct ifconf {
#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
};
-#ifdef KERNEL
-#include "../net/if_arp.h"
-struct ifqueue rawintrq; /* raw packet input queue */
-struct ifnet *ifnet;
-struct ifaddr *ifa_ifwithaddr(), *ifa_ifwithnet();
-struct ifaddr *ifa_ifwithdstaddr();
-#else KERNEL
#include <net/if_arp.h>
-#endif KERNEL
-#endif /* !_NET_IF_H_ */
+#ifdef KERNEL
+#define IFAFREE(ifa) \
+ if ((ifa)->ifa_refcnt <= 0) \
+ ifafree(ifa); \
+ else \
+ (ifa)->ifa_refcnt--;
+
+struct ifnet *ifnet;
+
+void ether_ifattach __P((struct ifnet *));
+void ether_input __P((struct ifnet *, struct ether_header *, struct mbuf *));
+int ether_output __P((struct ifnet *,
+ struct mbuf *, struct sockaddr *, struct rtentry *));
+char *ether_sprintf __P((u_char *));
+
+void if_attach __P((struct ifnet *));
+void if_down __P((struct ifnet *));
+void if_qflush __P((struct ifqueue *));
+void if_slowtimo __P((void *));
+void if_up __P((struct ifnet *));
+#ifdef vax
+void ifubareset __P((int));
+#endif
+int ifconf __P((int, caddr_t));
+void ifinit __P((void));
+int ifioctl __P((struct socket *, int, caddr_t, struct proc *));
+int ifpromisc __P((struct ifnet *, int));
+struct ifnet *ifunit __P((char *));
+
+struct ifaddr *ifa_ifwithaddr __P((struct sockaddr *));
+struct ifaddr *ifa_ifwithaf __P((int));
+struct ifaddr *ifa_ifwithdstaddr __P((struct sockaddr *));
+struct ifaddr *ifa_ifwithnet __P((struct sockaddr *));
+struct ifaddr *ifa_ifwithroute __P((int, struct sockaddr *,
+ struct sockaddr *));
+struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *));
+void ifafree __P((struct ifaddr *));
+void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
+
+int loioctl __P((struct ifnet *, int, caddr_t));
+void loopattach __P((int));
+int looutput __P((struct ifnet *,
+ struct mbuf *, struct sockaddr *, struct rtentry *));
+void lortrequest __P((int, struct rtentry *, struct sockaddr *));
+#endif /* KERNEL */
diff --git a/sys/net/if_arp.h b/sys/net/if_arp.h
index 0e2cf7fdc6b..c3217a13412 100644
--- a/sys/net/if_arp.h
+++ b/sys/net/if_arp.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1986 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1986, 1993
+ * 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
@@ -30,13 +30,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if_arp.h 7.4 (Berkeley) 6/28/90
- * $Id: if_arp.h,v 1.5 1993/09/05 00:46:54 cassidy Exp $
+ * from: @(#)if_arp.h 8.1 (Berkeley) 6/10/93
+ * $Id: if_arp.h,v 1.6 1994/05/13 06:02:31 mycroft Exp $
*/
-#ifndef _NET_IF_ARP_H_
-#define _NET_IF_ARP_H_
-
/*
* Address Resolution Protocol.
*
@@ -49,23 +46,28 @@
*/
struct arphdr {
u_short ar_hrd; /* format of hardware address */
-#define ARPHRD_ETHER 1 /* ethernet hardware address */
+#define ARPHRD_ETHER 1 /* ethernet hardware format */
+#define ARPHRD_FRELAY 15 /* frame relay hardware format */
u_short ar_pro; /* format of protocol address */
u_char ar_hln; /* length of hardware address */
u_char ar_pln; /* length of protocol address */
u_short ar_op; /* one of: */
#define ARPOP_REQUEST 1 /* request to resolve address */
#define ARPOP_REPLY 2 /* response to previous request */
-#define REVARP_REQUEST 3 /* reverse ARP request */
-#define REVARP_REPLY 4 /* reverse ARP reply */
+#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
+#define ARPOP_REVREPLY 4 /* response giving protocol address */
+#define ARPOP_INVREQUEST 8 /* request to identify peer */
+#define ARPOP_INVREPLY 9 /* response identifying peer */
/*
* The remaining fields are variable in size,
* according to the sizes above.
*/
-/* u_char ar_sha[]; * sender hardware address */
-/* u_char ar_spa[]; * sender protocol address */
-/* u_char ar_tha[]; * target hardware address */
-/* u_char ar_tpa[]; * target protocol address */
+#ifdef COMMENT_ONLY
+ u_char ar_sha[]; /* sender hardware address */
+ u_char ar_spa[]; /* sender protocol address */
+ u_char ar_tha[]; /* target hardware address */
+ u_char ar_tpa[]; /* target protocol address */
+#endif
};
/*
@@ -82,5 +84,3 @@ struct arpreq {
#define ATF_PERM 0x04 /* permanent entry */
#define ATF_PUBL 0x08 /* publish entry (respond for other host) */
#define ATF_USETRAILERS 0x10 /* has requested trailers */
-
-#endif /* !_NET_IF_ARP_H_ */
diff --git a/sys/net/if_dl.h b/sys/net/if_dl.h
index b2ad2d39730..9ac9ec7ea61 100644
--- a/sys/net/if_dl.h
+++ b/sys/net/if_dl.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1990 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1990, 1993
+ * 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
@@ -30,13 +30,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if_dl.h 7.2 (Berkeley) 2/22/91
- * $Id: if_dl.h,v 1.3 1993/05/20 03:05:58 cgd Exp $
+ * from: @(#)if_dl.h 8.1 (Berkeley) 6/10/93
+ * $Id: if_dl.h,v 1.4 1994/05/13 06:02:33 mycroft Exp $
*/
-#ifndef _NET_IF_DL_H_
-#define _NET_IF_DL_H_
-
/*
* A Link-Level Sockaddr may specify the interface in one of two
* ways: either by means of a system-provided index number (computed
@@ -82,5 +79,3 @@ char *link_ntoa __P((const struct sockaddr_dl *));
__END_DECLS
#endif /* !KERNEL */
-
-#endif /* !_NET_IF_DL_H_ */
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index f11af232e08..4424761360e 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1982, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1989, 1993
+ * 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
@@ -30,8 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if_ethersubr.c 7.13 (Berkeley) 4/20/91
- * $Id: if_ethersubr.c,v 1.7 1994/04/18 06:18:10 glass Exp $
+ * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
*/
#include <sys/param.h>
@@ -45,11 +44,14 @@
#include <sys/errno.h>
#include <sys/syslog.h>
+#include <machine/cpu.h>
+
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/if_llc.h>
#include <net/if_dl.h>
+#include <net/if_types.h>
#ifdef INET
#include <netinet/in.h>
@@ -69,10 +71,18 @@
#include <netiso/iso_snpac.h>
#endif
-#include <machine/cpu.h>
+#ifdef LLC
+#include <netccitt/dll.h>
+#include <netccitt/llc_var.h>
+#endif
+
+#if defined(LLC) && defined(CCITT)
+extern struct ifqueue pkintrq;
+#endif
u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
extern struct ifnet loif;
+#define senderr(e) { error = (e); goto bad;}
/*
* Ethernet output routine.
@@ -81,55 +91,64 @@ extern struct ifnet loif;
* packet leaves a multiple of 512 bytes of data in remainder.
* Assumes that ifp is actually pointer to arpcom structure.
*/
-ether_output(ifp, m0, dst, rt)
+int
+ether_output(ifp, m0, dst, rt0)
register struct ifnet *ifp;
struct mbuf *m0;
struct sockaddr *dst;
- struct rtentry *rt;
+ struct rtentry *rt0;
{
- u_short type;
+ u_short etype;
int s, error = 0;
u_char edst[6];
- struct in_addr idst;
register struct mbuf *m = m0;
+ register struct rtentry *rt;
struct mbuf *mcopy = (struct mbuf *)0;
register struct ether_header *eh;
- int usetrailers, off, len = m->m_pkthdr.len;
-#define ac ((struct arpcom *)ifp)
+ int off, len = m->m_pkthdr.len;
+ struct arpcom *ac = (struct arpcom *)ifp;
- if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
- error = ENETDOWN;
- goto bad;
- }
+ if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ senderr(ENETDOWN);
ifp->if_lastchange = time;
+ if (rt = rt0) {
+ if ((rt->rt_flags & RTF_UP) == 0) {
+ if (rt0 = rt = rtalloc1(dst, 1))
+ rt->rt_refcnt--;
+ else
+ senderr(EHOSTUNREACH);
+ }
+ if (rt->rt_flags & RTF_GATEWAY) {
+ if (rt->rt_gwroute == 0)
+ goto lookup;
+ if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
+ rtfree(rt); rt = rt0;
+ lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
+ if ((rt = rt->rt_gwroute) == 0)
+ senderr(EHOSTUNREACH);
+ }
+ }
+ if (rt->rt_flags & RTF_REJECT)
+ if (rt->rt_rmx.rmx_expire == 0 ||
+ time.tv_sec < rt->rt_rmx.rmx_expire)
+ senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
+ }
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- idst = ((struct sockaddr_in *)dst)->sin_addr;
- if (!arpresolve(ac, m, &idst, edst, &usetrailers))
+ if (!arpresolve(ac, rt, m, dst, edst))
return (0); /* if not yet resolved */
/* If broadcasting on a simplex interface, loopback a copy */
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;
- if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
- (m->m_flags & M_EXT) == 0 &&
- m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) {
- type = ETHERTYPE_TRAIL + (off>>9);
- m->m_data -= 2 * sizeof (u_short);
- m->m_len += 2 * sizeof (u_short);
- len += 2 * sizeof (u_short);
- *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
- *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
- goto gottrailertype;
- }
- type = ETHERTYPE_IP;
- goto gottype;
+ etype = ETHERTYPE_IP;
+ break;
#endif
#ifdef NS
case AF_NS:
- type = ETHERTYPE_NS;
+ etype = ETHERTYPE_NS;
bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
(caddr_t)edst, sizeof (edst));
if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
@@ -137,36 +156,24 @@ ether_output(ifp, m0, dst, rt)
/* If broadcasting on a simplex interface, loopback a copy */
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
mcopy = m_copy(m, 0, (int)M_COPYALL);
- goto gottype;
+ break;
#endif
#ifdef ISO
case AF_ISO: {
int snpalen;
struct llc *l;
-
- iso_again:
- if (rt && rt->rt_gateway && (rt->rt_flags & RTF_UP)) {
- if (rt->rt_flags & RTF_GATEWAY) {
- if (rt->rt_llinfo) {
- rt = (struct rtentry *)rt->rt_llinfo;
- goto iso_again;
- }
- } else {
- register struct sockaddr_dl *sdl =
- (struct sockaddr_dl *)rt->rt_gateway;
- if (sdl && sdl->sdl_family == AF_LINK
- && sdl->sdl_alen > 0) {
- bcopy(LLADDR(sdl), (char *)edst,
- sizeof(edst));
- goto iso_resolved;
- }
- }
- }
- if ((error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
- (char *)edst, &snpalen)) > 0)
+ register struct sockaddr_dl *sdl;
+
+ if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
+ sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
+ bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
+ } else if (error =
+ iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
+ (char *)edst, &snpalen))
goto bad; /* Not Resolved */
- iso_resolved:
/* If broadcasting on a simplex interface, loopback a copy */
+ if (*edst & 1)
+ m->m_flags |= (M_BCAST|M_MCAST);
if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
(mcopy = m_copy(m, 0, (int)M_COPYALL))) {
M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
@@ -181,7 +188,7 @@ ether_output(ifp, m0, dst, rt)
M_PREPEND(m, 3, M_DONTWAIT);
if (m == NULL)
return (0);
- type = m->m_pkthdr.len;
+ etype = m->m_pkthdr.len;
l = mtod(m, struct llc *);
l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
l->llc_control = LLC_UI;
@@ -193,46 +200,62 @@ ether_output(ifp, m0, dst, rt)
printf("%x ", edst[i] & 0xff);
printf("\n");
ENDDEBUG
+ } break;
+#endif /* ISO */
+#ifdef LLC
+/* case AF_NSAP: */
+ case AF_CCITT: {
+ register struct sockaddr_dl *sdl =
+ (struct sockaddr_dl *) rt -> rt_gateway;
+
+ if (sdl && sdl->sdl_family == AF_LINK
+ && sdl->sdl_alen > 0) {
+ bcopy(LLADDR(sdl), (char *)edst,
+ sizeof(edst));
+ } else goto bad; /* Not a link interface ? Funny ... */
+ if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
+ (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
+ M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
+ if (mcopy) {
+ eh = mtod(mcopy, struct ether_header *);
+ bcopy((caddr_t)edst,
+ (caddr_t)eh->ether_dhost, sizeof (edst));
+ bcopy((caddr_t)ac->ac_enaddr,
+ (caddr_t)eh->ether_shost, sizeof (edst));
+ }
}
- goto gottype;
-#endif ISO
-#ifdef RMP
- case AF_RMP:
- /*
- * This is IEEE 802.3 -- the Ethernet `type' field is
- * really a `length' field.
- */
- type = m->m_len;
- bcopy((caddr_t)dst->sa_data, (caddr_t)edst, sizeof(edst));
- break;
-#endif
+ etype = m->m_pkthdr.len;
+#ifdef LLC_DEBUG
+ {
+ int i;
+ register struct llc *l = mtod(m, struct llc *);
+
+ printf("ether_output: sending LLC2 pkt to: ");
+ for (i=0; i<6; i++)
+ printf("%x ", edst[i] & 0xff);
+ printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
+ etype & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
+ l->llc_control & 0xff);
+
+ }
+#endif /* LLC_DEBUG */
+ } break;
+#endif /* LLC */
case AF_UNSPEC:
eh = (struct ether_header *)dst->sa_data;
bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
- /* AF_UNSPEC doesn't swap the byte order of the ether_type */
- type = ntohs(eh->ether_type);
- goto gottype;
+ /* AF_UNSPEC doesn't swap the byte order of the ether_type. */
+ etype = ntohs(eh->ether_type);
+ break;
default:
printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
dst->sa_family);
- error = EAFNOSUPPORT;
- goto bad;
+ senderr(EAFNOSUPPORT);
}
-gottrailertype:
- /*
- * Packet to be sent as trailer: move first packet
- * (control information) to end of chain.
- */
- while (m->m_next)
- m = m->m_next;
- m->m_next = m0;
- m = m0->m_next;
- m0->m_next = 0;
-gottype:
if (mcopy)
(void) looutput(ifp, mcopy, dst, rt);
/*
@@ -240,13 +263,11 @@ gottype:
* allocate another.
*/
M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
- if (m == 0) {
- error = ENOBUFS;
- goto bad;
- }
+ if (m == 0)
+ senderr(ENOBUFS);
eh = mtod(m, struct ether_header *);
- type = htons((u_short)type);
- bcopy((caddr_t)&type,(caddr_t)&eh->ether_type,
+ etype = htons(etype);
+ bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
sizeof(eh->ether_type));
bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
@@ -259,8 +280,7 @@ gottype:
if (IF_QFULL(&ifp->if_snd)) {
IF_DROP(&ifp->if_snd);
splx(s);
- error = ENOBUFS;
- goto bad;
+ senderr(ENOBUFS);
}
IF_ENQUEUE(&ifp->if_snd, m);
if ((ifp->if_flags & IFF_OACTIVE) == 0)
@@ -282,6 +302,7 @@ bad:
* the packet is in the mbuf chain m without
* the ether header, which is provided separately.
*/
+void
ether_input(ifp, eh, m)
struct ifnet *ifp;
register struct ether_header *eh;
@@ -290,17 +311,22 @@ ether_input(ifp, eh, m)
register struct ifqueue *inq;
register struct llc *l;
u_short etype;
+ struct arpcom *ac = (struct arpcom *)ifp;
int s;
+ if ((ifp->if_flags & IFF_UP) == 0) {
+ m_freem(m);
+ return;
+ }
ifp->if_lastchange = time;
ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
- if (eh->ether_dhost[0] & 1) {
- if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
- sizeof(etherbroadcastaddr)) == 0)
- m->m_flags |= M_BCAST;
- else
- m->m_flags |= M_MCAST;
- }
+ if (eh->ether_dhost[0] & 1) {
+ if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
+ sizeof(etherbroadcastaddr)) == 0)
+ m->m_flags |= M_BCAST;
+ else
+ m->m_flags |= M_MCAST;
+ }
if (m->m_flags & (M_BCAST|M_MCAST))
ifp->if_imcasts++;
@@ -313,11 +339,12 @@ ether_input(ifp, eh, m)
break;
case ETHERTYPE_ARP:
- arpinput((struct arpcom *)ifp, m);
- return;
+ schednetisr(NETISR_ARP);
+ inq = &arpintrq;
+ break;
case ETHERTYPE_REVARP:
- revarpinput((struct arpcom *) ifp, m);
+ revarpinput(m); /* XXX queue? */
return;
#endif
#ifdef NS
@@ -328,76 +355,107 @@ ether_input(ifp, eh, m)
#endif
default:
-#ifdef ISO
- if (etype > ETHERMTU)
+#if defined (ISO) || defined (LLC)
+ if (eh->ether_type > ETHERMTU)
goto dropanyway;
l = mtod(m, struct llc *);
- switch (l->llc_control) {
- case LLC_UI:
- /* LLC_UI_P forbidden in class 1 service */
- if ((l->llc_dsap == LLC_ISO_LSAP) &&
- (l->llc_ssap == LLC_ISO_LSAP)) {
- /* LSAP for ISO */
- if (m->m_pkthdr.len > etype)
- m_adj(m, etype - m->m_pkthdr.len);
- m->m_data += 3; /* XXX */
- m->m_len -= 3; /* XXX */
- m->m_pkthdr.len -= 3; /* XXX */
- M_PREPEND(m, sizeof *eh, M_DONTWAIT);
- if (m == 0)
+ switch (l->llc_dsap) {
+#ifdef ISO
+ case LLC_ISO_LSAP:
+ switch (l->llc_control) {
+ case LLC_UI:
+ /* LLC_UI_P forbidden in class 1 service */
+ if ((l->llc_dsap == LLC_ISO_LSAP) &&
+ (l->llc_ssap == LLC_ISO_LSAP)) {
+ /* LSAP for ISO */
+ if (m->m_pkthdr.len > eh->ether_type)
+ m_adj(m, eh->ether_type - m->m_pkthdr.len);
+ m->m_data += 3; /* XXX */
+ m->m_len -= 3; /* XXX */
+ m->m_pkthdr.len -= 3; /* XXX */
+ M_PREPEND(m, sizeof *eh, M_DONTWAIT);
+ if (m == 0)
+ return;
+ *mtod(m, struct ether_header *) = *eh;
+ IFDEBUG(D_ETHER)
+ printf("clnp packet");
+ ENDDEBUG
+ schednetisr(NETISR_ISO);
+ inq = &clnlintrq;
+ break;
+ }
+ goto dropanyway;
+
+ case LLC_XID:
+ case LLC_XID_P:
+ if(m->m_len < 6)
+ goto dropanyway;
+ l->llc_window = 0;
+ l->llc_fid = 9;
+ l->llc_class = 1;
+ l->llc_dsap = l->llc_ssap = 0;
+ /* Fall through to */
+ case LLC_TEST:
+ case LLC_TEST_P:
+ {
+ struct sockaddr sa;
+ register struct ether_header *eh2;
+ int i;
+ u_char c = l->llc_dsap;
+
+ l->llc_dsap = l->llc_ssap;
+ l->llc_ssap = c;
+ if (m->m_flags & (M_BCAST | M_MCAST))
+ bcopy((caddr_t)ac->ac_enaddr,
+ (caddr_t)eh->ether_dhost, 6);
+ sa.sa_family = AF_UNSPEC;
+ sa.sa_len = sizeof(sa);
+ eh2 = (struct ether_header *)sa.sa_data;
+ for (i = 0; i < 6; i++) {
+ eh2->ether_shost[i] = c = eh->ether_dhost[i];
+ eh2->ether_dhost[i] =
+ eh->ether_dhost[i] = eh->ether_shost[i];
+ eh->ether_shost[i] = c;
+ }
+ ifp->if_output(ifp, m, &sa, NULL);
return;
- *mtod(m, struct ether_header *) = *eh;
- IFDEBUG(D_ETHER)
- printf("clnp packet");
- ENDDEBUG
- schednetisr(NETISR_ISO);
- inq = &clnlintrq;
+ }
+ default:
+ m_freem(m);
+ return;
+ }
break;
- }
- goto dropanyway;
-
- case LLC_XID:
- case LLC_XID_P:
- if(m->m_len < 6)
- goto dropanyway;
- l->llc_window = 0;
- l->llc_fid = 9;
- l->llc_class = 1;
- l->llc_dsap = l->llc_ssap = 0;
- /* Fall through to */
- case LLC_TEST:
- case LLC_TEST_P:
+#endif /* ISO */
+#ifdef LLC
+ case LLC_X25_LSAP:
{
- struct sockaddr sa;
- register struct ether_header *eh2;
- int i;
- u_char c = l->llc_dsap;
- l->llc_dsap = l->llc_ssap;
- l->llc_ssap = c;
- if (m->m_flags & (M_BCAST | M_MCAST))
- bcopy((caddr_t)ac->ac_enaddr,
- (caddr_t)eh->ether_dhost, 6);
- sa.sa_family = AF_UNSPEC;
- sa.sa_len = sizeof(sa);
- eh2 = (struct ether_header *)sa.sa_data;
- for (i = 0; i < 6; i++) {
- eh2->ether_shost[i] = c = eh->ether_dhost[i];
- eh2->ether_dhost[i] =
- eh->ether_dhost[i] = eh->ether_shost[i];
- eh->ether_shost[i] = c;
- }
- ifp->if_output(ifp, m, &sa);
- return;
+ if (m->m_pkthdr.len > eh->ether_type)
+ m_adj(m, eh->ether_type - m->m_pkthdr.len);
+ M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
+ if (m == 0)
+ return;
+ if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
+ eh->ether_dhost, LLC_X25_LSAP, 6,
+ mtod(m, struct sdl_hdr *)))
+ panic("ETHER cons addr failure");
+ mtod(m, struct sdl_hdr *)->sdlhdr_len = eh->ether_type;
+#ifdef LLC_DEBUG
+ printf("llc packet\n");
+#endif /* LLC_DEBUG */
+ schednetisr(NETISR_CCITT);
+ inq = &llcintrq;
+ break;
}
+#endif /* LLC */
dropanyway:
default:
- m_freem(m);
- return;
- }
-#else
+ m_freem(m);
+ return;
+ }
+#else /* ISO || LLC */
m_freem(m);
return;
-#endif ISO
+#endif /* ISO || LLC */
}
s = splimp();
@@ -429,12 +487,34 @@ ether_sprintf(ap)
*--cp = 0;
return (etherbuf);
}
-
+
+/*
+ * Perform common duties while attaching to interface list
+ */
+void
+ether_ifattach(ifp)
+ register struct ifnet *ifp;
+{
+ register struct ifaddr *ifa;
+ register struct sockaddr_dl *sdl;
+
+ ifp->if_type = IFT_ETHER;
+ ifp->if_addrlen = 6;
+ ifp->if_hdrlen = 14;
+ ifp->if_mtu = ETHERMTU;
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+ if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
+ sdl->sdl_family == AF_LINK) {
+ sdl->sdl_type = IFT_ETHER;
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
+ LLADDR(sdl), ifp->if_addrlen);
+ break;
+ }
+}
+
u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
-
-/* XXX */
-#undef ac
/*
* Add an Ethernet multicast address or range of addresses to the list for a
* given interface.
diff --git a/sys/net/if_llc.h b/sys/net/if_llc.h
index 42609a03ef1..6d705919ac2 100644
--- a/sys/net/if_llc.h
+++ b/sys/net/if_llc.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ * 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
@@ -30,13 +30,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if_llc.h 7.2 (Berkeley) 6/28/90
- * $Id: if_llc.h,v 1.3 1993/05/20 03:06:00 cgd Exp $
+ * from: @(#)if_llc.h 8.1 (Berkeley) 6/10/93
+ * $Id: if_llc.h,v 1.4 1994/05/13 06:02:41 mycroft Exp $
*/
-#ifndef _NET_IF_LLC_H_
-#define _NET_IF_LLC_H_
-
/*
* IEEE 802.2 Link Level Control headers, for use in conjunction with
* 802.{3,4,5} media access control methods.
@@ -64,25 +61,80 @@ struct llc {
u_char num_rcv_x2;
} type_s;
struct {
+ u_char control;
+ struct frmrinfo {
+ u_char rej_pdu_0;
+ u_char rej_pdu_1;
+ u_char frmr_control;
+ u_char frmr_control_ext;
+ u_char frmr_cause;
+ } frmrinfo;
+ } type_frmr;
+ struct {
u_char control;
u_char org_code[3];
u_short ether_type;
} type_snap;
+ struct {
+ u_char control;
+ u_char control_ext;
+ } type_raw;
} llc_un;
};
-#define llc_control llc_un.type_u.control
-#define llc_fid llc_un.type_u.format_id
-#define llc_class llc_un.type_u.class
-#define llc_window llc_un.type_u.window_x2
+#define llc_control llc_un.type_u.control
+#define llc_control_ext llc_un.type_raw.control_ext
+#define llc_fid llc_un.type_u.format_id
+#define llc_class llc_un.type_u.class
+#define llc_window llc_un.type_u.window_x2
+#define llc_frmrinfo llc_un.type_frmr.frmrinfo
+#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0
+#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1
+#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control
+#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext
+#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext
+
+/*
+ * Don't use sizeof(struct llc_un) for LLC header sizes
+ */
+#define LLC_ISFRAMELEN 4
+#define LLC_UFRAMELEN 3
+#define LLC_FRMRLEN 7
+/*
+ * Unnumbered LLC format commands
+ */
#define LLC_UI 0x3
#define LLC_UI_P 0x13
-#define LLC_XID 0xaf
-#define LLC_XID_P 0xbf
+#define LLC_DISC 0x43
+#define LLC_DISC_P 0x53
+#define LLC_UA 0x63
+#define LLC_UA_P 0x73
#define LLC_TEST 0xe3
#define LLC_TEST_P 0xf3
+#define LLC_FRMR 0x87
+#define LLC_FRMR_P 0x97
+#define LLC_DM 0x0f
+#define LLC_DM_P 0x1f
+#define LLC_XID 0xaf
+#define LLC_XID_P 0xbf
+#define LLC_SABME 0x6f
+#define LLC_SABME_P 0x7f
-#define LLC_ISO_LSAP 0xfe
-#define LLC_SNAP_LSAP 0xaa
+/*
+ * Supervisory LLC commands
+ */
+#define LLC_RR 0x01
+#define LLC_RNR 0x05
+#define LLC_REJ 0x09
+
+/*
+ * Info format - dummy only
+ */
+#define LLC_INFO 0x00
-#endif /* !_NET_IF_LLC_H_ */
+/*
+ * ISO PDTR 10178 contains among others
+ */
+#define LLC_X25_LSAP 0x7e
+#define LLC_SNAP_LSAP 0xaa
+#define LLC_ISO_LSAP 0xfe
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index b6760a03ed4..bc9f09bd11f 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1993
+ * 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
@@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)if_loop.c 7.13 (Berkeley) 4/26/91
- * $Id: if_loop.c,v 1.10 1994/02/02 01:21:35 hpeyerl Exp $
+ * from: @(#)if_loop.c 8.1 (Berkeley) 6/10/93
+ * $Id: if_loop.c,v 1.11 1994/05/13 06:02:44 mycroft Exp $
*/
/*
@@ -43,11 +43,14 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
-#include <sys/protosw.h>
+#include <sys/time.h>
+
+#include <machine/cpu.h>
#include <net/if.h>
#include <net/if_types.h>
@@ -72,31 +75,26 @@
#endif
#if NBPFILTER > 0
-#include <sys/time.h>
#include <net/bpf.h>
-static caddr_t lo_bpf;
#endif
-#include <machine/cpu.h>
-
-#define LOMTU (1024+512)
+#define LOMTU (32768)
struct ifnet loif[NLOOP];
-int looutput(), loioctl();
void
-loopattach()
+loopattach(n)
+ int n;
{
register int i;
register struct ifnet *ifp;
- for (i = 0; i < NLOOP; i++)
- {
+ for (i = 0; i < NLOOP; i++) {
ifp = &loif[i];
ifp->if_unit = i;
ifp->if_name = "lo";
ifp->if_mtu = LOMTU;
- ifp->if_flags = IFF_LOOPBACK|IFF_MULTICAST;
+ ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
ifp->if_ioctl = loioctl;
ifp->if_output = looutput;
ifp->if_type = IFT_LOOP;
@@ -104,11 +102,12 @@ loopattach()
ifp->if_addrlen = 0;
if_attach(ifp);
#if NBPFILTER > 0
- bpfattach(&lo_bpf, ifp, DLT_NULL, sizeof(u_int));
+ bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
#endif
}
}
+int
looutput(ifp, m, dst, rt)
struct ifnet *ifp;
register struct mbuf *m;
@@ -120,8 +119,9 @@ looutput(ifp, m, dst, rt)
if ((m->m_flags & M_PKTHDR) == 0)
panic("looutput no HDR");
+ ifp->if_lastchange = time;
#if NBPFILTER > 0
- if (lo_bpf) {
+ if (ifp->if_bpf) {
/*
* We need to prepend the address family as
* a four byte field. Cons up a dummy header
@@ -136,14 +136,15 @@ looutput(ifp, m, dst, rt)
m0.m_len = 4;
m0.m_data = (char *)&af;
- bpf_mtap(lo_bpf, &m0);
+ bpf_mtap(ifp->if_bpf, &m0);
}
#endif
m->m_pkthdr.rcvif = ifp;
- if (rt && rt->rt_flags & RTF_REJECT) {
+ if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
m_freem(m);
- return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
+ rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
}
ifp->if_opackets++;
ifp->if_obytes += m->m_pkthdr.len;
@@ -189,10 +190,13 @@ looutput(ifp, m, dst, rt)
}
/* ARGSUSED */
+void
lortrequest(cmd, rt, sa)
-struct rtentry *rt;
-struct sockaddr *sa;
+ int cmd;
+ struct rtentry *rt;
+ struct sockaddr *sa;
{
+
if (rt)
rt->rt_rmx.rmx_mtu = LOMTU;
}
@@ -201,6 +205,7 @@ struct sockaddr *sa;
* Process an ioctl request.
*/
/* ARGSUSED */
+int
loioctl(ifp, cmd, data)
register struct ifnet *ifp;
int cmd;
@@ -208,7 +213,7 @@ loioctl(ifp, cmd, data)
{
register struct ifaddr *ifa;
register struct ifreq *ifr;
- int error = 0;
+ register int error = 0;
switch (cmd) {
@@ -235,11 +240,13 @@ loioctl(ifp, cmd, data)
case AF_INET:
break;
#endif
+
default:
error = EAFNOSUPPORT;
break;
}
break;
+
default:
error = EINVAL;
}