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

📄 eth.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
	eth_fd->ef_rd_buf= 0;
}

PRIVATE int eth_checkopt (eth_fd)
eth_fd_t *eth_fd;
{
/* bug: we don't check access modes yet */

	unsigned long flags;
	unsigned int en_di_flags;
	eth_port_t *eth_port;
	acc_t *acc, *acc2;

	eth_port= eth_fd->ef_port;
	flags= eth_fd->ef_ethopt.nweo_flags;
#if DEBUG & 256
 { where(); printf("eth_fd_table[%d].ef_ethopt.nweo_flags= 0x%x\n",
	eth_fd-eth_fd_table, flags); }
#endif
	en_di_flags= (flags >>16) | (flags & 0xffff);

	if ((en_di_flags & NWEO_ACC_MASK) &&
		(en_di_flags & NWEO_LOC_MASK) &&
		(en_di_flags & NWEO_BROAD_MASK) &&
		(en_di_flags & NWEO_MULTI_MASK) &&
		(en_di_flags & NWEO_PROMISC_MASK) &&
		(en_di_flags & NWEO_REM_MASK) &&
		(en_di_flags & NWEO_TYPE_MASK) &&
		(en_di_flags & NWEO_RW_MASK))
	{
		eth_fd->ef_flags |= EFF_OPTSET;
		eth_fd->ef_pack_stat= EPS_EMPTY;
		if (flags & NWEO_EN_LOC)
			eth_fd->ef_pack_stat |= EPS_LOC;
		if (flags & NWEO_EN_BROAD)
			eth_fd->ef_pack_stat |= EPS_BROAD;
		if (flags & NWEO_EN_MULTI)
			eth_fd->ef_pack_stat |= EPS_MULTI;
		if (flags & NWEO_EN_PROMISC)
			eth_fd->ef_pack_stat |= (EPS_PROMISC|EPS_MULTI|
				EPS_BROAD);
	}
	else
		eth_fd->ef_flags &= ~EFF_OPTSET;
	
	for (acc= eth_fd->ef_rd_buf; acc;)
	{
		acc2= acc->acc_ext_link;
		bf_afree(acc);
		acc= acc2;
	}
	eth_fd->ef_rd_buf= 0;

	return NW_OK;
}

PUBLIC int eth_get_work(eth_port)
eth_port_t *eth_port;
{
	eth_fd_t *eth_fd;
	int i;

#if DEBUG & 256
 { where(); printf("eth_get_work called\n"); }
#endif
	if (eth_port->etp_wr_pack)
		return 0;
	if (!(eth_port->etp_flags & EPF_MORE2WRITE))
		return 0;

	for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
	{
		if ((eth_fd->ef_flags & (EFF_INUSE|EFF_WRITE_IP)) !=
			(EFF_INUSE|EFF_WRITE_IP))
			continue;
		if (eth_fd->ef_port != eth_port)
			continue;
#if DEBUG & 256
 { where(); printf("eth_get_work calling restart_write_fd\n"); }
#endif
		restart_write_fd(eth_fd);
		if (eth_port->etp_wr_pack)
			return 1;
	}
	eth_port->etp_flags &= ~EPF_MORE2WRITE;
	return 0;
}

PUBLIC void eth_arrive (eth_port, pack)
eth_port_t *eth_port;
acc_t *pack;
{
	time_t exp_tim;
	eth_hdr_t *eth_hdr;
	static ether_addr_t broadcast= {255, 255, 255, 255, 255, 255},
		multi_addr, rem_addr, packaddr;
	int pack_stat;
	ether_type_t type;
	eth_fd_t *eth_fd, *share_fd;
	acc_t *acc;
	int i;

#if DEBUG & 256
 { where(); printf("eth_arrive(0x%x, 0x%x) called\n", eth_port, pack); }
#endif
assert(pack->acc_linkC);
	exp_tim= get_time() + EXPIRE_TIME;

	pack= bf_packIffLess(pack, ETH_HDR_SIZE);
	eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);
#if DEBUG & 256
 { where(); printf("src= "); writeEtherAddr(&eth_hdr->eh_src); printf(" dst= "); 	writeEtherAddr(&eth_hdr->eh_dst);
	printf(" proto= 0x%x\n", ntohs(eth_hdr->eh_proto));
	printf(" my addr= "); writeEtherAddr(&eth_port->etp_ethaddr);
	printf("\n"); }
#endif

	packaddr= eth_hdr->eh_dst;
	if (packaddr.ea_addr[0] & 0x01)
	{
		/* multi cast or broadcast */
		if (!eth_addrcmp(packaddr, broadcast))
			pack_stat= EPS_BROAD;
		else
		{
			pack_stat= EPS_MULTI;
#if DEBUG
 { where(); printf("Got a multicast packet\n"); }
#endif
		}
	}
	else
	{
		if (!eth_addrcmp (packaddr, eth_port->etp_ethaddr))
			pack_stat= EPS_LOC;
		else
			pack_stat= EPS_PROMISC;
	}
	type= eth_hdr->eh_proto;

#if DEBUG & 256
 { where(); printf("pack_stat= 0x%x\n", pack_stat); }
#endif

	share_fd= 0;
	for (i=0, eth_fd=eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
	{
		if (!(eth_fd->ef_flags & EFF_OPTSET))
		{
#if DEBUG & 256
 { where(); printf("fd %d doesn't have EFF_OPTSET\n", i); }
#endif
			continue;
		}
		if (eth_fd->ef_port != eth_port)
		{
#if DEBUG
 { where(); printf("fd %d uses port %d, packet is on port %d\n", i, 
	eth_fd->ef_port-eth_port_table, eth_port-eth_port_table); }
#endif
			continue;
		}
		if (!(eth_fd->ef_pack_stat & pack_stat))
		{
#if DEBUG & 256
 { where(); printf("fd %d has ef_pack_stat 0x%x, expecting 0x%x\n", i,
	eth_fd->ef_pack_stat, pack_stat); }
#endif
			continue;
		}
		if ((eth_fd->ef_ethopt.nweo_flags & NWEO_TYPESPEC) &&
			type != eth_fd->ef_ethopt.nweo_type)
		{
#if DEBUG & 256
 { where(); printf("fd %d uses type 0x%x, expecting 0x%x\n", i,
	eth_fd->ef_ethopt.nweo_type, type); }
#endif
			continue;
		}
#if DEBUG & 256
 { where(); printf("multi OK\n"); }
#endif
		if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC)
		{
			rem_addr= eth_fd->ef_ethopt.nweo_rem;
			if (eth_addrcmp (eth_hdr->eh_src,
				rem_addr))
				continue;
		}
#if DEBUG & 256
 { where(); printf("rem NW_OK\n"); }
#endif
		if (eth_fd->ef_rd_buf)
		{
			if (eth_fd->ef_ethopt.nweo_flags == NWEO_SHARED)
			{
				share_fd= eth_fd;
				continue;
			}
		}
		acc= bf_dupacc(pack);
		acc->acc_ext_link= NULL;
		if (!eth_fd->ef_rd_buf)
		{
			eth_fd->ef_rd_buf= acc;
			eth_fd->ef_exp_tim= exp_tim;
		}
		else
			eth_fd->ef_rd_tail->acc_ext_link= acc;
		eth_fd->ef_rd_tail= acc;

		if (eth_fd->ef_flags & EFF_READ_IP)
			packet2user(eth_fd);
		if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) != NWEO_COPY)
		{
			bf_afree(pack);
			pack= 0;
			break;
		}
	}
	if (share_fd && pack)
	{
		acc= bf_dupacc(pack);
		acc->acc_ext_link= NULL;
		if (!share_fd->ef_rd_buf)
		{
			share_fd->ef_rd_buf= acc;
			share_fd->ef_exp_tim= exp_tim;
		}
		else
			share_fd->ef_rd_tail->acc_ext_link= acc;
		share_fd->ef_rd_tail= acc;
	}
	if (pack)
		bf_afree(pack);
}

PRIVATE int packet2user (eth_fd)
eth_fd_t *eth_fd;
{
	acc_t *pack, *header;
	int result;
	size_t size;

#if DEBUG & 256
 { where(); printf("packet2user() called\n"); }
#endif
	pack= eth_fd->ef_rd_buf;
	eth_fd->ef_rd_buf= pack->acc_ext_link;
	if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
	{
		pack= bf_packIffLess (pack, ETH_HDR_SIZE);

		assert (pack->acc_length >= ETH_HDR_SIZE);

		if (pack->acc_linkC >1)
		{
			header= bf_dupacc (pack);
			bf_afree(pack);
			pack= header;
		}

		assert (pack->acc_linkC == 1);

		pack->acc_offset += ETH_HDR_SIZE;
		pack->acc_length -= ETH_HDR_SIZE;
	}

	size= bf_bufsize (pack);

	eth_fd->ef_flags &= ~EFF_READ_IP;
	result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack,
		FALSE);
	if (result >=0)
		reply_thr_put(eth_fd, size, FALSE);
	return result<0 ? result : NW_OK;
}

PRIVATE int ok_for_me (eth_fd, pack)
eth_fd_t *eth_fd;
acc_t *pack;
{
	eth_port_t *eth_port;
	eth_hdr_t *eth_hdr;
	ether_type_t type;
	static ether_addr_t broadcast= {255, 255, 255, 255, 255, 255},
		packaddr, portaddr, multi_addr, rem_addr;
	int pack_kind;

	assert (pack->acc_length >= ETH_HDR_SIZE);

	eth_port= eth_fd->ef_port;

	eth_hdr= (eth_hdr_t *)ptr2acc_data(pack);
	packaddr= eth_hdr->eh_dst;
	if (packaddr.ea_addr[0] & 0x01)
		/* multi cast or broadcast */
		if (!eth_addrcmp (packaddr, broadcast))
			pack_kind= EPS_BROAD;
		else
			pack_kind= EPS_MULTI;
	else
	{
		portaddr= eth_port->etp_ethaddr;
		if (!eth_addrcmp(packaddr, portaddr))
			pack_kind= EPS_LOC;
		else
			pack_kind= EPS_PROMISC;
	}

	pack_kind &= eth_fd->ef_pack_stat;

	if (!pack_kind)
		return FALSE;

	type= eth_hdr->eh_proto;

	if ((eth_fd->ef_ethopt.nweo_flags & NWEO_TYPESPEC) &&
		type != eth_fd->ef_ethopt.nweo_type)
		return FALSE;

	if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC)
	{
		rem_addr= eth_fd->ef_ethopt.nweo_rem;
		if (eth_addrcmp(eth_hdr->eh_src, rem_addr))
			return FALSE;
	}
	return TRUE;
}

PRIVATE void eth_buffree (priority, reqsize)
int priority;
size_t reqsize;
{
	int i, once_more;
	time_t curr_tim;
	acc_t *acc;

	if (priority <ETH_PRI_EXP_FDBUFS)
		return;

#if DEBUG & 256
 { where(); printf("eth_buffree called\n"); }
#endif

	curr_tim= get_time();
	for (i=0; i<ETH_FD_NR; i++)
	{
		if (!(eth_fd_table[i].ef_flags & EFF_INUSE) )
			continue;
		acc= eth_fd_table[i].ef_rd_buf;
		if (acc && eth_fd_table[i].ef_exp_tim < curr_tim)
		{
			eth_fd_table[i].ef_rd_buf= acc->acc_ext_link;
			bf_afree(acc);
			if (bf_free_buffsize >= reqsize)
				return;
		}
	}

	if (priority <ETH_PRI_FDBUFS)
		return;

	once_more= 1;
	while (once_more)
	{
		once_more= 0;
		for (i=0; i<ETH_FD_NR; i++)
		{
			if (!(eth_fd_table[i].ef_flags & EFF_INUSE))
				continue;
			acc= eth_fd_table[i].ef_rd_buf;
			if (acc)
			{
				eth_fd_table[i].ef_rd_buf= acc->acc_ext_link;
				bf_afree(acc);
				if (bf_free_buffsize >= reqsize)
					return;
				once_more= 1;
			}
		}
	}
}

PRIVATE void restart_write_fd(eth_fd)
eth_fd_t *eth_fd;
{
	eth_port_t *eth_port;
	acc_t *user_data, *header;
	int size;
	unsigned long nweo_flags;
	eth_hdr_t *eth_hdr;

	eth_port= eth_fd->ef_port;

	if (eth_port->etp_wr_pack)
	{
		eth_port->etp_flags |= EPF_MORE2WRITE;
		return;
	}

assert (eth_fd->ef_flags & EFF_WRITE_IP);
	eth_fd->ef_flags &= ~EFF_WRITE_IP;

assert (!eth_port->etp_wr_pack);

#if DEBUG & 256
 { where(); printf("calling *get_userdata\n"); }
#endif
	user_data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, 0,
		eth_fd->ef_write_count, FALSE);
	if (!user_data)
	{
		eth_fd->ef_flags &= ~EFF_WRITE_IP;
		reply_thr_get (eth_fd, EFAULT, FALSE);
		return;
	}
	size= bf_bufsize (user_data);

	nweo_flags= eth_fd->ef_ethopt.nweo_flags;

	if (nweo_flags & NWEO_RWDATONLY)
	{
		header= bf_memreq(ETH_HDR_SIZE);
		header->acc_next= user_data;
		user_data= header;
	}

	user_data= bf_packIffLess (user_data, ETH_HDR_SIZE);

	eth_hdr= (eth_hdr_t *)ptr2acc_data(user_data);

	if (nweo_flags & NWEO_REMSPEC)
		eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem;

	eth_hdr->eh_src= eth_port->etp_ethaddr;

	if (nweo_flags & NWEO_TYPESPEC)
		eth_hdr->eh_proto= eth_fd->ef_ethopt.nweo_type;

assert (!eth_port->etp_wr_pack);
	eth_port->etp_wr_pack= user_data;

	if (!(eth_port->etp_flags & EPF_WRITE_IP))
	{
		eth_write_port(eth_port);
	}
	reply_thr_get (eth_fd, size, FALSE);
}

PRIVATE void reply_thr_get (eth_fd, result, for_ioctl)
eth_fd_t *eth_fd;
size_t result;
int for_ioctl;
{
	acc_t *data;

#if DEBUG & 256
 { where(); printf("calling *get_userdata(fd= %d, %d, 0)\n", eth_fd->
	ef_srfd, result, 0); }
#endif
	data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);
assert (!data);	
}

PRIVATE void reply_thr_put (eth_fd, result, for_ioctl)
eth_fd_t *eth_fd;
size_t result;
int for_ioctl;
{
	int error;

	error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0,
		for_ioctl);
assert(!error);
}

⌨️ 快捷键说明

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