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

📄 tcp_input.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	$OpenBSD: tcp_input.c,v 1.60 2000/04/28 00:31:48 itojun Exp $	*//*	$NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $	*//* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)tcp_input.c	8.5 (Berkeley) 4/10/94 *//*%%% portions-copyright-nrl-95Portions of this software are Copyright 1995-1998 by Randall Atkinson,Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All RightsReserved. All rights under this copyright have been assigned to the USNaval Research Laboratory (NRL). The NRL Copyright Notice and LicenseAgreement Version 1.1 (January 17, 1995) applies to these portions of thesoftware.You should have received a copy of the license with this software. If youdidn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.*/#ifndef TUBA_INCLUDE#include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/errno.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/in_pcb.h>#include <netinet/ip_var.h>#include <netinet/tcp.h>#include <netinet/tcp_fsm.h>#include <netinet/tcp_seq.h>#include <netinet/tcp_timer.h>#include <netinet/tcp_var.h>#include <netinet/tcpip.h>#include <netinet/tcp_debug.h>#ifndef PMON#include <dev/rndvar.h>#endif /* PMON */#include <machine/stdarg.h>#ifdef TCP_SIGNATURE#include <sys/md5k.h>#endif /* TCP_SIGNATURE */#ifdef PMON#include <pmon.h>#endif /* PMON */#ifdef IPSEC#include <netinet/ip_ipsp.h>#endif /* IPSEC */#ifdef INET6#ifndef INET#include <netinet/in.h>#endif#include <sys/domain.h>#include <netinet6/in6_var.h>#include <netinet/ip6.h>#include <netinet6/ip6_var.h>#include <netinet6/tcpipv6.h>#include <netinet/icmp6.h>#include <netinet6/nd6.h>#ifndef CREATE_IPV6_MAPPED#define CREATE_IPV6_MAPPED(a6, a4) \do { \	bzero(&(a6), sizeof(a6));			\	(a6).s6_addr[10] = (a6).s6_addr[11] = 0xff;	\	*(u_int32_t *)&(a6).s6_addr[12] = (a4);		\} while (0)#endifstruct	tcpiphdr tcp_saveti;struct  tcpipv6hdr tcp_saveti6;/* for the packet header length in the mbuf */#define M_PH_LEN(m)      (((struct mbuf *)(m))->m_pkthdr.len)#define M_V6_LEN(m)      (M_PH_LEN(m) - sizeof(struct ip6_hdr))#define M_V4_LEN(m)      (M_PH_LEN(m) - sizeof(struct ip))#endif /* INET6 */int	tcprexmtthresh = 3;struct	tcpiphdr tcp_saveti;int	tcptv_keep_init = TCPTV_KEEP_INIT;extern u_long sb_max;#endif /* TUBA_INCLUDE */#define TCP_PAWS_IDLE	(24 * 24 * 60 * 60 * PR_SLOWHZ)/* for modulo comparisons of timestamps */#define TSTMP_LT(a,b)	((int)((a)-(b)) < 0)#define TSTMP_GEQ(a,b)	((int)((a)-(b)) >= 0)/* * Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */#ifdef INET6#define ND6_HINT(tp) \do { \	if (tp && tp->t_inpcb && (tp->t_inpcb->inp_flags & INP_IPV6) \	 && !(tp->t_inpcb->inp_flags & INP_IPV6_MAPPED) \	 && tp->t_inpcb->inp_route6.ro_rt) { \		nd6_nud_hint(tp->t_inpcb->inp_route6.ro_rt, NULL); \	} \} while (0)#else#define ND6_HINT(tp)#endif/* * Insert segment ti into reassembly queue of tcp with * control block tp.  Return TH_FIN if reassembly now includes * a segment with FIN.  The macro form does the common case inline * (segment is the next to be received on an established connection, * and the queue is empty), avoiding linkage into and removal * from the queue and repetition of various conversions. * Set DELACK for segments received in order, but ack immediately * when segments are out of order (so fast retransmit can work). */#ifndef TUBA_INCLUDEinttcp_reass(tp, th, m, tlen)	register struct tcpcb *tp;	register struct tcphdr *th;	struct mbuf *m;	int *tlen;{	register struct ipqent *p, *q, *nq, *tiqe;	struct socket *so = tp->t_inpcb->inp_socket;	int flags;	/*	 * Call with th==0 after become established to	 * force pre-ESTABLISHED data up to user socket.	 */	if (th == 0)		goto present;	/*	 * Allocate a new queue entry, before we throw away any data.	 * If we can't, just drop the packet.  XXX	 */	MALLOC(tiqe, struct ipqent *, sizeof (struct ipqent), M_IPQ, M_NOWAIT);	if (tiqe == NULL) {		tcpstat.tcps_rcvmemdrop++;		m_freem(m);		return (0);	}	/*	 * Find a segment which begins after this one does.	 */	for (p = NULL, q = tp->segq.lh_first; q != NULL;	    p = q, q = q->ipqe_q.le_next)		if (SEQ_GT(q->ipqe_tcp->th_seq, th->th_seq))			break;	/*	 * If there is a preceding segment, it may provide some of	 * our data already.  If so, drop the data from the incoming	 * segment.  If it provides all of our data, drop us.	 */	if (p != NULL) {		register struct tcphdr *phdr = p->ipqe_tcp;		register int i;		/* conversion to int (in i) handles seq wraparound */		i = phdr->th_seq + phdr->th_reseqlen - th->th_seq;		if (i > 0) {		        if (i >= *tlen) {				tcpstat.tcps_rcvduppack++;				tcpstat.tcps_rcvdupbyte += *tlen;				m_freem(m);				FREE(tiqe, M_IPQ);				return (0);			}			m_adj(m, i);			*tlen -= i;			th->th_seq += i;		}	}	tcpstat.tcps_rcvoopack++;	tcpstat.tcps_rcvoobyte += *tlen;	/*	 * While we overlap succeeding segments trim them or,	 * if they are completely covered, dequeue them.	 */	for (; q != NULL; q = nq) {		register struct tcphdr *qhdr = q->ipqe_tcp;		register int i = (th->th_seq + *tlen) - qhdr->th_seq;		if (i <= 0)			break;		if (i < qhdr->th_reseqlen) {			qhdr->th_seq += i;			qhdr->th_reseqlen -= i;			m_adj(q->ipqe_m, i);			break;		}		nq = q->ipqe_q.le_next;		m_freem(q->ipqe_m);		LIST_REMOVE(q, ipqe_q);		FREE(q, M_IPQ);	}	/* Insert the new fragment queue entry into place. */	tiqe->ipqe_m = m;	th->th_reseqlen = *tlen;	tiqe->ipqe_tcp = th;	if (p == NULL) {		LIST_INSERT_HEAD(&tp->segq, tiqe, ipqe_q);	} else {		LIST_INSERT_AFTER(p, tiqe, ipqe_q);	}present:	/*	 * Present data to user, advancing rcv_nxt through	 * completed sequence space.	 */	if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)		return (0);	q = tp->segq.lh_first;	if (q == NULL || q->ipqe_tcp->th_seq != tp->rcv_nxt)		return (0);	if (tp->t_state == TCPS_SYN_RECEIVED && q->ipqe_tcp->th_reseqlen)		return (0);	do {		tp->rcv_nxt += q->ipqe_tcp->th_reseqlen;		flags = q->ipqe_tcp->th_flags & TH_FIN;		nq = q->ipqe_q.le_next;		LIST_REMOVE(q, ipqe_q);		ND6_HINT(tp);		if (so->so_state & SS_CANTRCVMORE)			m_freem(q->ipqe_m);		else			sbappend(&so->so_rcv, q->ipqe_m);		FREE(q, M_IPQ);		q = nq;	} while (q != NULL && q->ipqe_tcp->th_seq == tp->rcv_nxt);	sorwakeup(so);	return (flags);}/* * First check for a port-specific bomb. We do not want to drop half-opens * for other ports if this is the only port being bombed.  We only check * the bottom 40 half open connections, to avoid wasting too much time. * * Or, otherwise it is more likely a generic syn bomb, so delete the oldest * half-open connection. */voidtcpdropoldhalfopen(avoidtp, port)	struct tcpcb *avoidtp;	u_int16_t port;{	register struct inpcb *inp;	register struct tcpcb *tp;	int ncheck = 40;	int s;	s = splnet();	inp = tcbtable.inpt_queue.cqh_first;	if (inp)						/* XXX */	for (; inp != (struct inpcb *)&tcbtable.inpt_queue && --ncheck;	    inp = inp->inp_queue.cqe_prev) {		if ((tp = (struct tcpcb *)inp->inp_ppcb) &&		    tp != avoidtp &&		    tp->t_state == TCPS_SYN_RECEIVED &&		    port == inp->inp_lport) {			tcp_close(tp);			goto done;		}	}	inp = tcbtable.inpt_queue.cqh_first;	if (inp)						/* XXX */	for (; inp != (struct inpcb *)&tcbtable.inpt_queue;	    inp = inp->inp_queue.cqe_prev) {		if ((tp = (struct tcpcb *)inp->inp_ppcb) &&		    tp != avoidtp &&		    tp->t_state == TCPS_SYN_RECEIVED) {			tcp_close(tp);			goto done;		}	}done:	splx(s);}#if defined(INET6) && !defined(TCP6)inttcp6_input(mp, offp, proto)	struct mbuf **mp;	int *offp, proto;{	struct mbuf *m = *mp;#if defined(NFAITH) && 0 < NFAITH	if (m->m_pkthdr.rcvif) {		if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {			/* XXX send icmp6 host/port unreach? */			m_freem(m);			return IPPROTO_DONE;		}	}#endif	/*	 * draft-itojun-ipv6-tcp-to-anycast	 * better place to put this in?	 */	if (m->m_flags & M_ANYCAST6) {		if (m->m_len >= sizeof(struct ip6_hdr)) {			struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);			icmp6_error(m, ICMP6_DST_UNREACH,				ICMP6_DST_UNREACH_ADDR,				(caddr_t)&ip6->ip6_dst - (caddr_t)ip6);		} else			m_freem(m);		return IPPROTO_DONE;	}	tcp_input(m, *offp, proto);	return IPPROTO_DONE;}#endif/* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */void#if __STDC__tcp_input(struct mbuf *m, ...)#elsetcp_input(m, va_alist)	register struct mbuf *m;#endif{	register struct tcpiphdr *ti;	register struct inpcb *inp;	caddr_t optp = NULL;	int optlen = 0;	int len, tlen, off;	register struct tcpcb *tp = 0;	register int tiflags;	struct socket *so = NULL;	int todrop, acked, ourfinisacked, needoutput = 0;	int hdroptlen = 0;	short ostate = 0;	struct in_addr laddr;	int dropsocket = 0;	int iss = 0;	u_long tiwin;	u_int32_t ts_val, ts_ecr;	int ts_present = 0;	int iphlen;	va_list ap;	register struct tcphdr *th;#ifdef IPSEC	struct tdb *tdb = NULL;#endif /* IPSEC */#ifdef INET6	struct in6_addr laddr6;	unsigned short is_ipv6;     /* Type of incoming datagram. */	struct ip6_hdr *ipv6 = NULL;#endif /* INET6 */	va_start(ap, m);	iphlen = va_arg(ap, int);	va_end(ap);	tcpstat.tcps_rcvtotal++;#ifdef IPSEC	/* Save the last SA which was used to process the mbuf */	if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) {		struct tdb_ident *tdbi = m->m_pkthdr.tdbi;		/* XXX gettdb() should really be called at spltdb().      */		/* XXX this is splsoftnet(), currently they are the same. */		tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);		free(m->m_pkthdr.tdbi, M_TEMP);		m->m_pkthdr.tdbi = NULL;	}#endif /* IPSEC */#ifdef INET6	/*	 * Before we do ANYTHING, we have to figure out if it's TCP/IPv6 or	 * TCP/IPv4. 	 */	is_ipv6 = mtod(m, struct ip *)->ip_v == 6;#endif /* INET6 */	/*	 * Get IP and TCP header together in first mbuf.	 * Note: IP leaves IP header in first mbuf.	 */#ifndef INET6	ti = mtod(m, struct tcpiphdr *);#else /* INET6 */	if (!is_ipv6)#endif /* INET6 */	if (iphlen > sizeof (struct ip)) {#if 0	/*XXX*/		ip_stripoptions(m, (struct mbuf *)0);#else		printf("extension headers are not allowed\n");		m_freem(m);		return;#endif	}	if (m->m_len < iphlen + sizeof(struct tcphdr)) {		if ((m = m_pullup2(m, iphlen + sizeof(struct tcphdr))) == 0) {			tcpstat.tcps_rcvshort++;			return;		}#ifndef INET6		ti = mtod(m, struct tcpiphdr *);#endif /* INET6 */	}	tlen = m->m_pkthdr.len - iphlen;#ifdef INET6	/*	 * After that, do initial segment processing which is still very	 * dependent on what IP version you're using.

⌨️ 快捷键说明

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