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