|
|
1.1 root 1: /*
2: * udp device driver.
3: */
4:
5: #include "sys/param.h"
6: #include "sys/stream.h"
7: #include "sys/conf.h"
8: #include "sys/inet/in.h"
9: #include "sys/inet/ip.h"
10: #include "sys/inet/ip_var.h"
11: #include "sys/inet/udp.h"
12: #include "sys/inet/udp_var.h"
13: #include "sys/inet/udp_user.h"
14:
15: int udpprintfs;
16: long udpdopen();
17: int udpdclose(), udpdput();
18: int udpdosrv();
19: int udpdisrv();
20: static struct qinit udpdrinit = { noput, udpdisrv, udpdopen, udpdclose, 8*1024, 64 };
21: static struct qinit udpdwinit = { udpdput, udpdosrv, udpdopen, udpdclose,
22: UDP_BODY_LIMIT, 64 };
23: struct streamtab udpdinfo = { &udpdrinit, &udpdwinit };
24:
25: struct cdevsw udpcdev = cstrinit(&udpdinfo);
26:
27: extern int udpcnt; /* for netstat */
28: extern struct udp udpconn[];
29:
30: in_addr udpbaddst;
31:
32: long
33: udpdopen(q, dev)
34: register struct queue *q;
35: dev_t dev;
36: {
37: register struct udp *udp;
38:
39: dev = minor(dev);
40: if(dev >= udpcnt)
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 = NULL;
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:
70: switch(bp->type){
71: case M_IOCTL:
72: bp->type = M_IOCNAK;
73: bp->wptr = bp->rptr;
74: qreply(q, bp);
75: return;
76: case M_DATA:
77: putq(q, bp);
78: if (bp->class&S_DELIM)
79: qenable(q);
80: return;
81: default:
82: freeb(bp);
83: return;
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: if (bp->type != M_DATA)
96: panic("udpdosrv");
97: bp->next = NULL;
98: if (udp->head == NULL)
99: udp->head = bp;
100: else
101: udp->tail->next = bp;
102: udp->tail = bp;
103: if ((bp->class & S_DELIM) == 0)
104: continue;
105: /*
106: * have entire datagram
107: */
108: bp->class &=~ S_DELIM;
109: if (udp->flags & UDP_INIT)
110: udpduser(udp->head, udp);
111: else {
112: if ((udp->flags & UDP_CONNECTED) == 0
113: && udpdaddr(udp) == 0)
114: continue; /* couldn't get an addr */
115: udp_output(udp->head, udp);
116: }
117: udp->head = udp->tail = NULL;
118: }
119: }
120:
121: /*
122: * extract address from an outbound datagram
123: * return 0 if can't find one
124: * -- if return 0, have freed bad message and cleared udp->head
125: */
126: udpdaddr(udp)
127: register struct udp *udp;
128: {
129: register struct udpaddr *uap;
130:
131: /* get destination */
132: if((udp->head = bp_pullup(udp->head, sizeof(struct udpaddr))) == NULL)
133: return(0);
134: uap = (struct udpaddr *)udp->head->rptr;
135: udp->dst = uap->host;
136: udp->dport = uap->port;
137: udp->head->rptr += sizeof(struct udpaddr);
138:
139: /* host address for datagrams depends on route */
140: if ((udp->flags & UDP_CONNECTED) == 0) {
141: udp->src = ip_hoston(udp->dst);
142: if(udp->src == 0) {
143: udpbaddst = udp->dst;
144: bp_free(udp->head);
145: udp->head = NULL;
146: return(0);
147: }
148: }
149: return(1);
150: }
151:
152: udpdisrv(q)
153: register struct queue *q;
154: {
155: register struct block *bp;
156:
157: while((q->next->flag & QFULL)==0){
158: bp = getq(q);
159: if(bp == 0)
160: break;
161: (*q->next->qinfo->putp)(q->next, bp);
162: }
163: }
164:
165: udpdrint(bp, ui)
166: register struct block *bp;
167: struct udpiphdr *ui;
168: {
169: register struct block *bp1;
170: register struct queue *q;
171: register struct udp *udp;
172: register struct udpaddr *uap;
173: register struct udp *udpend;
174: int ps = spl6();
175:
176: /* find the udp port */
177: udpend = &udpconn[udpcnt];
178: for (udp = udpconn; udp < udpend; ++udp) {
179: if (udp->rq == 0)
180: continue;
181: if (udp->sport != ui->ui_dport)
182: continue;
183: if (udp->flags & UDP_LISTEN)
184: break;
185: if ((udp->flags & UDP_CONNECTED) == 0)
186: break;
187: if (udp->dport == ui->ui_sport && udp->dst == ui->ui_src)
188: break;
189: }
190:
191: if (udp >= udpend) {
192: if(udpprintfs)
193: printf("no udpconn: %d\n", ui->ui_dport);
194: udpstat.udps_badport++;
195: bp_free(bp);
196: splx(ps);
197: return;
198: }
199: if (udp->flags & UDP_LISTEN) {
200: udp->dport = ui->ui_sport;
201: udp->dst = ui->ui_src;
202: if (udp->src == 0) {
203: /* use host name connecting end called us */
204: udp->src = ui->ui_dst;
205: }
206: udp->flags |= UDP_CONNECTED;
207: udp->flags &= ~UDP_LISTEN;
208: udpreply(udp);
209: }
210: splx(ps);
211:
212: if((q = udp->rq) == NULL) {
213: printf("udpdrint but no read queue\n");
214: bp_free(bp);
215: return;
216: }
217: if(q->flag & QFULL) {
218: if(udpprintfs)
219: printf("udpq: %x.%d %x.%d\n", ui->ui_src, ui->ui_sport,
220: ui->ui_dst, ui->ui_dport);
221: udpstat.udps_inqfull++;
222: bp_free(bp);
223: return;
224: }
225: if ((udp->flags & UDP_CONNECTED) == 0) {
226: /* if not acting as a connected protocol, pass user source addr */
227: bp1 = allocb(sizeof(struct udpaddr));
228: if (bp1 == NULL) {
229: printf("udpdrint: out of blocks\n");
230: bp_free(bp);
231: return;
232: }
233: bp1->wptr += sizeof(struct udpaddr);
234: uap = (struct udpaddr *)bp1->rptr;
235: uap->host = ui->ui_src;
236: uap->port = ui->ui_sport;
237: putq(q, bp1);
238: }
239: while(bp){
240: bp1 = bp->next;
241: if (bp1==NULL)
242: bp->class |= S_DELIM;
243: putq(q, bp);
244: bp = bp1;
245: }
246: qenable(q);
247: }
248:
249: /*
250: * first write on this device:
251: * data is a command from the user
252: */
253: udpduser(bp, udp)
254: register struct block *bp;
255: register struct udp *udp;
256: {
257: register struct udpuser *uu;
258:
259: if ((bp = bp_pullup(bp, sizeof(struct udpuser))) == 0) {
260: printf("udpuser short\n");
261: bp_free(bp);
262: return;
263: }
264: uu = (struct udpuser *)bp->rptr;
265: switch(uu->cmd){
266: case UDPC_DATAGRAM:
267: if (udpbind(udp, uu->sport))
268: goto bad;
269: udp->flags &= ~UDP_INIT;
270: udpreply(udp);
271: break;
272: case UDPC_CONNECT:
273: if (udpbind(udp, uu->sport))
274: goto bad;
275: udp->dport = uu->dport;
276: udp->dst = uu->dst;
277: udp->flags |= UDP_CONNECTED;
278: udp->flags &= ~UDP_INIT;
279: udpreply(udp);
280: /* pick a local address related to the destination */
281: udp->src = ip_hoston(udp->dst);
282: if(udp->src == 0)
283: goto bad;
284: break;
285: case UDPC_LISTEN:
286: if (udpbind(udp, uu->sport))
287: goto bad;
288: udp->flags |= UDP_LISTEN;
289: udp->flags &= ~UDP_INIT;
290: break;
291: default:
292: bad: putctl(udp->rq->next, M_HANGUP);
293: return;
294: }
295: bp_free(bp);
296: }
297:
298: udpreply(udp)
299: register struct udp *udp;
300: {
301: register struct queue *q;
302: struct udpreply ur;
303:
304: ur.reply = UDPR_OK;
305: ur.dport = udp->dport;
306: ur.dst = udp->dst;
307: ur.udpdev = udp - udpconn;
308:
309: q = udp->rq;
310: putcpy(q->next, &ur, sizeof(ur));
311: putctld(q->next, M_DATA);
312: }
313:
314: udpbind(udp, port)
315: register struct udp *udp;
316: register int port;
317: {
318: register struct udp *udp2;
319: static udp_port udpport = 600;
320:
321: udp->sport = 0;
322: if(port){
323: for(udp2 = &udpconn[0]; udp2 < &udpconn[udpcnt]; udp2++){
324: if(udp2->rq == 0)
325: continue;
326: if(udp2->sport == port)
327: return(1);
328: }
329: udp->sport = port;
330: return(0);
331: }
332:
333: /* pick one for him */
334: if(udpport >= 1024)
335: udpport = 600;
336: port = udpport;
337: while(1){
338: if(udpbind(udp, udpport) == 0){
339: udpport++;
340: return(0);
341: }
342: udpport++;
343: if(udpport >= 1024)
344: udpport = 600;
345: if(udpport == port) /* tried them all */
346: break;
347: }
348: return(1);
349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.