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