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

📄 ip_eth.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		ip_port->ip_mtu + sizeof(*eth_hdr))	{		r= eth_send(ip_port->ip_dl.dl_eth.de_fd,			eth_pack, pack_size);		if (r == NW_OK)			return NW_OK;		/* A non-blocking send is not possible, start a regular		 * send.		 */		assert(r == NW_WOULDBLOCK);		ip_port->ip_dl.dl_eth.de_frame= eth_pack;		r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);		if (r == NW_SUSPEND)		{			assert(!(ip_port->ip_dl.dl_eth.de_flags &				IEF_WRITE_SP));			ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;		}		assert(r == NW_OK || r == NW_SUSPEND);		return NW_OK;	}	/* Enqueue the packet, and store the current time, in the	 * space for the ethernet source address.	 */	t= get_time();	assert(sizeof(t) <= sizeof(eth_hdr->eh_src));	memcpy(&eth_hdr->eh_src, &t, sizeof(t));	eth_pack->acc_ext_link= NULL;	if (ip_port->ip_dl.dl_eth.de_q_head == NULL)		ip_port->ip_dl.dl_eth.de_q_head= eth_pack;	else	{		ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link= eth_pack;	}	ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;	if (ip_port->ip_dl.dl_eth.de_frame == NULL)		ipeth_restart_send(ip_port);	return NW_OK;}PRIVATE void ipeth_restart_send(ip_port)ip_port_t *ip_port;{	time_t now, enq_time;	int i, r;	acc_t *eth_pack, *ip_pack, *next_eth_pack, *next_part, *tail;	size_t pack_size;	eth_hdr_t *eth_hdr, *next_eth_hdr;	u32_t *p;	now= get_time();	while (ip_port->ip_dl.dl_eth.de_q_head != NULL)	{		eth_pack= ip_port->ip_dl.dl_eth.de_q_head;		ip_port->ip_dl.dl_eth.de_q_head= eth_pack->acc_ext_link;		eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);		pack_size= bf_bufsize(eth_pack);		if (pack_size > ip_port->ip_mtu+sizeof(*eth_hdr))		{			/* Split the IP packet */			assert(eth_pack->acc_linkC == 1);			ip_pack= eth_pack->acc_next; eth_pack->acc_next= NULL;			next_part= ip_pack; ip_pack= NULL;			ip_pack= ip_split_pack(ip_port, &next_part, 							ip_port->ip_mtu);			if (ip_pack == NULL)			{				bf_afree(eth_pack);				continue;			}			eth_pack->acc_next= ip_pack; ip_pack= NULL;			/* Allocate new ethernet header */			next_eth_pack= bf_memreq(sizeof(*next_eth_hdr));			next_eth_hdr= (eth_hdr_t *)ptr2acc_data(next_eth_pack);			*next_eth_hdr= *eth_hdr;			next_eth_pack->acc_next= next_part;			next_eth_pack->acc_ext_link= NULL;			if (ip_port->ip_dl.dl_eth.de_q_head == NULL)				ip_port->ip_dl.dl_eth.de_q_head= next_eth_pack;			else			{				ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link= 								next_eth_pack;			}			ip_port->ip_dl.dl_eth.de_q_tail= next_eth_pack;			pack_size= bf_bufsize(eth_pack);		}		memcpy(&enq_time, &eth_hdr->eh_src, sizeof(enq_time));		if (enq_time + HZ < now)		{			r= ipeth_update_ttl(enq_time, now, eth_pack);			if (r == ETIMEDOUT)			{					ip_pack= bf_delhead(eth_pack, sizeof(*eth_hdr));				eth_pack= NULL;				icmp_snd_time_exceeded(ip_port->ip_port,					ip_pack, ICMP_TTL_EXC);				continue;			}			assert(r == NW_OK);		}		if (pack_size<ETH_MIN_PACK_SIZE)		{			tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);			/* Clear padding */			for (i= (ETH_MIN_PACK_SIZE-pack_size)/sizeof(*p),				p= (u32_t *)ptr2acc_data(tail);				i >= 0; i--, p++)			{				*p= 0xdeadbeef;			}			eth_pack= bf_append(eth_pack, tail);			pack_size= ETH_MIN_PACK_SIZE;		}		assert(ip_port->ip_dl.dl_eth.de_frame == NULL);		r= eth_send(ip_port->ip_dl.dl_eth.de_fd, eth_pack, pack_size);		if (r == NW_OK)			continue;		/* A non-blocking send is not possible, start a regular		 * send.		 */		assert(r == NW_WOULDBLOCK);		ip_port->ip_dl.dl_eth.de_frame= eth_pack;		r= eth_write(ip_port->ip_dl.dl_eth.de_fd, pack_size);		if (r == NW_SUSPEND)		{			assert(!(ip_port->ip_dl.dl_eth.de_flags &				IEF_WRITE_SP));			ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;			return;		}		assert(r == NW_OK);	}}PRIVATE void ipeth_arp_reply(ip_port_nr, ipaddr, eth_addr)int ip_port_nr;ipaddr_t ipaddr;ether_addr_t *eth_addr;{	acc_t *prev, *eth_pack;	int r;	xmit_hdr_t *xmit_hdr;	ip_port_t *ip_port;	time_t t;	eth_hdr_t *eth_hdr;	ether_addr_t tmp_eth_addr;	assert (ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);	ip_port= &ip_port_table[ip_port_nr];	for (;;)	{		for (prev= 0, eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;			eth_pack;			prev= eth_pack, eth_pack= eth_pack->acc_ext_link)		{			xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);			if (xmit_hdr->xh_ipaddr == ipaddr)				break;		}		if (eth_pack == NULL)		{			/* No packet found. */			break;		}		/* Delete packet from the queue. */		if (prev == NULL)		{			ip_port->ip_dl.dl_eth.de_arp_head=				eth_pack->acc_ext_link;		}		else		{			prev->acc_ext_link= eth_pack->acc_ext_link;			if (prev->acc_ext_link == NULL)				ip_port->ip_dl.dl_eth.de_arp_tail= prev;		}		if (eth_addr == NULL)		{			/* Destination is unreachable, delete packet. */			bf_afree(eth_pack);			continue;		}		/* Fill in the ethernet address and put the packet on the 		 * transmit queue.		 */		t= xmit_hdr->xh_time;		eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);		eth_hdr->eh_dst= *eth_addr;		memcpy(&eth_hdr->eh_src, &t, sizeof(t));		eth_pack->acc_ext_link= NULL;		if (ip_port->ip_dl.dl_eth.de_q_head == NULL)			ip_port->ip_dl.dl_eth.de_q_head= eth_pack;		else		{			ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=				eth_pack;		}		ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;	}	/* Try to get some more ARPs in progress. */	while (ip_port->ip_dl.dl_eth.de_arp_head)	{		eth_pack= ip_port->ip_dl.dl_eth.de_arp_head;		xmit_hdr= (xmit_hdr_t *)ptr2acc_data(eth_pack);		r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,			xmit_hdr->xh_ipaddr, &tmp_eth_addr);		if (r == NW_SUSPEND)			break;				/* Normal case */		/* Dequeue the packet */		ip_port->ip_dl.dl_eth.de_arp_head= eth_pack->acc_ext_link;		if (r == EDSTNOTRCH)		{			bf_afree(eth_pack);			continue;		}		assert(r == NW_OK);		/* Fill in the ethernet address and put the packet on the 		 * transmit queue.		 */		t= xmit_hdr->xh_time;		eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);		eth_hdr->eh_dst= tmp_eth_addr;		memcpy(&eth_hdr->eh_src, &t, sizeof(t));		eth_pack->acc_ext_link= NULL;		if (ip_port->ip_dl.dl_eth.de_q_head == NULL)			ip_port->ip_dl.dl_eth.de_q_head= eth_pack;		else		{			ip_port->ip_dl.dl_eth.de_q_tail->acc_ext_link=				eth_pack;		}		ip_port->ip_dl.dl_eth.de_q_tail= eth_pack;	}	/* Restart sending ethernet packets. */	if (ip_port->ip_dl.dl_eth.de_frame == NULL)		ipeth_restart_send(ip_port);}PRIVATE int ipeth_update_ttl(enq_time, now, eth_pack)time_t enq_time;time_t now;acc_t *eth_pack;{	int ttl_diff;	ip_hdr_t *ip_hdr;	u32_t sum;	u16_t word;	acc_t *ip_pack;	ttl_diff= (now-enq_time)/HZ;	enq_time += ttl_diff*HZ;	assert(enq_time <= now && enq_time + HZ > now);	ip_pack= eth_pack->acc_next;	assert(ip_pack->acc_length >= sizeof(*ip_hdr));	assert(ip_pack->acc_linkC == 1 &&		ip_pack->acc_buffer->buf_linkC == 1);	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);	if (ip_hdr->ih_ttl <= ttl_diff)		return ETIMEDOUT;	sum= (u16_t)~ip_hdr->ih_hdr_chk;	word= *(u16_t *)&ip_hdr->ih_ttl;	if (word > sum)		sum += 0xffff - word;	else		sum -= word;	ip_hdr->ih_ttl -= ttl_diff;	word= *(u16_t *)&ip_hdr->ih_ttl;	sum += word;	if (sum > 0xffff)		sum -= 0xffff;	assert(!(sum & 0xffff0000));	ip_hdr->ih_hdr_chk= ~sum;	assert(ip_hdr->ih_ttl > 0);	return NW_OK;}PRIVATE void do_eth_read(ip_port)ip_port_t *ip_port;{	int result;	assert(!(ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP));	for (;;)	{		ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_IP;		result= eth_read (ip_port->ip_dl.dl_eth.de_fd,			ETH_MAX_PACK_SIZE);		if (result == NW_SUSPEND)		{			assert(!(ip_port->ip_dl.dl_eth.de_flags & 								IEF_READ_SP));			ip_port->ip_dl.dl_eth.de_flags |= IEF_READ_SP;			return;		}		ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;		if (result<0)		{			return;		}	}}PRIVATE void ip_eth_arrived(port, pack, pack_size)int port;acc_t *pack;size_t pack_size;{	int broadcast;	ip_port_t *ip_port;	ip_port= &ip_port_table[port];	broadcast= (*(u8_t *)ptr2acc_data(pack) & 1);	pack= bf_delhead(pack, ETH_HDR_SIZE);	if (broadcast)		ip_arrived_broadcast(ip_port, pack);	else		ip_arrived(ip_port, pack);}/* * $PchId: ip_eth.c,v 1.25 2005/06/28 14:18:10 philip Exp $ */

⌨️ 快捷键说明

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