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); }
/* * 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; }
int ipxnet_netmatch(struct sockaddr_ipx *sxn1, struct sockaddr_ipx *sxn2) { return (ipx_neteq(sxn1->sipx_addr, sxn2->sipx_addr)); }
/* * 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); } }