Beispiel #1
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);
}
Beispiel #2
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;
}
Beispiel #3
0
int
ipxnet_netmatch(struct sockaddr_ipx *sxn1, struct sockaddr_ipx *sxn2)
{
	return (ipx_neteq(sxn1->sipx_addr, sxn2->sipx_addr));
}
Beispiel #4
0
/*
 * Generic internet control operations (ioctl's).
 */
int
ipx_control_oncpu(struct socket *so, u_long cmd, caddr_t data,
	struct ifnet *ifp, struct thread *td)
{
	struct ifreq *ifr = (struct ifreq *)data;
	struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
	struct ipx_ifaddr *ia;
	struct ifaddr *ifa;
	struct ipx_ifaddr *oia;
	int dstIsNew, hostIsNew;
	int error = 0;

	/*
	 * Find address for this interface, if it exists.
	 */
	if (ifp == NULL)
		return (EADDRNOTAVAIL);
	for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
		if (ia->ia_ifp == ifp)
			break;

	switch (cmd) {

	case SIOCGIFADDR:
		if (ia == NULL)
			return (EADDRNOTAVAIL);
		*(struct sockaddr_ipx *)&ifr->ifr_addr = ia->ia_addr;
		return (0);

	case SIOCGIFBRDADDR:
		if (ia == NULL)
			return (EADDRNOTAVAIL);
		if ((ifp->if_flags & IFF_BROADCAST) == 0)
			return (EINVAL);
		*(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
		return (0);

	case SIOCGIFDSTADDR:
		if (ia == NULL)
			return (EADDRNOTAVAIL);
		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
			return (EINVAL);
		*(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
		return (0);
	}

	if ((error = priv_check(td, PRIV_ROOT)) != 0)
		return (error);

	switch (cmd) {
	case SIOCAIFADDR:
	case SIOCDIFADDR:
		if (ifra->ifra_addr.sipx_family == AF_IPX)
		    for (oia = ia; ia != NULL; ia = ia->ia_next) {
			if (ia->ia_ifp == ifp  &&
			    ipx_neteq(ia->ia_addr.sipx_addr,
				  ifra->ifra_addr.sipx_addr))
			    break;
		    }
		if (cmd == SIOCDIFADDR && ia == NULL)
			return (EADDRNOTAVAIL);
		/* FALLTHROUGH */

	case SIOCSIFADDR:
	case SIOCSIFDSTADDR:
		if (ia == NULL) {
			oia = ifa_create(sizeof(*ia), M_WAITOK);
			if ((ia = ipx_ifaddr) != NULL) {
				for ( ; ia->ia_next != NULL; ia = ia->ia_next)
					;
				ia->ia_next = oia;
			} else
				ipx_ifaddr = oia;
			ia = oia;
			ifa = (struct ifaddr *)ia;
			ifa_iflink(ifa, ifp, 1);
			ia->ia_ifp = ifp;
			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;

			ifa->ifa_netmask = (struct sockaddr *)&ipx_netmask;

			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
			if (ifp->if_flags & IFF_BROADCAST) {
				ia->ia_broadaddr.sipx_family = AF_IPX;
				ia->ia_broadaddr.sipx_len = sizeof(ia->ia_addr);
				ia->ia_broadaddr.sipx_addr.x_host = ipx_broadhost;
			}
		}
	}

	switch (cmd) {

	case SIOCSIFDSTADDR:
		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
			return (EINVAL);
		if (ia->ia_flags & IFA_ROUTE) {
			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
			ia->ia_flags &= ~IFA_ROUTE;
		}
		if (ifp->if_ioctl) {
			ifnet_serialize_all(ifp);
			error = ifp->if_ioctl(ifp, SIOCSIFDSTADDR,
					      (void *)ia, td->td_proc->p_ucred);
			ifnet_deserialize_all(ifp);
			if (error)
				return (error);
		}
		*(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
		return (0);

	case SIOCSIFADDR:
		return (ipx_ifinit(ifp, ia,
				(struct sockaddr_ipx *)&ifr->ifr_addr, 1));

	case SIOCDIFADDR:
		ipx_ifscrub(ifp, ia);
		ifa = (struct ifaddr *)ia;
		ifa_ifunlink(ifa, ifp);
		oia = ia;
		if (oia == (ia = ipx_ifaddr)) {
			ipx_ifaddr = ia->ia_next;
		} else {
			while (ia->ia_next && (ia->ia_next != oia)) {
				ia = ia->ia_next;
			}
			if (ia->ia_next)
			    ia->ia_next = oia->ia_next;
			else
				kprintf("Didn't unlink ipxifadr from list\n");
		}
		ifa_destroy(&oia->ia_ifa);
		return (0);
	
	case SIOCAIFADDR:
		dstIsNew = 0;
		hostIsNew = 1;
		if (ia->ia_addr.sipx_family == AF_IPX) {
			if (ifra->ifra_addr.sipx_len == 0) {
				ifra->ifra_addr = ia->ia_addr;
				hostIsNew = 0;
			} else if (ipx_neteq(ifra->ifra_addr.sipx_addr,
					 ia->ia_addr.sipx_addr))
				hostIsNew = 0;
		}
		if ((ifp->if_flags & IFF_POINTOPOINT) &&
		    (ifra->ifra_dstaddr.sipx_family == AF_IPX)) {
			if (hostIsNew == 0)
				ipx_ifscrub(ifp, ia);
			ia->ia_dstaddr = ifra->ifra_dstaddr;
			dstIsNew  = 1;
		}
		if (ifra->ifra_addr.sipx_family == AF_IPX &&
					    (hostIsNew || dstIsNew))
			error = ipx_ifinit(ifp, ia, &ifra->ifra_addr, 0);
		return (error);

	default:
		if (ifp->if_ioctl == NULL)
			return (EOPNOTSUPP);
		ifnet_serialize_all(ifp);
		error = ifp->if_ioctl(ifp, cmd, data, td->td_proc->p_ucred);
		ifnet_deserialize_all(ifp);
		return (error);
	}
}