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

📄 tcp_subr.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives	 * reasonable initial retransmit time.	 */	tp->t_srtt = TCPTV_SRTTBASE;	tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << (TCP_RTTVAR_SHIFT + 2 - 1);	tp->t_rttmin = TCPTV_MIN;	TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),	    TCPTV_MIN, TCPTV_REXMTMAX);	tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;	tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;#ifdef INET6	/*	 * If we want to use tp->pf for a quick-n-easy way to determine	 * the outbound dgram type, we cannot make this decision	 * until a connection is established!  Bzero() sets pf to zero, and	 * that's the way we want it, unless, of course, it's an AF_INET	 * socket...	 */	if ((inp->inp_flags & INP_IPV6) == 0)		tp->pf = PF_INET;  /* If AF_INET socket, we can't do v6 from it. */#else	tp->pf = PF_INET;#endif#ifdef INET6	if (inp->inp_flags & INP_IPV6) 		inp->inp_ipv6.ip6_hlim = ip6_defhlim;	else#endif /* INET6 */		inp->inp_ip.ip_ttl = ip_defttl;	inp->inp_ppcb = (caddr_t)tp;	return (tp);}/* * Drop a TCP connection, reporting * the specified error.  If connection is synchronized, * then send a RST to peer. */struct tcpcb *tcp_drop(tp, errno)	register struct tcpcb *tp;	int errno;{	struct socket *so = tp->t_inpcb->inp_socket;	if (TCPS_HAVERCVDSYN(tp->t_state)) {		tp->t_state = TCPS_CLOSED;		(void) tcp_output(tp);		tcpstat.tcps_drops++;	} else		tcpstat.tcps_conndrops++;	if (errno == ETIMEDOUT && tp->t_softerror)		errno = tp->t_softerror;	so->so_error = errno;	return (tcp_close(tp));}/* * Close a TCP control block: *	discard all space held by the tcp *	discard internet protocol block *	wake up any sleepers */struct tcpcb *tcp_close(tp)	register struct tcpcb *tp;{	register struct ipqent *qe;	struct inpcb *inp = tp->t_inpcb;	struct socket *so = inp->inp_socket;#ifdef TCP_SACK	struct sackhole *p, *q;#endif#ifdef RTV_RTT	register struct rtentry *rt;#ifdef INET6	register int bound_to_specific = 0;  /* I.e. non-default */	/*	 * This code checks the nature of the route for this connection.	 * Normally this is done by two simple checks in the next	 * INET/INET6 ifdef block, but because of two possible lower layers,	 * that check is done here.	 *	 * Perhaps should be doing this only for a RTF_HOST route.	 */	rt = inp->inp_route.ro_rt;  /* Same for route or route6. */	if (tp->pf == PF_INET6) {		if (rt)			bound_to_specific =			    !(IN6_IS_ADDR_UNSPECIFIED(&			    ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr));	} else {		if (rt)			bound_to_specific =			    (((struct sockaddr_in *)rt_key(rt))->			    sin_addr.s_addr != INADDR_ANY);	}#endif /* INET6 */	/*	 * If we sent enough data to get some meaningful characteristics,	 * save them in the routing entry.  'Enough' is arbitrarily 	 * defined as the sendpipesize (default 4K) * 16.  This would	 * give us 16 rtt samples assuming we only get one sample per	 * window (the usual case on a long haul net).  16 samples is	 * enough for the srtt filter to converge to within 5% of the correct	 * value; fewer samples and we could save a very bogus rtt.	 *	 * Don't update the default route's characteristics and don't	 * update anything that the user "locked".	 */#ifdef INET6	/*	 * Note that rt and bound_to_specific are set above.	 */	if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&	    rt && bound_to_specific) {#else /* INET6 */	if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&	    (rt = inp->inp_route.ro_rt) &&	    satosin(rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {#endif /* INET6 */		register u_long i = 0;		if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {			i = tp->t_srtt *			    (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));			if (rt->rt_rmx.rmx_rtt && i)				/*				 * filter this update to half the old & half				 * the new values, converting scale.				 * See route.h and tcp_var.h for a				 * description of the scaling constants.				 */				rt->rt_rmx.rmx_rtt =				    (rt->rt_rmx.rmx_rtt + i) / 2;			else				rt->rt_rmx.rmx_rtt = i;		}		if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {			i = tp->t_rttvar *			    (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));			if (rt->rt_rmx.rmx_rttvar && i)				rt->rt_rmx.rmx_rttvar =				    (rt->rt_rmx.rmx_rttvar + i) / 2;			else				rt->rt_rmx.rmx_rttvar = i;		}		/*		 * update the pipelimit (ssthresh) if it has been updated		 * already or if a pipesize was specified & the threshhold		 * got below half the pipesize.  I.e., wait for bad news		 * before we start updating, then update on both good		 * and bad news.		 */		if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&		    (i = tp->snd_ssthresh) && rt->rt_rmx.rmx_ssthresh) ||		    i < (rt->rt_rmx.rmx_sendpipe / 2)) {			/*			 * convert the limit from user data bytes to			 * packets then to packet data bytes.			 */			i = (i + tp->t_maxseg / 2) / tp->t_maxseg;			if (i < 2)				i = 2;#ifdef INET6			if (tp->pf == PF_INET6)				i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr)				    + sizeof(struct ip6_hdr));			else#endif /* INET6 */				i *= (u_long)(tp->t_maxseg +				    sizeof (struct tcpiphdr));			if (rt->rt_rmx.rmx_ssthresh)				rt->rt_rmx.rmx_ssthresh =				    (rt->rt_rmx.rmx_ssthresh + i) / 2;			else				rt->rt_rmx.rmx_ssthresh = i;		}	}#endif /* RTV_RTT */	/* free the reassembly queue, if any */#ifdef INET6	/* Reassembling TCP segments in v6 might be sufficiently different	 * to merit two codepaths to free the reasssembly queue.	 * If an undecided TCP socket, then the IPv4 codepath will be used 	 * because it won't matter much anyway.	 */	if (tp->pf == AF_INET6) {		while ((qe = tp->segq.lh_first) != NULL) {			LIST_REMOVE(qe, ipqe_q);			m_freem(qe->ipqe_m);			FREE(qe, M_IPQ);		}	} else#endif /* INET6 */		while ((qe = tp->segq.lh_first) != NULL) {			LIST_REMOVE(qe, ipqe_q);			m_freem(qe->ipqe_m);			FREE(qe, M_IPQ);		}#ifdef TCP_SACK	/* Free SACK holes. */	q = p = tp->snd_holes;	while (p != 0) {		q = p->next;		free(p, M_PCB);		p = q;	}#endif	if (tp->t_template)		(void) m_free(tp->t_template);	free(tp, M_PCB);	inp->inp_ppcb = 0;	soisdisconnected(so);	in_pcbdetach(inp);	tcpstat.tcps_closed++;	return ((struct tcpcb *)0);}voidtcp_drain(){}/* * Notify a tcp user of an asynchronous error; * store error as soft error, but wake up user * (for now, won't do anything until can select for soft error). */voidtcp_notify(inp, error)	struct inpcb *inp;	int error;{	register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;	register struct socket *so = inp->inp_socket;	/*	 * Ignore some errors if we are hooked up.	 * If connection hasn't completed, has retransmitted several times,	 * and receives a second error, give up now.  This is better	 * than waiting a long time to establish a connection that	 * can never complete.	 */	if (tp->t_state == TCPS_ESTABLISHED &&	     (error == EHOSTUNREACH || error == ENETUNREACH ||	      error == EHOSTDOWN)) {		return;	} else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&	    tp->t_rxtshift > 3 && tp->t_softerror)		so->so_error = error;	else 		tp->t_softerror = error;	wakeup((caddr_t) &so->so_timeo);	sorwakeup(so);	sowwakeup(so);}#if defined(INET6) && !defined(TCP6)voidtcp6_ctlinput(cmd, sa, d)	int cmd;	struct sockaddr *sa;	void *d;{	(void)tcp_ctlinput(cmd, sa, NULL);	/*XXX*/}#endifvoid *tcp_ctlinput(cmd, sa, v)	int cmd;	struct sockaddr *sa;	register void *v;{	register struct ip *ip = v;	register struct tcphdr *th;	extern int inetctlerrmap[];	void (*notify) __P((struct inpcb *, int)) = tcp_notify;	int errno;	if ((unsigned)cmd >= PRC_NCMDS)		return NULL;	errno = inetctlerrmap[cmd];	if (cmd == PRC_QUENCH)		notify = tcp_quench;	else if (PRC_IS_REDIRECT(cmd))		notify = in_rtchange, ip = 0;	else if (cmd == PRC_HOSTDEAD)		ip = 0;	else if (errno == 0)		return NULL;#ifdef INET6	if (sa->sa_family == AF_INET6) {		if (ip) {			struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;			th = (struct tcphdr *)(ipv6 + 1);#if 0 /*XXX*/			in6_pcbnotify(&tcbtable, sa, th->th_dport,			    &ipv6->ip6_src, th->th_sport, cmd, notify);#endif		} else {#if 0 /*XXX*/			in6_pcbnotify(&tcbtable, sa, 0,			    (struct in6_addr *)&in6addr_any, 0, cmd, notify);#endif		}	} else#endif /* INET6 */	{		if (ip) {			th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));			in_pcbnotify(&tcbtable, sa, th->th_dport, ip->ip_src,			    th->th_sport, errno, notify);		} else			in_pcbnotifyall(&tcbtable, sa, errno, notify);	}	return NULL;}/* * When a source quench is received, close congestion window * to one segment.  We will gradually open it again as we proceed. */voidtcp_quench(inp, errno)	struct inpcb *inp;	int errno;{	struct tcpcb *tp = intotcpcb(inp);	if (tp)		tp->snd_cwnd = tp->t_maxseg;}#ifdef TCP_SIGNATUREinttcp_signature_tdb_attach(){	return (0);}inttcp_signature_tdb_init(tdbp, xsp, ii)	struct tdb *tdbp;	struct xformsw *xsp;	struct ipsecinit *ii;{	char *c;#define isdigit(c)	  (((c) >= '0') && ((c) <= '9'))#define isalpha(c)	( (((c) >= 'A') && ((c) <= 'Z')) || \			  (((c) >= 'a') && ((c) <= 'z')) )	if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80))		return (EINVAL);	c = (char *)ii->ii_authkey;	while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) {		if (isdigit(*c)) {			if (*(c + 1) == ' ')				return (EINVAL);		} else {			if (!isalpha(*c))				return (EINVAL);		}		c++;	}	if (!isdigit(*c) && !isalpha(*c))		return (EINVAL);	tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);	if (tdbp->tdb_amxkey == NULL)		return (ENOMEM);	bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);	tdbp->tdb_amxkeylen = ii->ii_authkeylen;	return (0);}inttcp_signature_tdb_zeroize(tdbp)	struct tdb *tdbp;{	if (tdbp->tdb_amxkey) {		bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);		free(tdbp->tdb_amxkey, M_XDATA);		tdbp->tdb_amxkey = NULL;	}	return (0);}inttcp_signature_tdb_input(m, tdbp, skip, protoff)	struct mbuf *m;	struct tdb *tdbp;	int skip, protoff;{	return (0);}inttcp_signature_tdb_output(m, tdbp, mp, skip, protoff)	struct mbuf *m;	struct tdb *tdbp;	struct mbuf **mp;	int skip, protoff;{	return (EINVAL);}inttcp_signature_apply(fstate, data, len)	caddr_t fstate;	caddr_t data;	unsigned int len;{	MD5Update((MD5_CTX *)fstate, (char *)data, len);	return 0;}#endif /* TCP_SIGNATURE */

⌨️ 快捷键说明

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