summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2000-01-11 20:54:14 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2000-01-11 20:54:14 +0000
commit579c4d8436915ac1af8b3ac907bdf116d0954767 (patch)
tree6d1b73233a8c4d2af021378ed13d4e52a27b1e48 /sys
parentcefebd83acd5b52913e496a6280b760b7f08cfb1 (diff)
Add output routine to broadcast type 20 (Netbios) packets; from FreeBSD.
Diffstat (limited to 'sys')
-rw-r--r--sys/netipx/ipx_outputfl.c110
1 files changed, 109 insertions, 1 deletions
diff --git a/sys/netipx/ipx_outputfl.c b/sys/netipx/ipx_outputfl.c
index dca73944fb2..f0eb2b2678c 100644
--- a/sys/netipx/ipx_outputfl.c
+++ b/sys/netipx/ipx_outputfl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipx_outputfl.c,v 1.2 1996/10/26 09:34:52 mickey Exp $ */
+/* $OpenBSD: ipx_outputfl.c,v 1.3 2000/01/11 20:54:13 fgsch Exp $ */
/*-
*
@@ -160,3 +160,111 @@ done:
}
return (error);
}
+
+/*
+ * This will broadcast the type 20 (Netbios) packet to all the interfaces
+ * that have ipx configured and isn't in the list yet.
+ */
+int
+ipx_output_type20(m)
+ struct mbuf *m;
+{
+ register struct ipx *ipx;
+ union ipx_net *nbnet;
+ struct ipx_ifaddr *ia, *tia = NULL;
+ int error = 0;
+ struct mbuf *m1;
+ int i;
+ struct ifnet *ifp;
+ struct sockaddr_ipx dst;
+
+ /*
+ * We have to get to the 32 bytes after the ipx header also, so
+ * that we can fill in the network address of the receiving
+ * interface.
+ */
+ if ((m->m_flags & M_EXT || m->m_len < (sizeof(struct ipx) + 32)) &&
+ (m = m_pullup(m, sizeof(struct ipx) + 32)) == NULL) {
+ ipxstat.ipxs_toosmall++;
+ return (0);
+ }
+ ipx = mtod(m, struct ipx *);
+ nbnet = (union ipx_net *)(ipx + 1);
+
+ if (ipx->ipx_tc >= 8)
+ goto bad;
+ /*
+ * Now see if we have already seen this.
+ */
+ for (ia = ipx_ifaddr.tqh_first; ia != NULL; ia = ia->ia_list.tqe_next)
+ if(ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) {
+ if(tia == NULL)
+ tia = ia;
+
+ for (i=0;i<ipx->ipx_tc;i++,nbnet++)
+ if(ipx_neteqnn(ia->ia_addr.sipx_addr.ipx_net,
+ *nbnet))
+ goto bad;
+ }
+ /*
+ * Don't route the packet if the interface where it come from
+ * does not have an IPX address.
+ */
+ if(tia == NULL)
+ goto bad;
+
+ /*
+ * Add our receiving interface to the list.
+ */
+ nbnet = (union ipx_net *)(ipx + 1);
+ nbnet += ipx->ipx_tc;
+ *nbnet = tia->ia_addr.sipx_addr.ipx_net;
+
+ /*
+ * Increment the hop count.
+ */
+ ipx->ipx_tc++;
+ ipxstat.ipxs_forward++;
+
+ /*
+ * Send to all directly connected ifaces not in list and
+ * not to the one it came from.
+ */
+ m->m_flags &= ~M_BCAST;
+ bzero(&dst, sizeof(dst));
+ dst.sipx_family = AF_IPX;
+ dst.sipx_len = sizeof(dst);
+ dst.sipx_addr.ipx_host = ipx_broadhost;
+
+ for (ia = ipx_ifaddr.tqh_first; ia != NULL; ia = ia->ia_list.tqe_next)
+ if(ia->ia_ifa.ifa_ifp != m->m_pkthdr.rcvif) {
+ nbnet = (union ipx_net *)(ipx + 1);
+ for (i=0;i<ipx->ipx_tc;i++,nbnet++)
+ if(ipx_neteqnn(ia->ia_addr.sipx_addr.ipx_net,
+ *nbnet))
+ goto skip_this;
+
+ /*
+ * Insert the net address of the dest net and
+ * calculate the new checksum if needed.
+ */
+ ifp = ia->ia_ifa.ifa_ifp;
+ dst.sipx_addr.ipx_net = ia->ia_addr.sipx_addr.ipx_net;
+ ipx->ipx_dna.ipx_net = dst.sipx_addr.ipx_net;
+ m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
+
+ if(ipx->ipx_sum != 0xffff)
+ ipx->ipx_sum =
+ ipx_cksum(m, ntohs(ipx->ipx_len));
+ if(m1) {
+ error = (*ifp->if_output)(ifp, m1,
+ (struct sockaddr *)&dst, NULL);
+ /* XXX ipxstat.ipxs_localout++; */
+ }
+skip_this: ;
+ }
+
+bad:
+ m_freem(m);
+ return (error);
+}