|
|
1.1 ! root 1: #include "inet.h" ! 2: #if NINET > 0 ! 3: ! 4: #include "../h/param.h" ! 5: #include "../h/stream.h" ! 6: #include "../h/conf.h" ! 7: #include "../h/inet/in.h" ! 8: #include "../h/inet/ip.h" ! 9: #include "../h/inet/ip_var.h" ! 10: #include "../h/inet/mbuf.h" ! 11: #include "sparam.h" ! 12: ! 13: extern long time; ! 14: ! 15: struct block * ! 16: bp_get() ! 17: { ! 18: register struct block *bp; ! 19: ! 20: bp = allocb(64); ! 21: if(bp) ! 22: bp->next = 0; ! 23: return(bp); ! 24: } ! 25: ! 26: bp_check(bp) ! 27: register struct block *bp; ! 28: { ! 29: while(bp){ ! 30: BLOCKCHK(bp); ! 31: bp = bp->next; ! 32: } ! 33: } ! 34: ! 35: /* given a char *, come up with the block that holds it. yuk. */ ! 36: int dtom_hits, dtom_misses; ! 37: static u_char *xfirst16, *xfirst64, *xfirst1024, *xp; ! 38: struct block *xbp; ! 39: ! 40: struct block * ! 41: bp_dtom(p) ! 42: u_char *p; ! 43: { ! 44: extern struct block cblock[]; ! 45: extern u_char blkdata[]; ! 46: register u_char *first16, *first64, *first1024; ! 47: register struct block *bp; ! 48: ! 49: /* guess. the order of things in blkdata is NBLK4, NBLK16, ... */ ! 50: #ifdef CHKBLK ! 51: first16 = &blkdata[5 * NBLK4]; ! 52: first64 = &first16[17 * NBLK16]; ! 53: first1024 = &first64[65 * NBLK64]; ! 54: if(p < first16){ ! 55: bp = &cblock[(p - blkdata) / 5]; ! 56: } else if(p < first64){ ! 57: bp = &cblock[NBLK4 + (p - first16) / 17]; ! 58: } else if(p < first1024){ ! 59: bp = &cblock[NBLK4 + NBLK16 + (p - first64) / 65]; ! 60: } else { ! 61: bp = &cblock[NBLK4 + NBLK16 + NBLK64 + (p - first1024) / 1025]; ! 62: } ! 63: #else ! 64: first16 = &blkdata[4 * NBLK4]; ! 65: first64 = &first16[16 * NBLK16]; ! 66: first1024 = &first64[64 * NBLK64]; ! 67: if(p < first16){ ! 68: bp = &cblock[(p - blkdata) / 4]; ! 69: } else if(p < first64){ ! 70: bp = &cblock[NBLK4 + (p - first16) / 16]; ! 71: } else if(p < first1024){ ! 72: bp = &cblock[NBLK4 + NBLK16 + (p - first64) / 64]; ! 73: } else { ! 74: bp = &cblock[NBLK4 + NBLK16 + NBLK64 + (p - first1024) / 1024]; ! 75: } ! 76: #endif CHKBLK ! 77: if(bp->base && bp->lim && bp->rptr && bp->wptr ! 78: && (p >= bp->base) && (p < bp->lim)){ ! 79: BLOCKCHK(bp); ! 80: dtom_hits++; ! 81: return(bp); ! 82: } ! 83: xfirst16 = first16; ! 84: xfirst64 = first64; ! 85: xfirst1024 = first1024; ! 86: xp = p; ! 87: xbp = bp; ! 88: dtom_misses++; ! 89: for(bp = &cblock[NBLOCK-1]; bp >= &cblock[0]; --bp){ ! 90: if(bp->base == 0 || bp->lim == 0 || bp->rptr == 0 || bp->wptr == 0) ! 91: continue; ! 92: if((p >= bp->base) && (p < bp->lim)){ ! 93: return(bp); ! 94: } ! 95: } ! 96: panic("bp_dtom"); ! 97: /* NOTREACHED */ ! 98: } ! 99: ! 100: /* bp_pullup: make the first block have at least len bytes */ ! 101: struct block * ! 102: bp_pullup(bp, len) ! 103: register struct block *bp; ! 104: { ! 105: register struct block *m, *n, *nn; ! 106: int count; ! 107: ! 108: n = bp; ! 109: if(len > MAXBLEN) ! 110: goto bad; ! 111: m = allocb(MAXBLEN); ! 112: if(m == 0) ! 113: goto bad; ! 114: do{ ! 115: count = len; ! 116: if (m->lim - m->wptr < count) ! 117: count = m->lim - m->wptr; ! 118: if (BLEN(n) < count) ! 119: count = BLEN(n); ! 120: bcopy(n->rptr, m->wptr, (unsigned)count); ! 121: len -= count; ! 122: m->wptr += count; ! 123: n->rptr += count; ! 124: if(BLEN(n)) ! 125: break; ! 126: nn = n->next; ! 127: freeb(n); ! 128: n = nn; ! 129: } while(n); ! 130: if(len){ ! 131: freeb(m); ! 132: goto bad; ! 133: } ! 134: m->next = n; ! 135: MCHECK(m); ! 136: return(m); ! 137: bad: ! 138: printf("m_pullup bad\n"); ! 139: bp_free(n); ! 140: return(0); ! 141: } ! 142: ! 143: bp_free(bp) ! 144: register struct block *bp; ! 145: { ! 146: register struct block *p; ! 147: ! 148: while(bp){ ! 149: p = bp->next; ! 150: BLOCKCHK(bp); ! 151: freeb(bp); ! 152: bp = p; ! 153: } ! 154: } ! 155: ! 156: struct block * ! 157: bp_copy(m, off, len) ! 158: register struct block *m; ! 159: int off; ! 160: register int len; ! 161: { ! 162: register struct block *n, **np; ! 163: struct block *top; ! 164: register int clen; ! 165: ! 166: MCHECK(m); ! 167: if(len == 0) ! 168: return(0); ! 169: if(off < 0 || len < 0) ! 170: panic("m_copy"); ! 171: while(off > 0){ ! 172: if(m == 0) ! 173: panic("m_copy 1"); ! 174: if(off < BLEN(m)) ! 175: break; ! 176: off -= BLEN(m); ! 177: m = m->next; ! 178: } ! 179: np = ⊤ ! 180: top = 0; ! 181: while(len > 0){ ! 182: if(m == 0) ! 183: panic("m_copy 2"); ! 184: n = allocb(len); ! 185: *np = n; ! 186: if(n == 0) ! 187: goto nospace; ! 188: n->next = 0; ! 189: np = &n->next; ! 190: do { ! 191: clen = len; ! 192: if (BLEN(m) - off < clen) ! 193: clen = BLEN(m) - off; ! 194: if (n->lim - n->wptr < clen) ! 195: clen = n->lim - n->wptr; ! 196: bcopy((caddr_t)m->rptr+off, (caddr_t)n->wptr, clen); ! 197: n->wptr += clen; ! 198: len -= clen; ! 199: if (len <= 0) { ! 200: MCHECK(top); ! 201: return (top); ! 202: } ! 203: if (m->rptr + off + clen < m->wptr) ! 204: off += clen; ! 205: else { ! 206: off = 0; ! 207: m = m->next; ! 208: } ! 209: } while (n->wptr < n->lim); ! 210: } ! 211: MCHECK(top); ! 212: return(top); ! 213: nospace: ! 214: bp_free(top); ! 215: return(0); ! 216: } ! 217: ! 218: bp_adj(m, len) ! 219: register struct block *m; ! 220: register int len; ! 221: { ! 222: ! 223: if (m == NULL) ! 224: return; ! 225: MCHECK(m); ! 226: if (len > 0) { ! 227: while(m && len > 0){ ! 228: if(BLEN(m) <= len){ ! 229: len -= BLEN(m); ! 230: m->wptr = m->rptr; ! 231: m = m->next; ! 232: } else { ! 233: m->rptr += len; ! 234: break; ! 235: } ! 236: } ! 237: } ! 238: else if (len < 0) { ! 239: len = bp_len(m) + len; ! 240: if (len <= 0) { ! 241: if (m->next) ! 242: bp_free(m->next); ! 243: m->next = 0; ! 244: m->wptr = m->rptr; ! 245: return; ! 246: } ! 247: while ((len -= BLEN(m)) > 0) { ! 248: if ((m = m->next) == NULL) ! 249: return; ! 250: } ! 251: m->wptr += len; /* len is <= 0 */ ! 252: bp_free(m->next); ! 253: m->next = 0; ! 254: } ! 255: MCHECK(m); ! 256: } ! 257: ! 258: m_cat(m, n) ! 259: register struct block *m, *n; ! 260: { ! 261: struct mbuf *xn; ! 262: ! 263: MCHECK(m); MCHECK(n); ! 264: while(m->next) ! 265: m = m->next; ! 266: while(n){ ! 267: if((m->wptr + BLEN(n)) >= m->lim){ ! 268: /* just join the two chains */ ! 269: m->next = n; ! 270: break; ! 271: } ! 272: /* splat the data from one into the other */ ! 273: bcopy(n->rptr, m->wptr, BLEN(n)); ! 274: m->wptr += BLEN(n); ! 275: xn = n->next; ! 276: freeb(n); ! 277: n = xn; ! 278: } ! 279: MCHECK(m); ! 280: } ! 281: ! 282: /* C version of 4.2bsd's Internet checksum routine */ ! 283: /* This version assumes that no message exceeds 2^16 words */ ! 284: in_cksum(m, len) ! 285: register struct mbuf *m; ! 286: register int len; ! 287: { ! 288: register u_short *w; ! 289: register u_long sum = 0; ! 290: register int mlen = 0; ! 291: ! 292: MCHECK(m); ! 293: for (; len!=0; m=m->m_next) { ! 294: if (m == NULL) { ! 295: printf("cksum: out of data\n"); ! 296: break; ! 297: } ! 298: w = mtod(m, u_short *); ! 299: if (mlen == -1) { ! 300: /* last block ended on an odd numbered byte */ ! 301: sum += *(u_char *)w << 8; ! 302: w = (u_short *)((char *)w + 1); ! 303: mlen = BLEN(m) - 1; ! 304: len--; ! 305: } else ! 306: mlen = BLEN(m); ! 307: if (len < mlen) ! 308: mlen = len; ! 309: len -= mlen; ! 310: /* vecadd returns a 16-bit checksum of the block + sum */ ! 311: sum = vecadd(w, mlen, sum); ! 312: } ! 313: /* return complement of sum */ ! 314: return sum^0xffff; ! 315: } ! 316: ! 317: in_addr ! 318: in_netof(x) ! 319: in_addr x; ! 320: { ! 321: in_addr netmask; ! 322: struct ipif *ifp; ! 323: ! 324: if(IN_CLASSC(x)) ! 325: netmask = IN_CLASSC_NET; ! 326: else if(IN_CLASSB(x)) ! 327: netmask = IN_CLASSB_NET; ! 328: else ! 329: netmask = IN_CLASSA_NET; ! 330: ! 331: /* look for an interface for this network and use its subnet mask */ ! 332: for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){ ! 333: if(ifp->flags & IFF_UP){ ! 334: if(netmask&x == netmask&ifp->that) ! 335: if (ifp->mask==0) ! 336: return(x&netmask); ! 337: else ! 338: return(x&ifp->mask); ! 339: } ! 340: } ! 341: ! 342: /* no interface for this network, assume no subnetting */ ! 343: return x&netmask; ! 344: } ! 345: ! 346: /* ! 347: * Hash table for route entries. Collision resolution is linear search until ! 348: * encountering a hole. Replacement is LRU. ! 349: */ ! 350: #define NROUTES 128 ! 351: struct ip_route ip_routes[NROUTES]; ! 352: int Nip_route = NROUTES; /* let netstat know number of routes */ ! 353: #define HASH(x) (((x)+((x)>>8))%NROUTES) ! 354: struct ip_route ip_default_route; ! 355: ! 356: ip_doroute(dst, gate) ! 357: in_addr dst, gate; ! 358: { ! 359: register struct ip_route *rp, *sp, *op; ! 360: register struct ipif *ifp; ! 361: ! 362: /* default is a special case */ ! 363: if (dst == 0){ ! 364: ip_default_route.gate = gate; ! 365: return(0); ! 366: } ! 367: ! 368: /* look for what should be a noop */ ! 369: if(gate){ ! 370: /* don't accept an indirect route, if we have a direct one */ ! 371: for(ifp = ipif; ifp < &ipif[NINET]; ifp++){ ! 372: if((ifp->flags&IFF_UP) && ifp->that==dst) ! 373: return(0); ! 374: } ! 375: } else ! 376: gate = dst; ! 377: ! 378: /* look through existing routes */ ! 379: op = sp = rp = &ip_routes[HASH(dst)]; ! 380: do { ! 381: if (rp->dst==0 || rp->dst==dst) { ! 382: op = rp; ! 383: break; ! 384: } ! 385: if (rp->time<op->time) ! 386: op = rp; ! 387: if (++rp==&ip_routes[NROUTES]) ! 388: rp = ip_routes; ! 389: } while (rp != sp); ! 390: ! 391: /* add a new route */ ! 392: op->dst = dst; ! 393: op->gate = gate; ! 394: op->time = time; ! 395: return(0); ! 396: } ! 397: ! 398: /* Look for a route on the circular list. If the route is found, move ! 399: * it to the beginning of the list. ! 400: */ ! 401: struct ip_route_info ! 402: ip_route(dst) ! 403: in_addr dst; ! 404: { ! 405: register struct ip_route *rp, *sp; ! 406: extern unsigned long in_netof(); ! 407: unsigned long netof_dst; ! 408: struct ip_route_info info; ! 409: ! 410: /* try a network to which we are directly connected */ ! 411: info.addr = dst; ! 412: info.ifp = ip_ifonnetof(dst); ! 413: if (info.ifp) ! 414: return info; ! 415: ! 416: /* look for host routes */ ! 417: sp = rp = &ip_routes[HASH(dst)]; ! 418: do { ! 419: if (dst==rp->dst && rp->dst!=rp->gate) { ! 420: info.addr = rp->gate; ! 421: info.ifp = ip_ifonnetof(info.addr); ! 422: rp->time = time; ! 423: return(info); ! 424: } ! 425: if (rp->dst==0) ! 426: break; ! 427: if (++rp==&ip_routes[NROUTES]) ! 428: rp = ip_routes; ! 429: } while (rp != sp); ! 430: ! 431: /* now try nets */ ! 432: netof_dst = in_netof(dst); ! 433: sp = rp = &ip_routes[HASH(netof_dst)]; ! 434: do { ! 435: if (netof_dst==rp->dst && rp->dst!=rp->gate) { ! 436: info.addr = rp->gate; ! 437: info.ifp = ip_ifonnetof(info.addr); ! 438: rp->time = time; ! 439: return(info); ! 440: } ! 441: if (rp->dst==0) ! 442: break; ! 443: if (++rp==&ip_routes[NROUTES]) ! 444: rp = ip_routes; ! 445: } while (rp != sp); ! 446: ! 447: /* if all else fails, use default route */ ! 448: /* N.B. If the gate is a network, don't change the destination ! 449: * address. This allows multiple networks on one wire by ! 450: * making that wire the default. ! 451: */ ! 452: if (ip_default_route.gate!=in_netof(ip_default_route.gate)) ! 453: info.addr = ip_default_route.gate; ! 454: else ! 455: info.addr = dst; ! 456: info.ifp = ip_ifonnetof(ip_default_route.gate); ! 457: return(info); ! 458: } ! 459: ! 460: bp_len(bp) ! 461: register struct block *bp; ! 462: { ! 463: register int n; ! 464: ! 465: n = 0; ! 466: while(bp){ ! 467: n += BLEN(bp); ! 468: bp = bp->next; ! 469: } ! 470: return(n); ! 471: } ! 472: ! 473: bp_putback(q, list) ! 474: struct queue *q; ! 475: struct block *list; ! 476: { ! 477: register struct block *bp; ! 478: register struct block *prev, *next; ! 479: ! 480: /* ! 481: * reverse the list, to keep data in order ! 482: */ ! 483: prev = next = NULL; ! 484: for (bp = list; bp; bp = next) { ! 485: next = bp->next; ! 486: bp->next = prev; ! 487: prev = bp; ! 488: } ! 489: for (bp = prev; bp; bp = next) { ! 490: next = bp->next; ! 491: putbq(q, bp); ! 492: } ! 493: } ! 494: ! 495: in_addr ! 496: ip_hoston(dst) ! 497: in_addr dst; ! 498: { ! 499: struct ip_route_info info; ! 500: ! 501: info = ip_route(dst); ! 502: if(info.ifp == 0) ! 503: return(0); ! 504: return(info.ifp->thishost); ! 505: } ! 506: ! 507: in_lnaof(i) ! 508: register u_long i; ! 509: { ! 510: ! 511: if(IN_CLASSA(i)) ! 512: return((i)&IN_CLASSA_HOST); ! 513: else if(IN_CLASSB(i)) ! 514: return((i)&IN_CLASSB_HOST); ! 515: else ! 516: return((i)&IN_CLASSC_HOST); ! 517: } ! 518: #endif NINET
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.