⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_usrreq.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
	case PRU_RCVOOB:		if ((so->so_oobmark == 0 &&		    (so->so_state & SS_RCVATMARK) == 0) ||		    so->so_options & SO_OOBINLINE ||		    tp->t_oobflags & TCPOOB_HADDATA) {			error = EINVAL;			break;		}		if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {			error = EWOULDBLOCK;			break;		}		m->m_len = 1;		*mtod(m, caddr_t) = tp->t_iobc;		if (((long)nam & MSG_PEEK) == 0)			tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);		break;	case PRU_SENDOOB:		if (sbspace(&so->so_snd) < -512) {			m_freem(m);			error = ENOBUFS;			break;		}		/*		 * According to RFC961 (Assigned Protocols),		 * the urgent pointer points to the last octet		 * of urgent data.  We continue, however,		 * to consider it to indicate the first octet		 * of data past the urgent section.		 * Otherwise, snd_up should be one lower.		 */		sbappend(&so->so_snd, m);		tp->snd_up = tp->snd_una + so->so_snd.sb_cc;		tp->t_force = 1;		error = tcp_output(tp);		tp->t_force = 0;		break;	case PRU_SOCKADDR:#ifdef INET6		if (inp->inp_flags & INP_IPV6)			in6_setsockaddr(inp, nam);		else#endif			in_setsockaddr(inp, nam);		break;	case PRU_PEERADDR:#ifdef INET6		if (inp->inp_flags & INP_IPV6)			in6_setpeeraddr(inp, nam);		else#endif			in_setpeeraddr(inp, nam);		break;	/*	 * TCP slow timer went off; going through this	 * routine for tracing's sake.	 */	case PRU_SLOWTIMO:		tp = tcp_timers(tp, (long)nam);		req |= (long)nam << 8;		/* for debug's sake */		break;	default:		panic("tcp_usrreq");	}	if (tp && (so->so_options & SO_DEBUG))		tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0);	splx(s);	return (error);}inttcp_ctloutput(op, so, level, optname, mp)	int op;	struct socket *so;	int level, optname;	struct mbuf **mp;{	int error = 0, s;	struct inpcb *inp;	register struct tcpcb *tp;	register struct mbuf *m;	register int i;	s = splsoftnet();	inp = sotoinpcb(so);	if (inp == NULL) {		splx(s);		if (op == PRCO_SETOPT && *mp)			(void) m_free(*mp);		return (ECONNRESET);	}#ifdef INET6	tp = intotcpcb(inp);#endif /* INET6 */	if (level != IPPROTO_TCP) {#ifdef INET6		if (so->so_proto->pr_domain->dom_family == PF_INET6)			error = ip6_ctloutput(op, so, level, optname, mp);		else#endif /* INET6 */			error = ip_ctloutput(op, so, level, optname, mp);		splx(s);		return (error);	}#ifndef INET6	tp = intotcpcb(inp);#endif /* !INET6 */	switch (op) {	case PRCO_SETOPT:		m = *mp;		switch (optname) {		case TCP_NODELAY:			if (m == NULL || m->m_len < sizeof (int))				error = EINVAL;			else if (*mtod(m, int *))				tp->t_flags |= TF_NODELAY;			else				tp->t_flags &= ~TF_NODELAY;			break;		case TCP_MAXSEG:			if (m == NULL || m->m_len < sizeof (int)) {				error = EINVAL;				break;			}			i = *mtod(m, int *);			if (i > 0 && i <= tp->t_maxseg)				tp->t_maxseg = i;			else				error = EINVAL;			break;#ifdef TCP_SACK		case TCP_SACK_DISABLE:			if (m == NULL || m->m_len < sizeof (int)) {				error = EINVAL;				break;			}			if (TCPS_HAVEESTABLISHED(tp->t_state)) {				error = EPERM;				break;			}			if (tp->t_flags & TF_SIGNATURE) {				error = EPERM;				break;			}			if (*mtod(m, int *))				tp->sack_disable = 1;			else				tp->sack_disable = 0;			break;#endif#ifdef TCP_SIGNATURE		case TCP_SIGNATURE_ENABLE:			if (m == NULL || m->m_len < sizeof (int)) {				error = EINVAL;				break;			}			if (TCPS_HAVEESTABLISHED(tp->t_state)) {				error = EPERM;				break;			}			if (*mtod(m, int *)) {				tp->t_flags |= TF_SIGNATURE;#ifdef TCP_SACK				tp->sack_disable = 1;#endif /* TCP_SACK */			} else				tp->t_flags &= ~TF_SIGNATURE;			break;#endif /* TCP_SIGNATURE */ 		default:			error = ENOPROTOOPT;			break;		}		if (m)			(void) m_free(m);		break;	case PRCO_GETOPT:		*mp = m = m_get(M_WAIT, MT_SOOPTS);		m->m_len = sizeof(int);		switch (optname) {		case TCP_NODELAY:			*mtod(m, int *) = tp->t_flags & TF_NODELAY;			break;		case TCP_MAXSEG:			*mtod(m, int *) = tp->t_maxseg;			break;#ifdef TCP_SACK		case TCP_SACK_DISABLE:			*mtod(m, int *) = tp->sack_disable;			break;#endif		default:			error = ENOPROTOOPT;			break;		}		break;	}	splx(s);	return (error);}#ifndef TCP_SENDSPACE#define	TCP_SENDSPACE	1024*16;#endifu_int	tcp_sendspace = TCP_SENDSPACE;#ifndef TCP_RECVSPACE#define	TCP_RECVSPACE	1024*16;#endifu_int	tcp_recvspace = TCP_RECVSPACE;/* * Attach TCP protocol to socket, allocating * internet protocol control block, tcp control block, * bufer space, and entering LISTEN state if to accept connections. */inttcp_attach(so)	struct socket *so;{	register struct tcpcb *tp;	struct inpcb *inp;	int error;	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {		error = soreserve(so, tcp_sendspace, tcp_recvspace);		if (error)			return (error);	}	error = in_pcballoc(so, &tcbtable);	if (error)		return (error);	inp = sotoinpcb(so);	tp = tcp_newtcpcb(inp);	if (tp == NULL) {		int nofd = so->so_state & SS_NOFDREF;	/* XXX */		so->so_state &= ~SS_NOFDREF;	/* don't free the socket yet */		in_pcbdetach(inp);		so->so_state |= nofd;		return (ENOBUFS);	}	tp->t_state = TCPS_CLOSED;	return (0);}/* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). * If in ``let data drain'' option and linger null, just drop. * Otherwise (hard), mark socket disconnecting and drop * current input data; switch states based on user close, and * send segment to peer (with FIN). */struct tcpcb *tcp_disconnect(tp)	register struct tcpcb *tp;{	struct socket *so = tp->t_inpcb->inp_socket;	if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)		tp = tcp_close(tp);	else if ((so->so_options & SO_LINGER) && so->so_linger == 0)		tp = tcp_drop(tp, 0);	else {		soisdisconnecting(so);		sbflush(&so->so_rcv);		tp = tcp_usrclosed(tp);		if (tp)			(void) tcp_output(tp);	}	return (tp);}/* * User issued close, and wish to trail through shutdown states: * if never received SYN, just forget it.  If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state.  In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just have to play tedious game waiting * for peer to send FIN or not respond to keep-alives, etc. * We can let the user exit from the close as soon as the FIN is acked. */struct tcpcb *tcp_usrclosed(tp)	register struct tcpcb *tp;{	switch (tp->t_state) {	case TCPS_CLOSED:	case TCPS_LISTEN:	case TCPS_SYN_SENT:		tp->t_state = TCPS_CLOSED;		tp = tcp_close(tp);		break;	case TCPS_SYN_RECEIVED:	case TCPS_ESTABLISHED:		tp->t_state = TCPS_FIN_WAIT_1;		break;	case TCPS_CLOSE_WAIT:		tp->t_state = TCPS_LAST_ACK;		break;	}	if (tp && tp->t_state >= TCPS_FIN_WAIT_2) {		soisdisconnected(tp->t_inpcb->inp_socket);		/*		 * If we are in FIN_WAIT_2, we arrived here because the		 * application did a shutdown of the send side.  Like the		 * case of a transition from FIN_WAIT_1 to FIN_WAIT_2 after		 * a full close, we start a timer to make sure sockets are		 * not left in FIN_WAIT_2 forever.		 */		if (tp->t_state == TCPS_FIN_WAIT_2)			tp->t_timer[TCPT_2MSL] = tcp_maxidle;	}	return (tp);}/* * Look up a socket for ident.. */inttcp_ident(oldp, oldlenp, newp, newlen)	void *oldp;	size_t *oldlenp;	void *newp;	size_t newlen;{	int error = 0, s;	struct tcp_ident_mapping tir;	struct inpcb *inp;	struct sockaddr_in *fin, *lin;	if (oldp == NULL || newp != NULL || newlen != 0)		return (EINVAL);	if  (*oldlenp < sizeof(tir))		return (ENOMEM);	if ((error = copyin(oldp, &tir, sizeof (tir))) != 0 )		return (error);	if (tir.faddr.sa_len != sizeof (struct sockaddr) ||	    tir.faddr.sa_family != AF_INET)		return (EINVAL);	fin = (struct sockaddr_in *)&tir.faddr;	lin = (struct sockaddr_in *)&tir.laddr;	s = splsoftnet();	inp = in_pcbhashlookup(&tcbtable,  fin->sin_addr, fin->sin_port,	    lin->sin_addr, lin->sin_port);	if (inp == NULL) {		++tcpstat.tcps_pcbhashmiss;		inp = in_pcblookup(&tcbtable, &fin->sin_addr, fin->sin_port,		    &lin->sin_addr, lin->sin_port, 0);	}	if (inp != NULL && (inp->inp_socket->so_state & SS_CONNECTOUT)) {		tir.ruid = inp->inp_socket->so_ruid;		tir.euid = inp->inp_socket->so_euid;	} else {		tir.ruid = -1;		tir.euid = -1;	}	splx(s);	*oldlenp = sizeof (tir);	error = copyout((void *)&tir, oldp, sizeof (tir));	return (error);}/* * Sysctl for tcp variables. */inttcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)	int *name;	u_int namelen;	void *oldp;	size_t *oldlenp;	void *newp;	size_t newlen;{	/* All sysctl names at this level are terminal. */	if (namelen != 1)		return (ENOTDIR);	switch (name[0]) {	case TCPCTL_RFC1323:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &tcp_do_rfc1323));#ifdef TCP_SACK	case TCPCTL_SACK:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &tcp_do_sack));#endif	case TCPCTL_MSSDFLT:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &tcp_mssdflt));	case TCPCTL_KEEPINITTIME:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &tcptv_keep_init));	case TCPCTL_KEEPIDLE:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &tcp_keepidle));	case TCPCTL_KEEPINTVL:		return (sysctl_int(oldp, oldlenp, newp, newlen,		    &tcp_keepintvl));	case TCPCTL_SLOWHZ:		return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ));	case TCPCTL_BADDYNAMIC:		return (sysctl_struct(oldp, oldlenp, newp, newlen,		    baddynamicports.tcp, sizeof(baddynamicports.tcp)));	case TCPCTL_RECVSPACE:		return (sysctl_int(oldp, oldlenp, newp, newlen,&tcp_recvspace));	case TCPCTL_SENDSPACE:		return (sysctl_int(oldp, oldlenp, newp, newlen,&tcp_sendspace));	case TCPCTL_IDENT:		return (tcp_ident(oldp, oldlenp, newp, newlen));	default:		return (ENOPROTOOPT);	}	/* NOTREACHED */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -