Exemplo n.º 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);
}
Exemplo n.º 2
0
void
ipxnet_output(int s, int flags, struct sockaddr_ipx *sipx, int size)
{
	struct sockaddr_ipx dst;

	dst = *sipx;
	sipx = &dst;
	if (sipx->sipx_addr.x_port == 0)
		sipx->sipx_addr.x_port = htons(IPXPORT_RIP);
#ifdef DEBUG
	if(do_output || ntohs(msg->rip_cmd) == RIPCMD_REQUEST)
#endif	
	/*
	 * Kludge to allow us to get routes out to machines that
	 * don't know their addresses yet; send to that address on
	 * ALL connected nets
	 */
	 if (ipx_neteqnn(sipx->sipx_addr.x_net, ipx_zeronet)) {
	 	extern struct interface *ifnet;
	 	struct interface *ifp;
		
		for (ifp = ifnet; ifp; ifp = ifp->int_next) {
			sipx->sipx_addr.x_net = 
				satoipx_addr(ifp->int_addr).x_net;
			sendto(s, msg, size, flags,
			    (struct sockaddr *)sipx, sizeof (*sipx));
		}
		return;
	}
	
	sendto(s, msg, size, flags,
	    (struct sockaddr *)sipx, sizeof (*sipx));
}
Exemplo n.º 3
0
/*
 *  This may also be called for raw listeners.
 */
void
ipx_input(struct mbuf *m, struct ipxpcb *ipxp)
{
	struct ipx *ipx = mtod(m, struct ipx *);
	struct ifnet *ifp = m->m_pkthdr.rcvif;
	struct sockaddr_ipx ipx_ipx;

	KASSERT(ipxp != NULL, ("ipx_input: NULL ipxpcb"));
	IPX_LOCK_ASSERT(ipxp);
	/*
	 * Construct sockaddr format source address.
	 * Stuff source address and datagram in user buffer.
	 */
	ipx_ipx.sipx_len = sizeof(ipx_ipx);
	ipx_ipx.sipx_family = AF_IPX;
	ipx_ipx.sipx_addr = ipx->ipx_sna;
	ipx_ipx.sipx_zero[0] = '\0';
	ipx_ipx.sipx_zero[1] = '\0';
	if (ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet) && ifp != NULL) {
		struct ifaddr *ifa;

		for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL;
		     ifa = TAILQ_NEXT(ifa, ifa_link)) {
			if (ifa->ifa_addr->sa_family == AF_IPX) {
				ipx_ipx.sipx_addr.x_net =
					IA_SIPX(ifa)->sipx_addr.x_net;
				break;
			}
		}
	}
	ipxp->ipxp_rpt = ipx->ipx_pt;
	if ((ipxp->ipxp_flags & IPXP_RAWIN) == 0) {
		m->m_len -= sizeof(struct ipx);
		m->m_pkthdr.len -= sizeof(struct ipx);
		m->m_data += sizeof(struct ipx);
	}
#ifdef MAC
	if (mac_socket_check_deliver(ipxp->ipxp_socket, m) != 0) {
		m_freem(m);
		return;
	}
#endif
	if (sbappendaddr(&ipxp->ipxp_socket->so_rcv,
	    (struct sockaddr *)&ipx_ipx, m, NULL) == 0)
		m_freem(m);
	else
		sorwakeup(ipxp->ipxp_socket);
}
Exemplo n.º 4
0
void
process(int fd, int pkt_type)
{
	struct sockaddr from;
	int fromlen = sizeof (from), cc, omask;
	struct ipx *ipxdp = (struct ipx *)packet;

	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
	if (cc <= 0) {
		if (cc < 0 && errno != EINTR)
			syslog(LOG_ERR, "recvfrom: %m");
		return;
	}
	if (tracepackets > 1 && ftrace) {
	    fprintf(ftrace,"rcv %d bytes on %s ", 
		    cc, ipxdp_ntoa(&ipxdp->ipx_dna));
	    fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
	}
	
	if (noteremoterequests && 
	    !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
	    !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
	{
		syslog(LOG_ERR,
		       "net of interface (%s) != net on ether (%s)!\n",
		       ipxdp_nettoa(ipxdp->ipx_dna.x_net),
		       ipxdp_nettoa(ipxdp->ipx_sna.x_net));
	}
			
	/* We get the IPX header in front of the RIF packet*/
	cc -= sizeof (struct ipx);
#define	mask(s)	(1<<((s)-1))
	omask = sigblock(mask(SIGALRM));
	switch(pkt_type) {
		case SAP_PKT: sap_input(&from, cc);
				break;
		case RIP_PKT: rip_input(&from, cc);
				break;
	}
	sigsetmask(omask);
}
Exemplo n.º 5
0
/*
 * 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;
}
Exemplo n.º 6
0
/*
 * Supply dst with the contents of the routing tables.
 * If this won't fit in one packet, chop it up into several.
 *
 * This must be done using the split horizon algorithm.
 * 1. Don't send routing info to the interface from where it was received.
 * 2. Don't publish an interface to itself.
 * 3. If a route is received from more than one interface and the cost is
 *    the same, don't publish it on either interface. I am calling this
 *    clones.
 */
void
supply(struct sockaddr *dst, int flags, struct interface *ifp,
       int changesonly)
{
	struct rt_entry *rt;
	struct rt_entry *crt; /* Clone route */
	struct rthash *rh;
	struct netinfo *nn;
	struct netinfo *n = msg->rip_nets;
	struct sockaddr_ipx *sipx =  (struct sockaddr_ipx *) dst;
	af_output_t *output = afswitch[dst->sa_family].af_output;
	int size, metric, ticks;
	union ipx_net net;
	int delay = 0;

	if (sipx->sipx_port == 0)
		sipx->sipx_port = htons(IPXPORT_RIP);

	msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
	for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) {
		for (rt = rh->rt_forw; rt != (struct rt_entry *)rh;
		     rt = rt->rt_forw) {
			size = (char *)n - (char *)msg;
			if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) +
				sizeof (msg->rip_cmd))) {
				(*output)(ripsock, flags, dst, size);
				TRACE_OUTPUT(ifp, dst, size);
				n = msg->rip_nets;
				delay++;
				if(delay == 2) {
					usleep(50000);
					delay = 0;
				}
			}

			if (changesonly && !(rt->rt_state & RTS_CHANGED))
				continue;

			/*
			 * This should do rule one and two of the split horizon
			 * algorithm.
			 */
			if (rt->rt_ifp == ifp)
				continue;

			/*
			 * Rule 3.
			 * Look if we have clones (different routes to the same
			 * place with exactly the same cost).
			 *
			 * We should not publish on any of the clone
			 * interfaces.
			 */
			crt = rt->rt_clone;
			while (crt) {
				if (crt->rt_ifp == ifp)
					goto next;
				crt = crt->rt_clone;
			}

			sipx = (struct sockaddr_ipx *)&rt->rt_dst;
			if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) ==
			    RTF_HOST)
				sipx = (struct sockaddr_ipx *)&rt->rt_router;
			if (rt->rt_metric == HOPCNT_INFINITY)
				metric = HOPCNT_INFINITY;
			else {
				metric = rt->rt_metric + 1;
				/*
				 * We don't advertize routes with more than
				 * 15 hops.
				 */
				if (metric >= HOPCNT_INFINITY)
					continue;
			}
			/*
			 * XXX One day we should cater for slow interfaces
			 * also.
			 */
			ticks = rt->rt_ticks + 1;
			net = sipx->sipx_addr.x_net;

			/*
			 * Make sure that we don't put out a two net entries
			 * for a pt to pt link (one for the G route, one for
			 * the if)
			 * This is a kludge, and won't work if there are lots
			 * of nets.
			 */
			for (nn = msg->rip_nets; nn < n; nn++) {
				if (ipx_neteqnn(net, nn->rip_dst)) {
					if (ticks < ntohs(nn->rip_ticks)) {
						nn->rip_metric = htons(metric);
						nn->rip_ticks = htons(ticks);
					} else if ((ticks == ntohs(nn->rip_ticks)) &&
					    (metric < ntohs(nn->rip_metric))) {
						nn->rip_metric = htons(metric);
						nn->rip_ticks = htons(ticks);
					}
					goto next;
				}
			}
			n->rip_dst = net;
			n->rip_metric = htons(metric);
			n->rip_ticks = htons(ticks);
			n++;
next:
			;
		}
		if (n != msg->rip_nets) {
			size = (char *)n - (char *)msg;
			(*output)(ripsock, flags, dst, size);
			TRACE_OUTPUT(ifp, dst, size);
		}
	}
}
Exemplo n.º 7
0
/*
 * 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(struct mbuf *m)
{
	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; ia != NULL; ia = ia->ia_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.x_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.x_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 = 12;
	dst.sipx_addr.x_host = ipx_broadhost;

	for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_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.x_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.x_net = ia->ia_addr.sipx_addr.x_net;
			ipx->ipx_dna.x_net = dst.sipx_addr.x_net;
			if(ipx->ipx_sum != 0xffff)
				ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len));

			m1 = m_copym(m, 0, M_COPYALL, MB_DONTWAIT);
			if(m1) {
				error = ifp->if_output(ifp, m1,
					(struct sockaddr *)&dst, NULL);
				/* XXX ipxstat.ipxs_localout++; */
			}
skip_this: ;
		}

bad:
	m_freem(m);
	return (error);
}