|
|
1.1 root 1: /*
2: * tcp_device.c
3: */
4:
5: #include "tcp.h"
6: #if NTCP
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/mbuf.h"
16: #include "../h/inet/tcp.h"
17: #include "../h/inet/tcp_timer.h"
18: #include "../h/inet/tcp_seq.h"
19: #include "../h/inet/tcp_var.h"
20: #include "../h/inet/tcp_user.h"
21: #include "../h/inet/tcp_fsm.h"
22: #include "../h/inet/socket.h"
23:
24: extern int tcp_busy; /* set to discourage timers & ensuing panics */
25:
26: int nodev(), tcpdopen(), tcpdclose(), tcpdput();
27: int tcpdosrv(), tcpdisrv();
28: static struct qinit tcpdrinit = { nodev, tcpdisrv, tcpdopen, tcpdclose, 2048, 64 };
29: /* was 1024, 64 originally */
30: struct qinit tcpdwinit = { tcpdput, tcpdosrv, tcpdopen, tcpdclose, 512, 64 };
31: /* was 256, 64 originally */
32: struct streamtab tcpdinfo = { &tcpdrinit, &tcpdwinit };
33:
34: int Ntcp = NTCP; /* for netstat */
35: struct tcpcb tcpcb[NTCP];
36: struct socket tcpsocks[NTCP];
37:
38: tcpdopen(q, dev)
39: register struct queue *q;
40: dev_t dev;
41: {
42: struct socket *so;
43:
44: dev = minor(dev);
45: if(dev >= NTCP)
46: return(0);
47: so = &tcpsocks[dev];
48: if((dev&01) == 0 && (so->so_state&SS_ACTIVE) == 0)
49: return(0);
50: if(so->so_state&SS_WAITING)
51: return(0);
52: if((so->so_options&SO_ACCEPTCONN) && (so->so_state&SS_OPEN))
53: return(0);
54: if((so->so_state & (SS_ACTIVE|SS_OPEN|SS_PLEASEOPEN)) == SS_ACTIVE)
55: return(0);
56: if(q->ptr && dev&01) /* re-opening outgoing port */
57: return(0);
58: if(q->ptr)
59: return(1);
60: tcp_busy++;
61: if((so->so_state & SS_PLEASEOPEN) == 0){
62: bzero(so, sizeof(struct socket));
63: so->so_state |= SS_WAITING;
64: }
65: so->so_state |= SS_OPEN;
66: so->so_dev = dev;
67: so->so_rq = q;
68: so->so_wq = WR(q);
69: q->ptr = (caddr_t)so;
70: WR(q)->flag |= QNOENB|QBIGB;
71: WR(q)->ptr = (caddr_t)so;
72: --tcp_busy;
73: if(so->so_state & SS_PLEASEOPEN){
74: so->so_state &= ~SS_PLEASEOPEN;
75: qenable(WR(q)); /* to force out rcv wnd update */
76: }
77: return(1);
78: }
79:
80: tcpdclose(q)
81: register struct queue *q;
82: {
83: struct socket *so;
84: struct tcpcb *tp;
85:
86: so = (struct socket *)q->ptr;
87: tcp_busy++;
88: so->so_state &= ~(SS_OPEN|SS_WAITING);
89: so->so_rq = so->so_wq = (struct queue *) 0;
90: so->so_wcount = so->so_rcount = 0;
91: tp = so->so_tcpcb;
92: if(tp == 0){
93: --tcp_busy;
94: return;
95: }
96: if(tp->t_state > TCPS_LISTEN)
97: tcp_disconnect(tp);
98: else
99: tcp_close(tp);
100: --tcp_busy;
101: }
102:
103: tcpdput(q, bp)
104: register struct queue *q;
105: register struct block *bp;
106: {
107: struct socket *so;
108: int s, x;
109: register union stmsg *sp;
110: struct tcpcb *tp;
111:
112: so = (struct socket *)q->ptr;
113: switch(bp->type){
114: case M_IOCTL:
115: sp = (union stmsg *)bp->rptr;
116: bp->type = M_IOCACK;
117: switch(sp->ioc0.com){
118: case TIOCSETP:
119: case TIOCSETN:
120: x = sp->ioc1.sb.sg_ispeed;
121: bp->wptr = bp->rptr;
122: bp->type = M_IOCACK;
123: qreply(q, bp);
124: if(x == 0)
125: tcp_putctl(OTHERQ(q), M_HANGUP);
126: return;
127: case TIOCGETP:
128: sp->ioc1.sb.sg_ispeed =
129: sp->ioc1.sb.sg_ospeed = B9600;
130: break;
131: case TCPIOHUP:
132: so->so_state |= SS_HANGUP;
133: bp->wptr = bp->rptr;
134: bp->type = M_IOCACK;
135: qreply(q, bp);
136: return;
137: default:
138: bp->type = M_IOCNAK;
139: }
140: qreply(q, bp);
141: return;
142: case M_DATA:
143: if(socantsendmore(so)){
144: freeb(bp);
145: return;
146: }
147: s = spl6();
148: so->so_delimcnt = 0;
149: so->so_wcount += BLEN(bp); /* BEFORE the putq */
150: putq(q, bp);
151: splx(s);
152: if((so->so_options&SO_ACCEPTCONN) == 0
153: && (so->so_state&SS_WAITING) == 0
154: && (tp = so->so_tcpcb)){
155: /* so as to invoke tcp_output() */
156: if(tp->t_state > TCPS_CLOSE_WAIT)
157: printf("data after CLOSE_WAIT?\n");
158: qenable(q);
159: }
160: break;
161: case M_DELIM:
162: if(so->so_options&SO_ACCEPTCONN){
163: printf("DELIM on listener\n");
164: } else if(so->so_state & SS_WAITING){
165: putq(q, bp);
166: /* to invoke tcpduser */
167: qenable(q);
168: } else {
169: /* two back to back delims constitute logical eof */
170: freeb(bp);
171: s = spl6();
172: if(socantsendmore(so)){
173: splx(s);
174: return;
175: }
176: if(++(so->so_delimcnt) > 1){
177: splx(s);
178: qenable(q);
179: } else
180: splx(s);
181: }
182: break;
183: default:
184: freeb(bp);
185: break;
186: }
187: }
188:
189: tcpdosrv(q)
190: struct queue *q;
191: {
192: register struct socket *so;
193: register struct tcpcb *tp;
194:
195: so = (struct socket *)q->ptr;
196: if (so->so_state&SS_WCLOSED)
197: return;
198: tcp_busy++;
199: if(so->so_delimcnt > 1){
200: so->so_state |= SS_WCLOSED;
201: if((tp = so->so_tcpcb) == 0){
202: printf("delimcnt but no tp\n");
203: --tcp_busy;
204: return;
205: }
206: tp = tcp_usrclosed(tp);
207: if(tp)
208: tcp_output(tp);
209: } else {
210: if((so->so_options&SO_ACCEPTCONN) == 0
211: && (so->so_state&SS_WAITING) == 0
212: && (tp = so->so_tcpcb)){
213: tcp_output(tp);
214: } else {
215: tcpduser(so);
216: }
217: }
218: --tcp_busy;
219: }
220:
221: tcpdrint(bp, so)
222: register struct block *bp;
223: struct socket *so;
224: {
225: register struct block *bp1;
226: register struct queue *q;
227:
228: q = so->so_rq;
229: if(q){
230: while(bp){
231: bp1 = bp->next;
232: so->so_rcount += bp->wptr - bp->rptr;
233: if(bp->wptr == bp->rptr)
234: freeb(bp);
235: else
236: putq(q, bp);
237: bp = bp1;
238: }
239: } else {
240: printf("tcpdrint but no so->so_rq\n");
241: bp_free(bp);
242: }
243: }
244:
245: tcpdisrv(q)
246: struct queue *q;
247: {
248: struct socket *so = (struct socket *)(q->ptr);
249: struct block *bp;
250:
251: while((q->next->flag&QFULL) == 0){
252: if(bp = getq(q)){
253: if(bp->type == M_DATA)
254: so->so_rcount -= bp->wptr - bp->rptr;
255: if(so->so_rcount < 0)
256: panic("so_rcount");
257: (*q->next->qinfo->putp)(q->next, bp);
258: } else
259: break;
260: }
261: if(q->count <= q->qinfo->lolimit)
262: qenable(OTHERQ(q)); /* update remote send window */
263: }
264:
265: /*
266: * imitation tcp_usrreq
267: */
268: tcpduser(so)
269: register struct socket *so;
270: {
271: extern struct ipif *ip_ifwithaddr();
272: struct tcpuser *tu;
273: struct block *bp, *bp1, *head;
274: register struct tcpcb *tp;
275:
276: bp = bp1 = head = NULL;
277: while(bp = getq(so->so_wq)){
278: if(bp->type != M_DATA){
279: freeb(bp);
280: } else if(bp1 == NULL){
281: bp1 = head = bp;
282: bp->next = NULL;
283: } else {
284: bp1->next = bp;
285: bp1 = bp;
286: bp->next = NULL;
287: }
288: }
289: if(head == NULL)
290: return;
291: so->so_wcount = 0;
292: bp = head;
293: if(BLEN(bp) < sizeof(struct tcpuser)){
294: /*
295: printf("tcpuser short\n");
296: */
297: bp_free(bp);
298: return;
299: }
300: tu = (struct tcpuser *)bp->rptr;
301: if(so->so_tcpcb)
302: printf("%d: tcpduser w/ tcpcb\n", so->so_dev);
303: switch(tu->cmd){
304: case TCPC_CONNECT:
305: if(so->so_state&SS_ACTIVE)
306: goto bad;
307: if (tu->src != INADDR_ANY) {
308: /* has the user has specified a legal local address? */
309: if (ip_ifwithaddr(tu->src) == 0)
310: goto bad;
311: } else {
312: /* pick a local address related to the destination */
313: tu->src = ip_hoston(tu->dst);
314: if(tu->src == INADDR_ANY)
315: goto bad;
316: }
317: if(tcp_attach(so))
318: goto bad;
319: if(sobind(so, tu->src, tu->sport))
320: goto bad;
321: tp = so->so_tcpcb;
322: so->so_fport = tu->dport;
323: so->so_faddr = tu->dst;
324: so->so_options = 0;
325: tp->t_template = tcp_template(tp);
326: if(tp->t_template == 0)
327: goto bad;
328: soisconnecting(so);
329: tp->t_state = TCPS_SYN_SENT;
330: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
331: tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
332: tcp_sendseqinit(tp);
333: so->so_state &= ~SS_WAITING;
334: tcp_output(tp);
335: break;
336: case TCPC_LISTEN:
337: if(so->so_state&SS_ACTIVE)
338: goto bad;
339: if (tu->src != INADDR_ANY) {
340: /* has the user has specified a legal local address? */
341: if (ip_ifwithaddr(tu->src) == 0)
342: goto bad;
343: }
344: if(tcp_attach(so))
345: goto bad;
346: if(sobind(so, tu->src, tu->sport))
347: goto bad;
348: tp = so->so_tcpcb;
349: tp->t_state = TCPS_LISTEN;
350: so->so_options |= SO_ACCEPTCONN;
351: so->so_fport = tu->dport;
352: so->so_state &= ~SS_WAITING;
353: break;
354: default:
355: goto bad;
356: }
357: bp_free(bp);
358: return;
359: bad:
360: bp_free(bp);
361: tcp_hungup(so);
362: }
363:
364: tcp_attach(so)
365: struct socket *so;
366: {
367: register struct tcpcb *tp;
368: extern struct tcpcb *tcp_newtcpcb();
369:
370: tp = tcp_newtcpcb(so);
371: if(tp == 0)
372: return(1);
373: tp->t_socket = so;
374: tp->t_state = TCPS_CLOSED;
375: return(0);
376: }
377:
378: struct tcpcb *
379: tcp_disconnect(tp)
380: register struct tcpcb *tp;
381: {
382: struct socket *so = tp->t_socket;
383:
384: if(tp->t_state < TCPS_ESTABLISHED)
385: tp = tcp_close(tp);
386: else {
387: soisdisconnecting(so);
388: tp = tcp_usrclosed(tp);
389: if(tp)
390: tcp_output(tp);
391: }
392: return(tp);
393: }
394:
395: struct tcpcb *
396: tcp_usrclosed(tp)
397: register struct tcpcb *tp;
398: {
399:
400: switch(tp->t_state){
401:
402: case TCPS_CLOSED:
403: case TCPS_LISTEN:
404: case TCPS_SYN_SENT:
405: tp->t_state = TCPS_CLOSED;
406: tp = tcp_close(tp);
407: break;
408:
409: case TCPS_SYN_RECEIVED:
410: case TCPS_ESTABLISHED:
411: tp->t_state = TCPS_FIN_WAIT_1;
412: break;
413:
414: case TCPS_CLOSE_WAIT:
415: tp->t_state = TCPS_LAST_ACK;
416: break;
417: }
418: if(tp && tp->t_state >= TCPS_FIN_WAIT_2)
419: soisdisconnected(tp->t_socket);
420: return(tp);
421: }
422:
423: tcp_isconnected(so)
424: struct socket *so;
425: {
426: struct block *bp;
427: struct tcpreply *tr;
428: struct socket *rso;
429:
430: if(so->so_head)
431: rso = so->so_head;
432: else
433: rso = so;
434: if((rso->so_state & SS_OPEN) == 0){
435: printf("isconnected, no fd ref\n");
436: return;
437: }
438: bp = allocb(64);
439: if(bp == 0)
440: return;
441: bp->next = NULL;
442: bp->type = M_DATA;
443: bp->wptr += sizeof(struct tcpreply);
444: tr = (struct tcpreply *)bp->rptr;
445: tr->reply = TCPR_OK;
446: tr->dport = so->so_fport;
447: tr->dst = so->so_faddr;
448: tr->src = so->so_laddr;
449: tr->tcpdev = so->so_dev;
450: tcpdrint(bp, rso);
451: }
452:
453: tcp_hungup(so)
454: register struct socket *so;
455: {
456: register struct queue *q;
457:
458: q = so->so_rq;
459: if(q == 0)
460: return;
461: tcp_putctl(q, M_HANGUP);
462: }
463:
464: /*
465: * find a spare odd tcp device for a new passive-end
466: * connection.
467: */
468: struct socket *
469: tcp_newconn(so)
470: struct socket *so;
471: {
472: struct socket *nso;
473:
474: if(so->so_rq && (so->so_rq->flag&QFULL)){
475: printf("listen %d q full\n", so->so_lport);
476: return(0);
477: }
478: for(nso = &tcpsocks[0]; nso < &tcpsocks[NTCP]; nso += 2){
479: if((nso->so_state & (SS_OPEN|SS_ACTIVE)) == 0){
480: bzero(nso, sizeof(struct socket));
481: nso->so_head = so;
482: nso->so_dev = nso - tcpsocks;
483: return(nso);
484: }
485: }
486: return(0);
487: }
488:
489: struct socket *
490: so_lookup(faddr, fport, laddr, lport)
491: in_addr faddr, laddr;
492: tcp_port fport, lport;
493: {
494: register struct socket *so, *match = 0;
495: register in_addr net, host;
496: int matchwild = 5, wildcard;
497:
498: net = in_netof(laddr);
499: host = in_hostof(laddr);
500: for(so = &tcpsocks[0]; so < &tcpsocks[NTCP]; so++){
501: if(so->so_tcpcb == 0)
502: continue;
503: if((so->so_state&(SS_OPEN|SS_ACTIVE)) == 0)
504: continue;
505: if(so->so_state & SS_WAITING)
506: continue;
507: wildcard = 0;
508:
509: if(so->so_lport != TCPPORT_ANY){
510: if(so->so_lport != lport)
511: continue;
512: } else
513: wildcard++; /* port is wildcarded */
514:
515: if(so->so_laddr == net){
516: wildcard++; /* host is wildcarded */
517: } else if(so->so_laddr != INADDR_ANY){
518: if(laddr == INADDR_ANY)
519: wildcard += 2; /* host & net wildcarded */
520: else if(so->so_laddr != laddr)
521: continue;
522: } else {
523: if(laddr != INADDR_ANY)
524: wildcard += 2; /* host & net wildcarded */
525: }
526: if(so->so_faddr != INADDR_ANY){
527: if(faddr == INADDR_ANY)
528: wildcard += 2; /* host & net wildcarded */
529: else if(so->so_faddr != faddr ||
530: so->so_fport != fport)
531: continue;
532: } else {
533: if(faddr)
534: wildcard += 2; /* host & net wildcarded */
535: }
536: if(wildcard < matchwild){
537: match = so;
538: matchwild = wildcard;
539: if(matchwild == 0)
540: break;
541: }
542: }
543: return(match);
544: }
545:
546: /* n chars were acked; drop them now */
547: sbsnddrop(so, n)
548: register struct socket *so;
549: register int n;
550: {
551: register struct queue *q;
552: register int i;
553: register struct block *bp;
554:
555: q = so->so_wq;
556: if(q == 0)
557: return;
558: bp = 0;
559: while(n > 0 && (bp = getq(q))){
560: i = MIN(BLEN(bp), n);
561: bp->rptr += i;
562: n -= i;
563: so->so_wcount -= i;
564: if(bp->rptr >= bp->wptr){
565: freeb(bp);
566: bp = 0;
567: } else if(n > 0){
568: panic("sbsnddrop");
569: }
570: }
571: if(bp)
572: putbq(q, bp);
573: }
574:
575:
576: sobind(so, addr, port)
577: register struct socket *so;
578: register in_addr addr;
579: register tcp_port port;
580: {
581: register struct socket *sp;
582: static tcp_port next_port = 600;
583:
584: so->so_lport = 0;
585: if(port){
586: /* what about, for instance, restarting rlogind when
587: * people are rlogin'd here?
588: */
589: for(sp = &tcpsocks[0]; sp < &tcpsocks[NTCP]; sp++){
590: if(sp->so_tcpcb == 0)
591: continue;
592: if((sp->so_state&(SS_OPEN|SS_ACTIVE)) == 0)
593: continue;
594: if(sp->so_lport == port && sp->so_laddr == addr) {
595: return(1);
596: }
597: }
598: so->so_lport = port;
599: so->so_laddr = addr;
600: return(0);
601: }
602: /* pick one for him */
603: if(next_port >= 1024)
604: next_port = 600;
605: port = next_port;
606: while(1){
607: if(sobind(so, addr, next_port) == 0){
608: next_port++;
609: return(0);
610: }
611: next_port++;
612: if(next_port >= 1024)
613: next_port = 600;
614: if(next_port == port) /* tried them all */
615: break;
616: }
617: return(1);
618: }
619:
620: tcp_cantrcvmore(so)
621: register struct socket *so;
622: {
623: register struct queue *q;
624:
625: q = so->so_rq;
626: if(q == NULL)
627: return;
628: if(so->so_state & SS_HANGUP)
629: tcp_putctl(q, M_HANGUP);
630: else {
631: /* two delims ensure a zero length read at the process */
632: tcp_putctl(q, M_DELIM);
633: tcp_putctl(q, M_DELIM);
634: }
635: }
636:
637: tcp_putctl(q, c)
638: register struct queue *q;
639: {
640: register struct block *bp;
641:
642: if ((bp = allocb(0)) == NULL) {
643: printf("tcp_putctl: no more blocks\n");
644: return(0);
645: }
646: bp->type = c;
647: putq(q, bp);
648: return(1);
649: }
650: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.