xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5165)
1*5165Swnj /* tcp_usrreq.c 1.38 81/12/02 */
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 
234954Swnj struct	tcpcb *tcp_newtcpcb();
244734Swnj /*
254731Swnj  * Process a TCP user request for tcp tb.  If this is a send request
264731Swnj  * then m is the mbuf chain of send data.  If this is a timer expiration
274731Swnj  * (called from the software clock routine), then timertype tells which timer.
284731Swnj  */
294809Swnj tcp_usrreq(so, req, m, addr)
304809Swnj 	struct socket *so;
314809Swnj 	int req;
324731Swnj 	struct mbuf *m;
334809Swnj 	caddr_t addr;
344497Swnj {
354886Swnj 	register struct inpcb *inp = sotoinpcb(so);
364911Swnj 	register struct tcpcb *tp;
374567Swnj 	int s = splnet();
384809Swnj 	int error = 0;
394567Swnj COUNT(TCP_USRREQ);
404497Swnj 
414886Swnj 	/*
424886Swnj 	 * Make sure attached.  If not,
434886Swnj 	 * only PRU_ATTACH is valid.
444886Swnj 	 */
455089Swnj 	if (inp == 0 && req != PRU_ATTACH) {
465075Swnj 		splx(s);
475075Swnj 		return (EINVAL);
485075Swnj 	}
495075Swnj 	if (inp) {
504911Swnj 		tp = intotcpcb(inp);
514731Swnj #ifdef KPROF
525075Swnj 		tcp_acounts[tp->t_state][req]++;
534731Swnj #endif
544911Swnj 	}
554809Swnj 	switch (req) {
564497Swnj 
574809Swnj 	case PRU_ATTACH:
584954Swnj 		if (inp) {
594809Swnj 			error = EISCONN;
604911Swnj 			break;
614886Swnj 		}
62*5165Swnj 		error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
635075Swnj 		if (error)
644954Swnj 			break;
654954Swnj 		inp = (struct inpcb *)so->so_pcb;
665062Swnj 		if (so->so_options & SO_ACCEPTCONN) {
675062Swnj 			tp = tcp_newtcpcb(inp);
685062Swnj 			if (tp == 0) {
69*5165Swnj 				in_pcbdetach(inp);
705062Swnj 				error = ENOBUFS;
715062Swnj 				break;
725062Swnj 			}
735075Swnj 			tp->t_state = TCPS_LISTEN;
745062Swnj 		} else
755075Swnj 			tp->t_state = TCPS_CLOSED;
764567Swnj 		break;
774497Swnj 
784809Swnj 	case PRU_DETACH:
79*5165Swnj 		in_pcbdetach(inp);
804809Swnj 		break;
814809Swnj 
824809Swnj 	case PRU_CONNECT:
83*5165Swnj 		error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
844954Swnj 		if (error)
854886Swnj 			break;
865062Swnj 		tp = tcp_newtcpcb(inp);
875062Swnj 		if (tp == 0) {
88*5165Swnj 			in_pcbdisconnect(inp);
895062Swnj 			error = ENOBUFS;
905062Swnj 			break;
915062Swnj 		}
925062Swnj 		tp->t_inpcb = inp;
935062Swnj 		inp->inp_ppcb = (caddr_t)tp;
944886Swnj 		soisconnecting(so);
955075Swnj 		tp->t_state = TCPS_SYN_SENT;
965113Swnj 		(void) tcp_output(tp);
974567Swnj 		break;
984497Swnj 
994925Swnj 	case PRU_ACCEPT:
1004954Swnj 		soisconnected(so);
1014954Swnj 		break;
1024925Swnj 
1034809Swnj 	case PRU_DISCONNECT:
1045075Swnj 		if (tp->t_state < TCPS_ESTABLISHED)
1055075Swnj 			tcp_close(tp);
1064886Swnj 		else {
1074886Swnj 			soisdisconnecting(so);
1085113Swnj 			(void) tcp_output(tp);
1094886Swnj 		}
1104809Swnj 		break;
1114809Swnj 
1124809Swnj 	case PRU_SHUTDOWN:
1135089Swnj 		socantsendmore(so);
1145075Swnj 		switch (tp->t_state) {
1154497Swnj 
1165066Swnj 		case TCPS_LISTEN:
1175066Swnj 		case TCPS_SYN_SENT:
1185075Swnj 			tp->t_state = TCPS_CLOSED;
1194731Swnj 			break;
1204731Swnj 
1215089Swnj 		case TCPS_SYN_RECEIVED:
1225089Swnj 		case TCPS_ESTABLISHED:
1235075Swnj 			tp->t_state = TCPS_FIN_WAIT_1;
1245113Swnj 			(void) tcp_output(tp);
1255075Swnj 			break;
1265075Swnj 
1275066Swnj 		case TCPS_CLOSE_WAIT:
1285075Swnj 			tp->t_state = TCPS_LAST_ACK;
1295113Swnj 			(void) tcp_output(tp);
1304731Swnj 			break;
1314731Swnj 		}
1324567Swnj 		break;
1334497Swnj 
1344809Swnj 	case PRU_RCVD:
1355113Swnj 		(void) tcp_output(tp);
1364567Swnj 		break;
1374497Swnj 
1384809Swnj 	case PRU_SEND:
1395075Swnj 		sbappend(&so->so_snd, m);
1405089Swnj /*
1415089Swnj 		if (tp->t_flags & TF_PUSH)
1425075Swnj 			tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
1435089Swnj  */
1445089Swnj 		if (tp->t_flags & TF_URG)
1455089Swnj 			tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
1465113Swnj 		(void) tcp_output(tp);
1474567Swnj 		break;
1484567Swnj 
1494809Swnj 	case PRU_ABORT:
1505075Swnj 		tcp_drop(tp, ECONNABORTED);
1514567Swnj 		break;
1524567Swnj 
1534809Swnj 	case PRU_CONTROL:
1544886Swnj 		error = EOPNOTSUPP;
1554809Swnj 		break;
1564809Swnj 
1575113Swnj 	case PRU_SENSE:
1585113Swnj 		error = EOPNOTSUPP;
1595113Swnj 		break;
1605113Swnj 
1615113Swnj 	case PRU_RCVOOB:
1625113Swnj 		error = EOPNOTSUPP;
1635113Swnj 		break;
1645113Swnj 
1655113Swnj 	case PRU_SENDOOB:
1665113Swnj 		error = EOPNOTSUPP;
1675113Swnj 		break;
1685113Swnj 
1694809Swnj 	case PRU_SLOWTIMO:
1705075Swnj 		tcp_timers(tp, (int)addr);
1714809Swnj 		break;
1724809Swnj 
1734731Swnj 	default:
1744731Swnj 		panic("tcp_usrreq");
1754567Swnj 	}
1764567Swnj 	splx(s);
1774886Swnj 	return (error);
1784497Swnj }
179