1139823Simp/*- 211819Sjulian * Copyright (c) 1984, 1985, 1986, 1987, 1993 311819Sjulian * The Regents of the University of California. All rights reserved. 411819Sjulian * 511819Sjulian * Redistribution and use in source and binary forms, with or without 611819Sjulian * modification, are permitted provided that the following conditions 711819Sjulian * are met: 811819Sjulian * 1. Redistributions of source code must retain the above copyright 911819Sjulian * notice, this list of conditions and the following disclaimer. 1011819Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1111819Sjulian * notice, this list of conditions and the following disclaimer in the 1211819Sjulian * documentation and/or other materials provided with the distribution. 13165899Srwatson * 4. Neither the name of the University nor the names of its contributors 14165899Srwatson * may be used to endorse or promote products derived from this software 15165899Srwatson * without specific prior written permission. 16165899Srwatson * 17165899Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18165899Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19165899Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20165899Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21165899Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22165899Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23165899Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24165899Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25165899Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26165899Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27165899Srwatson * SUCH DAMAGE. 28165899Srwatson * 29165899Srwatson * Copyright (c) 1995, Mike Mitchell 30165899Srwatson * 31165899Srwatson * Redistribution and use in source and binary forms, with or without 32165899Srwatson * modification, are permitted provided that the following conditions 33165899Srwatson * are met: 34165899Srwatson * 1. Redistributions of source code must retain the above copyright 35165899Srwatson * notice, this list of conditions and the following disclaimer. 36165899Srwatson * 2. Redistributions in binary form must reproduce the above copyright 37165899Srwatson * notice, this list of conditions and the following disclaimer in the 38165899Srwatson * documentation and/or other materials provided with the distribution. 3911819Sjulian * 3. All advertising materials mentioning features or use of this software 4011819Sjulian * must display the following acknowledgement: 4111819Sjulian * This product includes software developed by the University of 4211819Sjulian * California, Berkeley and its contributors. 4311819Sjulian * 4. Neither the name of the University nor the names of its contributors 4411819Sjulian * may be used to endorse or promote products derived from this software 4511819Sjulian * without specific prior written permission. 4611819Sjulian * 4711819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 4811819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4911819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5011819Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5111819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5211819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5311819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5411819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5511819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5611819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5711819Sjulian * SUCH DAMAGE. 5811819Sjulian * 5912057Sjulian * @(#)ipx_outputfl.c 6011819Sjulian */ 6111819Sjulian 62116189Sobrien#include <sys/cdefs.h> 63116189Sobrien__FBSDID("$FreeBSD$"); 64116189Sobrien 6511819Sjulian#include <sys/param.h> 6611819Sjulian#include <sys/systm.h> 6711819Sjulian#include <sys/mbuf.h> 6811819Sjulian#include <sys/socket.h> 6911819Sjulian 7011819Sjulian#include <net/if.h> 7111819Sjulian#include <net/route.h> 7211819Sjulian 7311819Sjulian#include <netipx/ipx.h> 7411819Sjulian#include <netipx/ipx_if.h> 7511819Sjulian#include <netipx/ipx_var.h> 7611819Sjulian 7711819Sjulianint 78169463Srwatsonipx_outputfl(struct mbuf *m0, struct route *ro, int flags) 7911819Sjulian{ 80169463Srwatson struct ipx *ipx = mtod(m0, struct ipx *); 81169463Srwatson struct ifnet *ifp = NULL; 8211819Sjulian int error = 0; 8311819Sjulian struct sockaddr_ipx *dst; 8411819Sjulian struct route ipxroute; 8511819Sjulian 8611819Sjulian /* 8711819Sjulian * Route packet. 8811819Sjulian */ 8925652Sjhay if (ro == NULL) { 9011819Sjulian ro = &ipxroute; 9125652Sjhay bzero((caddr_t)ro, sizeof(*ro)); 9211819Sjulian } 9311819Sjulian dst = (struct sockaddr_ipx *)&ro->ro_dst; 9425652Sjhay if (ro->ro_rt == NULL) { 9511819Sjulian dst->sipx_family = AF_IPX; 9625652Sjhay dst->sipx_len = sizeof(*dst); 9711819Sjulian dst->sipx_addr = ipx->ipx_dna; 9811819Sjulian dst->sipx_addr.x_port = 0; 9911819Sjulian /* 10011819Sjulian * If routing to interface only, 10111819Sjulian * short circuit routing lookup. 10211819Sjulian */ 10311819Sjulian if (flags & IPX_ROUTETOIF) { 104194608Srwatson struct ipx_ifaddr *ia; 10511819Sjulian 106194608Srwatson IPX_IFADDR_RLOCK(); 107194608Srwatson ia = ipx_iaonnetof(&ipx->ipx_dna); 10825652Sjhay if (ia == NULL) { 109194608Srwatson IPX_IFADDR_RUNLOCK(); 11025652Sjhay ipxstat.ipxs_noroute++; 11111819Sjulian error = ENETUNREACH; 11211819Sjulian goto bad; 11311819Sjulian } 11411819Sjulian ifp = ia->ia_ifp; 115194608Srwatson IPX_IFADDR_RUNLOCK(); 11611819Sjulian goto gotif; 11711819Sjulian } 118139556Srwatson rtalloc_ign(ro, 0); 11911819Sjulian } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 12011819Sjulian /* 12111819Sjulian * The old route has gone away; try for a new one. 12211819Sjulian */ 123139557Srwatson RTFREE(ro->ro_rt); 12411819Sjulian ro->ro_rt = NULL; 125139556Srwatson rtalloc_ign(ro, 0); 12611819Sjulian } 12725652Sjhay if (ro->ro_rt == NULL || (ifp = ro->ro_rt->rt_ifp) == NULL) { 12825652Sjhay ipxstat.ipxs_noroute++; 12911819Sjulian error = ENETUNREACH; 13011819Sjulian goto bad; 13111819Sjulian } 13211819Sjulian ro->ro_rt->rt_use++; 13311819Sjulian if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 13411819Sjulian dst = (struct sockaddr_ipx *)ro->ro_rt->rt_gateway; 13511819Sjuliangotif: 13611819Sjulian /* 13711819Sjulian * Look for multicast addresses and 13811819Sjulian * and verify user is allowed to send 13911819Sjulian * such a packet. 14011819Sjulian */ 14111819Sjulian if (dst->sipx_addr.x_host.c_host[0]&1) { 14243712Sjhay if ((ifp->if_flags & (IFF_BROADCAST | IFF_LOOPBACK)) == 0) { 14311819Sjulian error = EADDRNOTAVAIL; 14411819Sjulian goto bad; 14511819Sjulian } 14611819Sjulian if ((flags & IPX_ALLOWBROADCAST) == 0) { 14711819Sjulian error = EACCES; 14811819Sjulian goto bad; 14911819Sjulian } 15043712Sjhay m0->m_flags |= M_BCAST; 15111819Sjulian } 15211819Sjulian 15311819Sjulian if (htons(ipx->ipx_len) <= ifp->if_mtu) { 15425652Sjhay ipxstat.ipxs_localout++; 15511819Sjulian error = (*ifp->if_output)(ifp, m0, 156191148Skmacy (struct sockaddr *)dst, ro); 15711819Sjulian goto done; 15825652Sjhay } else { 15925652Sjhay ipxstat.ipxs_mtutoosmall++; 16025652Sjhay error = EMSGSIZE; 16125652Sjhay } 16211819Sjulianbad: 16311819Sjulian m_freem(m0); 16411819Sjuliandone: 16525652Sjhay if (ro == &ipxroute && (flags & IPX_ROUTETOIF) == 0 && 16625652Sjhay ro->ro_rt != NULL) { 16711819Sjulian RTFREE(ro->ro_rt); 16825652Sjhay ro->ro_rt = NULL; 16911819Sjulian } 17011819Sjulian return (error); 17111819Sjulian} 17225652Sjhay 17325652Sjhay/* 17425652Sjhay * This will broadcast the type 20 (Netbios) packet to all the interfaces 17525652Sjhay * that have ipx configured and isn't in the list yet. 17625652Sjhay */ 17725652Sjhayint 178169463Srwatsonipx_output_type20(struct mbuf *m) 17925652Sjhay{ 180169463Srwatson struct ipx *ipx; 18145572Seivind union ipx_net *nbnet; 182194905Srwatson struct ipx_ifaddr *ia, *tia; 18325652Sjhay int error = 0; 18425652Sjhay struct mbuf *m1; 18525652Sjhay int i; 18625652Sjhay struct ifnet *ifp; 18725652Sjhay struct sockaddr_ipx dst; 18825652Sjhay 18925652Sjhay /* 19025652Sjhay * We have to get to the 32 bytes after the ipx header also, so 19125652Sjhay * that we can fill in the network address of the receiving 19225652Sjhay * interface. 19325652Sjhay */ 19425652Sjhay if ((m->m_flags & M_EXT || m->m_len < (sizeof(struct ipx) + 32)) && 19525652Sjhay (m = m_pullup(m, sizeof(struct ipx) + 32)) == NULL) { 19625652Sjhay ipxstat.ipxs_toosmall++; 19725652Sjhay return (0); 19825652Sjhay } 19925652Sjhay ipx = mtod(m, struct ipx *); 20025652Sjhay nbnet = (union ipx_net *)(ipx + 1); 20125652Sjhay 20225652Sjhay if (ipx->ipx_tc >= 8) 20325652Sjhay goto bad; 20425652Sjhay /* 20525652Sjhay * Now see if we have already seen this. 20625652Sjhay */ 207194905Srwatson tia = NULL; 208194608Srwatson IPX_IFADDR_RLOCK(); 209194905Srwatson TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) { 210194905Srwatson if (ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) { 211194905Srwatson if (tia == NULL) 21225652Sjhay tia = ia; 213194905Srwatson for (i=0; i < ipx->ipx_tc; i++, nbnet++) { 214194905Srwatson if (ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 215194905Srwatson *nbnet)) { 216194608Srwatson IPX_IFADDR_RUNLOCK(); 21725652Sjhay goto bad; 218194608Srwatson } 219194905Srwatson } 22025652Sjhay } 221194905Srwatson } 222194608Srwatson 22325652Sjhay /* 22425652Sjhay * Don't route the packet if the interface where it come from 22525652Sjhay * does not have an IPX address. 22625652Sjhay */ 227194608Srwatson if (tia == NULL) { 228194608Srwatson IPX_IFADDR_RUNLOCK(); 22925652Sjhay goto bad; 230194608Srwatson } 23125652Sjhay 23225652Sjhay /* 23325652Sjhay * Add our receiving interface to the list. 23425652Sjhay */ 23525652Sjhay nbnet = (union ipx_net *)(ipx + 1); 23625652Sjhay nbnet += ipx->ipx_tc; 23725652Sjhay *nbnet = tia->ia_addr.sipx_addr.x_net; 23825652Sjhay 23925652Sjhay /* 24025652Sjhay * Increment the hop count. 24125652Sjhay */ 24225652Sjhay ipx->ipx_tc++; 24325652Sjhay ipxstat.ipxs_forward++; 24425652Sjhay 24525652Sjhay /* 24625652Sjhay * Send to all directly connected ifaces not in list and 24725652Sjhay * not to the one it came from. 24825652Sjhay */ 24925652Sjhay m->m_flags &= ~M_BCAST; 25025652Sjhay bzero(&dst, sizeof(dst)); 25125652Sjhay dst.sipx_family = AF_IPX; 25225652Sjhay dst.sipx_len = 12; 25325652Sjhay dst.sipx_addr.x_host = ipx_broadhost; 25425652Sjhay 255194905Srwatson TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) { 256194905Srwatson if (ia->ia_ifa.ifa_ifp != m->m_pkthdr.rcvif) { 25725652Sjhay nbnet = (union ipx_net *)(ipx + 1); 258194905Srwatson for (i=0; i < ipx->ipx_tc; i++, nbnet++) 259194905Srwatson if (ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 260194905Srwatson *nbnet)) 26125652Sjhay goto skip_this; 26225652Sjhay 26325652Sjhay /* 26425652Sjhay * Insert the net address of the dest net and 26525652Sjhay * calculate the new checksum if needed. 26625652Sjhay */ 26725652Sjhay ifp = ia->ia_ifa.ifa_ifp; 26825652Sjhay dst.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net; 26925652Sjhay ipx->ipx_dna.x_net = dst.sipx_addr.x_net; 27050519Sjhay if(ipx->ipx_sum != 0xffff) 27150519Sjhay ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len)); 27259683Sbp 273243882Sglebius m1 = m_copym(m, 0, M_COPYALL, M_NOWAIT); 27425652Sjhay if(m1) { 27525652Sjhay error = (*ifp->if_output)(ifp, m1, 27625652Sjhay (struct sockaddr *)&dst, NULL); 27725652Sjhay /* XXX ipxstat.ipxs_localout++; */ 27825652Sjhay } 27927125Sbdeskip_this: ; 28025652Sjhay } 281194905Srwatson } 282194608Srwatson IPX_IFADDR_RUNLOCK(); 28325652Sjhay 28425652Sjhaybad: 28525652Sjhay m_freem(m); 28625652Sjhay return (error); 28725652Sjhay} 288