summaryrefslogtreecommitdiff
path: root/sys/net/if_loop.c
diff options
context:
space:
mode:
authorJulian Elischer <julian@FreeBSD.org>1998-06-12 03:48:19 +0000
committerJulian Elischer <julian@FreeBSD.org>1998-06-12 03:48:19 +0000
commited7509ace472df6920d5f272cd966f74e6dab7ab (patch)
tree14c5e57761857a3a0040e03b38cb34c8de013d9a /sys/net/if_loop.c
parent0cab75363d5b8c14b1133f91b59552b1195a45f3 (diff)
Notes
Diffstat (limited to 'sys/net/if_loop.c')
-rw-r--r--sys/net/if_loop.c89
1 files changed, 62 insertions, 27 deletions
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index f59452559aa8..c6f3832776d1 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)if_loop.c 8.1 (Berkeley) 6/10/93
- * $Id: if_loop.c,v 1.31 1998/04/30 19:37:00 phk Exp $
+ * $Id: if_loop.c,v 1.32 1998/06/07 17:12:03 dfr Exp $
*/
/*
@@ -83,6 +83,9 @@
#endif NETATALK
#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpfdesc.h>
+#endif
static int loioctl __P((struct ifnet *, u_long, caddr_t));
static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
@@ -90,6 +93,9 @@ static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
static void loopattach __P((void *));
PSEUDO_SET(loopattach, if_loop);
+static int looutput __P((struct ifnet *ifp,
+ struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
+
#ifdef TINY_LOMTU
#define LOMTU (1024+512)
#else
@@ -121,18 +127,50 @@ loopattach(dummy)
}
}
-int
+static int
looutput(ifp, m, dst, rt)
struct ifnet *ifp;
register struct mbuf *m;
struct sockaddr *dst;
register struct rtentry *rt;
{
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("looutput no HDR");
+
+ if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
+ m_freem(m);
+ return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
+ rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ }
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+ return(if_simloop(ifp, m, dst, 0));
+}
+
+/*
+ * if_simloop()
+ *
+ * This function is to support software emulation of hardware loopback,
+ * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
+ * hear their own broadcasts, we create a copy of the packet that we
+ * would normally receive via a hardware loopback.
+ *
+ * This function expects the packet to include the media header of length hlen.
+ */
+
+int
+if_simloop(ifp, m, dst, hlen)
+ struct ifnet *ifp;
+ register struct mbuf *m;
+ struct sockaddr *dst;
+ int hlen;
+{
int s, isr;
register struct ifqueue *ifq = 0;
if ((m->m_flags & M_PKTHDR) == 0)
- panic("looutput no HDR");
+ panic("%s: no HDR", __FUNCTION__);
+ m->m_pkthdr.rcvif = ifp;
#if NBPFILTER > 0
/* BPF write needs to be handled specially */
if (dst->sa_family == AF_UNSPEC) {
@@ -143,34 +181,31 @@ looutput(ifp, m, dst, rt)
}
if (ifp->if_bpf) {
- /*
- * We need to prepend the address family as
- * a four byte field. Cons up a dummy header
- * to pacify bpf. This is safe because bpf
- * will only read from the mbuf (i.e., it won't
- * try to free it or keep a pointer a to it).
- */
- struct mbuf m0;
+ struct mbuf m0, *n = m;
u_int af = dst->sa_family;
- m0.m_next = m;
- m0.m_len = 4;
- m0.m_data = (char *)&af;
-
- bpf_mtap(ifp, &m0);
+ if (ifp->if_bpf->bif_dlt == DLT_NULL) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a dummy header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+ n = &m0;
+ }
+ bpf_mtap(ifp, n);
}
#endif
- m->m_pkthdr.rcvif = ifp;
- if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
- m_freem(m);
- return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
- rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
- }
- ifp->if_opackets++;
- ifp->if_obytes += m->m_pkthdr.len;
- switch (dst->sa_family) {
+ /* Strip away media header */
+ if (hlen > 0)
+ m_adj(m, hlen);
+ switch (dst->sa_family) {
#ifdef INET
case AF_INET:
ifq = &ipintrq;
@@ -202,8 +237,8 @@ looutput(ifp, m, dst, rt)
break;
#endif NETATALK
default:
- printf("lo%d: can't handle af%d\n", ifp->if_unit,
- dst->sa_family);
+ printf("%s: can't handle af=%d\n",
+ __FUNCTION__, dst->sa_family);
m_freem(m);
return (EAFNOSUPPORT);
}