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: releng/10.2/sys/netipx/ipx_outputfl.c 263478 2014-03-21 15:15:30Z glebius $"); 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 77int 78ipx_outputfl(struct mbuf *m0, struct route *ro, int flags) 79{ 80 struct ipx *ipx = mtod(m0, struct ipx *); 81 struct ifnet *ifp = NULL; 82 int error = 0; 83 struct sockaddr_ipx *dst; 84 struct route ipxroute; 85 86 /* 87 * Route packet. 88 */ 89 if (ro == NULL) { 90 ro = &ipxroute; 91 bzero((caddr_t)ro, sizeof(*ro)); 92 } 93 dst = (struct sockaddr_ipx *)&ro->ro_dst; 94 if (ro->ro_rt == NULL) { 95 dst->sipx_family = AF_IPX; 96 dst->sipx_len = sizeof(*dst); 97 dst->sipx_addr = ipx->ipx_dna; 98 dst->sipx_addr.x_port = 0; 99 /* 100 * If routing to interface only, 101 * short circuit routing lookup. 102 */ 103 if (flags & IPX_ROUTETOIF) { 104 struct ipx_ifaddr *ia; 105 106 IPX_IFADDR_RLOCK(); 107 ia = ipx_iaonnetof(&ipx->ipx_dna); 108 if (ia == NULL) { 109 IPX_IFADDR_RUNLOCK(); 110 ipxstat.ipxs_noroute++; 111 error = ENETUNREACH; 112 goto bad; 113 } 114 ifp = ia->ia_ifp; 115 IPX_IFADDR_RUNLOCK(); 116 goto gotif; 117 } 118 rtalloc_ign(ro, 0); 119 } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 120 /* 121 * The old route has gone away; try for a new one. 122 */ 123 RTFREE(ro->ro_rt); 124 ro->ro_rt = NULL; 125 rtalloc_ign(ro, 0); 126 } 127 if (ro->ro_rt == NULL || (ifp = ro->ro_rt->rt_ifp) == NULL) { 128 ipxstat.ipxs_noroute++; 129 error = ENETUNREACH; 130 goto bad; 131 } 132 counter_u64_add(ro->ro_rt->rt_pksent, 1); 133 if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 134 dst = (struct sockaddr_ipx *)ro->ro_rt->rt_gateway; 135gotif: 136 /* 137 * Look for multicast addresses and 138 * and verify user is allowed to send 139 * such a packet. 140 */ 141 if (dst->sipx_addr.x_host.c_host[0]&1) { 142 if ((ifp->if_flags & (IFF_BROADCAST | IFF_LOOPBACK)) == 0) { 143 error = EADDRNOTAVAIL; 144 goto bad; 145 } 146 if ((flags & IPX_ALLOWBROADCAST) == 0) { 147 error = EACCES; 148 goto bad; 149 } 150 m0->m_flags |= M_BCAST; 151 } 152 153 if (htons(ipx->ipx_len) <= ifp->if_mtu) { 154 ipxstat.ipxs_localout++; 155 error = (*ifp->if_output)(ifp, m0, 156 (struct sockaddr *)dst, ro); 157 goto done; 158 } else { 159 ipxstat.ipxs_mtutoosmall++; 160 error = EMSGSIZE; 161 } 162bad: 163 m_freem(m0); 164done: 165 if (ro == &ipxroute && (flags & IPX_ROUTETOIF) == 0 && 166 ro->ro_rt != NULL) { 167 RTFREE(ro->ro_rt); 168 ro->ro_rt = NULL; 169 } 170 return (error); 171} 172 173/* 174 * This will broadcast the type 20 (Netbios) packet to all the interfaces 175 * that have ipx configured and isn't in the list yet. 176 */ 177int 178ipx_output_type20(struct mbuf *m) 179{ 180 struct ipx *ipx; 181 union ipx_net *nbnet; 182 struct ipx_ifaddr *ia, *tia; 183 int error = 0; 184 struct mbuf *m1; 185 int i; 186 struct ifnet *ifp; 187 struct sockaddr_ipx dst; 188 189 /* 190 * We have to get to the 32 bytes after the ipx header also, so 191 * that we can fill in the network address of the receiving 192 * interface. 193 */ 194 if ((m->m_flags & M_EXT || m->m_len < (sizeof(struct ipx) + 32)) && 195 (m = m_pullup(m, sizeof(struct ipx) + 32)) == NULL) { 196 ipxstat.ipxs_toosmall++; 197 return (0); 198 } 199 ipx = mtod(m, struct ipx *); 200 nbnet = (union ipx_net *)(ipx + 1); 201 202 if (ipx->ipx_tc >= 8) 203 goto bad; 204 /* 205 * Now see if we have already seen this. 206 */ 207 tia = NULL; 208 IPX_IFADDR_RLOCK(); 209 TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) { 210 if (ia->ia_ifa.ifa_ifp == m->m_pkthdr.rcvif) { 211 if (tia == NULL) 212 tia = ia; 213 for (i=0; i < ipx->ipx_tc; i++, nbnet++) { 214 if (ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 215 *nbnet)) { 216 IPX_IFADDR_RUNLOCK(); 217 goto bad; 218 } 219 } 220 } 221 } 222 223 /* 224 * Don't route the packet if the interface where it come from 225 * does not have an IPX address. 226 */ 227 if (tia == NULL) { 228 IPX_IFADDR_RUNLOCK(); 229 goto bad; 230 } 231 232 /* 233 * Add our receiving interface to the list. 234 */ 235 nbnet = (union ipx_net *)(ipx + 1); 236 nbnet += ipx->ipx_tc; 237 *nbnet = tia->ia_addr.sipx_addr.x_net; 238 239 /* 240 * Increment the hop count. 241 */ 242 ipx->ipx_tc++; 243 ipxstat.ipxs_forward++; 244 245 /* 246 * Send to all directly connected ifaces not in list and 247 * not to the one it came from. 248 */ 249 m->m_flags &= ~M_BCAST; 250 bzero(&dst, sizeof(dst)); 251 dst.sipx_family = AF_IPX; 252 dst.sipx_len = 12; 253 dst.sipx_addr.x_host = ipx_broadhost; 254 255 TAILQ_FOREACH(ia, &ipx_ifaddrhead, ia_link) { 256 if (ia->ia_ifa.ifa_ifp != m->m_pkthdr.rcvif) { 257 nbnet = (union ipx_net *)(ipx + 1); 258 for (i=0; i < ipx->ipx_tc; i++, nbnet++) 259 if (ipx_neteqnn(ia->ia_addr.sipx_addr.x_net, 260 *nbnet)) 261 goto skip_this; 262 263 /* 264 * Insert the net address of the dest net and 265 * calculate the new checksum if needed. 266 */ 267 ifp = ia->ia_ifa.ifa_ifp; 268 dst.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net; 269 ipx->ipx_dna.x_net = dst.sipx_addr.x_net; 270 if(ipx->ipx_sum != 0xffff) 271 ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len)); 272 273 m1 = m_copym(m, 0, M_COPYALL, M_NOWAIT); 274 if(m1) { 275 error = (*ifp->if_output)(ifp, m1, 276 (struct sockaddr *)&dst, NULL); 277 /* XXX ipxstat.ipxs_localout++; */ 278 } 279skip_this: ; 280 } 281 } 282 IPX_IFADDR_RUNLOCK(); 283 284bad: 285 m_freem(m); 286 return (error); 287} 288