xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5245)
1 /* tcp_usrreq.c 1.40 81/12/12 */
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/mbuf.h"
6 #include "../h/socket.h"
7 #include "../h/socketvar.h"
8 #include "../h/protosw.h"
9 #include "../net/in.h"
10 #include "../net/in_pcb.h"
11 #include "../net/in_systm.h"
12 #include "../net/if.h"
13 #include "../net/ip.h"
14 #include "../net/ip_var.h"
15 #include "../net/tcp.h"
16 #include "../net/tcp_fsm.h"
17 #include "../net/tcp_seq.h"
18 #include "../net/tcp_timer.h"
19 #include "../net/tcp_var.h"
20 #include "../net/tcpip.h"
21 #include "../errno.h"
22 
23 extern char *tcpstates[];
24 struct	tcpcb *tcp_newtcpcb();
25 /*
26  * Process a TCP user request for tcp tb.  If this is a send request
27  * then m is the mbuf chain of send data.  If this is a timer expiration
28  * (called from the software clock routine), then timertype tells which timer.
29  */
30 tcp_usrreq(so, req, m, addr)
31 	struct socket *so;
32 	int req;
33 	struct mbuf *m;
34 	caddr_t addr;
35 {
36 	register struct inpcb *inp = sotoinpcb(so);
37 	register struct tcpcb *tp;
38 	int s = splnet();
39 	int error = 0;
40 COUNT(TCP_USRREQ);
41 
42 	/*
43 	 * Make sure attached.  If not,
44 	 * only PRU_ATTACH is valid.
45 	 */
46 printf("tcp_usrreq %d so %x inp %x\n", req, so, inp);
47 	if (inp == 0 && req != PRU_ATTACH) {
48 		splx(s);
49 		return (EINVAL);
50 	}
51 	if (inp) {
52 		tp = intotcpcb(inp);
53 #ifdef KPROF
54 		tcp_acounts[tp->t_state][req]++;
55 #endif
56 	}
57 	switch (req) {
58 
59 	case PRU_ATTACH:
60 		if (inp) {
61 			error = EISCONN;
62 			break;
63 		}
64 		error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
65 		if (error)
66 			break;
67 		inp = (struct inpcb *)so->so_pcb;
68 		tp = tcp_newtcpcb(inp);
69 		if (so->so_options & SO_ACCEPTCONN) {
70 			if (tp == 0) {
71 				in_pcbdetach(inp);
72 				error = ENOBUFS;
73 				break;
74 			}
75 			tp->t_state = TCPS_LISTEN;
76 		} else
77 			tp->t_state = TCPS_CLOSED;
78 		break;
79 
80 	case PRU_DETACH:
81 		in_pcbdetach(inp);
82 		break;
83 
84 	case PRU_CONNECT:
85 		error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
86 		if (error)
87 			break;
88 		tp = tcp_newtcpcb(inp);
89 		if (tp == 0)
90 			goto badcon;
91 		tp->t_template = tcp_template(tp);
92 		if (tp->t_template == 0)
93 			goto badcon2;
94 		tp->t_inpcb = inp;
95 		inp->inp_ppcb = (caddr_t)tp;
96 		soisconnecting(so);
97 		tp->t_state = TCPS_SYN_SENT;
98 		tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
99 		tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
100 		tcp_sendseqinit(tp);
101 		(void) tcp_output(tp);
102 		break;
103 
104 badcon2:
105 		(void) m_free(dtom(tp));
106 badcon:
107 		in_pcbdisconnect(inp);
108 		error = ENOBUFS;
109 		break;
110 
111 	case PRU_ACCEPT:
112 		soisconnected(so);
113 		break;
114 
115 	case PRU_DISCONNECT:
116 		if (tp->t_state < TCPS_ESTABLISHED)
117 			tcp_close(tp);
118 		else {
119 			soisdisconnecting(so);
120 			tcp_usrclosed(tp);
121 			(void) tcp_output(tp);
122 		}
123 		break;
124 
125 	case PRU_SHUTDOWN:
126 		socantsendmore(so);
127 		tcp_usrclosed(tp);
128 		(void) tcp_output(tp);
129 		break;
130 
131 	case PRU_RCVD:
132 		(void) tcp_output(tp);
133 		break;
134 
135 	case PRU_SEND:
136 		sbappend(&so->so_snd, m);
137 /*
138 		if (tp->t_flags & TF_PUSH)
139 			tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
140  */
141 		if (tp->t_flags & TF_URG)
142 			tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
143 		(void) tcp_output(tp);
144 		break;
145 
146 	case PRU_ABORT:
147 		tcp_drop(tp, ECONNABORTED);
148 		break;
149 
150 	case PRU_CONTROL:
151 		error = EOPNOTSUPP;
152 		break;
153 
154 	case PRU_SENSE:
155 		error = EOPNOTSUPP;
156 		break;
157 
158 	case PRU_RCVOOB:
159 		error = EOPNOTSUPP;
160 		break;
161 
162 	case PRU_SENDOOB:
163 		error = EOPNOTSUPP;
164 		break;
165 
166 	case PRU_SLOWTIMO:
167 		tcp_timers(tp, (int)addr);
168 		break;
169 
170 	default:
171 		panic("tcp_usrreq");
172 	}
173 	splx(s);
174 	return (error);
175 }
176 
177 pseqno(tp)
178 struct tcpcb *tp;
179 {
180 printf("tp %x state %s rcv_nxt %x rcv_wnd %d irs %x\n", tp, tcpstates[tp->t_state],tp->rcv_nxt, tp->rcv_wnd, tp->irs);
181 printf("snd_una %x snd_nxt %x snd_wnd %d snd_wl1 %x snd_wl2 %x iss %x\n",
182 tp->snd_una, tp->snd_nxt, tp->snd_wnd, tp->snd_wl1, tp->snd_wl2, tp->iss);
183 }
184 
185 tcp_usrclosed(tp)
186 	struct tcpcb *tp;
187 {
188 
189 printf("usrclosed in %s\n", tcpstates[tp->t_state]);
190 	switch (tp->t_state) {
191 
192 	case TCPS_LISTEN:
193 	case TCPS_SYN_SENT:
194 		tp->t_state = TCPS_CLOSED;
195 		tcp_close(tp);
196 		break;
197 
198 	case TCPS_SYN_RECEIVED:
199 	case TCPS_ESTABLISHED:
200 		tp->t_state = TCPS_FIN_WAIT_1;
201 		break;
202 
203 	case TCPS_CLOSE_WAIT:
204 		tp->t_state = TCPS_LAST_ACK;
205 		break;
206 	}
207 printf("after usrclosed state %s\n", tcpstates[tp->t_state]);
208 }
209