xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 5089)
1*5089Swnj /* tcp_usrreq.c 1.36 81/11/26 */
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"
9*5089Swnj #include "../net/in.h"
10*5089Swnj #include "../net/in_pcb.h"
11*5089Swnj #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"
17*5089Swnj #include "../net/tcp_seq.h"
18*5089Swnj #include "../net/tcp_timer.h"
194809Swnj #include "../net/tcp_var.h"
20*5089Swnj #include "../net/tcpip.h"
214809Swnj #include "/usr/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;
395075Swnj 	struct tcpiphdr ti;
404567Swnj COUNT(TCP_USRREQ);
414497Swnj 
424886Swnj 	/*
434886Swnj 	 * Make sure attached.  If not,
444886Swnj 	 * only PRU_ATTACH is valid.
454886Swnj 	 */
46*5089Swnj 	if (inp == 0 && req != PRU_ATTACH) {
475075Swnj 		splx(s);
485075Swnj 		return (EINVAL);
495075Swnj 	}
505075Swnj 	if (inp) {
514911Swnj 		tp = intotcpcb(inp);
524731Swnj #ifdef KPROF
535075Swnj 		tcp_acounts[tp->t_state][req]++;
544731Swnj #endif
554911Swnj 	}
564809Swnj 	switch (req) {
574497Swnj 
584809Swnj 	case PRU_ATTACH:
594954Swnj 		if (inp) {
604809Swnj 			error = EISCONN;
614911Swnj 			break;
624886Swnj 		}
634954Swnj 		error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
645075Swnj 		if (error)
654954Swnj 			break;
664954Swnj 		inp = (struct inpcb *)so->so_pcb;
675062Swnj 		if (so->so_options & SO_ACCEPTCONN) {
685062Swnj 			tp = tcp_newtcpcb(inp);
695062Swnj 			if (tp == 0) {
705075Swnj 				in_pcbfree(inp);
715062Swnj 				error = ENOBUFS;
725062Swnj 				break;
735062Swnj 			}
745075Swnj 			tp->t_state = TCPS_LISTEN;
755062Swnj 		} else
765075Swnj 			tp->t_state = TCPS_CLOSED;
774567Swnj 		break;
784497Swnj 
794809Swnj 	case PRU_DETACH:
804809Swnj 		break;
814809Swnj 
824809Swnj 	case PRU_CONNECT:
834954Swnj 		error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
844954Swnj 		if (error)
854886Swnj 			break;
865062Swnj 		tp = tcp_newtcpcb(inp);
875062Swnj 		if (tp == 0) {
885062Swnj 			inp->inp_faddr.s_addr = 0;
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;
965075Swnj 		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);
1085075Swnj 			tcp_output(tp);
1094886Swnj 		}
1104809Swnj 		break;
1114809Swnj 
1124809Swnj 	case PRU_SHUTDOWN:
113*5089Swnj 		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 
121*5089Swnj 		case TCPS_SYN_RECEIVED:
122*5089Swnj 		case TCPS_ESTABLISHED:
1235075Swnj 			tp->t_state = TCPS_FIN_WAIT_1;
1245075Swnj 			tcp_output(tp);
1255075Swnj 			break;
1265075Swnj 
1275066Swnj 		case TCPS_CLOSE_WAIT:
1285075Swnj 			tp->t_state = TCPS_LAST_ACK;
1295075Swnj 			tcp_output(tp);
1304731Swnj 			break;
1314731Swnj 		}
1324567Swnj 		break;
1334497Swnj 
1344809Swnj 	case PRU_RCVD:
1355075Swnj 		tcp_output(tp);
1364567Swnj 		break;
1374497Swnj 
1384809Swnj 	case PRU_SEND:
1395075Swnj 		sbappend(&so->so_snd, m);
140*5089Swnj /*
141*5089Swnj 		if (tp->t_flags & TF_PUSH)
1425075Swnj 			tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
143*5089Swnj  */
144*5089Swnj 		if (tp->t_flags & TF_URG)
145*5089Swnj 			tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1;
1465075Swnj 		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 
1574809Swnj 	case PRU_SLOWTIMO:
1585075Swnj 		tcp_timers(tp, (int)addr);
1594809Swnj 		break;
1604809Swnj 
1614731Swnj 	default:
1624731Swnj 		panic("tcp_usrreq");
1634567Swnj 	}
1644567Swnj 	splx(s);
1654886Swnj 	return (error);
1664497Swnj }
167