xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5245)
1*5245Sroot /* tcp_usrreq.c 1.40 81/12/12 */
24567Swnj 
34497Swnj #include "../h/param.h"
44567Swnj #include "../h/systm.h"
54664Swnj #include "../h/mbuf.h"
64664Swnj #include "../h/socket.h"
74809Swnj #include "../h/socketvar.h"
84809Swnj #include "../h/protosw.h"
95089Swnj #include "../net/in.h"
105089Swnj #include "../net/in_pcb.h"
115089Swnj #include "../net/in_systm.h"
124954Swnj #include "../net/if.h"
134809Swnj #include "../net/ip.h"
144900Swnj #include "../net/ip_var.h"
154809Swnj #include "../net/tcp.h"
164809Swnj #include "../net/tcp_fsm.h"
175089Swnj #include "../net/tcp_seq.h"
185089Swnj #include "../net/tcp_timer.h"
194809Swnj #include "../net/tcp_var.h"
205089Swnj #include "../net/tcpip.h"
215113Swnj #include "../errno.h"
224497Swnj 
23*5245Sroot extern char *tcpstates[];
244954Swnj struct	tcpcb *tcp_newtcpcb();
254734Swnj /*
264731Swnj  * Process a TCP user request for tcp tb.  If this is a send request
274731Swnj  * then m is the mbuf chain of send data.  If this is a timer expiration
284731Swnj  * (called from the software clock routine), then timertype tells which timer.
294731Swnj  */
304809Swnj tcp_usrreq(so, req, m, addr)
314809Swnj 	struct socket *so;
324809Swnj 	int req;
334731Swnj 	struct mbuf *m;
344809Swnj 	caddr_t addr;
354497Swnj {
364886Swnj 	register struct inpcb *inp = sotoinpcb(so);
374911Swnj 	register struct tcpcb *tp;
384567Swnj 	int s = splnet();
394809Swnj 	int error = 0;
404567Swnj COUNT(TCP_USRREQ);
414497Swnj 
424886Swnj 	/*
434886Swnj 	 * Make sure attached.  If not,
444886Swnj 	 * only PRU_ATTACH is valid.
454886Swnj 	 */
46*5245Sroot printf("tcp_usrreq %d so %x inp %x\n", req, so, inp);
475089Swnj 	if (inp == 0 && req != PRU_ATTACH) {
485075Swnj 		splx(s);
495075Swnj 		return (EINVAL);
505075Swnj 	}
515075Swnj 	if (inp) {
524911Swnj 		tp = intotcpcb(inp);
534731Swnj #ifdef KPROF
545075Swnj 		tcp_acounts[tp->t_state][req]++;
554731Swnj #endif
564911Swnj 	}
574809Swnj 	switch (req) {
584497Swnj 
594809Swnj 	case PRU_ATTACH:
604954Swnj 		if (inp) {
614809Swnj 			error = EISCONN;
624911Swnj 			break;
634886Swnj 		}
645165Swnj 		error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
655075Swnj 		if (error)
664954Swnj 			break;
674954Swnj 		inp = (struct inpcb *)so->so_pcb;
68*5245Sroot 		tp = tcp_newtcpcb(inp);
695062Swnj 		if (so->so_options & SO_ACCEPTCONN) {
705062Swnj 			if (tp == 0) {
715165Swnj 				in_pcbdetach(inp);
725062Swnj 				error = ENOBUFS;
735062Swnj 				break;
745062Swnj 			}
755075Swnj 			tp->t_state = TCPS_LISTEN;
765062Swnj 		} else
775075Swnj 			tp->t_state = TCPS_CLOSED;
784567Swnj 		break;
794497Swnj 
804809Swnj 	case PRU_DETACH:
815165Swnj 		in_pcbdetach(inp);
824809Swnj 		break;
834809Swnj 
844809Swnj 	case PRU_CONNECT:
855165Swnj 		error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
864954Swnj 		if (error)
874886Swnj 			break;
885062Swnj 		tp = tcp_newtcpcb(inp);
89*5245Sroot 		if (tp == 0)
90*5245Sroot 			goto badcon;
915174Swnj 		tp->t_template = tcp_template(tp);
92*5245Sroot 		if (tp->t_template == 0)
93*5245Sroot 			goto badcon2;
945062Swnj 		tp->t_inpcb = inp;
955062Swnj 		inp->inp_ppcb = (caddr_t)tp;
964886Swnj 		soisconnecting(so);
975075Swnj 		tp->t_state = TCPS_SYN_SENT;
98*5245Sroot 		tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
99*5245Sroot 		tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
100*5245Sroot 		tcp_sendseqinit(tp);
1015113Swnj 		(void) tcp_output(tp);
1024567Swnj 		break;
1034497Swnj 
104*5245Sroot badcon2:
105*5245Sroot 		(void) m_free(dtom(tp));
106*5245Sroot badcon:
107*5245Sroot 		in_pcbdisconnect(inp);
108*5245Sroot 		error = ENOBUFS;
109*5245Sroot 		break;
110*5245Sroot 
1114925Swnj 	case PRU_ACCEPT:
1124954Swnj 		soisconnected(so);
1134954Swnj 		break;
1144925Swnj 
1154809Swnj 	case PRU_DISCONNECT:
1165075Swnj 		if (tp->t_state < TCPS_ESTABLISHED)
1175075Swnj 			tcp_close(tp);
1184886Swnj 		else {
1194886Swnj 			soisdisconnecting(so);
120*5245Sroot 			tcp_usrclosed(tp);
1215113Swnj 			(void) tcp_output(tp);
1224886Swnj 		}
1234809Swnj 		break;
1244809Swnj 
1254809Swnj 	case PRU_SHUTDOWN:
1265089Swnj 		socantsendmore(so);
127*5245Sroot 		tcp_usrclosed(tp);
128*5245Sroot 		(void) tcp_output(tp);
1294567Swnj 		break;
1304497Swnj 
1314809Swnj 	case PRU_RCVD:
1325113Swnj 		(void) tcp_output(tp);
1334567Swnj 		break;
1344497Swnj 
1354809Swnj 	case PRU_SEND:
1365075Swnj 		sbappend(&so->so_snd, m);
1375089Swnj /*
1385089Swnj 		if (tp->t_flags & TF_PUSH)
1395075Swnj 			tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
1405089Swnj  */
1415089Swnj 		if (tp->t_flags & TF_URG)
1425089Swnj 			tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
1435113Swnj 		(void) tcp_output(tp);
1444567Swnj 		break;
1454567Swnj 
1464809Swnj 	case PRU_ABORT:
1475075Swnj 		tcp_drop(tp, ECONNABORTED);
1484567Swnj 		break;
1494567Swnj 
1504809Swnj 	case PRU_CONTROL:
1514886Swnj 		error = EOPNOTSUPP;
1524809Swnj 		break;
1534809Swnj 
1545113Swnj 	case PRU_SENSE:
1555113Swnj 		error = EOPNOTSUPP;
1565113Swnj 		break;
1575113Swnj 
1585113Swnj 	case PRU_RCVOOB:
1595113Swnj 		error = EOPNOTSUPP;
1605113Swnj 		break;
1615113Swnj 
1625113Swnj 	case PRU_SENDOOB:
1635113Swnj 		error = EOPNOTSUPP;
1645113Swnj 		break;
1655113Swnj 
1664809Swnj 	case PRU_SLOWTIMO:
1675075Swnj 		tcp_timers(tp, (int)addr);
1684809Swnj 		break;
1694809Swnj 
1704731Swnj 	default:
1714731Swnj 		panic("tcp_usrreq");
1724567Swnj 	}
1734567Swnj 	splx(s);
1744886Swnj 	return (error);
1754497Swnj }
176*5245Sroot 
177*5245Sroot pseqno(tp)
178*5245Sroot struct tcpcb *tp;
179*5245Sroot {
180*5245Sroot 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*5245Sroot printf("snd_una %x snd_nxt %x snd_wnd %d snd_wl1 %x snd_wl2 %x iss %x\n",
182*5245Sroot tp->snd_una, tp->snd_nxt, tp->snd_wnd, tp->snd_wl1, tp->snd_wl2, tp->iss);
183*5245Sroot }
184*5245Sroot 
185*5245Sroot tcp_usrclosed(tp)
186*5245Sroot 	struct tcpcb *tp;
187*5245Sroot {
188*5245Sroot 
189*5245Sroot printf("usrclosed in %s\n", tcpstates[tp->t_state]);
190*5245Sroot 	switch (tp->t_state) {
191*5245Sroot 
192*5245Sroot 	case TCPS_LISTEN:
193*5245Sroot 	case TCPS_SYN_SENT:
194*5245Sroot 		tp->t_state = TCPS_CLOSED;
195*5245Sroot 		tcp_close(tp);
196*5245Sroot 		break;
197*5245Sroot 
198*5245Sroot 	case TCPS_SYN_RECEIVED:
199*5245Sroot 	case TCPS_ESTABLISHED:
200*5245Sroot 		tp->t_state = TCPS_FIN_WAIT_1;
201*5245Sroot 		break;
202*5245Sroot 
203*5245Sroot 	case TCPS_CLOSE_WAIT:
204*5245Sroot 		tp->t_state = TCPS_LAST_ACK;
205*5245Sroot 		break;
206*5245Sroot 	}
207*5245Sroot printf("after usrclosed state %s\n", tcpstates[tp->t_state]);
208*5245Sroot }
209