ipx_outputfl.c revision 139556
111819Sjulian/* 211819Sjulian * Copyright (c) 1995, Mike Mitchell 311819Sjulian * Copyright (c) 1984, 1985, 1986, 1987, 1993 411819Sjulian * The Regents of the University of California. All rights reserved. 511819Sjulian * 611819Sjulian * Redistribution and use in source and binary forms, with or without 711819Sjulian * modification, are permitted provided that the following conditions 811819Sjulian * are met: 911819Sjulian * 1. Redistributions of source code must retain the above copyright 1011819Sjulian * notice, this list of conditions and the following disclaimer. 1111819Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1211819Sjulian * notice, this list of conditions and the following disclaimer in the 1311819Sjulian * documentation and/or other materials provided with the distribution. 1411819Sjulian * 3. All advertising materials mentioning features or use of this software 1511819Sjulian * must display the following acknowledgement: 1611819Sjulian * This product includes software developed by the University of 1711819Sjulian * California, Berkeley and its contributors. 1811819Sjulian * 4. Neither the name of the University nor the names of its contributors 1911819Sjulian * may be used to endorse or promote products derived from this software 2011819Sjulian * without specific prior written permission. 2111819Sjulian * 2211819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2311819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2411819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2511819Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2611819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2711819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2811819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2911819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3011819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3111819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3211819Sjulian * SUCH DAMAGE. 3311819Sjulian * 3412057Sjulian * @(#)ipx_outputfl.c 3511819Sjulian */ 3611819Sjulian 37116189Sobrien#include <sys/cdefs.h> 38116189Sobrien__FBSDID("$FreeBSD: head/sys/netipx/ipx_outputfl.c 139556 2005-01-02 01:39:38Z rwatson $"); 39116189Sobrien 4011819Sjulian#include <sys/param.h> 4111819Sjulian#include <sys/systm.h> 4211819Sjulian#include <sys/mbuf.h> 4311819Sjulian#include <sys/socket.h> 4411819Sjulian 4511819Sjulian#include <net/if.h> 4611819Sjulian#include <net/route.h> 4711819Sjulian 4811819Sjulian#include <netipx/ipx.h> 4911819Sjulian#include <netipx/ipx_if.h> 5011819Sjulian#include <netipx/ipx_var.h> 5111819Sjulian 5233181Seivindstatic int ipx_copy_output = 0; 5311819Sjulian 5411819Sjulianint 5511819Sjulianipx_outputfl(m0, ro, flags) 5611819Sjulian struct mbuf *m0; 5711819Sjulian struct route *ro; 5811819Sjulian int flags; 5911819Sjulian{ 6011819Sjulian register struct ipx *ipx = mtod(m0, struct ipx *); 6125652Sjhay register struct ifnet *ifp = NULL; 6211819Sjulian int error = 0; 6311819Sjulian struct sockaddr_ipx *dst; 6411819Sjulian struct route ipxroute; 6511819Sjulian 6611819Sjulian /* 6711819Sjulian * Route packet. 6811819Sjulian */ 6925652Sjhay if (ro == NULL) { 7011819Sjulian ro = &ipxroute; 7125652Sjhay bzero((caddr_t)ro, sizeof(*ro)); 7211819Sjulian } 7311819Sjulian dst = (struct sockaddr_ipx *)&ro->ro_dst; 7425652Sjhay if (ro->ro_rt == NULL) { 7511819Sjulian dst->sipx_family = AF_IPX; 7625652Sjhay dst->sipx_len = sizeof(*dst); 7711819Sjulian dst->sipx_addr = ipx->ipx_dna; 7811819Sjulian dst->sipx_addr.x_port = 0; 7911819Sjulian /* 8011819Sjulian * If routing to interface only, 8111819Sjulian * short circuit routing lookup. 8211819Sjulian */ 8311819Sjulian if (flags & IPX_ROUTETOIF) { 8411819Sjulian struct ipx_ifaddr *ia = ipx_iaonnetof(&ipx->ipx_dna); 8511819Sjulian 8625652Sjhay if (ia == NULL) { 8725652Sjhay ipxstat.ipxs_noroute++; 8811819Sjulian error = ENETUNREACH; 8911819Sjulian goto bad; 9011819Sjulian } 9111819Sjulian ifp = ia->ia_ifp; 9211819Sjulian goto gotif; 9311819Sjulian } 94139556Srwatson rtalloc_ign(ro, 0); 9511819Sjulian } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 9611819Sjulian /* 9711819Sjulian * The old route has gone away; try for a new one. 9811819Sjulian */ 9911819Sjulian rtfree(ro->ro_rt); 10011819Sjulian ro->ro_rt = NULL; 101139556Srwatson rtalloc_ign(ro, 0); 10211819Sjulian } 10325652Sjhay if (ro->ro_rt == NULL || (ifp = ro->ro_rt->rt_ifp) == NULL) { 10425652Sjhay ipxstat.ipxs_noroute++; 10511819Sjulian error = ENETUNREACH; 10611819Sjulian goto bad; 10711819Sjulian } 10811819Sjulian ro->ro_rt->rt_use++; 10911819Sjulian if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 11011819Sjulian dst = (struct sockaddr_ipx *)ro->ro_rt->rt_gateway; 11111819Sjuliangotif: 11211819Sjulian /* 11311819Sjulian * Look for multicast addresses and 11411819Sjulian * and verify user is allowed to send 11511819Sjulian * such a packet. 11611819Sjulian */ 11711819Sjulian if (dst->sipx_addr.x_host.c_host[0]&1) { 11843712Sjhay if ((ifp->if_flags & (IFF_BROADCAST | IFF_LOOPBACK)) == 0) { 11911819Sjulian error = EADDRNOTAVAIL; 12011819Sjulian goto bad; 12111819Sjulian } 12211819Sjulian if ((flags & IPX_ALLOWBROADCAST) == 0) { 12311819Sjulian error = EACCES; 12411819Sjulian goto bad; 12511819Sjulian } 12643712Sjhay m0->m_flags |= M_BCAST; 12711819Sjulian } 12811819Sjulian 12911819Sjulian if (htons(ipx->ipx_len) <= ifp->if_mtu) { 13025652Sjhay ipxstat.ipxs_localout++; 13111819Sjulian if (ipx_copy_output) { 13211819Sjulian ipx_watch_output(m0, ifp); 13311819Sjulian } 13411819Sjulian error = (*ifp->if_output)(ifp, m0, 13511819Sjulian (struct sockaddr *)dst, ro->ro_rt); 13611819Sjulian goto done; 13725652Sjhay } else { 13825652Sjhay ipxstat.ipxs_mtutoosmall++; 13925652Sjhay error = EMSGSIZE; 14025652Sjhay } 14111819Sjulianbad: 14211819Sjulian if (ipx_copy_output) { 14311819Sjulian ipx_watch_output(m0, ifp); 14411819Sjulian } 14511819Sjulian m_freem(m0); 14611819Sjuliandone: 14725652Sjhay if (ro == &ipxroute && (flags & IPX_ROUTETOIF) == 0 && 14825652Sjhay ro->ro_rt != NULL) { 14911819Sjulian RTFREE(ro->ro_rt); 15025652Sjhay ro->ro_rt = NULL; 15111819Sjulian } 15211819Sjulian return (error); 15311819Sjulian} 15425652Sjhay 15525652Sjhay/* 15625652Sjhay * This will broadcast the type 20 (Netbios) packet to all the interfaces 15725652Sjhay * that have ipx configured and isn't in the list yet. 15825652Sjhay */ 15925652Sjhayint 16025652Sjhayipx_output_type20(m) 16125652Sjhay struct mbuf *m; 16225652Sjhay{ 16325652Sjhay register struct ipx *ipx; 16445572Seivind union ipx_net *nbnet; 16525652Sjhay struct ipx_ifaddr *ia, *tia = NULL; 16625652Sjhay int error = 0; 16725652Sjhay struct mbuf *m1; 16825652Sjhay int i; 16925652Sjhay struct ifnet *ifp; 17025652Sjhay struct sockaddr_ipx dst; 17125652Sjhay 17225652Sjhay /* 17325652Sjhay * We have to get to the 32 bytes after the ipx header also, so 17425652Sjhay * that we can fill in the network address of the receiving 17525652Sjhay * interface. 17625652Sjhay */ 17725652Sjhay if ((m->m_flags & M_EXT || m->m_len < (sizeof(struct ipx) + 32)) && 17825652Sjhay (m = m_pullup(m, sizeof(struct ipx) + 32)) == NULL) { 17925652Sjhay ipxstat.ipxs_toosmall++; 18025652Sjhay return (0); 18125652Sjhay } 18225652Sjhay ipx = mtod(m, struct ipx *); 18325652Sjhay nbnet = (union ipx_net *)(ipx + 1); 18425652Sjhay 18525652Sjhay if (ipx->ipx_tc >= 8) 18625652Sjhay goto bad; 18725652Sjhay /* 18825652Sjhay * Now see if we have already seen this. 18925652Sjhay */ 19025652Sjhay for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 19125652Sjhay if(ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) { 19225652Sjhay if(tia == NULL) 19325652Sjhay tia = ia; 19425652Sjhay 19525652Sjhay for (i=0;i<ipx->ipx_tc;i++,nbnet++) 19625652Sjhay if(ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 19725652Sjhay *nbnet)) 19825652Sjhay goto bad; 19925652Sjhay } 20025652Sjhay /* 20125652Sjhay * Don't route the packet if the interface where it come from 20225652Sjhay * does not have an IPX address. 20325652Sjhay */ 20425652Sjhay if(tia == NULL) 20525652Sjhay goto bad; 20625652Sjhay 20725652Sjhay /* 20825652Sjhay * Add our receiving interface to the list. 20925652Sjhay */ 21025652Sjhay nbnet = (union ipx_net *)(ipx + 1); 21125652Sjhay nbnet += ipx->ipx_tc; 21225652Sjhay *nbnet = tia->ia_addr.sipx_addr.x_net; 21325652Sjhay 21425652Sjhay /* 21525652Sjhay * Increment the hop count. 21625652Sjhay */ 21725652Sjhay ipx->ipx_tc++; 21825652Sjhay ipxstat.ipxs_forward++; 21925652Sjhay 22025652Sjhay /* 22125652Sjhay * Send to all directly connected ifaces not in list and 22225652Sjhay * not to the one it came from. 22325652Sjhay */ 22425652Sjhay m->m_flags &= ~M_BCAST; 22525652Sjhay bzero(&dst, sizeof(dst)); 22625652Sjhay dst.sipx_family = AF_IPX; 22725652Sjhay dst.sipx_len = 12; 22825652Sjhay dst.sipx_addr.x_host = ipx_broadhost; 22925652Sjhay 23025652Sjhay for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 23125652Sjhay if(ia->ia_ifa.ifa_ifp != m->m_pkthdr.rcvif) { 23225652Sjhay nbnet = (union ipx_net *)(ipx + 1); 23325652Sjhay for (i=0;i<ipx->ipx_tc;i++,nbnet++) 23425652Sjhay if(ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 23525652Sjhay *nbnet)) 23625652Sjhay goto skip_this; 23725652Sjhay 23825652Sjhay /* 23925652Sjhay * Insert the net address of the dest net and 24025652Sjhay * calculate the new checksum if needed. 24125652Sjhay */ 24225652Sjhay ifp = ia->ia_ifa.ifa_ifp; 24325652Sjhay dst.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net; 24425652Sjhay ipx->ipx_dna.x_net = dst.sipx_addr.x_net; 24550519Sjhay if(ipx->ipx_sum != 0xffff) 24650519Sjhay ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len)); 24759683Sbp 248111119Simp m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 24925652Sjhay if(m1) { 25025652Sjhay error = (*ifp->if_output)(ifp, m1, 25125652Sjhay (struct sockaddr *)&dst, NULL); 25225652Sjhay /* XXX ipxstat.ipxs_localout++; */ 25325652Sjhay } 25427125Sbdeskip_this: ; 25525652Sjhay } 25625652Sjhay 25725652Sjhaybad: 25825652Sjhay m_freem(m); 25925652Sjhay return (error); 26025652Sjhay} 261