/* * Return address info for specified internet network. */ struct ipx_ifaddr * ipx_iaonnetof(struct ipx_addr *dst) { struct ipx_ifaddr *ia; struct ipx_addr *compare; struct ifnet *ifp; struct ipx_ifaddr *ia_maybe = NULL; union ipx_net net = dst->x_net; for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) { if ((ifp = ia->ia_ifp) != NULL) { if (ifp->if_flags & IFF_POINTOPOINT) { compare = &satoipx_addr(ia->ia_dstaddr); if (ipx_hosteq(*dst, *compare)) return (ia); if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net)) ia_maybe = ia; } else { if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net)) return (ia); } } } return (ia_maybe); }
/* * IPX input routine. Pass to next level. */ void ipxintr() { register struct ipx *ipx; register struct mbuf *m; register struct ipxpcb *ipxp; struct ipx_ifaddr *ia; register int i; int len, s; char oddshortpacket = 0; next: /* * Get next datagram off input queue and get IPX header * in first mbuf. */ s = splimp(); IF_DEQUEUE(&ipxintrq, m); splx(s); if (m == NULL) return; /* * If no IPX addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. */ if (ipx_ifaddr == NULL) goto bad; ipxstat.ipxs_total++; if ((m->m_flags & M_EXT || m->m_len < sizeof(struct ipx)) && (m = m_pullup(m, sizeof(struct ipx))) == 0) { ipxstat.ipxs_toosmall++; goto next; } /* * Give any raw listeners a crack at the packet */ for (ipxp = ipxrawpcb.ipxp_next; ipxp != &ipxrawpcb; ipxp = ipxp->ipxp_next) { struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); if (m1 != NULL) ipx_input(m1, ipxp); } ipx = mtod(m, struct ipx *); len = ntohs(ipx->ipx_len); if ((len < m->m_pkthdr.len) && (oddshortpacket = len & 1)) { /* * If this packet is of odd length, and the length * inside the header is less than the received packet * length, preserve garbage byte for possible checksum. */ len++; } /* * Check that the amount of data in the buffers * is as at least much as the IPX header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < len) { ipxstat.ipxs_tooshort++; goto bad; } if (m->m_pkthdr.len > len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = len; m->m_pkthdr.len = len; } else m_adj(m, len - m->m_pkthdr.len); } if (ipxcksum && ((i = ipx->ipx_sum) != 0xffff)) { ipx->ipx_sum = 0; if (i != (ipx->ipx_sum = ipx_cksum(m, len))) { ipxstat.ipxs_badsum++; goto bad; } } /* * Propagated (Netbios) packets (type 20) has to be handled * different. :-( */ if (ipx->ipx_pt == IPXPROTO_NETBIOS) { if (ipxnetbios) { ipx_output_type20(m); goto next; } else goto bad; } /* * Is this a directed broadcast? */ if (ipx_hosteqnh(ipx_broadhost,ipx->ipx_dna.x_host)) { if ((!ipx_neteq(ipx->ipx_dna, ipx->ipx_sna)) && (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_broadnet)) && (!ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet)) && (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_zeronet)) ) { /* * If it is a broadcast to the net where it was * received from, treat it as ours. */ for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) if((ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) && ipx_neteq(ia->ia_addr.sipx_addr, ipx->ipx_dna)) goto ours; /* * Look to see if I need to eat this packet. * Algorithm is to forward all young packets * and prematurely age any packets which will * by physically broadcasted. * Any very old packets eaten without forwarding * would die anyway. * * Suggestion of Bill Nesheim, Cornell U. */ if (ipx->ipx_tc < IPX_MAXHOPS) { ipx_forward(m); goto next; } } /* * Is this our packet? If not, forward. */ } else { for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) if (ipx_hosteq(ipx->ipx_dna, ia->ia_addr.sipx_addr) && (ipx_neteq(ipx->ipx_dna, ia->ia_addr.sipx_addr) || ipx_neteqnn(ipx->ipx_dna.x_net, ipx_zeronet))) break; if (ia == NULL) { ipx_forward(m); goto next; } } ours: /* * Locate pcb for datagram. */ ipxp = ipx_pcblookup(&ipx->ipx_sna, ipx->ipx_dna.x_port, IPX_WILDCARD); /* * Switch out to protocol's input routine. */ if (ipxp != NULL) { if (oddshortpacket) { m_adj(m, -1); } ipxstat.ipxs_delivered++; if ((ipxp->ipxp_flags & IPXP_ALL_PACKETS) == 0) switch (ipx->ipx_pt) { case IPXPROTO_SPX: spx_input(m, ipxp); goto next; } ipx_input(m, ipxp); } else goto bad; goto next; bad: m_freem(m); goto next; }