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