Subject: bpf write() to local host
To: None <tech-net@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-net
Date: 01/18/2003 22:10:00
--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
I'd like to commit the attached patch. This patch makes packets coming
to ether_output with the pseudo-family pseudo_AF_HDRCMPLT and a dest address
matching the local host redirected or copied to ether_input() (depending
if they are unicast or not). Only bpf write() seems to use pseudo_AF_HDRCMPLT
right now.
This is to solve a problem with simh: it uses bpf writes to send packets,
which makes it impossible to send packets to the local machine.
With this change (and a fix to simh) I can NFS mount from a NetBSD/vax in simh
a partition of the NetBSD/i386 hosting it.
Does anyone object to this change ?
Yes it's incomplete; similar changes should probably be done to other
output routines supporting pseudo_AF_HDRCMPLT but as I can't test I won't
do it.
--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel.Bouyer@lip6.fr
NetBSD: 23 ans d'experience feront toujours la difference
--
--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.input"
Index: if_ethersubr.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_ethersubr.c,v
retrieving revision 1.95
diff -u -r1.95 if_ethersubr.c
--- if_ethersubr.c 2002/05/18 22:52:44 1.95
+++ if_ethersubr.c 2003/01/18 20:58:08
@@ -202,6 +202,7 @@
struct mbuf *m = m0;
struct rtentry *rt;
struct mbuf *mcopy = (struct mbuf *)0;
+ struct mbuf *minput;
struct ether_header *eh;
ALTQ_DECL(struct altq_pktattr pktattr;)
#ifdef INET
@@ -456,6 +457,14 @@
bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
/* AF_UNSPEC doesn't swap the byte order of the ether_type. */
etype = eh->ether_type;
+ /* set M_BCAST or M_MCAST accrodingly, upper layer (e.g. bpf)
+ * may not have set it.
+ */
+
+ if (memcmp(etherbroadcastaddr, edst, ETHER_ADDR_LEN) == 0)
+ m->m_flags |= M_BCAST;
+ else if (ETHER_IS_MULTICAST(edst))
+ m->m_flags |= M_MCAST;
break;
default:
@@ -495,6 +504,29 @@
if (m == NULL)
return (0);
#endif
+ if (hdrcmplt) {
+ /* check if destination is for us */
+ if (memcmp(LLADDR(ifp->if_sadl), edst, ETHER_ADDR_LEN) == 0) {
+ /* just pass it to ether_input, no need to wire. */
+ m->m_pkthdr.rcvif = ifp;
+ s = splnet();
+ ether_input(ifp, m);
+ splx(s);
+ return (0);
+ } else if (m->m_flags & (M_BCAST | M_MCAST)) {
+ /*
+ * in this case we have to copy a packet to
+ * ether_input.
+ */
+ minput = m_copypacket(m, M_DONTWAIT);
+ if (minput) {
+ minput->m_pkthdr.rcvif = ifp;
+ s = splnet();
+ ether_input(ifp, minput);
+ splx(s);
+ }
+ }
+ }
#if NBRIDGE > 0
/*
--YiEDa0DAkWCtVeE4--