|
|
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 are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: * ! 17: * @(#)ns_input.c 7.4 (Berkeley) 6/29/88 ! 18: */ ! 19: ! 20: #include "param.h" ! 21: #include "systm.h" ! 22: #include "mbuf.h" ! 23: #include "domain.h" ! 24: #include "protosw.h" ! 25: #include "socket.h" ! 26: #include "socketvar.h" ! 27: #include "errno.h" ! 28: #include "time.h" ! 29: #include "kernel.h" ! 30: ! 31: #include "../net/if.h" ! 32: #include "../net/route.h" ! 33: #include "../net/raw_cb.h" ! 34: ! 35: #include "ns.h" ! 36: #include "ns_if.h" ! 37: #include "ns_pcb.h" ! 38: #include "idp.h" ! 39: #include "idp_var.h" ! 40: #include "ns_error.h" ! 41: ! 42: /* ! 43: * NS initialization. ! 44: */ ! 45: union ns_host ns_thishost; ! 46: union ns_host ns_zerohost; ! 47: union ns_host ns_broadhost; ! 48: union ns_net ns_zeronet; ! 49: union ns_net ns_broadnet; ! 50: ! 51: static u_short allones[] = {-1, -1, -1}; ! 52: ! 53: struct nspcb nspcb; ! 54: struct nspcb nsrawpcb; ! 55: ! 56: struct ifqueue nsintrq; ! 57: int nsqmaxlen = IFQ_MAXLEN; ! 58: ! 59: int idpcksum = 1; ! 60: long ns_pexseq; ! 61: ! 62: ns_init() ! 63: { ! 64: extern struct timeval time; ! 65: ! 66: ns_broadhost = * (union ns_host *) allones; ! 67: ns_broadnet = * (union ns_net *) allones; ! 68: nspcb.nsp_next = nspcb.nsp_prev = &nspcb; ! 69: nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb; ! 70: nsintrq.ifq_maxlen = nsqmaxlen; ! 71: ns_pexseq = time.tv_usec; ! 72: } ! 73: ! 74: /* ! 75: * Idp input routine. Pass to next level. ! 76: */ ! 77: int nsintr_getpck = 0; ! 78: int nsintr_swtch = 0; ! 79: nsintr() ! 80: { ! 81: register struct idp *idp; ! 82: register struct mbuf *m; ! 83: register struct nspcb *nsp; ! 84: struct ifnet *ifp; ! 85: struct mbuf *m0; ! 86: register int i; ! 87: int len, s, error; ! 88: char oddpacketp; ! 89: ! 90: next: ! 91: /* ! 92: * Get next datagram off input queue and get IDP header ! 93: * in first mbuf. ! 94: */ ! 95: s = splimp(); ! 96: IF_DEQUEUEIF(&nsintrq, m, ifp); ! 97: splx(s); ! 98: nsintr_getpck++; ! 99: if (m == 0) ! 100: return; ! 101: if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct idp)) && ! 102: (m = m_pullup(m, sizeof (struct idp))) == 0) { ! 103: idpstat.idps_toosmall++; ! 104: goto next; ! 105: } ! 106: ! 107: /* ! 108: * Give any raw listeners a crack at the packet ! 109: */ ! 110: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { ! 111: struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); ! 112: if (m1) idp_input(m1, nsp, ifp); ! 113: } ! 114: ! 115: idp = mtod(m, struct idp *); ! 116: len = ntohs(idp->idp_len); ! 117: if (oddpacketp = len & 1) { ! 118: len++; /* If this packet is of odd length, ! 119: preserve garbage byte for checksum */ ! 120: } ! 121: ! 122: /* ! 123: * Check that the amount of data in the buffers ! 124: * is as at least much as the IDP header would have us expect. ! 125: * Trim mbufs if longer than we expect. ! 126: * Drop packet if shorter than we expect. ! 127: */ ! 128: i = -len; ! 129: m0 = m; ! 130: for (;;) { ! 131: i += m->m_len; ! 132: if (m->m_next == 0) ! 133: break; ! 134: m = m->m_next; ! 135: } ! 136: if (i != 0) { ! 137: if (i < 0) { ! 138: idpstat.idps_tooshort++; ! 139: m = m0; ! 140: goto bad; ! 141: } ! 142: if (i <= m->m_len) ! 143: m->m_len -= i; ! 144: else ! 145: m_adj(m0, -i); ! 146: } ! 147: m = m0; ! 148: if (idpcksum && ((i = idp->idp_sum)!=0xffff)) { ! 149: idp->idp_sum = 0; ! 150: if (i != (idp->idp_sum = ns_cksum(m,len))) { ! 151: idpstat.idps_badsum++; ! 152: idp->idp_sum = i; ! 153: if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host)) ! 154: error = NS_ERR_BADSUM; ! 155: else ! 156: error = NS_ERR_BADSUM_T; ! 157: ns_error(m, error, 0); ! 158: goto next; ! 159: } ! 160: } ! 161: /* ! 162: * Is this a directed broadcast? ! 163: */ ! 164: if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) { ! 165: if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) && ! 166: (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) && ! 167: (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) && ! 168: (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) { ! 169: /* ! 170: * Look to see if I need to eat this packet. ! 171: * Algorithm is to forward all young packets ! 172: * and prematurely age any packets which will ! 173: * by physically broadcasted. ! 174: * Any very old packets eaten without forwarding ! 175: * would die anyway. ! 176: * ! 177: * Suggestion of Bill Nesheim, Cornell U. ! 178: */ ! 179: if (idp->idp_tc < NS_MAXHOPS) { ! 180: idp_forward(idp); ! 181: goto next; ! 182: } ! 183: } ! 184: /* ! 185: * Is this our packet? If not, forward. ! 186: */ ! 187: } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) { ! 188: idp_forward(idp); ! 189: goto next; ! 190: } ! 191: /* ! 192: * Locate pcb for datagram. ! 193: */ ! 194: nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD); ! 195: /* ! 196: * Switch out to protocol's input routine. ! 197: */ ! 198: nsintr_swtch++; ! 199: if (nsp) { ! 200: if (oddpacketp) { ! 201: m_adj(m0, -1); ! 202: } ! 203: if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0) ! 204: switch (idp->idp_pt) { ! 205: ! 206: case NSPROTO_SPP: ! 207: spp_input(m, nsp, ifp); ! 208: goto next; ! 209: ! 210: case NSPROTO_ERROR: ! 211: ns_err_input(m); ! 212: goto next; ! 213: } ! 214: idp_input(m, nsp, ifp); ! 215: } else { ! 216: ns_error(m, NS_ERR_NOSOCK, 0); ! 217: } ! 218: goto next; ! 219: ! 220: bad: ! 221: m_freem(m); ! 222: goto next; ! 223: } ! 224: ! 225: u_char nsctlerrmap[PRC_NCMDS] = { ! 226: ECONNABORTED, ECONNABORTED, 0, 0, ! 227: 0, 0, EHOSTDOWN, EHOSTUNREACH, ! 228: ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, ! 229: EMSGSIZE, 0, 0, 0, ! 230: 0, 0, 0, 0 ! 231: }; ! 232: ! 233: idp_donosocks = 1; ! 234: ! 235: idp_ctlinput(cmd, arg) ! 236: int cmd; ! 237: caddr_t arg; ! 238: { ! 239: struct ns_addr *ns; ! 240: struct nspcb *nsp; ! 241: struct ns_errp *errp; ! 242: int idp_abort(); ! 243: extern struct nspcb *idp_drop(); ! 244: int type; ! 245: ! 246: if (cmd < 0 || cmd > PRC_NCMDS) ! 247: return; ! 248: if (nsctlerrmap[cmd] == 0) ! 249: return; /* XXX */ ! 250: type = NS_ERR_UNREACH_HOST; ! 251: switch (cmd) { ! 252: struct sockaddr_ns *sns; ! 253: ! 254: case PRC_IFDOWN: ! 255: case PRC_HOSTDEAD: ! 256: case PRC_HOSTUNREACH: ! 257: sns = (struct sockaddr_ns *)arg; ! 258: if (sns->sns_family != AF_INET) ! 259: return; ! 260: ns = &sns->sns_addr; ! 261: break; ! 262: ! 263: default: ! 264: errp = (struct ns_errp *)arg; ! 265: ns = &errp->ns_err_idp.idp_dna; ! 266: type = errp->ns_err_num; ! 267: type = ntohs((u_short)type); ! 268: } ! 269: switch (type) { ! 270: ! 271: case NS_ERR_UNREACH_HOST: ! 272: ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0); ! 273: break; ! 274: ! 275: case NS_ERR_NOSOCK: ! 276: nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port, ! 277: NS_WILDCARD); ! 278: if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr)) ! 279: (void) idp_drop(nsp, (int)nsctlerrmap[cmd]); ! 280: } ! 281: } ! 282: ! 283: int idpprintfs = 0; ! 284: int idpforwarding = 1; ! 285: /* ! 286: * Forward a packet. If some error occurs return the sender ! 287: * an error packet. Note we can't always generate a meaningful ! 288: * error message because the NS errors don't have a large enough repetoire ! 289: * of codes and types. ! 290: */ ! 291: struct route idp_droute; ! 292: struct route idp_sroute; ! 293: ! 294: idp_forward(idp) ! 295: register struct idp *idp; ! 296: { ! 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(dtom(idp), 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(dtom(idp)); ! 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(dtom(idp), &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(dtom(idp), 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_family = AF_NS; ! 423: dst->sns_addr = *src; ! 424: dst->sns_addr.x_port = 0; ! 425: rtalloc(ro); ! 426: if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { ! 427: return (0); ! 428: } ! 429: ro->ro_rt->rt_use++; ! 430: return (1); ! 431: } ! 432: ! 433: idp_undo_route(ro) ! 434: register struct route *ro; ! 435: { ! 436: if (ro->ro_rt) {RTFREE(ro->ro_rt);} ! 437: } ! 438: static union ns_net ! 439: ns_zeronet; ! 440: ! 441: ns_watch_output(m, ifp) ! 442: struct mbuf *m; ! 443: struct ifnet *ifp; ! 444: { ! 445: register struct nspcb *nsp; ! 446: register struct ifaddr *ia; ! 447: /* ! 448: * Give any raw listeners a crack at the packet ! 449: */ ! 450: for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { ! 451: struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL); ! 452: if (m0) { ! 453: struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); ! 454: ! 455: if(m1 == NULL) ! 456: m_freem(m0); ! 457: else { ! 458: register struct idp *idp; ! 459: ! 460: m1->m_off = MMINOFF; ! 461: m1->m_len = sizeof (*idp); ! 462: m1->m_next = m0; ! 463: idp = mtod(m1, struct idp *); ! 464: idp->idp_sna.x_net = ns_zeronet; ! 465: idp->idp_sna.x_host = ns_thishost; ! 466: if (ifp && (ifp->if_flags & IFF_POINTOPOINT)) ! 467: for(ia = ifp->if_addrlist; ia; ! 468: ia = ia->ifa_next) { ! 469: if (ia->ifa_addr.sa_family==AF_NS) { ! 470: idp->idp_sna = ! 471: satons_addr(ia->ifa_dstaddr); ! 472: break; ! 473: } ! 474: } ! 475: idp->idp_len = 0xffff; ! 476: idp_input(m1, nsp, ifp); ! 477: } ! 478: } ! 479: } ! 480: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.