diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 1cfc7c266f75..634738ba7e9b 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 @@ -43,7 +43,6 @@ #include #include #include -#include #include #include diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index d96b026a3112..0345b84e0996 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 #include -#include #include #include #include #include #include #include +#include #include #include #include +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,15 +74,15 @@ 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) { @@ -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 0c660b7acc74..2f5aef7c6f0f 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 #include #include #include +#include #define MBTYPES #include #include @@ -46,7 +47,6 @@ #include #include -#include 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 = ⊤ + 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 7fa130d2163b..7880710a0872 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 @@ -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 6d1cb5a539fd..528a763157da 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 @@ -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 f0ecb914058f..63ed94c289da 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 @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 5ebec8ef1ae7..796474feafb2 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 #include #include #include +#include #include #include #include #include -#include #include +#if defined(sparc) && BSD < 199103 +#include +#endif #include #include @@ -67,16 +72,27 @@ #include #include + +#include +#include #include -#include -#include "sl.h" -#include "ppp.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 +#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); /* @@ -224,9 +356,48 @@ bpfclose(dev, flag) return (0); } +/* + * 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) { - /* - * 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. - */ - 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; - } + 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) + /* + * 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; + } } /* * 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) { + ifp = d->bd_bif->bif_ifp; -#if NSL > 0 - case DLT_SLIP: - dst.sa_family = AF_INET; - hlen = 0; - break; -#endif + if (uio->uio_resid == 0) + return (0); -#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; - - case DLT_NULL: - dst.sa_family = AF_UNSPEC; - hlen = 0; - break; - - 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); - - /* - * XXX Avoid complicated buffer chaining --- - * bail if it won't fit in a single mbuf. - */ - if (len > MCLBYTES) - 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); + error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen); + if (error) 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; + + if (datlen > ifp->if_mtu) + return (EMSGSIZE); + 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); @@ -842,29 +927,44 @@ bpf_ifname(ifp, ifr) *d = '\0'; } +/* + * 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 -#endif (NBPFILTER > 0) +#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; + + 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 c8160808f187..f4494f34a4f2 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 767145d28a51..0fbb1aeaaa06 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 #include #include -#include - #ifdef sun #include #endif @@ -161,6 +159,7 @@ m_xhalf(m, k, err) } #endif +#include /* * 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 f6108d9cc087..6f414589e23e 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 /* * 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 7287ef4c148b..e0b3ed515ef5 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 #include #include +#include #include #include #include -#include #include #include #include #include #include -#include - -#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 = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); - ifa->ifa_netmask = (struct sockaddr *)sdl; - sdl->sdl_len = socksize - ifp->if_addrlen; - while (namelen != 0) - sdl->sdl_data[--namelen] = 0xff; + 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 = masklen; + while (namelen != 0) + sdl->sdl_data[--namelen] = 0xff; } /* * 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 + /* * 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 ba18fb9165f4..27b862cf479d 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 +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'' */ - 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 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_timer; /* time 'til if_watchdog called */ + 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 */ +#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 */ +}; + +/* + * 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 -#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 0e2cf7fdc6bc..c3217a13412a 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 b2ad2d39730f..9ac9ec7ea61a 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 f11af232e085..4424761360ee 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 @@ -45,11 +44,14 @@ #include #include +#include + #include #include #include #include #include +#include #ifdef INET #include @@ -69,10 +71,18 @@ #include #endif -#include +#ifdef LLC +#include +#include +#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; + register struct sockaddr_dl *sdl; - 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) + 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); + 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; + } + default: + m_freem(m); + return; + } + break; +#endif /* ISO */ +#ifdef LLC + case LLC_X25_LSAP: + { + 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; - *mtod(m, struct ether_header *) = *eh; - IFDEBUG(D_ETHER) - printf("clnp packet"); - ENDDEBUG - schednetisr(NETISR_ISO); - inq = &clnlintrq; + 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; - } - 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); - return; } +#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 42609a03ef1c..6d705919ac2b 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. @@ -63,26 +60,81 @@ struct llc { u_char control; 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 +/* + * Supervisory LLC commands + */ +#define LLC_RR 0x01 +#define LLC_RNR 0x05 +#define LLC_REJ 0x09 + +/* + * Info format - dummy only + */ +#define LLC_INFO 0x00 + +/* + * ISO PDTR 10178 contains among others + */ +#define LLC_X25_LSAP 0x7e #define LLC_SNAP_LSAP 0xaa - -#endif /* !_NET_IF_LLC_H_ */ +#define LLC_ISO_LSAP 0xfe diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index b6760a03ed4b..bc9f09bd11f4 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 #include +#include #include #include #include #include -#include +#include + +#include #include #include @@ -72,31 +75,26 @@ #endif #if NBPFILTER > 0 -#include #include -static caddr_t lo_bpf; #endif -#include - -#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 *)⁡ - 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; }