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