ipx_outputfl.c revision 191148
1/*- 2 * Copyright (c) 1984, 1985, 1986, 1987, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * Copyright (c) 1995, Mike Mitchell 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer. 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 3. All advertising materials mentioning features or use of this software 40 * must display the following acknowledgement: 41 * This product includes software developed by the University of 42 * California, Berkeley and its contributors. 43 * 4. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)ipx_outputfl.c 60 */ 61 62#include <sys/cdefs.h> 63__FBSDID("$FreeBSD: head/sys/netipx/ipx_outputfl.c 191148 2009-04-16 20:30:28Z kmacy $"); 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/mbuf.h> 68#include <sys/socket.h> 69 70#include <net/if.h> 71#include <net/route.h> 72 73#include <netipx/ipx.h> 74#include <netipx/ipx_if.h> 75#include <netipx/ipx_var.h> 76 77static int ipx_copy_output = 0; 78 79int 80ipx_outputfl(struct mbuf *m0, struct route *ro, int flags) 81{ 82 struct ipx *ipx = mtod(m0, struct ipx *); 83 struct ifnet *ifp = NULL; 84 int error = 0; 85 struct sockaddr_ipx *dst; 86 struct route ipxroute; 87 88 /* 89 * Route packet. 90 */ 91 if (ro == NULL) { 92 ro = &ipxroute; 93 bzero((caddr_t)ro, sizeof(*ro)); 94 } 95 dst = (struct sockaddr_ipx *)&ro->ro_dst; 96 if (ro->ro_rt == NULL) { 97 dst->sipx_family = AF_IPX; 98 dst->sipx_len = sizeof(*dst); 99 dst->sipx_addr = ipx->ipx_dna; 100 dst->sipx_addr.x_port = 0; 101 /* 102 * If routing to interface only, 103 * short circuit routing lookup. 104 */ 105 if (flags & IPX_ROUTETOIF) { 106 struct ipx_ifaddr *ia = ipx_iaonnetof(&ipx->ipx_dna); 107 108 if (ia == NULL) { 109 ipxstat.ipxs_noroute++; 110 error = ENETUNREACH; 111 goto bad; 112 } 113 ifp = ia->ia_ifp; 114 goto gotif; 115 } 116 rtalloc_ign(ro, 0); 117 } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 118 /* 119 * The old route has gone away; try for a new one. 120 */ 121 RTFREE(ro->ro_rt); 122 ro->ro_rt = NULL; 123 rtalloc_ign(ro, 0); 124 } 125 if (ro->ro_rt == NULL || (ifp = ro->ro_rt->rt_ifp) == NULL) { 126 ipxstat.ipxs_noroute++; 127 error = ENETUNREACH; 128 goto bad; 129 } 130 ro->ro_rt->rt_use++; 131 if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 132 dst = (struct sockaddr_ipx *)ro->ro_rt->rt_gateway; 133gotif: 134 /* 135 * Look for multicast addresses and 136 * and verify user is allowed to send 137 * such a packet. 138 */ 139 if (dst->sipx_addr.x_host.c_host[0]&1) { 140 if ((ifp->if_flags & (IFF_BROADCAST | IFF_LOOPBACK)) == 0) { 141 error = EADDRNOTAVAIL; 142 goto bad; 143 } 144 if ((flags & IPX_ALLOWBROADCAST) == 0) { 145 error = EACCES; 146 goto bad; 147 } 148 m0->m_flags |= M_BCAST; 149 } 150 151 if (htons(ipx->ipx_len) <= ifp->if_mtu) { 152 ipxstat.ipxs_localout++; 153 if (ipx_copy_output) { 154 ipx_watch_output(m0, ifp); 155 } 156 error = (*ifp->if_output)(ifp, m0, 157 (struct sockaddr *)dst, ro); 158 goto done; 159 } else { 160 ipxstat.ipxs_mtutoosmall++; 161 error = EMSGSIZE; 162 } 163bad: 164 if (ipx_copy_output) { 165 ipx_watch_output(m0, ifp); 166 } 167 m_freem(m0); 168done: 169 if (ro == &ipxroute && (flags & IPX_ROUTETOIF) == 0 && 170 ro->ro_rt != NULL) { 171 RTFREE(ro->ro_rt); 172 ro->ro_rt = NULL; 173 } 174 return (error); 175} 176 177/* 178 * This will broadcast the type 20 (Netbios) packet to all the interfaces 179 * that have ipx configured and isn't in the list yet. 180 */ 181int 182ipx_output_type20(struct mbuf *m) 183{ 184 struct ipx *ipx; 185 union ipx_net *nbnet; 186 struct ipx_ifaddr *ia, *tia = NULL; 187 int error = 0; 188 struct mbuf *m1; 189 int i; 190 struct ifnet *ifp; 191 struct sockaddr_ipx dst; 192 193 /* 194 * We have to get to the 32 bytes after the ipx header also, so 195 * that we can fill in the network address of the receiving 196 * interface. 197 */ 198 if ((m->m_flags & M_EXT || m->m_len < (sizeof(struct ipx) + 32)) && 199 (m = m_pullup(m, sizeof(struct ipx) + 32)) == NULL) { 200 ipxstat.ipxs_toosmall++; 201 return (0); 202 } 203 ipx = mtod(m, struct ipx *); 204 nbnet = (union ipx_net *)(ipx + 1); 205 206 if (ipx->ipx_tc >= 8) 207 goto bad; 208 /* 209 * Now see if we have already seen this. 210 */ 211 for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 212 if(ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) { 213 if(tia == NULL) 214 tia = ia; 215 216 for (i=0;i<ipx->ipx_tc;i++,nbnet++) 217 if(ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 218 *nbnet)) 219 goto bad; 220 } 221 /* 222 * Don't route the packet if the interface where it come from 223 * does not have an IPX address. 224 */ 225 if(tia == NULL) 226 goto bad; 227 228 /* 229 * Add our receiving interface to the list. 230 */ 231 nbnet = (union ipx_net *)(ipx + 1); 232 nbnet += ipx->ipx_tc; 233 *nbnet = tia->ia_addr.sipx_addr.x_net; 234 235 /* 236 * Increment the hop count. 237 */ 238 ipx->ipx_tc++; 239 ipxstat.ipxs_forward++; 240 241 /* 242 * Send to all directly connected ifaces not in list and 243 * not to the one it came from. 244 */ 245 m->m_flags &= ~M_BCAST; 246 bzero(&dst, sizeof(dst)); 247 dst.sipx_family = AF_IPX; 248 dst.sipx_len = 12; 249 dst.sipx_addr.x_host = ipx_broadhost; 250 251 for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) 252 if(ia->ia_ifa.ifa_ifp != m->m_pkthdr.rcvif) { 253 nbnet = (union ipx_net *)(ipx + 1); 254 for (i=0;i<ipx->ipx_tc;i++,nbnet++) 255 if(ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 256 *nbnet)) 257 goto skip_this; 258 259 /* 260 * Insert the net address of the dest net and 261 * calculate the new checksum if needed. 262 */ 263 ifp = ia->ia_ifa.ifa_ifp; 264 dst.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net; 265 ipx->ipx_dna.x_net = dst.sipx_addr.x_net; 266 if(ipx->ipx_sum != 0xffff) 267 ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len)); 268 269 m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 270 if(m1) { 271 error = (*ifp->if_output)(ifp, m1, 272 (struct sockaddr *)&dst, NULL); 273 /* XXX ipxstat.ipxs_localout++; */ 274 } 275skip_this: ; 276 } 277 278bad: 279 m_freem(m); 280 return (error); 281} 282