|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1984, 1985, 1986, 1987, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)ns_input.c 8.1 (Berkeley) 6/10/93 ! 55: */ ! 56: ! 57: #include <sys/param.h> ! 58: #include <sys/systm.h> ! 59: #include <sys/malloc.h> ! 60: #include <sys/mbuf.h> ! 61: #include <sys/domain.h> ! 62: #include <sys/protosw.h> ! 63: #include <sys/socket.h> ! 64: #include <sys/socketvar.h> ! 65: #include <sys/errno.h> ! 66: #include <sys/time.h> ! 67: #include <sys/kernel.h> ! 68: ! 69: #include <net/if.h> ! 70: #include <net/route.h> ! 71: #include <net/raw_cb.h> ! 72: ! 73: #include <netns/ns.h> ! 74: #include <netns/ns_if.h> ! 75: #include <netns/ns_pcb.h> ! 76: #include <netns/idp.h> ! 77: #include <netns/idp_var.h> ! 78: #include <netns/ns_error.h> ! 79: ! 80: /* ! 81: * NS initialization. ! 82: */ ! 83: union ns_host ns_thishost; ! 84: union ns_host ns_zerohost; ! 85: union ns_host ns_broadhost; ! 86: union ns_net ns_zeronet; ! 87: union ns_net ns_broadnet; ! 88: struct sockaddr_ns ns_netmask, ns_hostmask; ! 89: ! 90: static u_short allones[] = {-1, -1, -1}; ! 91: ! 92: struct nspcb nspcb; ! 93: struct nspcb nsrawpcb; ! 94: ! 95: struct ifqueue nsintrq; ! 96: int nsqmaxlen = IFQ_MAXLEN; ! 97: ! 98: int idpcksum = 1; ! 99: long ns_pexseq; ! 100: ! 101: ns_init() ! 102: { ! 103: extern struct timeval time; ! 104: ! 105: ns_broadhost = * (union ns_host *) allones; ! 106: ns_broadnet = * (union ns_net *) allones; ! 107: nspcb.nsp_next = nspcb.nsp_prev = &nspcb; ! 108: nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb; ! 109: nsintrq.ifq_maxlen = nsqmaxlen; ! 110: ns_pexseq = time.tv_usec; ! 111: ns_netmask.sns_len = 6; ! 112: ns_netmask.sns_addr.x_net = ns_broadnet; ! 113: ns_hostmask.sns_len = 12; ! 114: ns_hostmask.sns_addr.x_net = ns_broadnet; ! 115: ns_hostmask.sns_addr.x_host = ns_broadhost; ! 116: } ! 117: ! 118: /* ! 119: * Idp input routine. Pass to next level. ! 120: */ ! 121: int nsintr_getpck = 0; ! 122: int nsintr_swtch = 0; ! 123: nsintr() ! 124: { ! 125: register struct idp *idp; ! 126: register struct mbuf *m; ! 127: register struct nspcb *nsp; ! 128: register int i; ! 129: int len, s, error; ! 130: char oddpacketp; ! 131: ! 132: next: ! 133: /* ! 134: * Get next datagram off input queue and get IDP header ! 135: * in first mbuf. ! 136: */ ! 137: s = splimp(); ! 138: IF_DEQUEUE(&nsintrq, m); ! 139: splx(s); ! 140: nsintr_getpck++; ! 141: if (m == 0) ! 142: return; ! 143: if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) && ! 144: (m = m_pullup(m, sizeof (struct idp))) == 0) { ! 145: idpstat.idps_toosmall++; ! 146: goto next; ! 147: } ! 148: ! 149: /* ! 150: * Give any raw listeners a crack at the packet ! 151: */ ! 152: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { ! 153: struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); ! 154: if (m1) idp_input(m1, nsp); ! 155: } ! 156: ! 157: idp = mtod(m, struct idp *); ! 158: len = ntohs(idp->idp_len); ! 159: if (oddpacketp = len & 1) { ! 160: len++; /* If this packet is of odd length, ! 161: preserve garbage byte for checksum */ ! 162: } ! 163: ! 164: /* ! 165: * Check that the amount of data in the buffers ! 166: * is as at least much as the IDP header would have us expect. ! 167: * Trim mbufs if longer than we expect. ! 168: * Drop packet if shorter than we expect. ! 169: */ ! 170: if (m->m_pkthdr.len < len) { ! 171: idpstat.idps_tooshort++; ! 172: goto bad; ! 173: } ! 174: if (m->m_pkthdr.len > len) { ! 175: if (m->m_len == m->m_pkthdr.len) { ! 176: m->m_len = len; ! 177: m->m_pkthdr.len = len; ! 178: } else ! 179: m_adj(m, len - m->m_pkthdr.len); ! 180: } ! 181: if (idpcksum && ((i = idp->idp_sum)!=0xffff)) { ! 182: idp->idp_sum = 0; ! 183: if (i != (idp->idp_sum = ns_cksum(m, len))) { ! 184: idpstat.idps_badsum++; ! 185: idp->idp_sum = i; ! 186: if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host)) ! 187: error = NS_ERR_BADSUM; ! 188: else ! 189: error = NS_ERR_BADSUM_T; ! 190: ns_error(m, error, 0); ! 191: goto next; ! 192: } ! 193: } ! 194: /* ! 195: * Is this a directed broadcast? ! 196: */ ! 197: if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) { ! 198: if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) && ! 199: (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) && ! 200: (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) && ! 201: (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) { ! 202: /* ! 203: * Look to see if I need to eat this packet. ! 204: * Algorithm is to forward all young packets ! 205: * and prematurely age any packets which will ! 206: * by physically broadcasted. ! 207: * Any very old packets eaten without forwarding ! 208: * would die anyway. ! 209: * ! 210: * Suggestion of Bill Nesheim, Cornell U. ! 211: */ ! 212: if (idp->idp_tc < NS_MAXHOPS) { ! 213: idp_forward(m); ! 214: goto next; ! 215: } ! 216: } ! 217: /* ! 218: * Is this our packet? If not, forward. ! 219: */ ! 220: } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) { ! 221: idp_forward(m); ! 222: goto next; ! 223: } ! 224: /* ! 225: * Locate pcb for datagram. ! 226: */ ! 227: nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD); ! 228: /* ! 229: * Switch out to protocol's input routine. ! 230: */ ! 231: nsintr_swtch++; ! 232: if (nsp) { ! 233: if (oddpacketp) { ! 234: m_adj(m, -1); ! 235: } ! 236: if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0) ! 237: switch (idp->idp_pt) { ! 238: ! 239: case NSPROTO_SPP: ! 240: spp_input(m, nsp); ! 241: goto next; ! 242: ! 243: case NSPROTO_ERROR: ! 244: ns_err_input(m); ! 245: goto next; ! 246: } ! 247: idp_input(m, nsp); ! 248: } else { ! 249: ns_error(m, NS_ERR_NOSOCK, 0); ! 250: } ! 251: goto next; ! 252: ! 253: bad: ! 254: m_freem(m); ! 255: goto next; ! 256: } ! 257: ! 258: u_char nsctlerrmap[PRC_NCMDS] = { ! 259: ECONNABORTED, ECONNABORTED, 0, 0, ! 260: 0, 0, EHOSTDOWN, EHOSTUNREACH, ! 261: ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, ! 262: EMSGSIZE, 0, 0, 0, ! 263: 0, 0, 0, 0 ! 264: }; ! 265: ! 266: int idp_donosocks = 1; ! 267: ! 268: idp_ctlinput(cmd, arg) ! 269: int cmd; ! 270: caddr_t arg; ! 271: { ! 272: struct ns_addr *ns; ! 273: struct nspcb *nsp; ! 274: struct ns_errp *errp; ! 275: int idp_abort(); ! 276: extern struct nspcb *idp_drop(); ! 277: int type; ! 278: ! 279: if (cmd < 0 || cmd > PRC_NCMDS) ! 280: return; ! 281: if (nsctlerrmap[cmd] == 0) ! 282: return; /* XXX */ ! 283: type = NS_ERR_UNREACH_HOST; ! 284: switch (cmd) { ! 285: struct sockaddr_ns *sns; ! 286: ! 287: case PRC_IFDOWN: ! 288: case PRC_HOSTDEAD: ! 289: case PRC_HOSTUNREACH: ! 290: sns = (struct sockaddr_ns *)arg; ! 291: if (sns->sns_family != AF_NS) ! 292: return; ! 293: ns = &sns->sns_addr; ! 294: break; ! 295: ! 296: default: ! 297: errp = (struct ns_errp *)arg; ! 298: ns = &errp->ns_err_idp.idp_dna; ! 299: type = errp->ns_err_num; ! 300: type = ntohs((u_short)type); ! 301: } ! 302: switch (type) { ! 303: ! 304: case NS_ERR_UNREACH_HOST: ! 305: ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0); ! 306: break; ! 307: ! 308: case NS_ERR_NOSOCK: ! 309: nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port, ! 310: NS_WILDCARD); ! 311: if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr)) ! 312: (void) idp_drop(nsp, (int)nsctlerrmap[cmd]); ! 313: } ! 314: } ! 315: ! 316: int idpprintfs = 0; ! 317: int idpforwarding = 1; ! 318: /* ! 319: * Forward a packet. If some error occurs return the sender ! 320: * an error packet. Note we can't always generate a meaningful ! 321: * error message because the NS errors don't have a large enough repetoire ! 322: * of codes and types. ! 323: */ ! 324: struct route idp_droute; ! 325: struct route idp_sroute; ! 326: ! 327: idp_forward(m) ! 328: struct mbuf *m; ! 329: { ! 330: register struct idp *idp = mtod(m, struct idp *); ! 331: register int error, type, code; ! 332: struct mbuf *mcopy = NULL; ! 333: int agedelta = 1; ! 334: int flags = NS_FORWARDING; ! 335: int ok_there = 0; ! 336: int ok_back = 0; ! 337: ! 338: if (idpprintfs) { ! 339: printf("forward: src "); ! 340: ns_printhost(&idp->idp_sna); ! 341: printf(", dst "); ! 342: ns_printhost(&idp->idp_dna); ! 343: printf("hop count %d\n", idp->idp_tc); ! 344: } ! 345: if (idpforwarding == 0) { ! 346: /* can't tell difference between net and host */ ! 347: type = NS_ERR_UNREACH_HOST, code = 0; ! 348: goto senderror; ! 349: } ! 350: idp->idp_tc++; ! 351: if (idp->idp_tc > NS_MAXHOPS) { ! 352: type = NS_ERR_TOO_OLD, code = 0; ! 353: goto senderror; ! 354: } ! 355: /* ! 356: * Save at most 42 bytes of the packet in case ! 357: * we need to generate an NS error message to the src. ! 358: */ ! 359: mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42)); ! 360: ! 361: if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) { ! 362: type = NS_ERR_UNREACH_HOST, code = 0; ! 363: goto senderror; ! 364: } ! 365: /* ! 366: * Here we think about forwarding broadcast packets, ! 367: * so we try to insure that it doesn't go back out ! 368: * on the interface it came in on. Also, if we ! 369: * are going to physically broadcast this, let us ! 370: * age the packet so we can eat it safely the second time around. ! 371: */ ! 372: if (idp->idp_dna.x_host.c_host[0] & 0x1) { ! 373: struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); ! 374: struct ifnet *ifp; ! 375: if (ia) { ! 376: /* I'm gonna hafta eat this packet */ ! 377: agedelta += NS_MAXHOPS - idp->idp_tc; ! 378: idp->idp_tc = NS_MAXHOPS; ! 379: } ! 380: if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) { ! 381: /* error = ENETUNREACH; He'll never get it! */ ! 382: m_freem(m); ! 383: goto cleanup; ! 384: } ! 385: if (idp_droute.ro_rt && ! 386: (ifp=idp_droute.ro_rt->rt_ifp) && ! 387: idp_sroute.ro_rt && ! 388: (ifp!=idp_sroute.ro_rt->rt_ifp)) { ! 389: flags |= NS_ALLOWBROADCAST; ! 390: } else { ! 391: type = NS_ERR_UNREACH_HOST, code = 0; ! 392: goto senderror; ! 393: } ! 394: } ! 395: /* need to adjust checksum */ ! 396: if (idp->idp_sum!=0xffff) { ! 397: union bytes { ! 398: u_char c[4]; ! 399: u_short s[2]; ! 400: long l; ! 401: } x; ! 402: register int shift; ! 403: x.l = 0; x.c[0] = agedelta; ! 404: shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf; ! 405: x.l = idp->idp_sum + (x.s[0] << shift); ! 406: x.l = x.s[0] + x.s[1]; ! 407: x.l = x.s[0] + x.s[1]; ! 408: if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l; ! 409: } ! 410: if ((error = ns_output(m, &idp_droute, flags)) && ! 411: (mcopy!=NULL)) { ! 412: idp = mtod(mcopy, struct idp *); ! 413: type = NS_ERR_UNSPEC_T, code = 0; ! 414: switch (error) { ! 415: ! 416: case ENETUNREACH: ! 417: case EHOSTDOWN: ! 418: case EHOSTUNREACH: ! 419: case ENETDOWN: ! 420: case EPERM: ! 421: type = NS_ERR_UNREACH_HOST; ! 422: break; ! 423: ! 424: case EMSGSIZE: ! 425: type = NS_ERR_TOO_BIG; ! 426: code = 576; /* too hard to figure out mtu here */ ! 427: break; ! 428: ! 429: case ENOBUFS: ! 430: type = NS_ERR_UNSPEC_T; ! 431: break; ! 432: } ! 433: mcopy = NULL; ! 434: senderror: ! 435: ns_error(m, type, code); ! 436: } ! 437: cleanup: ! 438: if (ok_there) ! 439: idp_undo_route(&idp_droute); ! 440: if (ok_back) ! 441: idp_undo_route(&idp_sroute); ! 442: if (mcopy != NULL) ! 443: m_freem(mcopy); ! 444: } ! 445: ! 446: idp_do_route(src, ro) ! 447: struct ns_addr *src; ! 448: struct route *ro; ! 449: { ! 450: ! 451: struct sockaddr_ns *dst; ! 452: ! 453: bzero((caddr_t)ro, sizeof (*ro)); ! 454: dst = (struct sockaddr_ns *)&ro->ro_dst; ! 455: ! 456: dst->sns_len = sizeof(*dst); ! 457: dst->sns_family = AF_NS; ! 458: dst->sns_addr = *src; ! 459: dst->sns_addr.x_port = 0; ! 460: rtalloc(ro); ! 461: if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { ! 462: return (0); ! 463: } ! 464: ro->ro_rt->rt_use++; ! 465: return (1); ! 466: } ! 467: ! 468: idp_undo_route(ro) ! 469: register struct route *ro; ! 470: { ! 471: if (ro->ro_rt) {RTFREE(ro->ro_rt);} ! 472: } ! 473: ! 474: ns_watch_output(m, ifp) ! 475: struct mbuf *m; ! 476: struct ifnet *ifp; ! 477: { ! 478: register struct nspcb *nsp; ! 479: register struct ifaddr *ifa; ! 480: /* ! 481: * Give any raw listeners a crack at the packet ! 482: */ ! 483: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { ! 484: struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL); ! 485: if (m0) { ! 486: register struct idp *idp; ! 487: ! 488: M_PREPEND(m0, sizeof (*idp), M_DONTWAIT); ! 489: if (m0 == NULL) ! 490: continue; ! 491: idp = mtod(m0, struct idp *); ! 492: idp->idp_sna.x_net = ns_zeronet; ! 493: idp->idp_sna.x_host = ns_thishost; ! 494: if (ifp && (ifp->if_flags & IFF_POINTOPOINT)) ! 495: for(ifa = ifp->if_addrlist; ifa; ! 496: ifa = ifa->ifa_next) { ! 497: if (ifa->ifa_addr->sa_family==AF_NS) { ! 498: idp->idp_sna = IA_SNS(ifa)->sns_addr; ! 499: break; ! 500: } ! 501: } ! 502: idp->idp_len = ntohl(m0->m_pkthdr.len); ! 503: idp_input(m0, nsp); ! 504: } ! 505: } ! 506: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.