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