xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5113)
1*5113Swnj /* tcp_usrreq.c 1.37 81/11/29 */
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*5113Swnj #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 		}
624954Swnj 		error = in_pcballoc(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) {
695075Swnj 				in_pcbfree(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:
794809Swnj 		break;
804809Swnj 
814809Swnj 	case PRU_CONNECT:
824954Swnj 		error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
834954Swnj 		if (error)
844886Swnj 			break;
855062Swnj 		tp = tcp_newtcpcb(inp);
865062Swnj 		if (tp == 0) {
875062Swnj 			inp->inp_faddr.s_addr = 0;
885062Swnj 			error = ENOBUFS;
895062Swnj 			break;
905062Swnj 		}
915062Swnj 		tp->t_inpcb = inp;
925062Swnj 		inp->inp_ppcb = (caddr_t)tp;
934886Swnj 		soisconnecting(so);
945075Swnj 		tp->t_state = TCPS_SYN_SENT;
95*5113Swnj 		(void) tcp_output(tp);
964567Swnj 		break;
974497Swnj 
984925Swnj 	case PRU_ACCEPT:
994954Swnj 		soisconnected(so);
1004954Swnj 		break;
1014925Swnj 
1024809Swnj 	case PRU_DISCONNECT:
1035075Swnj 		if (tp->t_state < TCPS_ESTABLISHED)
1045075Swnj 			tcp_close(tp);
1054886Swnj 		else {
1064886Swnj 			soisdisconnecting(so);
107*5113Swnj 			(void) tcp_output(tp);
1084886Swnj 		}
1094809Swnj 		break;
1104809Swnj 
1114809Swnj 	case PRU_SHUTDOWN:
1125089Swnj 		socantsendmore(so);
1135075Swnj 		switch (tp->t_state) {
1144497Swnj 
1155066Swnj 		case TCPS_LISTEN:
1165066Swnj 		case TCPS_SYN_SENT:
1175075Swnj 			tp->t_state = TCPS_CLOSED;
1184731Swnj 			break;
1194731Swnj 
1205089Swnj 		case TCPS_SYN_RECEIVED:
1215089Swnj 		case TCPS_ESTABLISHED:
1225075Swnj 			tp->t_state = TCPS_FIN_WAIT_1;
123*5113Swnj 			(void) tcp_output(tp);
1245075Swnj 			break;
1255075Swnj 
1265066Swnj 		case TCPS_CLOSE_WAIT:
1275075Swnj 			tp->t_state = TCPS_LAST_ACK;
128*5113Swnj 			(void) tcp_output(tp);
1294731Swnj 			break;
1304731Swnj 		}
1314567Swnj 		break;
1324497Swnj 
1334809Swnj 	case PRU_RCVD:
134*5113Swnj 		(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;
145*5113Swnj 		(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 
156*5113Swnj 	case PRU_SENSE:
157*5113Swnj 		error = EOPNOTSUPP;
158*5113Swnj 		break;
159*5113Swnj 
160*5113Swnj 	case PRU_RCVOOB:
161*5113Swnj 		error = EOPNOTSUPP;
162*5113Swnj 		break;
163*5113Swnj 
164*5113Swnj 	case PRU_SENDOOB:
165*5113Swnj 		error = EOPNOTSUPP;
166*5113Swnj 		break;
167*5113Swnj 
1684809Swnj 	case PRU_SLOWTIMO:
1695075Swnj 		tcp_timers(tp, (int)addr);
1704809Swnj 		break;
1714809Swnj 
1724731Swnj 	default:
1734731Swnj 		panic("tcp_usrreq");
1744567Swnj 	}
1754567Swnj 	splx(s);
1764886Swnj 	return (error);
1774497Swnj }
178