|
|
1.1 root 1: /*
2: * udp device driver.
3: */
4:
5: #include "udp.h"
6: #if NUDP
7: #include "../h/param.h"
8: #include "../h/systm.h"
9: #include "../h/stream.h"
10: #include "../h/ioctl.h"
11: #include "../h/ttyld.h"
12: #include "../h/buf.h"
13: #include "../h/conf.h"
14: #include "../h/inet/in.h"
15: #include "../h/inet/ip.h"
16: #include "../h/inet/ip_var.h"
17: #include "../h/inet/udp.h"
18: #include "../h/inet/udp_var.h"
19: #include "../h/inet/udp_user.h"
20:
21: int nodev(), udpdopen(), udpdclose(), udpdput();
22: int udpdosrv();
23: static struct qinit udpdrinit = { nodev, NULL, udpdopen, udpdclose, 0, 0 };
24: static struct qinit udpdwinit = { udpdput, udpdosrv, udpdopen, udpdclose,
25: UDP_BODY_LIMIT, 64 };
26: struct streamtab udpdinfo = { &udpdrinit, &udpdwinit };
27:
28: int Nudp = NUDP; /* for netstat */
29: struct udp udpconn[NUDP];
30:
31: in_addr udpbaddst;
32:
33: udpdopen(q, dev)
34: register struct queue *q;
35: dev_t dev;
36: {
37: struct udp *udp;
38:
39: dev = minor(dev);
40: if(dev >= NUDP)
41: return(0);
42: udp = &udpconn[dev];
43: if(q->ptr)
44: return(0);
45: udp->rq = q;
46: udp->flags = UDP_INIT;
47: udp->head = udp->tail = 0;
48: q->ptr = (caddr_t)udp;
49: q->flag |= QDELIM;
50: WR(q)->flag |= QBIGB;
51: WR(q)->ptr = (caddr_t)udp;
52: return(1);
53: }
54:
55: udpdclose(q)
56: register struct queue *q;
57: {
58: struct udp *udp;
59:
60: udp = (struct udp *)q->ptr;
61: udp->rq = (struct queue *)0;
62: q->ptr = (caddr_t)0;
63: }
64:
65: udpdput(q, bp)
66: register struct queue *q;
67: register struct block *bp;
68: {
69: struct udp *udp;
70: int s, x;
71: register union stmsg *sp;
72: struct foo{
73: u_long dst;
74: u_long gate;
75: } *foo;
76:
77: udp = (struct udp *)q->ptr;
78: switch(bp->type){
79: case M_IOCTL:
80: bp->type = M_IOCNAK;
81: bp->wptr = bp->rptr;
82: qreply(q, bp);
83: return;
84: case M_DATA:
85: putq(q, bp);
86: break;
87: case M_DELIM:
88: putq(q, bp);
89: qenable(q);
90: break;
91: default:
92: freeb(bp);
93: break;
94: }
95: }
96:
97: udpdosrv(q)
98: register struct queue *q;
99: {
100: register struct block *bp;
101: register struct udp *udp;
102:
103: udp = (struct udp *)q->ptr;
104: while(bp = getq(q)){
105: bp->next = 0;
106: if(bp->type != M_DATA) {
107: freeb(bp);
108: if (udp->flags & UDP_INIT)
109: udpduser(udp->head, udp);
110: else {
111: if ((udp->flags & UDP_CONNECTED) == 0) {
112: /* get user-supplied destination */
113: if(udpdaddr(udp)) {
114: bp_free(udp->head);
115: udp->head = udp->tail = NULL;
116: return;
117: }
118: } else if (udp->head == NULL) {
119: /* zero length message */
120: udp->head = allocb(0);
121: }
122: udp_output(udp->head, udp);
123: }
124: udp->head = udp->tail = NULL;
125: } else if(udp->head == 0){
126: udp->head = udp->tail = bp;
127: } else {
128: udp->tail->next = bp;
129: udp->tail = bp;
130: }
131: }
132: }
133:
134: /* extract address from a message */
135: udpdaddr(udp)
136: register struct udp *udp;
137: {
138: struct udpaddr *uap;
139:
140: /* get destination */
141: if((udp->head = bp_pullup(udp->head, sizeof(struct udpaddr))) == NULL)
142: return(1);
143: uap = (struct udpaddr *)udp->head->rptr;
144: udp->dst = uap->host;
145: udp->dport = uap->port;
146: udp->head->rptr += sizeof(struct udpaddr);
147:
148: /* host address for datagrams depends on route */
149: if ((udp->flags & UDP_CONNECTED) == 0) {
150: udp->src = ip_hoston(udp->dst);
151: if(udp->src == 0) {
152: udpbaddst = udp->dst;
153: return(1);
154: }
155: }
156: return(0);
157: }
158:
159: udpdrint(bp, ui)
160: register struct block *bp;
161: struct udpiphdr *ui;
162: {
163: register struct block *bp1;
164: register struct queue *q;
165: register struct udp *udp;
166: register struct udpaddr *uap;
167: int ps = spl6();
168:
169: /* find the udp port */
170: for (udp = udpconn; udp < &udpconn[NUDP]; ++udp) {
171: if (udp->rq == 0)
172: continue;
173: if (udp->sport != ui->ui_dport)
174: continue;
175: if (udp->flags & UDP_LISTEN)
176: break;
177: if ((udp->flags & UDP_CONNECTED) == 0)
178: break;
179: if (udp->dport == ui->ui_sport && udp->dst == ui->ui_src)
180: break;
181: }
182:
183: if (udp == &udpconn[NUDP]) {
184: bp_free(bp);
185: splx(ps);
186: return;
187: }
188: if (udp->flags & UDP_LISTEN) {
189: udp->dport = ui->ui_sport;
190: udp->dst = ui->ui_src;
191: if (udp->src == 0) {
192: /* use host name connecting end called us */
193: udp->src = ui->ui_dst;
194: }
195: udp->flags |= UDP_CONNECTED;
196: udp->flags &= ~UDP_LISTEN;
197: udpreply(udp);
198: }
199: splx(ps);
200:
201: if((q = udp->rq) == NULL) {
202: printf("udpdrint but no read queue\n");
203: bp_free(bp);
204: return;
205: }
206: if(q->next->flag & QFULL) {
207: bp_free(bp);
208: return;
209: }
210: if ((udp->flags & UDP_CONNECTED) == 0) {
211: /* if not acting as a connected protocol, pass user source addr */
212: bp1 = allocb(sizeof(struct udpaddr));
213: if (bp1 == NULL) {
214: printf("udprint: out of blocks\n");
215: bp_free(bp);
216: return;
217: }
218: bp1->wptr += sizeof(struct udpaddr);
219: uap = (struct udpaddr *)bp1->rptr;
220: uap->host = ui->ui_src;
221: uap->port = ui->ui_sport;
222: putq(q->next, bp1);
223: }
224: while(bp){
225: bp1 = bp->next;
226: putq(q->next, bp);
227: bp = bp1;
228: }
229: putctl(q->next, M_DELIM);
230: }
231:
232: /*
233: * imitation udp_usrreq
234: */
235: udpduser(bp, udp)
236: register struct block *bp;
237: register struct udp *udp;
238: {
239: struct udpuser *uu;
240:
241: if ((bp = bp_pullup(bp, sizeof(struct udpuser))) == 0) {
242: printf("udpuser short\n");
243: bp_free(bp);
244: return;
245: }
246: uu = (struct udpuser *)bp->rptr;
247: switch(uu->cmd){
248: case UDPC_DATAGRAM:
249: if (udpbind(udp, uu->sport))
250: goto bad;
251: udp->flags &= ~UDP_INIT;
252: udpreply(udp);
253: break;
254: case UDPC_CONNECT:
255: if (udpbind(udp, uu->sport))
256: goto bad;
257: udp->dport = uu->dport;
258: udp->dst = uu->dst;
259: udp->flags |= UDP_CONNECTED;
260: udp->flags &= ~UDP_INIT;
261: udpreply(udp);
262: /* pick a local address related to the destination */
263: udp->src = ip_hoston(udp->dst);
264: if(udp->src == 0)
265: goto bad;
266: break;
267: case UDPC_LISTEN:
268: if (udpbind(udp, uu->sport))
269: goto bad;
270: udp->flags |= UDP_LISTEN;
271: udp->flags &= ~UDP_INIT;
272: break;
273: default:
274: bad: putctl(udp->rq->next, M_HANGUP);
275: return;
276: }
277: bp_free(bp);
278: }
279:
280: udpreply(udp)
281: register struct udp *udp;
282: {
283: register struct queue *q;
284: struct udpreply ur;
285:
286: ur.reply = UDPR_OK;
287: ur.dport = udp->dport;
288: ur.dst = udp->dst;
289: ur.udpdev = udp - udpconn;
290:
291: q = udp->rq;
292: putcpy(q->next, &ur, sizeof(ur));
293: putctl(q->next, M_DELIM);
294: }
295:
296: udpbind(udp, port)
297: register struct udp *udp;
298: register int port;
299: {
300: register struct udp *udp2;
301: static udp_port udpport = 600;
302:
303: udp->sport = 0;
304: if(port){
305: for(udp2 = &udpconn[0]; udp2 < &udpconn[NUDP]; udp2++){
306: if(udp2->rq == 0)
307: continue;
308: if(udp2->sport == port)
309: return(1);
310: }
311: udp->sport = port;
312: return(0);
313: }
314:
315: /* pick one for him */
316: if(udpport >= 1024)
317: udpport = 600;
318: port = udpport;
319: while(1){
320: if(udpbind(udp, udpport) == 0){
321: udpport++;
322: return(0);
323: }
324: udpport++;
325: if(udpport >= 1024)
326: udpport = 600;
327: if(udpport == port) /* tried them all */
328: break;
329: }
330: return(1);
331: }
332:
333: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.