ipx_outputfl.c revision 59683
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 3512057Sjulian * 3650477Speter * $FreeBSD: head/sys/netipx/ipx_outputfl.c 59683 2000-04-27 10:29:14Z bp $ 3711819Sjulian */ 3811819Sjulian 3911819Sjulian#include <sys/param.h> 4011819Sjulian#include <sys/systm.h> 4111819Sjulian#include <sys/mbuf.h> 4211819Sjulian#include <sys/socket.h> 4311819Sjulian 4411819Sjulian#include <net/if.h> 4511819Sjulian#include <net/route.h> 4611819Sjulian 4711819Sjulian#include <netipx/ipx.h> 4811819Sjulian#include <netipx/ipx_if.h> 4911819Sjulian#include <netipx/ipx_var.h> 5011819Sjulian 5111819Sjulian#ifdef vax 5211819Sjulian#include <machine/mtpr.h> 5311819Sjulian#endif 5411819Sjulian 5533181Seivindstatic int ipx_copy_output = 0; 5611819Sjulian 5711819Sjulianint 5811819Sjulianipx_outputfl(m0, ro, flags) 5911819Sjulian struct mbuf *m0; 6011819Sjulian struct route *ro; 6111819Sjulian int flags; 6211819Sjulian{ 6311819Sjulian register struct ipx *ipx = mtod(m0, struct ipx *); 6425652Sjhay register struct ifnet *ifp = NULL; 6511819Sjulian int error = 0; 6611819Sjulian struct sockaddr_ipx *dst; 6711819Sjulian struct route ipxroute; 6811819Sjulian 6911819Sjulian /* 7011819Sjulian * Route packet. 7111819Sjulian */ 7225652Sjhay if (ro == NULL) { 7311819Sjulian ro = &ipxroute; 7425652Sjhay bzero((caddr_t)ro, sizeof(*ro)); 7511819Sjulian } 7611819Sjulian dst = (struct sockaddr_ipx *)&ro->ro_dst; 7725652Sjhay if (ro->ro_rt == NULL) { 7811819Sjulian dst->sipx_family = AF_IPX; 7925652Sjhay dst->sipx_len = sizeof(*dst); 8011819Sjulian dst->sipx_addr = ipx->ipx_dna; 8111819Sjulian dst->sipx_addr.x_port = 0; 8211819Sjulian /* 8311819Sjulian * If routing to interface only, 8411819Sjulian * short circuit routing lookup. 8511819Sjulian */ 8611819Sjulian if (flags & IPX_ROUTETOIF) { 8711819Sjulian struct ipx_ifaddr *ia = ipx_iaonnetof(&ipx->ipx_dna); 8811819Sjulian 8925652Sjhay if (ia == NULL) { 9025652Sjhay ipxstat.ipxs_noroute++; 9111819Sjulian error = ENETUNREACH; 9211819Sjulian goto bad; 9311819Sjulian } 9411819Sjulian ifp = ia->ia_ifp; 9511819Sjulian goto gotif; 9611819Sjulian } 9711819Sjulian rtalloc(ro); 9811819Sjulian } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 9911819Sjulian /* 10011819Sjulian * The old route has gone away; try for a new one. 10111819Sjulian */ 10211819Sjulian rtfree(ro->ro_rt); 10311819Sjulian ro->ro_rt = NULL; 10411819Sjulian rtalloc(ro); 10511819Sjulian } 10625652Sjhay if (ro->ro_rt == NULL || (ifp = ro->ro_rt->rt_ifp) == NULL) { 10725652Sjhay ipxstat.ipxs_noroute++; 10811819Sjulian error = ENETUNREACH; 10911819Sjulian goto bad; 11011819Sjulian } 11111819Sjulian ro->ro_rt->rt_use++; 11211819Sjulian if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 11311819Sjulian dst = (struct sockaddr_ipx *)ro->ro_rt->rt_gateway; 11411819Sjuliangotif: 11511819Sjulian /* 11611819Sjulian * Look for multicast addresses and 11711819Sjulian * and verify user is allowed to send 11811819Sjulian * such a packet. 11911819Sjulian */ 12011819Sjulian if (dst->sipx_addr.x_host.c_host[0]&1) { 12143712Sjhay if ((ifp->if_flags & (IFF_BROADCAST | IFF_LOOPBACK)) == 0) { 12211819Sjulian error = EADDRNOTAVAIL; 12311819Sjulian goto bad; 12411819Sjulian } 12511819Sjulian if ((flags & IPX_ALLOWBROADCAST) == 0) { 12611819Sjulian error = EACCES; 12711819Sjulian goto bad; 12811819Sjulian } 12943712Sjhay m0->m_flags |= M_BCAST; 13011819Sjulian } 13111819Sjulian 13211819Sjulian if (htons(ipx->ipx_len) <= ifp->if_mtu) { 13325652Sjhay ipxstat.ipxs_localout++; 13411819Sjulian if (ipx_copy_output) { 13511819Sjulian ipx_watch_output(m0, ifp); 13611819Sjulian } 13711819Sjulian error = (*ifp->if_output)(ifp, m0, 13811819Sjulian (struct sockaddr *)dst, ro->ro_rt); 13911819Sjulian goto done; 14025652Sjhay } else { 14125652Sjhay ipxstat.ipxs_mtutoosmall++; 14225652Sjhay error = EMSGSIZE; 14325652Sjhay } 14411819Sjulianbad: 14511819Sjulian if (ipx_copy_output) { 14611819Sjulian ipx_watch_output(m0, ifp); 14711819Sjulian } 14811819Sjulian m_freem(m0); 14911819Sjuliandone: 15025652Sjhay if (ro == &ipxroute && (flags & IPX_ROUTETOIF) == 0 && 15125652Sjhay ro->ro_rt != NULL) { 15211819Sjulian RTFREE(ro->ro_rt); 15325652Sjhay ro->ro_rt = NULL; 15411819Sjulian } 15511819Sjulian return (error); 15611819Sjulian} 15725652Sjhay 15825652Sjhay/* 15925652Sjhay * This will broadcast the type 20 (Netbios) packet to all the interfaces 16025652Sjhay * that have ipx configured and isn't in the list yet. 16125652Sjhay */ 16225652Sjhayint 16325652Sjhayipx_output_type20(m) 16425652Sjhay struct mbuf *m; 16525652Sjhay{ 16625652Sjhay register struct ipx *ipx; 16745572Seivind union ipx_net *nbnet; 16825652Sjhay struct ipx_ifaddr *ia, *tia = NULL; 16925652Sjhay int error = 0; 17025652Sjhay struct mbuf *m1; 17125652Sjhay int i; 17225652Sjhay struct ifnet *ifp; 17325652Sjhay struct sockaddr_ipx dst; 17425652Sjhay 17525652Sjhay /* 17625652Sjhay * We have to get to the 32 bytes after the ipx header also, so 17725652Sjhay * that we can fill in the network address of the receiving 17825652Sjhay * interface. 17925652Sjhay */ 18025652Sjhay if ((m->m_flags & M_EXT || m->m_len < (sizeof(struct ipx) + 32)) && 18125652Sjhay (m = m_pullup(m, sizeof(struct ipx) + 32)) == NULL) { 18225652Sjhay ipxstat.ipxs_toosmall++; 18325652Sjhay return (0); 18425652Sjhay } 18525652Sjhay ipx = mtod(m, struct ipx *); 18625652Sjhay nbnet = (union ipx_net *)(ipx + 1); 18725652Sjhay 18825652Sjhay if (ipx->ipx_tc >= 8) 18925652Sjhay goto bad; 19025652Sjhay /* 19125652Sjhay * Now see if we have already seen this. 19225652Sjhay */ 19325652Sjhay for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 19425652Sjhay if(ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) { 19525652Sjhay if(tia == NULL) 19625652Sjhay tia = ia; 19725652Sjhay 19825652Sjhay for (i=0;i<ipx->ipx_tc;i++,nbnet++) 19925652Sjhay if(ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 20025652Sjhay *nbnet)) 20125652Sjhay goto bad; 20225652Sjhay } 20325652Sjhay /* 20425652Sjhay * Don't route the packet if the interface where it come from 20525652Sjhay * does not have an IPX address. 20625652Sjhay */ 20725652Sjhay if(tia == NULL) 20825652Sjhay goto bad; 20925652Sjhay 21025652Sjhay /* 21125652Sjhay * Add our receiving interface to the list. 21225652Sjhay */ 21325652Sjhay nbnet = (union ipx_net *)(ipx + 1); 21425652Sjhay nbnet += ipx->ipx_tc; 21525652Sjhay *nbnet = tia->ia_addr.sipx_addr.x_net; 21625652Sjhay 21725652Sjhay /* 21825652Sjhay * Increment the hop count. 21925652Sjhay */ 22025652Sjhay ipx->ipx_tc++; 22125652Sjhay ipxstat.ipxs_forward++; 22225652Sjhay 22325652Sjhay /* 22425652Sjhay * Send to all directly connected ifaces not in list and 22525652Sjhay * not to the one it came from. 22625652Sjhay */ 22725652Sjhay m->m_flags &= ~M_BCAST; 22825652Sjhay bzero(&dst, sizeof(dst)); 22925652Sjhay dst.sipx_family = AF_IPX; 23025652Sjhay dst.sipx_len = 12; 23125652Sjhay dst.sipx_addr.x_host = ipx_broadhost; 23225652Sjhay 23325652Sjhay for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 23425652Sjhay if(ia->ia_ifa.ifa_ifp != m->m_pkthdr.rcvif) { 23525652Sjhay nbnet = (union ipx_net *)(ipx + 1); 23625652Sjhay for (i=0;i<ipx->ipx_tc;i++,nbnet++) 23725652Sjhay if(ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 23825652Sjhay *nbnet)) 23925652Sjhay goto skip_this; 24025652Sjhay 24125652Sjhay /* 24225652Sjhay * Insert the net address of the dest net and 24325652Sjhay * calculate the new checksum if needed. 24425652Sjhay */ 24525652Sjhay ifp = ia->ia_ifa.ifa_ifp; 24625652Sjhay dst.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net; 24725652Sjhay ipx->ipx_dna.x_net = dst.sipx_addr.x_net; 24850519Sjhay if(ipx->ipx_sum != 0xffff) 24950519Sjhay ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len)); 25059683Sbp 25159683Sbp m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 25225652Sjhay if(m1) { 25325652Sjhay error = (*ifp->if_output)(ifp, m1, 25425652Sjhay (struct sockaddr *)&dst, NULL); 25525652Sjhay /* XXX ipxstat.ipxs_localout++; */ 25625652Sjhay } 25727125Sbdeskip_this: ; 25825652Sjhay } 25925652Sjhay 26025652Sjhaybad: 26125652Sjhay m_freem(m); 26225652Sjhay return (error); 26325652Sjhay} 264