示例#1
0
/*
 * 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);
}
示例#2
0
文件: ipx_input.c 项目: kame/kame
/*
 * 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;
}