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

📄 tcp.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	newconf.nwtc_flags= ((unsigned long)new_di_flags		<< 16) | new_en_flags;	all_flags= new_en_flags | new_di_flags;	/* check the access modes */	if ((all_flags & NWTC_LOCPORT_MASK) != NWTC_LP_UNSET)	{		for (i=0, fd_ptr= tcp_fd_table; i<TCP_FD_NR; i++, fd_ptr++)		{			if (fd_ptr == tcp_fd)				continue;			if (!(fd_ptr->tf_flags & TFF_INUSE))				continue;			if (fd_ptr->tf_port != tcp_fd->tf_port)				continue;			flags= fd_ptr->tf_tcpconf.nwtc_flags;			if ((flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)				continue;			if (fd_ptr->tf_tcpconf.nwtc_locport !=				newconf.nwtc_locport)				continue;			if ((flags & NWTC_ACC_MASK) != (all_flags  &				NWTC_ACC_MASK) ||				(all_flags & NWTC_ACC_MASK) == NWTC_EXCL)			{				tcp_fd->tf_flags &= ~TFF_IOCTL_IP;				reply_thr_get(tcp_fd, EADDRINUSE, TRUE);				bf_afree(data);				return NW_OK;			}		}	}					tcp_fd->tf_tcpconf= newconf;	if ((all_flags & NWTC_ACC_MASK) &&		((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET ||		(all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL) &&		(all_flags & NWTC_REMADDR_MASK) &&		(all_flags & NWTC_REMPORT_MASK))		tcp_fd->tf_flags |= TFF_CONF_SET;	else	{		tcp_fd->tf_flags &= ~TFF_CONF_SET;	}	bf_afree(data);	tcp_fd->tf_flags &= ~TFF_IOCTL_IP;	reply_thr_get(tcp_fd, NW_OK, TRUE);	return NW_OK;}/*tcp_setopt*/PRIVATE int tcp_setopt(tcp_fd)tcp_fd_t *tcp_fd;{	nwio_tcpopt_t *tcpopt;	nwio_tcpopt_t oldopt, newopt;	acc_t *data;	unsigned int new_en_flags, new_di_flags,		old_en_flags, old_di_flags;	data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,		sizeof(nwio_tcpopt_t), TRUE);	if (!data)		return EFAULT;	data= bf_packIffLess(data, sizeof(nwio_tcpopt_t));assert (data->acc_length == sizeof(nwio_tcpopt_t));	tcpopt= (nwio_tcpopt_t *)ptr2acc_data(data);	oldopt= tcp_fd->tf_tcpopt;	newopt= *tcpopt;	old_en_flags= oldopt.nwto_flags & 0xffff;	old_di_flags= (oldopt.nwto_flags >> 16) & 0xffff;	new_en_flags= newopt.nwto_flags & 0xffff;	new_di_flags= (newopt.nwto_flags >> 16) & 0xffff;	if (new_en_flags & new_di_flags)	{		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;		reply_thr_get(tcp_fd, EBADMODE, TRUE);		return NW_OK;	}	/* NWTO_SND_URG_MASK */	if (!((new_en_flags | new_di_flags) & NWTO_SND_URG_MASK))	{		new_en_flags |= (old_en_flags & NWTO_SND_URG_MASK);		new_di_flags |= (old_di_flags & NWTO_SND_URG_MASK);	}	/* NWTO_RCV_URG_MASK */	if (!((new_en_flags | new_di_flags) & NWTO_RCV_URG_MASK))	{		new_en_flags |= (old_en_flags & NWTO_RCV_URG_MASK);		new_di_flags |= (old_di_flags & NWTO_RCV_URG_MASK);	}	/* NWTO_BSD_URG_MASK */	if (!((new_en_flags | new_di_flags) & NWTO_BSD_URG_MASK))	{		new_en_flags |= (old_en_flags & NWTO_BSD_URG_MASK);		new_di_flags |= (old_di_flags & NWTO_BSD_URG_MASK);	}	else	{		if (tcp_fd->tf_conn == NULL)		{			bf_afree(data);			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get(tcp_fd, EINVAL, TRUE);			return NW_OK;		}	}	/* NWTO_DEL_RST_MASK */	if (!((new_en_flags | new_di_flags) & NWTO_DEL_RST_MASK))	{		new_en_flags |= (old_en_flags & NWTO_DEL_RST_MASK);		new_di_flags |= (old_di_flags & NWTO_DEL_RST_MASK);	}	/* NWTO_BULK_MASK */	if (!((new_en_flags | new_di_flags) & NWTO_BULK_MASK))	{		new_en_flags |= (old_en_flags & NWTO_BULK_MASK);		new_di_flags |= (old_di_flags & NWTO_BULK_MASK);	}	newopt.nwto_flags= ((unsigned long)new_di_flags << 16) |		new_en_flags;	tcp_fd->tf_tcpopt= newopt;	if (newopt.nwto_flags & NWTO_SND_URG)		tcp_fd->tf_flags |= TFF_WR_URG;	else		tcp_fd->tf_flags &= ~TFF_WR_URG;	if (newopt.nwto_flags & NWTO_RCV_URG)		tcp_fd->tf_flags |= TFF_RECV_URG;	else		tcp_fd->tf_flags &= ~TFF_RECV_URG;	if (tcp_fd->tf_conn)	{		if (newopt.nwto_flags & NWTO_BSD_URG)			tcp_fd->tf_conn->tc_flags |= TCF_BSD_URG;		else			tcp_fd->tf_conn->tc_flags &= ~TCF_BSD_URG;	}	if (newopt.nwto_flags & NWTO_DEL_RST)		tcp_fd->tf_flags |= TFF_DEL_RST;	else		tcp_fd->tf_flags &= ~TFF_DEL_RST;	if (newopt.nwto_flags & NWTO_BULK)		tcp_fd->tf_flags &= ~TFF_PUSH_DATA;	else		tcp_fd->tf_flags |= TFF_PUSH_DATA;	bf_afree(data);	tcp_fd->tf_flags &= ~TFF_IOCTL_IP;	reply_thr_get(tcp_fd, NW_OK, TRUE);	return NW_OK;}PRIVATE tcpport_t find_unused_port(fd)int fd;{	tcpport_t port, nw_port;	for (port= 0x8000+fd; port < 0xffff-TCP_FD_NR; port+= TCP_FD_NR)	{		nw_port= htons(port);		if (is_unused_port(nw_port))			return nw_port;	}	for (port= 0x8000; port < 0xffff; port++)	{		nw_port= htons(port);		if (is_unused_port(nw_port))			return nw_port;	}	ip_panic(( "unable to find unused port (shouldn't occur)" ));	return 0;}PRIVATE int is_unused_port(port)tcpport_t port;{	int i;	tcp_fd_t *tcp_fd;	tcp_conn_t *tcp_conn;	for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,		tcp_fd++)	{		if (!(tcp_fd->tf_flags & TFF_CONF_SET))			continue;		if (tcp_fd->tf_tcpconf.nwtc_locport == port)			return FALSE;	}	for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;		i<TCP_CONN_NR; i++, tcp_conn++)		/* the first tcp_conf_nr ports are special */	{		if (!(tcp_conn->tc_flags & TCF_INUSE))			continue;		if (tcp_conn->tc_locport == port)			return FALSE;	}	return TRUE;}PRIVATE int reply_thr_put(tcp_fd, reply, for_ioctl)tcp_fd_t *tcp_fd;int reply;int for_ioctl;{	assert (tcp_fd);	return (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, reply,		(acc_t *)0, for_ioctl);}PRIVATE void reply_thr_get(tcp_fd, reply, for_ioctl)tcp_fd_t *tcp_fd;int reply;int for_ioctl;{	acc_t *result;	result= (*tcp_fd->tf_get_userdata)(tcp_fd->tf_srfd, reply,		(size_t)0, for_ioctl);	assert (!result);}PUBLIC int tcp_su4listen(tcp_fd, tcp_conn, do_listenq)tcp_fd_t *tcp_fd;tcp_conn_t *tcp_conn;int do_listenq;{	tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;	tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;	if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP)		tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;	else		tcp_conn->tc_remport= 0;	if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA)		tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;	else		tcp_conn->tc_remaddr= 0;	tcp_setup_conn(tcp_fd->tf_port, tcp_conn);	tcp_conn->tc_fd= tcp_fd;	tcp_conn->tc_connInprogress= 1;	tcp_conn->tc_orglisten= TRUE;	tcp_conn->tc_state= TCS_LISTEN;	tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_LISTEN;	if (do_listenq)	{		tcp_fd->tf_flags |= TFF_LISTENQ;		tcp_reply_ioctl(tcp_fd, NW_OK);		return NW_OK;	}	return NW_SUSPEND;}/*find_empty_connThis function returns a connection that is not inuse.This includes connections that are never used, and connections without auser that are not used for a while.*/PRIVATE tcp_conn_t *find_empty_conn(){	int i;	tcp_conn_t *tcp_conn;	for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i;		i<TCP_CONN_NR; i++, tcp_conn++)		/* the first tcp_conf_nr connections are reserved for		 * RSTs		 */	{		if (tcp_conn->tc_flags == TCF_EMPTY)		{			tcp_conn->tc_connInprogress= 0;			tcp_conn->tc_fd= NULL;			return tcp_conn;		}		if (tcp_conn->tc_fd)			continue;		if (tcp_conn->tc_senddis > get_time())			continue;		if (tcp_conn->tc_state != TCS_CLOSED)		{			 tcp_close_connection (tcp_conn, ENOCONN);		}		tcp_conn->tc_flags= 0;		return tcp_conn;	}	return NULL;}/*find_conn_entryThis function return a connection matching locport, locaddr, remport, remaddr.If no such connection exists NULL is returned.If a connection exists without mainuser it is closed.*/PRIVATE tcp_conn_t *find_conn_entry(locport, locaddr, remport, remaddr)tcpport_t locport;ipaddr_t locaddr;tcpport_t remport;ipaddr_t remaddr;{	tcp_conn_t *tcp_conn;	int i, state;	assert(remport);	assert(remaddr);	for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR;		i++, tcp_conn++)		/* the first tcp_conf_nr connections are reserved for			RSTs */	{		if (tcp_conn->tc_flags == TCF_EMPTY)			continue;		if (tcp_conn->tc_locport != locport ||			tcp_conn->tc_locaddr != locaddr ||			tcp_conn->tc_remport != remport ||			tcp_conn->tc_remaddr != remaddr)			continue;		if (tcp_conn->tc_fd)			return tcp_conn;		state= tcp_conn->tc_state;		if (state != TCS_CLOSED)		{			tcp_close_connection(tcp_conn, ENOCONN);		}		return tcp_conn;	}	return NULL;}PRIVATE void read_ip_packets(tcp_port)tcp_port_t *tcp_port;{	int result;	do	{		tcp_port->tp_flags |= TPF_READ_IP;		result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM);		if (result == NW_SUSPEND)		{			tcp_port->tp_flags |= TPF_READ_SP;			return;		}		assert(result == NW_OK);		tcp_port->tp_flags &= ~TPF_READ_IP;	} while(!(tcp_port->tp_flags & TPF_READ_IP));}/*find_best_conn*/PRIVATE tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)ip_hdr_t *ip_hdr;tcp_hdr_t *tcp_hdr;{		int best_level, new_level;	tcp_conn_t *best_conn, *listen_conn, *tcp_conn;	tcp_fd_t *tcp_fd;	int i;	ipaddr_t locaddr;	ipaddr_t remaddr;	tcpport_t locport;	tcpport_t remport;	locaddr= ip_hdr->ih_dst;	remaddr= ip_hdr->ih_src;	locport= tcp_hdr->th_dstport;	remport= tcp_hdr->th_srcport;	if (!remport)	/* This can interfere with a listen, so we reject it			 * by clearing the requested port 			 */		locport= 0;			best_level= 0;	best_conn= NULL;	listen_conn= NULL;	for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;		i<TCP_CONN_NR; i++, tcp_conn++)		/* the first tcp_conf_nr connections are reserved for			RSTs */	{		if (!(tcp_conn->tc_flags & TCF_INUSE))			continue;		/* First fast check for open connections. */		if (tcp_conn->tc_locaddr == locaddr && 			tcp_conn->tc_locport == locport &&			tcp_conn->tc_remport == remport &&			tcp_conn->tc_remaddr == remaddr &&			tcp_conn->tc_fd)		{			return tcp_conn;		}		/* Now check for listens and abandoned connections. */		if (tcp_conn->tc_locaddr != locaddr)		{			continue;		}		new_level= 0;		if (tcp_conn->tc_locport)		{			if (tcp_conn->tc_locport != locport)			{				continue;			}			new_level += 4;		}		if (tcp_conn->tc_remport)		{			if (tcp_conn->tc_remport != remport)			{				continue;			}			new_level += 1;		}		if (tcp_conn->tc_remaddr)		{			if (tcp_conn->tc_remaddr != remaddr)			{				continue;			}			new_level += 2;		}		if (new_level<best_level)			continue;		if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN)			continue;		if (new_level == 7)			/* We found an abandoned connection */		{		 	assert(!tcp_conn->tc_fd);			if (best_conn && tcp_Lmod4G(tcp_conn->tc_ISS,				best_conn->tc_ISS))			{				continue;			}			best_conn= tcp_conn;			continue;		}		if (!(tcp_hdr->th_flags & THF_SYN))			continue;		best_level= new_level;		listen_conn= tcp_conn;		assert(listen_conn->tc_fd != NULL);	}	if (listen_conn && listen_conn->tc_fd->tf_flags & TFF_LISTENQ &&		listen_conn->tc_fd->tf_conn == listen_conn)	{		/* Special processing for listen queues. Only accept the 		 * connection if there is empty space in the queue and		 * there are empty connections as well.		 */		listen_conn= new_conn_for_queue(listen_conn->tc_fd);	}		if (!best_conn && !listen_conn)	{		if ((tcp_hdr->th_flags & THF_SYN) &&			maybe_listen(locaddr, locport, remaddr, remport))		{			/* Quick hack to implement listen back logs:			 * if a SYN arrives and there is no listen waiting			 * for that packet, then no reply is sent.			 */			return NULL;		}		for (i=0, tcp_conn= tcp_conn_table; i<tcp_conf_nr;			i++, tcp_conn++)		{			/* find valid port to send RST */			if ((tcp_conn->tc_flags & TCF_INUSE) &&				tcp_conn->tc_locaddr==locaddr)			{				break;			}		}		assert (tcp_conn);		assert (tcp_conn->tc_state == TCS_CLOSED);		tcp_conn->tc_locport= locport;		tcp_conn->tc_locaddr= locaddr;		tcp_conn->tc_remport= remport;		tcp_conn->tc_remaddr= remaddr;		assert (!tcp_conn->tc_fd);		return tcp_conn;	}	if (best_conn)	{		if (!listen_conn)		{			assert(!best_conn->tc_fd);			return best_conn;		}		assert(listen_conn->tc_connInprogress);		tcp_fd= listen_conn->tc_fd;		assert(tcp_fd);		assert((tcp_fd->tf_flags & TFF_LISTENQ) ||			 tcp_fd->tf_conn == listen_conn);		if (best_conn->tc_state != TCS_CLOSED)			tcp_close_connection(best_conn, ENOCONN);

⌨️ 快捷键说明

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