|
|
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.