1/* 2 * Copyright (c) 1995, Mike Mitchell 3 * Copyright (c) 1984, 1985, 1986, 1987, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 *
| 1/* 2 * Copyright (c) 1995, Mike Mitchell 3 * Copyright (c) 1984, 1985, 1986, 1987, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 *
|
35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/malloc.h> 40#include <sys/mbuf.h> 41#include <sys/domain.h> 42#include <sys/protosw.h> 43#include <sys/socket.h> 44#include <sys/socketvar.h> 45#include <sys/errno.h> 46#include <sys/time.h> 47#include <sys/kernel.h> 48 49#include <net/if.h> 50#include <net/route.h> 51#include <net/netisr.h> 52#include <net/raw_cb.h> 53 54#include <netipx/ipx.h> 55#include <netipx/spx.h> 56#include <netipx/ipx_if.h> 57#include <netipx/ipx_pcb.h> 58#include <netipx/ipx_var.h> 59#include <netipx/ipx_error.h> 60 61#ifndef IPXFORWARDING 62#ifdef GATEWAY 63#define IPXFORWARDING 1 /* forward IPX packets not for us */ 64#else 65#define IPXFORWARDING 0 /* don't forward IPX packets not for us */ 66#endif 67#endif 68#ifndef IPXPRINTFS 69#define IPXPRINTFS 1 /* printing forwarding information */ 70#endif 71 72#ifndef IPXCKSUM 73#define IPXCKSUM 0 /* perform IPX checksum */ 74#endif 75 76#ifndef IXDONOSOCKS 77#define IPXDONOSOCKS 0 /* return no socket errors */ 78#endif 79 80int ipxcksum = IPXCKSUM; 81int ipxprintfs = IPXPRINTFS; 82int ipxdonosocks = IPXDONOSOCKS; 83int ipxforwarding = IPXFORWARDING; 84 85union ipx_host ipx_thishost; 86union ipx_net ipx_zeronet; 87union ipx_host ipx_zerohost; 88 89union ipx_net ipx_broadnet; 90union ipx_host ipx_broadhost; 91 92struct ipxstat ipxstat; 93struct sockaddr_ipx ipx_netmask, ipx_hostmask; 94 95int ipxintr_getpck = 0; 96int ipxintr_swtch = 0; 97 98static u_short allones[] = {-1, -1, -1}; 99 100struct ipxpcb ipxpcb; 101struct ipxpcb ipxrawpcb; 102 103struct ifqueue ipxintrq; 104int ipxqmaxlen = IFQ_MAXLEN; 105 106long ipx_pexseq; 107 108NETISR_SET(NETISR_IPX, ipxintr); 109 110/* 111 * IPX initialization. 112 */ 113 114void 115ipx_init() 116{ 117 ipx_broadnet = * (union ipx_net *) allones; 118 ipx_broadhost = * (union ipx_host *) allones; 119 120 ipx_pexseq = time.tv_usec; 121 ipxintrq.ifq_maxlen = ipxqmaxlen; 122 ipxpcb.ipxp_next = ipxpcb.ipxp_prev = &ipxpcb; 123 ipxrawpcb.ipxp_next = ipxrawpcb.ipxp_prev = &ipxrawpcb; 124 125 ipx_netmask.sipx_len = 6; 126 ipx_netmask.sipx_addr.x_net = ipx_broadnet; 127 128 ipx_hostmask.sipx_len = 12; 129 ipx_hostmask.sipx_addr.x_net = ipx_broadnet; 130 ipx_hostmask.sipx_addr.x_host = ipx_broadhost; 131} 132 133/* 134 * IPX input routine. Pass to next level. 135 */ 136void 137ipxintr() 138{ 139 register struct ipx *ipx; 140 register struct mbuf *m; 141 register struct ipxpcb *ipxp; 142 register int i; 143 int len, s, error; 144 char oddpacketp; 145 146next: 147 /* 148 * Get next datagram off input queue and get IPX header 149 * in first mbuf. 150 */ 151 s = splimp(); 152 IF_DEQUEUE(&ipxintrq, m); 153 splx(s); 154 ipxintr_getpck++; 155 if (m == 0) 156 return; 157 if ((m->m_flags & M_EXT || m->m_len < sizeof (struct ipx)) && 158 (m = m_pullup(m, sizeof (struct ipx))) == 0) { 159 ipxstat.ipxs_toosmall++; 160 goto next; 161 } 162 163 /* 164 * Give any raw listeners a crack at the packet 165 */ 166 for (ipxp = ipxrawpcb.ipxp_next; ipxp != &ipxrawpcb; ipxp = ipxp->ipxp_next) { 167 struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); 168 if (m1) ipx_input(m1, ipxp); 169 } 170 171 ipx = mtod(m, struct ipx *); 172 len = ntohs(ipx->ipx_len); 173 if (oddpacketp = len & 1) { 174 len++; /* If this packet is of odd length, 175 preserve garbage byte for checksum */ 176 } 177 178 /* 179 * Check that the amount of data in the buffers 180 * is as at least much as the IPX header would have us expect. 181 * Trim mbufs if longer than we expect. 182 * Drop packet if shorter than we expect. 183 */ 184 if (m->m_pkthdr.len < len) { 185 ipxstat.ipxs_tooshort++; 186 goto bad; 187 } 188 if (m->m_pkthdr.len > len) { 189 if (m->m_len == m->m_pkthdr.len) { 190 m->m_len = len; 191 m->m_pkthdr.len = len; 192 } else 193 m_adj(m, len - m->m_pkthdr.len); 194 } 195 if (ipxcksum && ((i = ipx->ipx_sum)!=0xffff)) { 196 ipx->ipx_sum = 0; 197 if (i != (ipx->ipx_sum = ipx_cksum(m, len))) { 198 ipxstat.ipxs_badsum++; 199 ipx->ipx_sum = i; 200 if (ipx_hosteqnh(ipx_thishost, ipx->ipx_dna.x_host)) 201 error = IPX_ERR_BADSUM; 202 else 203 error = IPX_ERR_BADSUM_T; 204 ipx_error(m, error, 0); 205 goto next; 206 } 207 } 208 /* 209 * Is this a directed broadcast? 210 */ 211 if (ipx_hosteqnh(ipx_broadhost,ipx->ipx_dna.x_host)) { 212 if ((!ipx_neteq(ipx->ipx_dna, ipx->ipx_sna)) && 213 (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_broadnet)) && 214 (!ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet)) && 215 (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_zeronet)) ) { 216 /* 217 * Look to see if I need to eat this packet. 218 * Algorithm is to forward all young packets 219 * and prematurely age any packets which will 220 * by physically broadcasted. 221 * Any very old packets eaten without forwarding 222 * would die anyway. 223 * 224 * Suggestion of Bill Nesheim, Cornell U. 225 */ 226 if (ipx->ipx_tc < IPX_MAXHOPS) { 227 ipx_forward(m); 228 goto next; 229 } 230 } 231 /* 232 * Is this our packet? If not, forward. 233 */ 234 } else if (!ipx_hosteqnh(ipx_thishost,ipx->ipx_dna.x_host)) { 235 ipx_forward(m); 236 goto next; 237 } 238 /* 239 * Locate pcb for datagram. 240 */ 241 ipxp = ipx_pcblookup(&ipx->ipx_sna, ipx->ipx_dna.x_port, IPX_WILDCARD); 242 /* 243 * Switch out to protocol's input routine. 244 */ 245 ipxintr_swtch++; 246 if (ipxp) { 247 if (oddpacketp) { 248 m_adj(m, -1); 249 } 250 if ((ipxp->ipxp_flags & IPXP_ALL_PACKETS)==0) 251 switch (ipx->ipx_pt) { 252 253 case IPXPROTO_SPX: 254 spx_input(m, ipxp); 255 goto next; 256 257 case IPXPROTO_ERROR: 258 ipx_err_input(m); 259 goto next; 260 } 261 ipx_input(m, ipxp); 262 } else { 263 ipx_error(m, IPX_ERR_NOSOCK, 0); 264 } 265 goto next; 266 267bad: 268 m_freem(m); 269 goto next; 270} 271 272u_char ipxctlerrmap[PRC_NCMDS] = { 273 ECONNABORTED, ECONNABORTED, 0, 0, 274 0, 0, EHOSTDOWN, EHOSTUNREACH, 275 ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 276 EMSGSIZE, 0, 0, 0, 277 0, 0, 0, 0 278}; 279 280void 281ipx_ctlinput(cmd, arg) 282 int cmd; 283 caddr_t arg; 284{ 285 struct ipx_addr *ipx; 286 struct ipxpcb *ipxp; 287 struct ipx_errp *errp; 288 int type; 289 290 if (cmd < 0 || cmd > PRC_NCMDS) 291 return; 292 if (ipxctlerrmap[cmd] == 0) 293 return; /* XXX */ 294 type = IPX_ERR_UNREACH_HOST; 295 errp = (struct ipx_errp *)arg; 296 switch (cmd) { 297 struct sockaddr_ipx *sipx; 298 299 case PRC_IFDOWN: 300 case PRC_HOSTDEAD: 301 case PRC_HOSTUNREACH: 302 sipx = (struct sockaddr_ipx *)arg; 303 if (sipx->sipx_family != AF_IPX) 304 return; 305 ipx = &sipx->sipx_addr; 306 break; 307 308 default: 309 ipx = &errp->ipx_err_ipx.ipx_dna; 310 type = errp->ipx_err_num; 311 type = ntohs((u_short)type); 312 break; 313 } 314 switch (type) { 315 316 case IPX_ERR_UNREACH_HOST: 317 ipx_pcbnotify(ipx, (int)ipxctlerrmap[cmd], ipx_abort, NULL); 318 break; 319 320 case IPX_ERR_NOSOCK: 321 ipxp = ipx_pcblookup(ipx, errp->ipx_err_ipx.ipx_sna.x_port, 322 IPX_WILDCARD); 323 if(ipxp && ipxdonosocks && ! ipx_nullhost(ipxp->ipxp_faddr)) 324 (void) ipx_drop(ipxp, (int)ipxctlerrmap[cmd]); 325 } 326} 327 328/* 329 * Forward a packet. If some error occurs return the sender 330 * an error packet. Note we can't always generate a meaningful 331 * error message because the IPX errors don't have a large enough repetoire 332 * of codes and types. 333 */ 334struct route ipx_droute; 335struct route ipx_sroute; 336 337void 338ipx_forward(m) 339struct mbuf *m; 340{ 341 register struct ipx *ipx = mtod(m, struct ipx *); 342 register int error, type, code; 343 struct mbuf *mcopy = NULL; 344 int agedelta = 1; 345 int flags = IPX_FORWARDING; 346 int ok_there = 0; 347 int ok_back = 0; 348 349 if (ipxforwarding == 0) { 350 /* can't tell difference between net and host */ 351 type = IPX_ERR_UNREACH_HOST, code = 0; 352 goto senderror; 353 } 354 ipx->ipx_tc++; 355 if (ipx->ipx_tc > IPX_MAXHOPS) { 356 type = IPX_ERR_TOO_OLD, code = 0; 357 goto senderror; 358 } 359 /* 360 * Save at most 42 bytes of the packet in case 361 * we need to generate an IPX error message to the src. 362 */ 363 mcopy = m_copy(m, 0, imin((int)ntohs(ipx->ipx_len), 42)); 364 365 if ((ok_there = ipx_do_route(&ipx->ipx_dna,&ipx_droute))==0) { 366 type = IPX_ERR_UNREACH_HOST, code = 0; 367 goto senderror; 368 } 369 /* 370 * Here we think about forwarding broadcast packets, 371 * so we try to insure that it doesn't go back out 372 * on the interface it came in on. Also, if we 373 * are going to physically broadcast this, let us 374 * age the packet so we can eat it safely the second time around. 375 */ 376 if (ipx->ipx_dna.x_host.c_host[0] & 0x1) { 377 struct ipx_ifaddr *ia = ipx_iaonnetof(&ipx->ipx_dna); 378 struct ifnet *ifp; 379 if (ia) { 380 /* I'm gonna hafta eat this packet */ 381 agedelta += IPX_MAXHOPS - ipx->ipx_tc; 382 ipx->ipx_tc = IPX_MAXHOPS; 383 } 384 if ((ok_back = ipx_do_route(&ipx->ipx_sna,&ipx_sroute))==0) { 385 /* error = ENETUNREACH; He'll never get it! */ 386 m_freem(m); 387 goto cleanup; 388 } 389 if (ipx_droute.ro_rt && 390 (ifp=ipx_droute.ro_rt->rt_ifp) && 391 ipx_sroute.ro_rt && 392 (ifp!=ipx_sroute.ro_rt->rt_ifp)) { 393 flags |= IPX_ALLOWBROADCAST; 394 } else { 395 type = IPX_ERR_UNREACH_HOST, code = 0; 396 goto senderror; 397 } 398 } 399 /* need to adjust checksum */ 400 if (ipxcksum && ipx->ipx_sum != 0xffff) { 401 union bytes { 402 u_char c[4]; 403 u_short s[2]; 404 long l; 405 } x; 406 register int shift; 407 x.l = 0; x.c[0] = agedelta; 408 shift = (((((int)ntohs(ipx->ipx_len))+1)>>1)-2) & 0xf; 409 x.l = ipx->ipx_sum + (x.s[0] << shift); 410 x.l = x.s[0] + x.s[1]; 411 x.l = x.s[0] + x.s[1]; 412 if (x.l==0xffff) ipx->ipx_sum = 0; else ipx->ipx_sum = x.l; 413 } else 414 ipx->ipx_sum = 0xffff; 415 416 error = ipx_outputfl(m, &ipx_droute, flags); 417 418 if (ipxprintfs && !error) { 419 printf("forward: "); 420 ipx_printhost(&ipx->ipx_sna); 421 printf(" to "); 422 ipx_printhost(&ipx->ipx_dna); 423 printf(" hops %d\n", ipx->ipx_tc); 424 } 425 426 if (error && mcopy != NULL) { 427 ipx = mtod(mcopy, struct ipx *); 428 type = IPX_ERR_UNSPEC_T, code = 0; 429 switch (error) { 430 431 case ENETUNREACH: 432 case EHOSTDOWN: 433 case EHOSTUNREACH: 434 case ENETDOWN: 435 case EPERM: 436 type = IPX_ERR_UNREACH_HOST; 437 break; 438 439 case EMSGSIZE: 440 type = IPX_ERR_TOO_BIG; 441 code = 576; /* too hard to figure out mtu here */ 442 break; 443 444 case ENOBUFS: 445 type = IPX_ERR_UNSPEC_T; 446 break; 447 } 448 mcopy = NULL; 449 senderror: 450 ipx_error(m, type, code); 451 } 452cleanup: 453 if (ok_there) 454 ipx_undo_route(&ipx_droute); 455 if (ok_back) 456 ipx_undo_route(&ipx_sroute); 457 if (mcopy != NULL) 458 m_freem(mcopy); 459} 460 461int 462ipx_do_route(src, ro) 463struct ipx_addr *src; 464struct route *ro; 465{ 466 struct sockaddr_ipx *dst; 467 468 bzero((caddr_t)ro, sizeof (*ro)); 469 dst = (struct sockaddr_ipx *)&ro->ro_dst; 470 471 dst->sipx_len = sizeof(*dst); 472 dst->sipx_family = AF_IPX; 473 dst->sipx_addr = *src; 474 dst->sipx_addr.x_port = 0; 475 rtalloc(ro); 476 if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { 477 return (0); 478 } 479 ro->ro_rt->rt_use++; 480 return (1); 481} 482 483void 484ipx_undo_route(ro) 485register struct route *ro; 486{ 487 if (ro->ro_rt) {RTFREE(ro->ro_rt);} 488} 489 490void 491ipx_watch_output(m, ifp) 492struct mbuf *m; 493struct ifnet *ifp; 494{ 495 register struct ipxpcb *ipxp; 496 register struct ifaddr *ifa; 497 /* 498 * Give any raw listeners a crack at the packet 499 */ 500 for (ipxp = ipxrawpcb.ipxp_next; ipxp != &ipxrawpcb; ipxp = ipxp->ipxp_next) { 501 struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL); 502 if (m0) { 503 register struct ipx *ipx; 504 505 M_PREPEND(m0, sizeof (*ipx), M_DONTWAIT); 506 if (m0 == NULL) 507 continue; 508 ipx = mtod(m0, struct ipx *); 509 ipx->ipx_sna.x_net = ipx_zeronet; 510 ipx->ipx_sna.x_host = ipx_thishost; 511 if (ifp && (ifp->if_flags & IFF_POINTOPOINT)) 512 for(ifa = ifp->if_addrlist; ifa; 513 ifa = ifa->ifa_next) { 514 if (ifa->ifa_addr->sa_family==AF_IPX) { 515 ipx->ipx_sna = IA_SIPX(ifa)->sipx_addr; 516 break; 517 } 518 } 519 ipx->ipx_len = ntohl(m0->m_pkthdr.len); 520 ipx_input(m0, ipxp); 521 } 522 } 523}
| 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/malloc.h> 40#include <sys/mbuf.h> 41#include <sys/domain.h> 42#include <sys/protosw.h> 43#include <sys/socket.h> 44#include <sys/socketvar.h> 45#include <sys/errno.h> 46#include <sys/time.h> 47#include <sys/kernel.h> 48 49#include <net/if.h> 50#include <net/route.h> 51#include <net/netisr.h> 52#include <net/raw_cb.h> 53 54#include <netipx/ipx.h> 55#include <netipx/spx.h> 56#include <netipx/ipx_if.h> 57#include <netipx/ipx_pcb.h> 58#include <netipx/ipx_var.h> 59#include <netipx/ipx_error.h> 60 61#ifndef IPXFORWARDING 62#ifdef GATEWAY 63#define IPXFORWARDING 1 /* forward IPX packets not for us */ 64#else 65#define IPXFORWARDING 0 /* don't forward IPX packets not for us */ 66#endif 67#endif 68#ifndef IPXPRINTFS 69#define IPXPRINTFS 1 /* printing forwarding information */ 70#endif 71 72#ifndef IPXCKSUM 73#define IPXCKSUM 0 /* perform IPX checksum */ 74#endif 75 76#ifndef IXDONOSOCKS 77#define IPXDONOSOCKS 0 /* return no socket errors */ 78#endif 79 80int ipxcksum = IPXCKSUM; 81int ipxprintfs = IPXPRINTFS; 82int ipxdonosocks = IPXDONOSOCKS; 83int ipxforwarding = IPXFORWARDING; 84 85union ipx_host ipx_thishost; 86union ipx_net ipx_zeronet; 87union ipx_host ipx_zerohost; 88 89union ipx_net ipx_broadnet; 90union ipx_host ipx_broadhost; 91 92struct ipxstat ipxstat; 93struct sockaddr_ipx ipx_netmask, ipx_hostmask; 94 95int ipxintr_getpck = 0; 96int ipxintr_swtch = 0; 97 98static u_short allones[] = {-1, -1, -1}; 99 100struct ipxpcb ipxpcb; 101struct ipxpcb ipxrawpcb; 102 103struct ifqueue ipxintrq; 104int ipxqmaxlen = IFQ_MAXLEN; 105 106long ipx_pexseq; 107 108NETISR_SET(NETISR_IPX, ipxintr); 109 110/* 111 * IPX initialization. 112 */ 113 114void 115ipx_init() 116{ 117 ipx_broadnet = * (union ipx_net *) allones; 118 ipx_broadhost = * (union ipx_host *) allones; 119 120 ipx_pexseq = time.tv_usec; 121 ipxintrq.ifq_maxlen = ipxqmaxlen; 122 ipxpcb.ipxp_next = ipxpcb.ipxp_prev = &ipxpcb; 123 ipxrawpcb.ipxp_next = ipxrawpcb.ipxp_prev = &ipxrawpcb; 124 125 ipx_netmask.sipx_len = 6; 126 ipx_netmask.sipx_addr.x_net = ipx_broadnet; 127 128 ipx_hostmask.sipx_len = 12; 129 ipx_hostmask.sipx_addr.x_net = ipx_broadnet; 130 ipx_hostmask.sipx_addr.x_host = ipx_broadhost; 131} 132 133/* 134 * IPX input routine. Pass to next level. 135 */ 136void 137ipxintr() 138{ 139 register struct ipx *ipx; 140 register struct mbuf *m; 141 register struct ipxpcb *ipxp; 142 register int i; 143 int len, s, error; 144 char oddpacketp; 145 146next: 147 /* 148 * Get next datagram off input queue and get IPX header 149 * in first mbuf. 150 */ 151 s = splimp(); 152 IF_DEQUEUE(&ipxintrq, m); 153 splx(s); 154 ipxintr_getpck++; 155 if (m == 0) 156 return; 157 if ((m->m_flags & M_EXT || m->m_len < sizeof (struct ipx)) && 158 (m = m_pullup(m, sizeof (struct ipx))) == 0) { 159 ipxstat.ipxs_toosmall++; 160 goto next; 161 } 162 163 /* 164 * Give any raw listeners a crack at the packet 165 */ 166 for (ipxp = ipxrawpcb.ipxp_next; ipxp != &ipxrawpcb; ipxp = ipxp->ipxp_next) { 167 struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); 168 if (m1) ipx_input(m1, ipxp); 169 } 170 171 ipx = mtod(m, struct ipx *); 172 len = ntohs(ipx->ipx_len); 173 if (oddpacketp = len & 1) { 174 len++; /* If this packet is of odd length, 175 preserve garbage byte for checksum */ 176 } 177 178 /* 179 * Check that the amount of data in the buffers 180 * is as at least much as the IPX header would have us expect. 181 * Trim mbufs if longer than we expect. 182 * Drop packet if shorter than we expect. 183 */ 184 if (m->m_pkthdr.len < len) { 185 ipxstat.ipxs_tooshort++; 186 goto bad; 187 } 188 if (m->m_pkthdr.len > len) { 189 if (m->m_len == m->m_pkthdr.len) { 190 m->m_len = len; 191 m->m_pkthdr.len = len; 192 } else 193 m_adj(m, len - m->m_pkthdr.len); 194 } 195 if (ipxcksum && ((i = ipx->ipx_sum)!=0xffff)) { 196 ipx->ipx_sum = 0; 197 if (i != (ipx->ipx_sum = ipx_cksum(m, len))) { 198 ipxstat.ipxs_badsum++; 199 ipx->ipx_sum = i; 200 if (ipx_hosteqnh(ipx_thishost, ipx->ipx_dna.x_host)) 201 error = IPX_ERR_BADSUM; 202 else 203 error = IPX_ERR_BADSUM_T; 204 ipx_error(m, error, 0); 205 goto next; 206 } 207 } 208 /* 209 * Is this a directed broadcast? 210 */ 211 if (ipx_hosteqnh(ipx_broadhost,ipx->ipx_dna.x_host)) { 212 if ((!ipx_neteq(ipx->ipx_dna, ipx->ipx_sna)) && 213 (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_broadnet)) && 214 (!ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet)) && 215 (!ipx_neteqnn(ipx->ipx_dna.x_net, ipx_zeronet)) ) { 216 /* 217 * Look to see if I need to eat this packet. 218 * Algorithm is to forward all young packets 219 * and prematurely age any packets which will 220 * by physically broadcasted. 221 * Any very old packets eaten without forwarding 222 * would die anyway. 223 * 224 * Suggestion of Bill Nesheim, Cornell U. 225 */ 226 if (ipx->ipx_tc < IPX_MAXHOPS) { 227 ipx_forward(m); 228 goto next; 229 } 230 } 231 /* 232 * Is this our packet? If not, forward. 233 */ 234 } else if (!ipx_hosteqnh(ipx_thishost,ipx->ipx_dna.x_host)) { 235 ipx_forward(m); 236 goto next; 237 } 238 /* 239 * Locate pcb for datagram. 240 */ 241 ipxp = ipx_pcblookup(&ipx->ipx_sna, ipx->ipx_dna.x_port, IPX_WILDCARD); 242 /* 243 * Switch out to protocol's input routine. 244 */ 245 ipxintr_swtch++; 246 if (ipxp) { 247 if (oddpacketp) { 248 m_adj(m, -1); 249 } 250 if ((ipxp->ipxp_flags & IPXP_ALL_PACKETS)==0) 251 switch (ipx->ipx_pt) { 252 253 case IPXPROTO_SPX: 254 spx_input(m, ipxp); 255 goto next; 256 257 case IPXPROTO_ERROR: 258 ipx_err_input(m); 259 goto next; 260 } 261 ipx_input(m, ipxp); 262 } else { 263 ipx_error(m, IPX_ERR_NOSOCK, 0); 264 } 265 goto next; 266 267bad: 268 m_freem(m); 269 goto next; 270} 271 272u_char ipxctlerrmap[PRC_NCMDS] = { 273 ECONNABORTED, ECONNABORTED, 0, 0, 274 0, 0, EHOSTDOWN, EHOSTUNREACH, 275 ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 276 EMSGSIZE, 0, 0, 0, 277 0, 0, 0, 0 278}; 279 280void 281ipx_ctlinput(cmd, arg) 282 int cmd; 283 caddr_t arg; 284{ 285 struct ipx_addr *ipx; 286 struct ipxpcb *ipxp; 287 struct ipx_errp *errp; 288 int type; 289 290 if (cmd < 0 || cmd > PRC_NCMDS) 291 return; 292 if (ipxctlerrmap[cmd] == 0) 293 return; /* XXX */ 294 type = IPX_ERR_UNREACH_HOST; 295 errp = (struct ipx_errp *)arg; 296 switch (cmd) { 297 struct sockaddr_ipx *sipx; 298 299 case PRC_IFDOWN: 300 case PRC_HOSTDEAD: 301 case PRC_HOSTUNREACH: 302 sipx = (struct sockaddr_ipx *)arg; 303 if (sipx->sipx_family != AF_IPX) 304 return; 305 ipx = &sipx->sipx_addr; 306 break; 307 308 default: 309 ipx = &errp->ipx_err_ipx.ipx_dna; 310 type = errp->ipx_err_num; 311 type = ntohs((u_short)type); 312 break; 313 } 314 switch (type) { 315 316 case IPX_ERR_UNREACH_HOST: 317 ipx_pcbnotify(ipx, (int)ipxctlerrmap[cmd], ipx_abort, NULL); 318 break; 319 320 case IPX_ERR_NOSOCK: 321 ipxp = ipx_pcblookup(ipx, errp->ipx_err_ipx.ipx_sna.x_port, 322 IPX_WILDCARD); 323 if(ipxp && ipxdonosocks && ! ipx_nullhost(ipxp->ipxp_faddr)) 324 (void) ipx_drop(ipxp, (int)ipxctlerrmap[cmd]); 325 } 326} 327 328/* 329 * Forward a packet. If some error occurs return the sender 330 * an error packet. Note we can't always generate a meaningful 331 * error message because the IPX errors don't have a large enough repetoire 332 * of codes and types. 333 */ 334struct route ipx_droute; 335struct route ipx_sroute; 336 337void 338ipx_forward(m) 339struct mbuf *m; 340{ 341 register struct ipx *ipx = mtod(m, struct ipx *); 342 register int error, type, code; 343 struct mbuf *mcopy = NULL; 344 int agedelta = 1; 345 int flags = IPX_FORWARDING; 346 int ok_there = 0; 347 int ok_back = 0; 348 349 if (ipxforwarding == 0) { 350 /* can't tell difference between net and host */ 351 type = IPX_ERR_UNREACH_HOST, code = 0; 352 goto senderror; 353 } 354 ipx->ipx_tc++; 355 if (ipx->ipx_tc > IPX_MAXHOPS) { 356 type = IPX_ERR_TOO_OLD, code = 0; 357 goto senderror; 358 } 359 /* 360 * Save at most 42 bytes of the packet in case 361 * we need to generate an IPX error message to the src. 362 */ 363 mcopy = m_copy(m, 0, imin((int)ntohs(ipx->ipx_len), 42)); 364 365 if ((ok_there = ipx_do_route(&ipx->ipx_dna,&ipx_droute))==0) { 366 type = IPX_ERR_UNREACH_HOST, code = 0; 367 goto senderror; 368 } 369 /* 370 * Here we think about forwarding broadcast packets, 371 * so we try to insure that it doesn't go back out 372 * on the interface it came in on. Also, if we 373 * are going to physically broadcast this, let us 374 * age the packet so we can eat it safely the second time around. 375 */ 376 if (ipx->ipx_dna.x_host.c_host[0] & 0x1) { 377 struct ipx_ifaddr *ia = ipx_iaonnetof(&ipx->ipx_dna); 378 struct ifnet *ifp; 379 if (ia) { 380 /* I'm gonna hafta eat this packet */ 381 agedelta += IPX_MAXHOPS - ipx->ipx_tc; 382 ipx->ipx_tc = IPX_MAXHOPS; 383 } 384 if ((ok_back = ipx_do_route(&ipx->ipx_sna,&ipx_sroute))==0) { 385 /* error = ENETUNREACH; He'll never get it! */ 386 m_freem(m); 387 goto cleanup; 388 } 389 if (ipx_droute.ro_rt && 390 (ifp=ipx_droute.ro_rt->rt_ifp) && 391 ipx_sroute.ro_rt && 392 (ifp!=ipx_sroute.ro_rt->rt_ifp)) { 393 flags |= IPX_ALLOWBROADCAST; 394 } else { 395 type = IPX_ERR_UNREACH_HOST, code = 0; 396 goto senderror; 397 } 398 } 399 /* need to adjust checksum */ 400 if (ipxcksum && ipx->ipx_sum != 0xffff) { 401 union bytes { 402 u_char c[4]; 403 u_short s[2]; 404 long l; 405 } x; 406 register int shift; 407 x.l = 0; x.c[0] = agedelta; 408 shift = (((((int)ntohs(ipx->ipx_len))+1)>>1)-2) & 0xf; 409 x.l = ipx->ipx_sum + (x.s[0] << shift); 410 x.l = x.s[0] + x.s[1]; 411 x.l = x.s[0] + x.s[1]; 412 if (x.l==0xffff) ipx->ipx_sum = 0; else ipx->ipx_sum = x.l; 413 } else 414 ipx->ipx_sum = 0xffff; 415 416 error = ipx_outputfl(m, &ipx_droute, flags); 417 418 if (ipxprintfs && !error) { 419 printf("forward: "); 420 ipx_printhost(&ipx->ipx_sna); 421 printf(" to "); 422 ipx_printhost(&ipx->ipx_dna); 423 printf(" hops %d\n", ipx->ipx_tc); 424 } 425 426 if (error && mcopy != NULL) { 427 ipx = mtod(mcopy, struct ipx *); 428 type = IPX_ERR_UNSPEC_T, code = 0; 429 switch (error) { 430 431 case ENETUNREACH: 432 case EHOSTDOWN: 433 case EHOSTUNREACH: 434 case ENETDOWN: 435 case EPERM: 436 type = IPX_ERR_UNREACH_HOST; 437 break; 438 439 case EMSGSIZE: 440 type = IPX_ERR_TOO_BIG; 441 code = 576; /* too hard to figure out mtu here */ 442 break; 443 444 case ENOBUFS: 445 type = IPX_ERR_UNSPEC_T; 446 break; 447 } 448 mcopy = NULL; 449 senderror: 450 ipx_error(m, type, code); 451 } 452cleanup: 453 if (ok_there) 454 ipx_undo_route(&ipx_droute); 455 if (ok_back) 456 ipx_undo_route(&ipx_sroute); 457 if (mcopy != NULL) 458 m_freem(mcopy); 459} 460 461int 462ipx_do_route(src, ro) 463struct ipx_addr *src; 464struct route *ro; 465{ 466 struct sockaddr_ipx *dst; 467 468 bzero((caddr_t)ro, sizeof (*ro)); 469 dst = (struct sockaddr_ipx *)&ro->ro_dst; 470 471 dst->sipx_len = sizeof(*dst); 472 dst->sipx_family = AF_IPX; 473 dst->sipx_addr = *src; 474 dst->sipx_addr.x_port = 0; 475 rtalloc(ro); 476 if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { 477 return (0); 478 } 479 ro->ro_rt->rt_use++; 480 return (1); 481} 482 483void 484ipx_undo_route(ro) 485register struct route *ro; 486{ 487 if (ro->ro_rt) {RTFREE(ro->ro_rt);} 488} 489 490void 491ipx_watch_output(m, ifp) 492struct mbuf *m; 493struct ifnet *ifp; 494{ 495 register struct ipxpcb *ipxp; 496 register struct ifaddr *ifa; 497 /* 498 * Give any raw listeners a crack at the packet 499 */ 500 for (ipxp = ipxrawpcb.ipxp_next; ipxp != &ipxrawpcb; ipxp = ipxp->ipxp_next) { 501 struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL); 502 if (m0) { 503 register struct ipx *ipx; 504 505 M_PREPEND(m0, sizeof (*ipx), M_DONTWAIT); 506 if (m0 == NULL) 507 continue; 508 ipx = mtod(m0, struct ipx *); 509 ipx->ipx_sna.x_net = ipx_zeronet; 510 ipx->ipx_sna.x_host = ipx_thishost; 511 if (ifp && (ifp->if_flags & IFF_POINTOPOINT)) 512 for(ifa = ifp->if_addrlist; ifa; 513 ifa = ifa->ifa_next) { 514 if (ifa->ifa_addr->sa_family==AF_IPX) { 515 ipx->ipx_sna = IA_SIPX(ifa)->sipx_addr; 516 break; 517 } 518 } 519 ipx->ipx_len = ntohl(m0->m_pkthdr.len); 520 ipx_input(m0, ipxp); 521 } 522 } 523}
|