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