xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5270)
1*5270Sroot /* tcp_usrreq.c 1.43 81/12/20 */
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"
21*5270Sroot #include "../net/tcp_debug.h"
225113Swnj #include "../errno.h"
234497Swnj 
245245Sroot extern char *tcpstates[];
254954Swnj struct	tcpcb *tcp_newtcpcb();
264734Swnj /*
274731Swnj  * Process a TCP user request for tcp tb.  If this is a send request
284731Swnj  * then m is the mbuf chain of send data.  If this is a timer expiration
294731Swnj  * (called from the software clock routine), then timertype tells which timer.
304731Swnj  */
314809Swnj tcp_usrreq(so, req, m, addr)
324809Swnj 	struct socket *so;
334809Swnj 	int req;
344731Swnj 	struct mbuf *m;
354809Swnj 	caddr_t addr;
364497Swnj {
374886Swnj 	register struct inpcb *inp = sotoinpcb(so);
384911Swnj 	register struct tcpcb *tp;
394567Swnj 	int s = splnet();
404809Swnj 	int error = 0;
41*5270Sroot 	int ostate;
424567Swnj COUNT(TCP_USRREQ);
434497Swnj 
444886Swnj 	/*
454886Swnj 	 * Make sure attached.  If not,
464886Swnj 	 * only PRU_ATTACH is valid.
474886Swnj 	 */
485089Swnj 	if (inp == 0 && req != PRU_ATTACH) {
495075Swnj 		splx(s);
505075Swnj 		return (EINVAL);
515075Swnj 	}
525075Swnj 	if (inp) {
534911Swnj 		tp = intotcpcb(inp);
544731Swnj #ifdef KPROF
555075Swnj 		tcp_acounts[tp->t_state][req]++;
564731Swnj #endif
57*5270Sroot 		ostate = tp->t_state;
584911Swnj 	}
594809Swnj 	switch (req) {
604497Swnj 
614809Swnj 	case PRU_ATTACH:
624954Swnj 		if (inp) {
634809Swnj 			error = EISCONN;
644911Swnj 			break;
654886Swnj 		}
665165Swnj 		error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
675075Swnj 		if (error)
684954Swnj 			break;
694954Swnj 		inp = (struct inpcb *)so->so_pcb;
705245Sroot 		tp = tcp_newtcpcb(inp);
715062Swnj 		if (so->so_options & SO_ACCEPTCONN) {
725062Swnj 			if (tp == 0) {
735165Swnj 				in_pcbdetach(inp);
745062Swnj 				error = ENOBUFS;
755062Swnj 				break;
765062Swnj 			}
775075Swnj 			tp->t_state = TCPS_LISTEN;
785062Swnj 		} else
795075Swnj 			tp->t_state = TCPS_CLOSED;
804567Swnj 		break;
814497Swnj 
824809Swnj 	case PRU_DETACH:
83*5270Sroot 		if (tp)
84*5270Sroot 			goto disconn;
855165Swnj 		in_pcbdetach(inp);
864809Swnj 		break;
874809Swnj 
884809Swnj 	case PRU_CONNECT:
895165Swnj 		error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
904954Swnj 		if (error)
914886Swnj 			break;
925174Swnj 		tp->t_template = tcp_template(tp);
935245Sroot 		if (tp->t_template == 0)
945245Sroot 			goto badcon2;
955062Swnj 		tp->t_inpcb = inp;
965062Swnj 		inp->inp_ppcb = (caddr_t)tp;
974886Swnj 		soisconnecting(so);
985075Swnj 		tp->t_state = TCPS_SYN_SENT;
995245Sroot 		tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
1005245Sroot 		tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
1015245Sroot 		tcp_sendseqinit(tp);
1025113Swnj 		(void) tcp_output(tp);
1034567Swnj 		break;
1044497Swnj 
1055245Sroot badcon2:
1065245Sroot 		(void) m_free(dtom(tp));
1075245Sroot badcon:
1085245Sroot 		in_pcbdisconnect(inp);
1095245Sroot 		error = ENOBUFS;
1105245Sroot 		break;
1115245Sroot 
1124925Swnj 	case PRU_ACCEPT:
113*5270Sroot 		*(struct sockaddr *)addr = so->so_addr;
1144954Swnj 		break;
1154925Swnj 
1164809Swnj 	case PRU_DISCONNECT:
117*5270Sroot disconn:
1185075Swnj 		if (tp->t_state < TCPS_ESTABLISHED)
1195075Swnj 			tcp_close(tp);
1204886Swnj 		else {
1214886Swnj 			soisdisconnecting(so);
1225245Sroot 			tcp_usrclosed(tp);
1235113Swnj 			(void) tcp_output(tp);
1244886Swnj 		}
1254809Swnj 		break;
1264809Swnj 
1274809Swnj 	case PRU_SHUTDOWN:
1285089Swnj 		socantsendmore(so);
1295245Sroot 		tcp_usrclosed(tp);
1305245Sroot 		(void) tcp_output(tp);
1314567Swnj 		break;
1324497Swnj 
1334809Swnj 	case PRU_RCVD:
1345113Swnj 		(void) tcp_output(tp);
1354567Swnj 		break;
1364497Swnj 
1374809Swnj 	case PRU_SEND:
1385075Swnj 		sbappend(&so->so_snd, m);
1395089Swnj /*
1405089Swnj 		if (tp->t_flags & TF_PUSH)
1415075Swnj 			tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
1425089Swnj  */
1435089Swnj 		if (tp->t_flags & TF_URG)
1445089Swnj 			tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
1455113Swnj 		(void) tcp_output(tp);
1464567Swnj 		break;
1474567Swnj 
1484809Swnj 	case PRU_ABORT:
1495075Swnj 		tcp_drop(tp, ECONNABORTED);
1504567Swnj 		break;
1514567Swnj 
1524809Swnj 	case PRU_CONTROL:
1534886Swnj 		error = EOPNOTSUPP;
1544809Swnj 		break;
1554809Swnj 
1565113Swnj 	case PRU_SENSE:
1575113Swnj 		error = EOPNOTSUPP;
1585113Swnj 		break;
1595113Swnj 
1605113Swnj 	case PRU_RCVOOB:
1615113Swnj 		error = EOPNOTSUPP;
1625113Swnj 		break;
1635113Swnj 
1645113Swnj 	case PRU_SENDOOB:
1655113Swnj 		error = EOPNOTSUPP;
1665113Swnj 		break;
1675113Swnj 
1684809Swnj 	case PRU_SLOWTIMO:
1695075Swnj 		tcp_timers(tp, (int)addr);
170*5270Sroot 		req |= (int)addr << 8;		/* for debug's sake */
1714809Swnj 		break;
1724809Swnj 
1734731Swnj 	default:
1744731Swnj 		panic("tcp_usrreq");
1754567Swnj 	}
176*5270Sroot 	if (tp && (so->so_options & SO_DEBUG))
177*5270Sroot 		tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req);
1784567Swnj 	splx(s);
1794886Swnj 	return (error);
1804497Swnj }
1815245Sroot 
1825245Sroot tcp_usrclosed(tp)
1835245Sroot 	struct tcpcb *tp;
1845245Sroot {
1855245Sroot 
1865245Sroot 	switch (tp->t_state) {
1875245Sroot 
1885245Sroot 	case TCPS_LISTEN:
1895245Sroot 	case TCPS_SYN_SENT:
1905245Sroot 		tp->t_state = TCPS_CLOSED;
1915245Sroot 		tcp_close(tp);
1925245Sroot 		break;
1935245Sroot 
1945245Sroot 	case TCPS_SYN_RECEIVED:
1955245Sroot 	case TCPS_ESTABLISHED:
1965245Sroot 		tp->t_state = TCPS_FIN_WAIT_1;
1975245Sroot 		break;
1985245Sroot 
1995245Sroot 	case TCPS_CLOSE_WAIT:
2005245Sroot 		tp->t_state = TCPS_LAST_ACK;
2015245Sroot 		break;
2025245Sroot 	}
2035245Sroot }
204