xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5174)
1*5174Swnj /* tcp_usrreq.c 1.39 81/12/03 */
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 		}
625165Swnj 		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) {
695165Swnj 				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:
795165Swnj 		in_pcbdetach(inp);
804809Swnj 		break;
814809Swnj 
824809Swnj 	case PRU_CONNECT:
835165Swnj 		error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
844954Swnj 		if (error)
854886Swnj 			break;
865062Swnj 		tp = tcp_newtcpcb(inp);
875062Swnj 		if (tp == 0) {
885165Swnj 			in_pcbdisconnect(inp);
895062Swnj 			error = ENOBUFS;
905062Swnj 			break;
915062Swnj 		}
92*5174Swnj 		tp->t_template = tcp_template(tp);
935062Swnj 		tp->t_inpcb = inp;
945062Swnj 		inp->inp_ppcb = (caddr_t)tp;
954886Swnj 		soisconnecting(so);
965075Swnj 		tp->t_state = TCPS_SYN_SENT;
975113Swnj 		(void) tcp_output(tp);
984567Swnj 		break;
994497Swnj 
1004925Swnj 	case PRU_ACCEPT:
1014954Swnj 		soisconnected(so);
1024954Swnj 		break;
1034925Swnj 
1044809Swnj 	case PRU_DISCONNECT:
1055075Swnj 		if (tp->t_state < TCPS_ESTABLISHED)
1065075Swnj 			tcp_close(tp);
1074886Swnj 		else {
1084886Swnj 			soisdisconnecting(so);
1095113Swnj 			(void) tcp_output(tp);
1104886Swnj 		}
1114809Swnj 		break;
1124809Swnj 
1134809Swnj 	case PRU_SHUTDOWN:
1145089Swnj 		socantsendmore(so);
1155075Swnj 		switch (tp->t_state) {
1164497Swnj 
1175066Swnj 		case TCPS_LISTEN:
1185066Swnj 		case TCPS_SYN_SENT:
1195075Swnj 			tp->t_state = TCPS_CLOSED;
1204731Swnj 			break;
1214731Swnj 
1225089Swnj 		case TCPS_SYN_RECEIVED:
1235089Swnj 		case TCPS_ESTABLISHED:
1245075Swnj 			tp->t_state = TCPS_FIN_WAIT_1;
1255113Swnj 			(void) tcp_output(tp);
1265075Swnj 			break;
1275075Swnj 
1285066Swnj 		case TCPS_CLOSE_WAIT:
1295075Swnj 			tp->t_state = TCPS_LAST_ACK;
1305113Swnj 			(void) tcp_output(tp);
1314731Swnj 			break;
1324731Swnj 		}
1334567Swnj 		break;
1344497Swnj 
1354809Swnj 	case PRU_RCVD:
1365113Swnj 		(void) tcp_output(tp);
1374567Swnj 		break;
1384497Swnj 
1394809Swnj 	case PRU_SEND:
1405075Swnj 		sbappend(&so->so_snd, m);
1415089Swnj /*
1425089Swnj 		if (tp->t_flags & TF_PUSH)
1435075Swnj 			tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
1445089Swnj  */
1455089Swnj 		if (tp->t_flags & TF_URG)
1465089Swnj 			tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
1475113Swnj 		(void) tcp_output(tp);
1484567Swnj 		break;
1494567Swnj 
1504809Swnj 	case PRU_ABORT:
1515075Swnj 		tcp_drop(tp, ECONNABORTED);
1524567Swnj 		break;
1534567Swnj 
1544809Swnj 	case PRU_CONTROL:
1554886Swnj 		error = EOPNOTSUPP;
1564809Swnj 		break;
1574809Swnj 
1585113Swnj 	case PRU_SENSE:
1595113Swnj 		error = EOPNOTSUPP;
1605113Swnj 		break;
1615113Swnj 
1625113Swnj 	case PRU_RCVOOB:
1635113Swnj 		error = EOPNOTSUPP;
1645113Swnj 		break;
1655113Swnj 
1665113Swnj 	case PRU_SENDOOB:
1675113Swnj 		error = EOPNOTSUPP;
1685113Swnj 		break;
1695113Swnj 
1704809Swnj 	case PRU_SLOWTIMO:
1715075Swnj 		tcp_timers(tp, (int)addr);
1724809Swnj 		break;
1734809Swnj 
1744731Swnj 	default:
1754731Swnj 		panic("tcp_usrreq");
1764567Swnj 	}
1774567Swnj 	splx(s);
1784886Swnj 	return (error);
1794497Swnj }
180