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