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

📄 tcp.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			break;		}		result= tcp_setconf(tcp_fd);		break;	case NWIOGTCPCONF & IOCTYPE_MASK:		if (req != NWIOGTCPCONF)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_put (tcp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		conf_acc= bf_memreq(sizeof(*tcp_conf));assert (conf_acc->acc_length == sizeof(*tcp_conf));		tcp_conf= (nwio_tcpconf_t *)ptr2acc_data(conf_acc);		*tcp_conf= tcp_fd->tf_tcpconf;		if (tcp_fd->tf_flags & TFF_CONNECTED)		{			tcp_conn= tcp_fd->tf_conn;			tcp_conf->nwtc_locport= tcp_conn->tc_locport;			tcp_conf->nwtc_remaddr= tcp_conn->tc_remaddr;			tcp_conf->nwtc_remport= tcp_conn->tc_remport;		}		tcp_conf->nwtc_locaddr= tcp_fd->tf_port->tp_ipaddr;		result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,			0, conf_acc, TRUE);		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;		reply_thr_put(tcp_fd, result, TRUE);		result= NW_OK;		break;	case NWIOTCPCONN & IOCTYPE_MASK:		if (req != NWIOTCPCONN)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		if (tcp_fd->tf_flags & TFF_CONNECTED)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EISCONN, TRUE);			result= NW_OK;			break;		}		result= tcp_connect(tcp_fd);		break;	case NWIOTCPLISTEN & IOCTYPE_MASK:		if (req != NWIOTCPLISTEN)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		if (tcp_fd->tf_flags & TFF_CONNECTED)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EISCONN, TRUE);			result= NW_OK;			break;		}		result= tcp_listen(tcp_fd);#if DEBUG & 256 { where(); printf("tcp_listen= %d\n", result); }#endif		break;#if 0	case NWIOTCPATTACH & IOCTYPE_MASK:		if (req != NWIOTCPATTACH)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		if (tcp_fd->tf_flags & TFF_CONNECTED)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EISCONN, TRUE);			result= NW_OK;			break;		}		result= tcp_attache(tcp_fd);		break;#endif	case NWIOTCPSHUTDOWN & IOCTYPE_MASK:		if (req != NWIOTCPSHUTDOWN)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		if (!(tcp_fd->tf_flags & TFF_CONNECTED))		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, ENOTCONN, TRUE);			result= NW_OK;			break;		}		tcp_fd->tf_flags |= TFF_IOCTL_IP;		tcp_fd->tf_ioreq= req;		tcp_conn= tcp_fd->tf_conn;		if (tcp_conn->tc_writeuser)			return NW_SUSPEND;		tcp_conn->tc_writeuser= tcp_fd;		tcp_restart_fd_write (tcp_conn);		if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))			return NW_OK;		else			return NW_SUSPEND;		break;	default:		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;		reply_thr_get(tcp_fd, EBADIOCTL, TRUE);		result= NW_OK;		break;	}	return result;}PRIVATE int tcp_setconf(tcp_fd)tcp_fd_t *tcp_fd;{	nwio_tcpconf_t *tcpconf;	nwio_tcpconf_t oldconf, newconf;	acc_t *data;	int result;	tcpport_t port;	tcp_fd_t *fd_ptr;	unsigned int new_en_flags, new_di_flags,		old_en_flags, old_di_flags, all_flags, flags;	int i;	data= (*tcp_fd->tf_get_userdata)		(tcp_fd->tf_srfd, 0,		sizeof(nwio_tcpconf_t), TRUE);	if (!data)		return EFAULT;	data= bf_packIffLess(data, sizeof(nwio_tcpconf_t));assert (data->acc_length == sizeof(nwio_tcpconf_t));	tcpconf= (nwio_tcpconf_t *)ptr2acc_data(data);	oldconf= tcp_fd->tf_tcpconf;	newconf= *tcpconf;	old_en_flags= oldconf.nwtc_flags & 0xffff;	old_di_flags= (oldconf.nwtc_flags >> 16) &		0xffff;	new_en_flags= newconf.nwtc_flags & 0xffff;	new_di_flags= (newconf.nwtc_flags >> 16) &		0xffff;	if (new_en_flags & new_di_flags)	{#if DEBUG { where(); printf("bad ioctl\n"); }#endif		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;		reply_thr_get(tcp_fd, EBADMODE, TRUE);		return NW_OK;	}	/* NWTC_ACC_MASK */	if (new_di_flags & NWTC_ACC_MASK)	{#if DEBUG { where(); printf("bad ioctl\n"); }#endif		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;		reply_thr_get(tcp_fd, EBADMODE, TRUE);		return NW_OK;		/* access modes can't be disabled */	}	if (!(new_en_flags & NWTC_ACC_MASK))		new_en_flags |= (old_en_flags & NWTC_ACC_MASK);		/* NWTC_LOCPORT_MASK */	if (new_di_flags & NWTC_LOCPORT_MASK)	{#if DEBUG { where(); printf("bad ioctl\n"); }#endif		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;		reply_thr_get(tcp_fd, EBADMODE, TRUE);		return NW_OK;		/* the loc ports can't be disabled */	}	if (!(new_en_flags & NWTC_LOCPORT_MASK))	{		new_en_flags |= (old_en_flags &			NWTC_LOCPORT_MASK);#if DEBUG { where(); printf("locport= old locport (=%u)\n",	ntohs(newconf.nwtc_locport)); }#endif		newconf.nwtc_locport= oldconf.nwtc_locport;	}	else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL)	{		newconf.nwtc_locport= find_unused_port(tcp_fd-			tcp_fd_table);#if DEBUG & 256 { where(); printf("locport selected (=%u)\n",	ntohs(newconf.nwtc_locport)); }#endif	}	else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)	{#if DEBUG & 256 { where(); printf("locport set (=%u)\n",   ntohs(newconf.nwtc_locport)); }#endif		if (!newconf.nwtc_locport)		{#if DEBUG { where(); printf("bad ioctl\n"); }#endif			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get(tcp_fd, EBADMODE, TRUE);			return NW_OK;		}	}		/* NWTC_REMADDR_MASK */	if (!((new_en_flags | new_di_flags) &		NWTC_REMADDR_MASK))	{		new_en_flags |= (old_en_flags &			NWTC_REMADDR_MASK);		new_di_flags |= (old_di_flags &			NWTC_REMADDR_MASK);		newconf.nwtc_remaddr= oldconf.nwtc_remaddr;	}	else if (new_en_flags & NWTC_SET_RA)	{		if (!newconf.nwtc_remaddr)		{#if DEBUG { where(); printf("bad ioctl\n"); }#endif			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get(tcp_fd, EBADMODE, TRUE);			return NW_OK;		}	}	else	{assert (new_di_flags & NWTC_REMADDR_MASK);		newconf.nwtc_remaddr= 0;	}	/* NWTC_REMPORT_MASK */	if (!((new_en_flags | new_di_flags) & NWTC_REMPORT_MASK))	{		new_en_flags |= (old_en_flags &			NWTC_REMPORT_MASK);		new_di_flags |= (old_di_flags &			NWTC_REMPORT_MASK);		newconf.nwtc_remport=			oldconf.nwtc_remport;	}	else if (new_en_flags & NWTC_SET_RP)	{		if (!newconf.nwtc_remport)		{#if DEBUG { where(); printf("bad ioctl\n"); }#endif			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get(tcp_fd, EBADMODE, TRUE);			return NW_OK;		}	}	else	{assert (new_di_flags & NWTC_REMPORT_MASK);		newconf.nwtc_remport= 0;	}	newconf.nwtc_flags= ((unsigned long)new_di_flags		<< 16) | new_en_flags;	all_flags= new_en_flags | new_di_flags;	/* Let's check the access modes */	if ((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL ||		(all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)	{		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;			flags= fd_ptr->tf_tcpconf.nwtc_flags;			if ((flags & NWTC_LOCPORT_MASK) != NWTC_LP_SEL &&				(flags &  NWTC_LOCPORT_MASK) != NWTC_LP_SET)				continue;			if (fd_ptr->tf_tcpconf.nwtc_locport !=				newconf.nwtc_locport)				continue;			if ((flags & NWTC_ACC_MASK) != (all_flags  &				NWTC_ACC_MASK))			{				tcp_fd->tf_flags &= ~TFF_IOCTL_IP;				reply_thr_get(tcp_fd, EADDRINUSE, TRUE);				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_OPTSET;	else	{#if DEBUG { where();   if (!(all_flags & NWTC_ACC_MASK)) printf("NWTC_ACC_MASK not set ");   if (!(all_flags & (NWTC_LP_SET|NWTC_LP_SEL)))    printf("local port not set ");   if (!(all_flags & NWTC_REMADDR_MASK))    printf("NWTC_REMADDR_MASK not set ");   if (!(all_flags & NWTC_REMPORT_MASK))    printf("NWTC_REMPORT_MASK not set "); }#endif		tcp_fd->tf_flags &= ~TFF_OPTSET;	}	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; 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_OPTSET))			continue;		if (tcp_fd->tf_tcpconf.nwtc_locport == port)			return FALSE;	}	for (i= TCP_PORT_NR, tcp_conn= tcp_conn_table+i;		i<TCP_CONN_NR; i++, tcp_conn++)		/* the first TCP_PORT_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;{#if DEBUG & 256 { where(); printf("reply_thr_put(..) called\n"); }#endif#if DEBUG & 256 { where(); printf("calling 0x%x\n", tcp_fd->tf_put_userdata); }#endifassert (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;#if DEBUG & 256 { where(); printf("reply_thr_get(..) called\n"); }#endif	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_fd_t *tcp_fd;{	tcp_conn_t *tcp_conn;	acc_t *tmp_acc;	tcp_conn= tcp_fd->tf_conn;	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_conn);	tcp_conn->tc_port= tcp_fd->tf_port;	tcp_conn->tc_mainuser= tcp_fd;	tcp_conn->tc_connuser= tcp_fd;	tcp_conn->tc_orglisten= TRUE;	tcp_conn->tc_state= TCS_LISTEN;#if DEBUG & 2 { where(); tcp_write_state(tcp_conn); }#endif	return NW_SUSPEND;}/*find_empty_connThis function returns a connection that is not inuse.This includes connections that are never used, and connection without auser that are not used for a while.*/PRIVATE tcp_conn_t *find_empty_conn(){	int i;	tcp_conn_t *tcp_conn;	int state;	for (i=TCP_PORT_NR, tcp_conn= tcp_conn_table+i;		i<TCP_CONN_NR; i++, tcp_conn++)		/* the first TCP_PORT_NR connection are reserved for			RSTs */	{		if (tcp_conn->tc_flags == TCF_EMPTY)		{			tcp_conn->tc_connuser= NULL;			tcp_conn->tc_mainuser= NULL;			return tcp_conn;		}		if (tcp_conn->tc_mainuser)			continue;		if (tcp_conn->tc_senddis > get_time())			continue;		if (tcp_conn->tc_state != TCS_CLOSED)		{#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif			 tcp_close_connection (tcp_conn, ENOCONN);		}		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;

⌨️ 快捷键说明

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