|
|
1.1 root 1: /*
2: * tcp_device.c
3: */
4:
5: #include "sys/param.h"
6: #include "sys/stream.h"
7: #include "sys/inio.h"
8: #include "sys/ttyio.h"
9: #include "sys/conf.h"
10: #include "sys/user.h"
11: #include "sys/inet/in.h"
12: #include "sys/inet/ip_var.h"
13: #include "sys/inet/tcp.h"
14: #include "sys/inet/tcp_timer.h"
15: #include "sys/inet/tcp_seq.h"
16: #include "sys/inet/tcp_var.h"
17: #include "sys/inet/tcpip.h"
18: #include "sys/inet/tcp_user.h"
19: #include "sys/inet/tcp_fsm.h"
20:
21: extern int tcp_busy; /* set to discourage timers & ensuing panics */
22: extern int tcp_maxseg;
23:
24: long tcpdopen();
25: int tcpdclose(), tcpdput();
26: int tcpdosrv(), tcpdisrv();
27: static struct qinit tcpdrinit = { noput, tcpdisrv, tcpdopen, tcpdclose, 2048, 64 };
28: struct qinit tcpdwinit = { tcpdput, tcpdosrv, tcpdopen, tcpdclose, 2048, 64};
29: struct streamtab tcpdinfo = { &tcpdrinit, &tcpdwinit };
30:
31: struct cdevsw tcpcdev = cstrinit(&tcpdinfo);
32:
33: extern int tcpcnt;
34: extern struct tcpcb tcpcb[];
35:
36: long
37: tcpdopen(q, dev)
38: register struct queue *q;
39: dev_t dev;
40: {
41: struct tcpcb *tp;
42:
43: dev = minor(dev);
44: if(dev >= tcpcnt)
45: return(0);
46: tp = &tcpcb[dev];
47: if(dev&01){
48: /* outgoing channel */
49: /*
50: * disallow if active
51: */
52: if(tp->t_state != TCPS_CLOSED)
53: return(0);
54: /*
55: * only one opener at a time for outgoing channels
56: */
57: if(q->ptr)
58: return(0);
59: } else {
60: /* incoming channel */
61: /*
62: * disallow if inactive
63: */
64: if(tp->t_state == TCPS_CLOSED) {
65: printf("tcp%d closed\n", dev);
66: return(0);
67: }
68: /*
69: * disallow if it's not open or waiting to be opened
70: */
71: if((tp->so_state&(SS_OPEN|SS_PLEASEOPEN))==0) {
72: printf("tcp%d state %x\n", dev, tp->so_state);
73: return(0);
74: }
75: /*
76: * if already open, just accept
77: */
78: if(q->ptr)
79: return(1);
80: }
81: tcp_busy++;
82: if((tp->so_state & SS_PLEASEOPEN) == 0){
83: tp->so_rcount = tp->so_wcount = tp->so_options = 0;
84: tp->so_laddr = tp->so_faddr = (in_addr)0;
85: tp->so_lport = tp->so_fport = (tcp_port)0;
86: tp->so_oobmark = tp->so_delimcnt = 0;
87: tp->so_head = (struct tcpcb *)0;
88: tp->so_state = SS_WAITING;
89: tp->t_maxseg = TCP_DEFMAXSEG; /* until changed by other end */
90: }
91: tp->so_state |= SS_OPEN;
92: tp->so_dev = dev;
93: tp->so_rq = q;
94: tp->so_wq = WR(q);
95: q->ptr = (caddr_t)tp;
96: WR(q)->flag |= QBIGB;
97: WR(q)->ptr = (caddr_t)tp;
98: --tcp_busy;
99: if(tp->so_state & SS_PLEASEOPEN){
100: tp->so_state &= ~SS_PLEASEOPEN;
101: qenable(WR(q)); /* to force out rcv wnd update */
102: }
103: return(1);
104: }
105:
106: tcpdclose(q)
107: register struct queue *q;
108: {
109: struct tcpcb *tp;
110:
111: tp = (struct tcpcb *)q->ptr;
112: tcp_busy++;
113: if(tp == 0){
114: --tcp_busy;
115: return;
116: }
117: tp->so_state &= ~(SS_OPEN|SS_WAITING);
118: tp->so_rq = tp->so_wq = (struct queue *) 0;
119: tp->so_wcount = tp->so_rcount = 0;
120: if(tp->t_state > TCPS_LISTEN)
121: tcp_disconnect(tp);
122: else
123: tcp_close(tp);
124: --tcp_busy;
125: }
126:
127: tcpdput(q, bp)
128: register struct queue *q;
129: register struct block *bp;
130: {
131: int s, x;
132: struct tcpcb *tp;
133: struct block *nbp;
134: struct foo {
135: int com;
136: struct tcpuser rep;
137: };
138: struct foo *fp;
139:
140: tp = (struct tcpcb *)q->ptr;
141: switch(bp->type){
142: case M_IOCTL:
143: bp->type = M_IOCACK;
144: switch(stiocom(bp)){
145: case TIOCSETP:
146: case TIOCSETN:
147: x = ((struct ttydevb *)stiodata(bp))->ispeed;
148: bp->wptr = bp->rptr;
149: bp->type = M_IOCACK;
150: qreply(q, bp);
151: if(x == 0)
152: qpctl(OTHERQ(q), M_HANGUP);
153: return;
154: case TIOCGETP:
155: ((struct ttydevb *)stiodata(bp))->ispeed =
156: ((struct ttydevb *)stiodata(bp))->ospeed = B9600;
157: break;
158: case TCPGETADDR:
159: nbp = allocb(sizeof(struct foo));
160: if (nbp == NULL) {
161: bp->type = M_IOCNAK;
162: break;
163: }
164: nbp->type = M_IOCACK;
165: fp = (struct foo *)nbp->rptr;
166: fp->com = stiocom(bp);
167: fp->rep.lport = tp->so_lport;
168: fp->rep.fport = tp->so_fport;
169: fp->rep.laddr = tp->so_laddr;
170: fp->rep.faddr = tp->so_faddr;
171: nbp->wptr = nbp->rptr + sizeof(struct foo);
172: freeb(bp);
173: bp = nbp;
174: break;
175: case TCPIOHUP:
176: tp->so_state |= SS_HANGUP;
177: bp->wptr = bp->rptr;
178: bp->type = M_IOCACK;
179: qreply(q, bp);
180: return;
181: default:
182: bp->type = M_IOCNAK;
183: }
184: qreply(q, bp);
185: return;
186: case M_DATA:
187: if(socantsendmore(tp)){
188: freeb(bp);
189: return;
190: }
191: s = spl6();
192: if (bp->wptr!=bp->rptr)
193: tp->so_delimcnt = 0;
194: if (bp->class&S_DELIM)
195: tp->so_delimcnt++; /* 2 delims are logical EOF */
196: if (bp->wptr==bp->rptr){
197: freeb(bp);
198: } else {
199: tp->so_wcount += BLEN(bp); /* BEFORE the putq */
200: putq(q, bp);
201: }
202: splx(s);
203: if(tp->so_delimcnt
204: || (tp->so_options&(SO_ACCEPTCONN|SS_WAITING)) == 0)
205: qenable(q);
206: break;
207: default:
208: freeb(bp);
209: break;
210: }
211: }
212:
213: tcpdosrv(q)
214: struct queue *q;
215: {
216: register struct tcpcb *tp;
217:
218: if((tp = (struct tcpcb *)q->ptr) == 0)
219: return;
220: if (tp->so_state&SS_WCLOSED)
221: return;
222: tcp_busy++;
223: if(tp->so_delimcnt > 1){
224: tp->so_state |= SS_WCLOSED;
225: tp = tcp_usrclosed(tp);
226: if(tp)
227: tcp_output(tp);
228: } else if ((tp->so_options & SO_ACCEPTCONN) == 0
229: && (tp->so_state & SS_WAITING) == 0)
230: tcp_output(tp);
231: else
232: tcpduser(tp);
233: --tcp_busy;
234: }
235:
236: tcpdrint(bp, tp)
237: register struct block *bp;
238: register struct tcpcb *tp;
239: {
240: register struct block *bp1;
241:
242: if (tp->so_rq == NULL) {
243: printf("tcpdrint but no tp->so_rq\n");
244: bp_free(bp);
245: return -1;
246: }
247: while(bp){
248: bp1 = bp->next;
249: tp->so_rcount += bp->wptr - bp->rptr;
250: if(bp->wptr <= bp->rptr)
251: freeb(bp);
252: else
253: putq(tp->so_rq, bp);
254: bp = bp1;
255: }
256: return 0;
257: }
258:
259: tcpdisrv(q)
260: register struct queue *q;
261: {
262: register struct tcpcb *tp = (struct tcpcb *)(q->ptr);
263: register struct block *bp;
264:
265: while ((q->next->flag&QFULL) == 0 && (bp = getq(q)) != NULL) {
266: if(bp->type == M_DATA)
267: tp->so_rcount -= bp->wptr - bp->rptr;
268: if(tp->so_rcount < 0){
269: printf("so_rcount %d\n", tp->so_rcount);
270: if(tp->so_state & SS_OPEN)
271: panic("so_rcount");
272: }
273: (*q->next->qinfo->putp)(q->next, bp);
274: }
275: if(q->count <= q->qinfo->lolimit)
276: qenable(OTHERQ(q)); /* update remote send window */
277: }
278:
279: /*
280: * here if channel isn't connected yet:
281: * output `data' is a user command
282: * grab all the data written so far,
283: * even though we'll discard the part we don't use
284: */
285: tcpduser(tp)
286: register struct tcpcb *tp;
287: {
288: extern struct ipif *ip_ifwithaddr();
289: struct tcpuser *tu;
290: struct block *bp, *tail, *head;
291:
292: tail = head = NULL;
293: while(bp = getq(tp->so_wq)){
294: if(bp->type != M_DATA){
295: freeb(bp);
296: continue;
297: }
298: bp->next = NULL;
299: if (head == NULL)
300: head = bp;
301: else
302: tail->next = bp;
303: tail = bp;
304: }
305: if(head == NULL)
306: return;
307: tp->so_wcount = 0;
308: bp = head;
309: if(BLEN(bp) < sizeof(struct tcpuser)){
310: bp_free(bp);
311: return;
312: }
313:
314: /*
315: * tu->code is a request to bind this channel
316: */
317: tu = (struct tcpuser *)bp->rptr;
318: switch(tu->code){
319: case TCPC_CONNECT:
320: if(tp->t_state != TCPS_CLOSED){
321: tu->code = TCPC_BADDEV;
322: goto bad;
323: }
324: if (tu->laddr != INADDR_ANY) {
325: /* has the user specified a legal local address? */
326: if (ip_ifwithaddr(tu->laddr) == 0) {
327: tu->code = TCPC_BADLOCAL;
328: goto bad;
329: }
330: } else {
331: /* pick a local address related to the destination */
332: tu->laddr = ip_hoston(tu->faddr);
333: if(tu->laddr == INADDR_ANY) {
334: tu->code = TCPC_NOROUTE;
335: goto bad;
336: }
337: }
338: tp->so_options = tu->param & ~SO_ACCEPTCONN;
339: if(tcpcb_bind(tp, tu->laddr, tu->lport)) {
340: tu->code = TCPC_BOUND;
341: goto bad;
342: }
343: tp->so_fport = tu->fport;
344: tp->so_faddr = tu->faddr;
345: tcp_template(tp);
346: if(tp->t_template == (struct block *)0) {
347: printf("no template - ");
348: tu->code = TCPC_BADDEV;
349: goto bad;
350: }
351: if (tp->so_options & SO_KEEPALIVE)
352: tcp_timers(tp, TCPT_KEEP);
353: tp->t_state = TCPS_SYN_SENT;
354: tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
355: tcp_sendseqinit(tp);
356: tp->so_state &= ~SS_WAITING;
357: tcp_output(tp);
358: break;
359: case TCPC_LISTEN:
360: if(tp->t_state != TCPS_CLOSED){
361: tu->code = TCPC_BADDEV;
362: goto bad;
363: }
364: if (tu->laddr != INADDR_ANY) {
365: /* has the user specified a legal local address? */
366: if (ip_ifwithaddr(tu->laddr) == 0) {
367: tu->code = TCPC_BADLOCAL;
368: goto bad;
369: }
370: }
371: tp->so_options = tu->param & ~SO_ACCEPTCONN;
372: if(tcpcb_bind(tp, tu->laddr, tu->lport)) {
373: tu->code = TCPC_BOUND;
374: goto bad;
375: }
376: tp->t_state = TCPS_LISTEN;
377: tp->so_options |= SO_ACCEPTCONN;
378: tp->so_fport = tu->fport==0 ? TCPPORT_ANY : tu->fport;
379: tp->so_faddr = tu->faddr;
380: tcp_template(tp);
381: if(tp->t_template == 0) {
382: tu->code = TCPC_BADDEV;
383: printf("no template - ");
384: goto bad;
385: }
386: tp->so_state &= ~SS_WAITING;
387: if (tcp_isconnected(tp)<0) {
388: tu->code = TCPC_BADDEV;
389: goto bad;
390: }
391: break;
392: default:
393: tu->code = TCPC_SORRY;
394: goto bad;
395: }
396: bp_free(bp);
397: return;
398: bad:
399: /*
400: * send reason for failure back to user.
401: */
402: if(bp->next) {
403: bp_free(bp->next);
404: bp->next = 0;
405: }
406: (*tp->so_rq->next->qinfo->putp)(tp->so_rq->next, bp);
407: tcp_hungup(tp);
408: }
409:
410: struct tcpcb *
411: tcp_disconnect(tp)
412: register struct tcpcb *tp;
413: {
414:
415: if(tp->t_state < TCPS_ESTABLISHED)
416: tp = tcp_close(tp);
417: else {
418: tp->so_state &= ~SS_PLEASEOPEN;
419: tcp_hungup(tp); /* sends M_HANGUP */
420: tp = tcp_usrclosed(tp);
421: if(tp)
422: tcp_output(tp);
423: }
424: return(tp);
425: }
426:
427: struct tcpcb *
428: tcp_usrclosed(tp)
429: register struct tcpcb *tp;
430: {
431:
432: switch(tp->t_state){
433:
434: case TCPS_CLOSED:
435: case TCPS_LISTEN:
436: case TCPS_SYN_SENT:
437: tp->t_state = TCPS_CLOSED;
438: tp = tcp_close(tp);
439: break;
440:
441: case TCPS_SYN_RECEIVED:
442: case TCPS_ESTABLISHED:
443: tp->t_state = TCPS_FIN_WAIT_1;
444: tp->so_options |= SO_KEEPALIVE;
445: tcp_timers(tp, TCPT_KEEP);
446: break;
447:
448: case TCPS_CLOSE_WAIT:
449: tp->t_state = TCPS_LAST_ACK;
450: tp->so_options |= SO_KEEPALIVE;
451: tcp_timers(tp, TCPT_KEEP);
452: break;
453: }
454: if(tp && tp->t_state >= TCPS_FIN_WAIT_2) {
455: tp->so_state &= ~(SS_PLEASEOPEN|SS_RCVATMARK);
456: if(tp->so_state&SS_OPEN && !(tp->so_state&SS_HUNGUP)) {
457: tp->so_state |= SS_HUNGUP;
458: tcp_hungup(tp);
459: }
460: }
461: return(tp);
462: }
463:
464: tcp_isconnected(tp)
465: struct tcpcb *tp;
466: {
467: struct block *bp;
468: struct tcpuser *tu;
469: struct tcpcb *rtp;
470:
471: if(tp->so_head)
472: rtp = tp->so_head;
473: else
474: rtp = tp;
475: if((rtp->so_state & SS_OPEN) == 0){
476: printf("isconnected, no fd ref\n");
477: return -1;
478: }
479: bp = allocb(sizeof(struct tcpuser));
480: if(bp == 0)
481: return -1;
482: bp->wptr += sizeof(struct tcpuser);
483: tu = (struct tcpuser *)bp->rptr;
484: tu->code = TCPC_OK;
485: tu->fport = tp->so_fport;
486: tu->faddr = tp->so_faddr;
487: tu->lport = tp->so_lport;
488: tu->laddr = tp->so_laddr;
489: tu->param = tp->so_dev;
490: bp->class |= S_DELIM;
491: return tcpdrint(bp, rtp);
492: }
493:
494: tcp_hungup(tp)
495: register struct tcpcb *tp;
496: {
497: register struct queue *q;
498:
499: q = tp->so_rq;
500: if(q == 0)
501: return;
502: qpctl(q, M_HANGUP);
503: }
504:
505: /*
506: * find a spare even-numbered tcp device for a new passive-end
507: * connection.
508: */
509: struct tcpcb *
510: tcp_newconn(tp)
511: register struct tcpcb *tp;
512: {
513: register struct tcpcb *ntp;
514: register struct tcpcb *tend;
515:
516: if(tp->so_rq && (tp->so_rq->flag&QFULL)){
517: printf("listen %d q full\n", tp->so_lport);
518: return(0);
519: }
520: tend = &tcpcb[tcpcnt];
521: for(ntp = &tcpcb[0]; ntp < tend; ntp += 2){
522: if(ntp->t_state == TCPS_CLOSED){
523: bzero(ntp, sizeof(struct tcpcb));
524: ntp->t_maxseg = TCP_DEFMAXSEG;
525: ntp->so_options = tp->so_options & SO_KEEPALIVE;
526: ntp->so_head = tp;
527: ntp->so_dev = ntp - tcpcb;
528: return(ntp);
529: }
530: }
531: return(0);
532: }
533:
534: struct tcpcb *
535: tcpcb_lookup(faddr, fport, laddr, lport)
536: register in_addr faddr, laddr;
537: register tcp_port fport, lport;
538: {
539: register struct tcpcb *tp;
540: int highscore = 0, score;
541: struct tcpcb *match = 0;
542: struct tcpcb *tend;
543:
544: tend = &tcpcb[tcpcnt];
545: for(tp = &tcpcb[0]; tp < tend; tp++){
546: if(tp->t_state == TCPS_CLOSED)
547: continue;
548: score = 22;
549: if(tp->so_faddr != faddr) {
550: if(tp->so_faddr != INADDR_ANY)
551: continue;
552: else
553: score -=8;
554: }
555: if(tp->so_fport != fport) {
556: if(tp->so_fport != TCPPORT_ANY)
557: continue;
558: else
559: score -=8;
560: }
561: if(tp->so_laddr != laddr) {
562: if(tp->so_laddr == in_netof(laddr))
563: score -=1;
564: else if(tp->so_laddr != INADDR_ANY)
565: continue;
566: else
567: score -=2;
568: }
569: if(tp->so_lport != lport) {
570: if(tp->so_lport != TCPPORT_ANY)
571: continue;
572: else
573: score -=4;
574: }
575: if (score==22)
576: return tp;
577: if (score<highscore)
578: continue;
579: match = tp;
580: highscore = score;
581: }
582: return(match);
583: }
584:
585: /* n chars were acked; drop them now */
586: sbsnddrop(tp, n)
587: register struct tcpcb *tp;
588: register int n;
589: {
590: register struct queue *q;
591: register int i;
592: register struct block *bp;
593:
594: q = tp->so_wq;
595: if(q == 0)
596: return;
597: bp = 0;
598: while(n > 0 && (bp = getq(q))){
599: i = MIN(BLEN(bp), n);
600: bp->rptr += i;
601: n -= i;
602: tp->so_wcount -= i;
603: if(bp->rptr >= bp->wptr){
604: freeb(bp);
605: bp = 0;
606: } else if(n > 0){
607: panic("sbsnddrop");
608: }
609: }
610: if(bp)
611: putbq(q, bp);
612: }
613:
614: static tcp_port portnext[] = { 600, 1024 };
615: static tcp_port portlow[] = { 600, 1024 };
616: static tcp_port porthigh[] = { 1024, 2048 };
617:
618: tcpcb_bind(tp, addr, port)
619: register struct tcpcb *tp;
620: register in_addr addr;
621: register tcp_port port;
622: {
623: register int i;
624:
625: tp->so_lport = 0;
626: if(port){
627: /*
628: * Don't let just anyone get a trusted port.
629: */
630: if(port<porthigh[0] && u.u_uid!=0)
631: return(1);
632: tp->so_lport = port;
633: tp->so_laddr = addr;
634: return(0);
635: }
636: /*
637: * No specific port, pick one. Root only gets a trusted
638: * port if explicitly requested, so privileged programs
639: * can make non-privileged calls.
640: */
641: i = (u.u_uid==0 && (tp->so_options&SO_TRUSTED)) ? 0 : 1;
642: if(portnext[i] >= porthigh[i])
643: portnext[i] = portlow[i];
644: port = portnext[i];
645: while(1){
646: if(tcpcb_bind(tp, addr, portnext[i]) == 0){
647: portnext[i]++;
648: return(0);
649: }
650: portnext[i]++;
651: if(portnext[i] >= porthigh[i])
652: portnext[i] = portlow[i];
653: if(portnext[i] == port) /* tried them all */
654: break;
655: }
656: return(1);
657: }
658:
659: tcp_cantrcvmore(tp)
660: register struct tcpcb *tp;
661: {
662: register struct queue *q;
663:
664: q = tp->so_rq;
665: if(q == NULL)
666: return;
667: if(tp->so_state & SS_HANGUP)
668: qpctl(q, M_HANGUP);
669: else {
670: /* two delims ensure a zero length read at the process */
671: qpctld(q, M_DATA);
672: qpctld(q, M_DATA);
673: }
674: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.