|
|
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: #define NBLOCK (NBLKBIG+NBLK64+NBLK16+NBLK4)
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: extern struct block cblock[];
30:
31: while(bp){
32: if(bp < cblock || cblock >= &cblock[NBLOCK])
33: panic("bp_check bad bp");
34: if(bp->rptr == 0 || bp->wptr == 0 || bp->base == 0 || bp->lim == 0)
35: panic("bp_check 0");
36: if(bp->rptr >= bp->lim || bp->rptr < bp->base)
37: panic("bp_check rptr");
38: if(bp->wptr > bp->lim || bp->wptr < bp->base)
39: panic("bp_check wptr");
40: bp = bp->next;
41: }
42: }
43:
44: /* given a char *, come up with the block that holds it. yuk. */
45: int dtom_hits, dtom_misses;
46: u_char *xfirst16, *xfirst64, *xfirst1024, *xp;
47: struct block *xbp;
48:
49: struct block *
50: bp_dtom(p)
51: u_char *p;
52: {
53: extern struct block cblock[];
54: extern u_char blkdata[];
55: register u_char *first16, *first64, *first1024;
56: register struct block *bp;
57:
58: /* guess. the order of things in blkdata is NBLK4, NBLK16, ... */
59: first16 = &blkdata[4 * NBLK4];
60: first64 = &first16[16 * NBLK16];
61: first1024 = &first64[64 * NBLK64];
62: if(p < first16){
63: bp = &cblock[(p - blkdata) / 4];
64: } else if(p < first64){
65: bp = &cblock[NBLK4 + (p - first16) / 16];
66: } else if(p < first1024){
67: bp = &cblock[NBLK4 + NBLK16 + (p - first64) / 64];
68: } else {
69: bp = &cblock[NBLK4 + NBLK16 + NBLK64 + (p - first1024) / 1024];
70: }
71: if(bp->base && bp->lim && bp->rptr && bp->wptr
72: && (p >= bp->base) && (p < bp->lim)){
73: dtom_hits++;
74: return(bp);
75: }
76: xfirst16 = first16;
77: xfirst64 = first64;
78: xfirst1024 = first1024;
79: xp = p;
80: xbp = bp;
81: dtom_misses++;
82: for(bp = &cblock[NBLOCK-1]; bp >= &cblock[0]; --bp){
83: if(bp->base == 0 || bp->lim == 0 || bp->rptr == 0 || bp->wptr == 0)
84: continue;
85: if((p >= bp->base) && (p < bp->lim)){
86: return(bp);
87: }
88: }
89: panic("bp_dtom");
90: /* NOTREACHED */
91: }
92:
93: /* bp_pullup: make the first block have at least len bytes */
94: struct block *
95: bp_pullup(bp, len)
96: register struct block *bp;
97: {
98: register struct block *m, *n, *nn;
99: int count;
100:
101: n = bp;
102: if(len > MAXBLEN)
103: goto bad;
104: m = allocb(MAXBLEN);
105: if(m == 0)
106: goto bad;
107: do{
108: count = MIN(BSZ(m) - BLEN(m), len);
109: if(count > BLEN(n))
110: count = BLEN(n);
111: bcopy(n->rptr, m->wptr, (unsigned)count);
112: len -= count;
113: m->wptr += count;
114: n->rptr += count;
115: if(BLEN(n))
116: break;
117: nn = n->next;
118: freeb(n);
119: n = nn;
120: } while(n);
121: if(len){
122: freeb(m);
123: goto bad;
124: }
125: m->next = n;
126: return(m);
127: bad:
128: printf("m_pullup bad\n");
129: bp_free(n);
130: return(0);
131: }
132:
133: bp_free(bp)
134: register struct block *bp;
135: {
136: register struct block *p;
137:
138: while(bp){
139: p = bp->next;
140: /*
141: if((bp->rptr >= bp->lim) || (bp->wptr > bp->lim))
142: panic("bp_free");
143: if((bp->rptr < bp->base) || (bp->wptr < bp->base)){
144: printf("bp 0x%x, rptr 0x%x\n", bp, bp->rptr);
145: panic("bp_free1");
146: }
147: */
148: freeb(bp);
149: bp = p;
150: }
151: }
152:
153: struct block *
154: bp_copy(m, off, len)
155: register struct block *m;
156: int off;
157: register int len;
158: {
159: register struct block *n, **np;
160: struct block *top;
161:
162: if(len == 0)
163: return(0);
164: if(off < 0 || len < 0)
165: panic("m_copy");
166: while(off > 0){
167: if(m == 0)
168: panic("m_copy 1");
169: if(off < BLEN(m))
170: break;
171: off -= BLEN(m);
172: m = m->m_next;
173: }
174: np = ⊤
175: top = 0;
176: while(len > 0){
177: if(m == 0)
178: panic("m_copy 2");
179: #undef FAKE
180: #ifdef FAKE
181: n = allocb(1); /* fake block, will adjust pointers */
182: #else
183: n = allocb(len);
184: #endif FAKE
185: *np = n;
186: if(n == 0)
187: goto nospace;
188: n->next = 0;
189: #ifdef FAKE
190: /* fake them up */
191: n->rptr = mtod(m, u_char *)+off;
192: n->wptr = n->rptr + MIN(len, BLEN(m) - off);
193: /* pu meht ekaf */
194: #else
195: n->wptr += MIN(len, BLEN(m) - off);
196: bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
197: (unsigned)BLEN(n));
198: #endif FAKE
199: len -= BLEN(n);
200: off = 0;
201: m = m->next;
202: np = &n->m_next;
203: }
204: return(top);
205: nospace:
206: m_freem(top);
207: return(0);
208: }
209:
210: m_adj(mp, len)
211: struct block *mp;
212: register int len;
213: {
214: register struct block *m, *n;
215:
216: if((m = mp) == NULL)
217: return;
218: if(len >= 0){
219: while(m && len > 0){
220: if(BLEN(m) <= len){
221: len -= BLEN(m);
222: m->wptr = m->rptr;
223: m = m->m_next;
224: } else {
225: m->rptr += len;
226: break;
227: }
228: }
229: } else {
230: len = -len;
231: while(len > 0 && m && BLEN(m) != 0){
232: while(m && BLEN(m) != 0){
233: n = m;
234: m = m->next;
235: }
236: if(BLEN(n) <= len){
237: len -= BLEN(n);
238: n->wptr = n->rptr;
239: m = mp;
240: } else {
241: n->wptr -= len;
242: break;
243: }
244: }
245: }
246: }
247:
248: m_cat(m, n)
249: register struct mbuf *m, *n;
250: {
251: register struct mbuf *xn;
252:
253: while(m->m_next)
254: m = m->m_next;
255:
256: while(n){
257: if((m->wptr + BLEN(n)) >= m->lim){
258: /* just join the two chains */
259: m->m_next = n;
260: return;
261: }
262: /* splat the data from one into the other */
263: bcopy(mtod(n, caddr_t), m->wptr, BLEN(n));
264: m->wptr += BLEN(n);
265: xn = n->next;
266: m_free(n);
267: n = xn;
268: }
269: }
270:
271:
272: /* in_cksum.c 6.1 83/07/29 */
273: /*
274: * yuck, but i can't get it right myself.
275: */
276:
277: /*
278: * Checksum routine for Internet Protocol family headers (VAX Version).
279: *
280: * This routine is very heavily used in the network
281: * code and should be modified for each CPU to be as fast as possible.
282: */
283:
284: in_cksum(m, len)
285: register struct mbuf *m;
286: register int len;
287: {
288: register u_short *w; /* on vax, known to be r9 */
289: register int sum = 0; /* on vax, known to be r8 */
290: register int mlen = 0;
291:
292: for (;;) {
293: /*
294: * Each trip around loop adds in
295: * word from one mbuf segment.
296: */
297: w = mtod(m, u_short *);
298: if (mlen == -1) {
299: /*
300: * There is a byte left from the last segment;
301: * add it into the checksum. Don't have to worry
302: * about a carry-out here because we make sure
303: * that high part of (32 bit) sum is small below.
304: */
305: sum += *(u_char *)w << 8;
306: w = (u_short *)((char *)w + 1);
307: mlen = BLEN(m) - 1;
308: len--;
309: } else
310: mlen = BLEN(m);
311: m = m->m_next;
312: if (len < mlen)
313: mlen = len;
314: len -= mlen;
315: /*
316: * Force to long boundary so we do longword aligned
317: * memory operations. It is too hard to do byte
318: * adjustment, do only word adjustment.
319: */
320: if (((int)w&0x2) && mlen >= 2) {
321: sum += *w++;
322: mlen -= 2;
323: }
324: /*
325: * Do as much of the checksum as possible 32 bits at at time.
326: * In fact, this loop is unrolled to make overhead from
327: * branches &c small.
328: *
329: * We can do a 16 bit ones complement sum 32 bits at a time
330: * because the 32 bit register is acting as two 16 bit
331: * registers for adding, with carries from the low added
332: * into the high (by normal carry-chaining) and carries
333: * from the high carried into the low on the next word
334: * by use of the adwc instruction. This lets us run
335: * this loop at almost memory speed.
336: *
337: * Here there is the danger of high order carry out, and
338: * we carefully use adwc.
339: */
340: while ((mlen -= 32) >= 0) {
341: #undef ADD
342: asm("clrl r0"); /* clears carry */
343: #define ADD asm("adwc (r9)+,r8;");
344: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
345: asm("adwc $0,r8");
346: }
347: mlen += 32;
348: while ((mlen -= 8) >= 0) {
349: asm("clrl r0");
350: ADD; ADD;
351: asm("adwc $0,r8");
352: }
353: mlen += 8;
354: /*
355: * Now eliminate the possibility of carry-out's by
356: * folding back to a 16 bit number (adding high and
357: * low parts together.) Then mop up trailing words
358: * and maybe an odd byte.
359: */
360: { asm("ashl $-16,r8,r0; addw2 r0,r8");
361: asm("adwc $0,r8; movzwl r8,r8"); }
362: while ((mlen -= 2) >= 0) {
363: asm("movzwl (r9)+,r0; addl2 r0,r8");
364: }
365: if (mlen == -1) {
366: sum += *(u_char *)w;
367: }
368: if (len == 0)
369: break;
370: /*
371: * Locate the next block with some data.
372: * If there is a word split across a boundary we
373: * will wrap to the top with mlen == -1 and
374: * then add it in shifted appropriately.
375: */
376: for (;;) {
377: if (m == 0) {
378: printf("cksum: out of data\n");
379: goto done;
380: }
381: if (BLEN(m))
382: break;
383: m = m->m_next;
384: }
385: }
386: done:
387: /*
388: * Add together high and low parts of sum
389: * and carry to get cksum.
390: * Have to be careful to not drop the last
391: * carry here.
392: */
393: { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
394: asm("mcoml r8,r8; movzwl r8,r8"); }
395: return (sum);
396: }
397:
398: in_addr
399: in_netof(x)
400: in_addr x;
401: {
402: if(IN_CLASSC(x))
403: return(x&IN_CLASSC_NET);
404: else if(IN_CLASSB(x))
405: return(x&IN_CLASSB_NET);
406: else
407: return(x&IN_CLASSA_NET);
408: }
409:
410: in_addr
411: in_hostof(x)
412: in_addr x;
413: {
414: if(IN_CLASSC(x))
415: return(x&IN_CLASSC_HOST);
416: else if(IN_CLASSB(x))
417: return(x&IN_CLASSB_HOST);
418: else
419: return(x&IN_CLASSA_HOST);
420: }
421:
422: /*
423: * Routes are kept in a circular list. Ip_default_route points to the
424: * "first" position in the list. On each acess, the accessed element is
425: * moved to this first position.
426: */
427: #define NROUTES 50
428: struct ip_route ip_routes[NROUTES];
429: int Nip_route = NROUTES; /* let netstat know number of routes */
430: struct ip_route ip_default_route = { 0, 0, &ip_default_route };
431:
432: ip_doroute(dst, gate)
433: in_addr dst, gate;
434: {
435: register struct ip_route *rp, *save;
436: register struct ipif *ifp;
437:
438: if(gate){
439: /* no-ops are ignored */
440: if (dst == gate)
441: return(0);
442:
443: /* don't accept an indirect route, if we have a direct one */
444: for(ifp = ipif; ifp < &ipif[NINET]; ifp++){
445: if((ifp->flags&IFF_UP)
446: && ifp->that == dst)
447: return(0);
448: }
449: }
450: /* look through existing routes (looks at ip_default_route first)*/
451: rp = &ip_default_route;
452: do {
453: if (dst == rp->next->dst) {
454: if (gate) {
455: rp->next->gate = gate;
456: } else {
457: rp->next->dst = rp->next->gate = 0;
458: rp->next = rp->next->next;
459: }
460: return(0);
461: }
462: rp = rp->next;
463: } while (rp != &ip_default_route);
464: if (gate == 0)
465: return(0);
466: /* add a new route */
467: for(rp = &ip_routes[0]; rp < &ip_routes[NROUTES]; rp++)
468: if(rp->dst == 0) {
469: rp->dst = dst;
470: rp->gate = gate;
471: rp->next = ip_default_route.next;
472: ip_default_route.next = rp;
473: return(0);
474: }
475: return(1);
476: }
477:
478: /* Look for a route on the circular list. If the route is found, move
479: * it to the beginning of the list.
480: */
481: struct ip_route_info
482: ip_route(dst)
483: in_addr dst;
484: {
485: extern unsigned long in_netof();
486: unsigned long netof_dst;
487: register struct ip_route *rp, *trp;
488: struct ip_route_info info;
489:
490: /* look for host routes (start after ip_default_route) */
491: for(rp = &ip_default_route; rp->next != &ip_default_route; rp=rp->next)
492: if (dst == rp->next->dst) {
493: /* make sure the interface exists */
494: info.addr = rp->next->gate;
495: info.ifp = ip_ifonnetof(info.addr);
496: if(info.ifp == 0)
497: break;
498: /* move to first */
499: trp = rp->next;
500: rp->next = rp->next->next;
501: trp->next = ip_default_route.next;
502: ip_default_route.next = trp;
503: return(info);
504: }
505: /* now try nets (start after ip_default_route) */
506: netof_dst = in_netof(dst);
507: for (rp = &ip_default_route; rp->next != &ip_default_route; rp=rp->next)
508: if(netof_dst == rp->next->dst){
509: /* make sure the interface exists */
510: info.addr = rp->next->gate;
511: info.ifp = ip_ifonnetof(info.addr);
512: if(info.ifp == 0)
513: break;
514: /* move to first */
515: trp = rp->next;
516: rp->next = rp->next->next;
517: trp->next = ip_default_route.next;
518: ip_default_route.next = trp;
519: return(info);
520: }
521: /* try a network to which we are directly connected */
522: info.addr = dst;
523: info.ifp = ip_ifonnetof(dst);
524: if (info.ifp)
525: return info;
526: /* if all else fails, use default route */
527: info.addr = ip_default_route.gate;
528: info.ifp = ip_ifonnetof(info.addr);
529: return(info);
530: }
531:
532: bp_len(bp)
533: register struct block *bp;
534: {
535: int n;
536:
537: n = 0;
538: while(bp){
539: n += BLEN(bp);
540: bp = bp->next;
541: }
542: return(n);
543: }
544:
545: in_addr
546: ip_hoston(dst)
547: in_addr dst;
548: {
549: struct ip_route_info info;
550:
551: info = ip_route(dst);
552: if(info.ifp == 0)
553: return(0);
554: return(info.ifp->thishost);
555: }
556:
557: in_lnaof(i)
558: register u_long i;
559: {
560:
561: if(IN_CLASSA(i))
562: return((i)&IN_CLASSA_HOST);
563: else if(IN_CLASSB(i))
564: return((i)&IN_CLASSB_HOST);
565: else
566: return((i)&IN_CLASSC_HOST);
567: }
568: #endif NINET
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.