|
|
1.1 root 1: /*
2: * ip line discipline, to be pushed on an ethernet controller.
3: * collects data till a delim, passes it to ip_input().
4: */
5:
6: #include "inet.h"
7: #include "arp.h"
8: #include "uarp.h"
9: #if NINET > 0
10: #include "../h/param.h"
11: #include "../h/systm.h"
12: #include "../h/stream.h"
13: #include "../h/ioctl.h"
14: #include "../h/ttyld.h"
15: #include "../h/map.h"
16: #include "../h/buf.h"
17: #include "../h/ubavar.h"
18: #include "../h/conf.h"
19: #include "../h/inet/in.h"
20: #include "../h/inet/ip_var.h"
21: #include "../h/ethernet.h"
22:
23: struct ipif ipif[NINET];
24: int Ninet = NINET; /* let netstat find the number of interfaces */
25:
26: int ipopen(), ipiput(), ipisrv(), ipclose();
27: int iposrv(), ipoput();
28: static struct qinit iprinit = { ipiput, ipisrv, ipopen, ipclose, IP_MSG_LIMIT, 64};
29: /* was IP_MSG_LIMIT (4096), 64 originally */
30: static struct qinit ipwinit = { putq, iposrv, ipopen, ipclose, 1024, 64 };
31: /* was 512, 64 originally */
32: struct streamtab ipinfo = { &iprinit, &ipwinit };
33:
34: ipopen(q, dev)
35: register struct queue *q;
36: {
37: static int timing;
38: register i;
39: register struct ipif *fp;
40:
41: if (q->ptr)
42: return(1);
43: if(!timing){
44: timing = 1;
45: ip_slowtimo();
46: }
47: for (i=0; ipif[i].queue!=0 && i<NINET; i++)
48: ;
49: if (i >= NINET)
50: return(0);
51: fp = &ipif[i];
52: fp->queue = q; /* that's the RD q */
53: fp->flags = IFF_UP;
54: fp->that = fp->thishost = 0;
55: fp->ipackets = fp->opackets = fp->ierrors = fp->oerrors = 0;
56: fp->mtu = 1500;
57: fp->arp = -1;
58: fp->dev = dev;
59: q->flag |= QDELIM;
60: WR(q)->flag |= QDELIM;
61: q->ptr = (caddr_t)fp;
62: WR(q)->ptr = (caddr_t)fp;
63: q->flag |= QNOENB; /* ipiput calls qenable() */
64: return(1);
65: }
66:
67: ipclose(q)
68: register struct queue *q;
69: {
70: register struct ipif *ifp;
71:
72: ifp = (struct ipif *)q->ptr;
73: #if NARP > 0
74: if (ifp->arp >= 0)
75: arp_disable(ifp->arp);
76: #endif
77: ifp->queue = 0;
78: ifp->flags = 0;
79: }
80:
81: ipisrv(q)
82: register struct queue *q;
83: {
84: register struct block *bp, *head, *tail;
85: register struct ipif *ifp;
86:
87: /* there is now a whole packet waiting
88: * on this queue; strip it off and pass to ip_input().
89: * things other than data or delims are forwarded directly
90: * by ipiput().
91: */
92: head = tail = (struct block *) 0;
93: ifp = (struct ipif *)q->ptr;
94: while(bp = getq(q)){
95: if(bp->type == M_DELIM){
96: freeb(bp);
97: if(head){
98: if((ifp->flags & IFF_ARP)
99: && (head->wptr - head->rptr) >= 14){
100: /* blow away ether header */
101: head->rptr += 6 + 6 + 2;
102: }
103: ip_input(head);
104: ifp->ipackets++;
105: } else {
106: printf("ipisrv: delim, no data\n");
107: ifp->ierrors++;
108: }
109: head = tail = (struct block *) 0;
110: } else if(bp->type == M_DATA){
111: bp->next = (struct block *) 0;
112: if(head == (struct block *) 0){
113: head = bp;
114: } else {
115: tail->next = bp;
116: }
117: tail = bp;
118: } else {
119: printf("weird type %d in ipisrv\n", bp->type);
120: (*q->next->qinfo->putp)(q->next, bp);
121: }
122: }
123: if(head || tail){
124: printf("ipisrv: data & no dELIM\n");
125: }
126: }
127:
128:
129: ipiput(q, bp)
130: register struct queue *q;
131: register struct block *bp;
132: {
133: switch(bp->type){
134: case M_DATA:
135: putq(q, bp); /* putq does compression into blocks */
136: break;
137: case M_DELIM:
138: putq(q, bp);
139: qenable(q);
140: break;
141: default:
142: (*q->next->qinfo->putp)(q->next, bp);
143: break;
144: }
145:
146: }
147:
148: iposrv(q)
149: register struct queue *q;
150: {
151: struct x{
152: unsigned int in;
153: unsigned char en[6];
154: } *xp;
155: register union stmsg *sp;
156: register struct block *bp;
157: register struct ipif *ifp;
158: register int *intp;
159:
160: ifp = (struct ipif *)q->ptr;
161: while(bp = getq(q)){
162: if(bp->type == M_IOCTL){
163: sp = (union stmsg *)bp->rptr;
164: switch(sp->ioc0.com){
165: case IPIOARP:
166: #if NARP > 0
167: if (ifp->arp >= 0)
168: printf("IP: already arping\n");
169: else {
170: ifp->arp = arp_enable(ifp->dev,
171: ETHERPUP_IPTYPE,
172: sizeof(u_long), 1,
173: &ifp->thishost);
174: if (ifp->arp == -1) {
175: bp->type = M_IOCNAK;
176: qreply(q, bp);
177: break;
178: }
179: }
180: #endif
181: ifp->flags |= IFF_ARP;
182: bp->type = M_IOCACK;
183: bp->wptr = bp->rptr;
184: qreply(q, bp);
185: break;
186: case IPIORESOLVE:
187: xp = (struct x *)(sp->iocx.xxx);
188: #if NUARP > 0
189: arp_install(xp->in, xp->en);
190: #endif
191: bp->wptr = bp->rptr;
192: bp->type = M_IOCACK;
193: qreply(q, bp);
194: break;
195: case IPIOHOST:
196: intp = (int *)(sp->iocx.xxx);
197: ifp->that = *intp;
198: ifp->flags |= IFF_HOST;
199: bp->type = M_IOCACK;
200: qreply(q, bp);
201: ip_doroute(ifp->that, 0);
202: break;
203: case IPIOMTU:
204: intp = (int *)(sp->iocx.xxx);
205: ifp->that = *intp;
206: ifp->mtu = *intp;
207: bp->type = M_IOCACK;
208: qreply(q, bp);
209: break;
210: case IPIONET:
211: intp = (int *)(sp->iocx.xxx);
212: ifp->that = *intp;
213: ifp->flags &= (~IFF_HOST);
214: bp->type = M_IOCACK;
215: qreply(q, bp);
216: ip_doroute(ifp->that, 0);
217: break;
218: case IPIOLOCAL:
219: intp = (int *)(sp->iocx.xxx);
220: ifp->thishost = *intp;
221: bp->type = M_IOCACK;
222: qreply(q, bp);
223: break;
224: default:
225: (*q->next->qinfo->putp)(q->next, bp);
226: break;
227: }
228: } else {
229: (*q->next->qinfo->putp)(q->next, bp);
230: if(bp->type == M_DELIM)
231: ifp->opackets++;
232: }
233: }
234: }
235:
236: struct ipif *
237: ip_ifonnetof(dst)
238: unsigned long dst;
239: {
240: extern ipprintfs;
241: struct ipif *ifp;
242:
243: /* point-to-point links first */
244: for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){
245: if((ifp->flags & IFF_UP) && (ifp->flags & IFF_HOST)){
246: if(dst == ifp->that)
247: return(ifp);
248: }
249: }
250: /* now normal nets */
251: for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){
252: if((ifp->flags & (IFF_UP|IFF_HOST)) == IFF_UP){
253: if(in_netof(dst) == ifp->that)
254: return(ifp);
255: }
256: }
257: if(ipprintfs)
258: printf("ifonnetof %x?\n", dst);
259: return(0);
260: }
261:
262: struct ipif *
263: ip_ifwithaddr(addr)
264: unsigned long addr;
265: {
266: struct ipif *ifp;
267: unsigned long net;
268:
269: net = in_netof(addr);
270: for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){
271: if(ifp->flags & IFF_UP){
272: /* address of this host */
273: if(addr == ifp->thishost)
274: return(ifp);
275: /* address of this host's network */
276: if(addr == in_netof(ifp->thishost))
277: return(ifp);
278: /* address on a network simulated by this node */
279: if(net == ifp->thishost)
280: return(ifp);
281: }
282: }
283: return(0);
284: }
285:
286: ip_ldout(bp, dst, ifp)
287: register struct block *bp;
288: unsigned long dst; /* host byte order */
289: register struct ipif *ifp;
290: {
291: #if NARP > 0 || NUARP > 0
292: extern struct block *arp_resolve();
293: #endif
294: register struct block *bp1;
295: struct goo{
296: unsigned int addr;
297: char unused[4];
298: } *goop;
299: register struct queue *q;
300:
301: if(ifp->queue == 0){
302: printf("ifp but no queue in ip_ldout\n");
303: bp_free(bp);
304: return(0);
305: }
306: q = WR(ifp->queue);
307: if(q->next->flag & QFULL){
308: bp_free(bp);
309: ifp->oerrors++;
310: return(1);
311: }
312: #if NARP > 0
313: if(ifp->flags & IFF_ARP){
314: bp = arp_resolve(ifp->arp, bp, &dst);
315: if(bp == 0)
316: return(1);
317: }
318: #endif
319: #if NUARP > 0
320: if(ifp->flags & IFF_ARP){
321: bp = arp_resolve(ifp->queue, bp, dst);
322: if(bp == 0)
323: return(1);
324: }
325: #endif
326: while(bp){
327: if(bp->rptr < bp->base || bp->rptr >= bp->lim
328: || bp->wptr < bp->base || bp->wptr > bp->lim){
329: printf("ip_ldout: bad block 0x%x\n", bp);
330: panic("ip_ldout");
331: }
332: bp1 = bp->next;
333: (*q->next->qinfo->putp)(q->next, bp);
334: bp = bp1;
335: }
336: bp1 = allocb(0);
337: if(bp1){
338: bp1->type = M_DELIM;
339: (*q->next->qinfo->putp)(q->next, bp1);
340: ifp->opackets++;
341: } else {
342: printf("ip_ldout: no allocb for delim\n");
343: ifp->oerrors++;
344: }
345: return(0);
346: }
347: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.