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

📄 ip_eth.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*generic/ip_eth.cEthernet specific part of the IP implementationCreated:	Apr 22, 1993 by Philip HomburgCopyright 1995 Philip Homburg*/#include "inet.h"#include "type.h"#include "arp.h"#include "assert.h"#include "buf.h"#include "clock.h"#include "eth.h"#include "event.h"#include "icmp_lib.h"#include "io.h"#include "ip.h"#include "ip_int.h"THIS_FILEtypedef struct xmit_hdr{	time_t xh_time;	ipaddr_t xh_ipaddr;} xmit_hdr_t;PRIVATE ether_addr_t broadcast_ethaddr={	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};PRIVATE ether_addr_t ipmulticast_ethaddr={	{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }};FORWARD void do_eth_read ARGS(( ip_port_t *port ));FORWARD acc_t *get_eth_data ARGS(( int fd, size_t offset,	size_t count, int for_ioctl ));FORWARD int put_eth_data ARGS(( int fd, size_t offset,	acc_t *data, int for_ioctl ));FORWARD void ipeth_main ARGS(( ip_port_t *port ));FORWARD void ipeth_set_ipaddr ARGS(( ip_port_t *port ));FORWARD void ipeth_restart_send ARGS(( ip_port_t *ip_port ));FORWARD int ipeth_send ARGS(( struct ip_port *ip_port, ipaddr_t dest, 	acc_t *pack, int type ));FORWARD void ipeth_arp_reply ARGS(( int ip_port_nr, ipaddr_t ipaddr,	ether_addr_t *dst_ether_ptr ));FORWARD int ipeth_update_ttl ARGS(( time_t enq_time, time_t now,	acc_t *eth_pack ));FORWARD void ip_eth_arrived ARGS(( int port, acc_t *pack,	size_t pack_size ));PUBLIC int ipeth_init(ip_port)ip_port_t *ip_port;{	assert(BUF_S >= sizeof(xmit_hdr_t));	assert(BUF_S >= sizeof(eth_hdr_t));	ip_port->ip_dl.dl_eth.de_fd= eth_open(ip_port->		ip_dl.dl_eth.de_port, ip_port->ip_port,		get_eth_data, put_eth_data, ip_eth_arrived,		0 /* no select_res */);	if (ip_port->ip_dl.dl_eth.de_fd < 0)	{		DBLOCK(1, printf("ip.c: unable to open eth port\n"));		return -1;	}	ip_port->ip_dl.dl_eth.de_state= IES_EMPTY;	ip_port->ip_dl.dl_eth.de_flags= IEF_EMPTY;	ip_port->ip_dl.dl_eth.de_q_head= NULL;	ip_port->ip_dl.dl_eth.de_q_tail= NULL;	ip_port->ip_dl.dl_eth.de_arp_head= NULL;	ip_port->ip_dl.dl_eth.de_arp_tail= NULL;	ip_port->ip_dev_main= ipeth_main;	ip_port->ip_dev_set_ipaddr= ipeth_set_ipaddr;	ip_port->ip_dev_send= ipeth_send;	ip_port->ip_mtu= ETH_MAX_PACK_SIZE-ETH_HDR_SIZE;	ip_port->ip_mtu_max= ip_port->ip_mtu;	return 0;}PRIVATE void ipeth_main(ip_port)ip_port_t *ip_port;{	int result;	switch (ip_port->ip_dl.dl_eth.de_state)	{	case IES_EMPTY:		ip_port->ip_dl.dl_eth.de_state= IES_SETPROTO;		result= eth_ioctl(ip_port->ip_dl.dl_eth.de_fd, NWIOSETHOPT);		if (result == NW_SUSPEND)			ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;		if (result<0)		{			DBLOCK(1, printf("eth_ioctl(..,0x%lx)=%d\n",				(unsigned long)NWIOSETHOPT, result));			return;		}		if (ip_port->ip_dl.dl_eth.de_state != IES_SETPROTO)			return;		/* drops through */	case IES_SETPROTO:		result= arp_set_cb(ip_port->ip_dl.dl_eth.de_port,			ip_port->ip_port,			ipeth_arp_reply);		if (result != NW_OK)		{			printf("ipeth_main: arp_set_cb failed: %d\n",				result);			return;		}		/* Wait until the interface is configured up. */		ip_port->ip_dl.dl_eth.de_state= IES_GETIPADDR;		if (!(ip_port->ip_flags & IPF_IPADDRSET))		{			ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;			return;		}		/* fall through */	case IES_GETIPADDR:		ip_port->ip_dl.dl_eth.de_state= IES_MAIN;		do_eth_read(ip_port);		return;	default:		ip_panic(( "unknown state: %d",			ip_port->ip_dl.dl_eth.de_state));	}}PRIVATE acc_t *get_eth_data (fd, offset, count, for_ioctl)int fd;size_t offset;size_t count;int for_ioctl;{	ip_port_t *ip_port;	acc_t *data;	int result;	ip_port= &ip_port_table[fd];	switch (ip_port->ip_dl.dl_eth.de_state)	{	case IES_SETPROTO:		if (!count)		{			result= (int)offset;			if (result<0)			{				ip_port->ip_dl.dl_eth.de_state= IES_ERROR;				break;			}			if (ip_port->ip_dl.dl_eth.de_flags & IEF_SUSPEND)				ipeth_main(ip_port);			return NW_OK;		}		assert ((!offset) && (count == sizeof(struct nwio_ethopt)));		{			struct nwio_ethopt *ethopt;			acc_t *acc;			acc= bf_memreq(sizeof(*ethopt));			ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);			ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|				NWEO_EN_MULTI|NWEO_TYPESPEC;			ethopt->nweo_type= HTONS(ETH_IP_PROTO);			return acc;		}	case IES_MAIN:		if (!count)		{			result= (int)offset;			if (result<0)				ip_warning(( "error on write: %d\n", result ));			bf_afree (ip_port->ip_dl.dl_eth.de_frame);			ip_port->ip_dl.dl_eth.de_frame= 0;			if (ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_SP)			{				ip_port->ip_dl.dl_eth.de_flags &=					~IEF_WRITE_SP;				ipeth_restart_send(ip_port);			}			return NW_OK;		}		data= bf_cut (ip_port->ip_dl.dl_eth.de_frame, offset, count);		assert (data);		return data;	default:		printf(		"get_eth_data(%d, 0x%d, 0x%d) called but ip_state=0x%x\n",			fd, offset, count, ip_port->ip_dl.dl_eth.de_state);		break;	}	return 0;}PRIVATE int put_eth_data (port, offset, data, for_ioctl)int port;size_t offset;acc_t *data;int for_ioctl;{	ip_port_t *ip_port;	int result;	ip_port= &ip_port_table[port];	assert(0);	if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP)	{		if (!data)		{			result= (int)offset;			if (result<0)			{				DBLOCK(1, printf(				"ip.c: put_eth_data(..,%d,..)\n", result));				return NW_OK;			}			if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_SP)			{				ip_port->ip_dl.dl_eth.de_flags &= 						~(IEF_READ_IP|IEF_READ_SP);				do_eth_read(ip_port);			}			else				ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;			return NW_OK;		}		assert (!offset);		/* Warning: the above assertion is illegal; puts and		   gets of data can be brokenup in any piece the server		   likes. However we assume that the server is eth.c		   and it transfers only whole packets. */		ip_eth_arrived(port, data, bf_bufsize(data));		return NW_OK;	}	printf("ip_port->ip_dl.dl_eth.de_state= 0x%x",		ip_port->ip_dl.dl_eth.de_state);	ip_panic (( "strange status" ));}PRIVATE void ipeth_set_ipaddr(ip_port)ip_port_t *ip_port;{	arp_set_ipaddr (ip_port->ip_dl.dl_eth.de_port, ip_port->ip_ipaddr);	if (ip_port->ip_dl.dl_eth.de_state == IES_GETIPADDR)		ipeth_main(ip_port);}PRIVATE int ipeth_send(ip_port, dest, pack, type)struct ip_port *ip_port;ipaddr_t dest;acc_t *pack;int type;{	int i, r;	acc_t *eth_pack, *tail;	size_t pack_size;	eth_hdr_t *eth_hdr;	xmit_hdr_t *xmit_hdr;	ipaddr_t hostpart, tmpaddr;	time_t t;	u32_t *p;	/* Start optimistic: the arp will succeed without blocking and the	 * ethernet packet can be sent without blocking also. Start with	 * the allocation of the ethernet header.	 */	eth_pack= bf_memreq(sizeof(*eth_hdr));	assert(eth_pack->acc_next == NULL);	eth_pack->acc_next= pack;	pack_size= bf_bufsize(eth_pack);	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);	}	eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);	/* Lookup the ethernet address */	if (type != IP_LT_NORMAL)	{		if (type == IP_LT_BROADCAST)			eth_hdr->eh_dst= broadcast_ethaddr;		else		{			tmpaddr= ntohl(dest);			eth_hdr->eh_dst= ipmulticast_ethaddr;			eth_hdr->eh_dst.ea_addr[5]= tmpaddr & 0xff;			eth_hdr->eh_dst.ea_addr[4]= (tmpaddr >> 8) & 0xff;			eth_hdr->eh_dst.ea_addr[3]= (tmpaddr >> 16) & 0x7f;		}	}	else	{		if ((dest ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask)		{			ip_panic(( "invalid destination" ));		}		hostpart= (dest & ~ip_port->ip_subnetmask);		assert(dest != ip_port->ip_ipaddr);		r= arp_ip_eth(ip_port->ip_dl.dl_eth.de_port,			dest, &eth_hdr->eh_dst);		if (r == NW_SUSPEND)		{			/* Unfortunately, the arp takes some time, use			 * the ethernet header to store the next hop			 * ip address and the current time.			 */			xmit_hdr= (xmit_hdr_t *)eth_hdr;			xmit_hdr->xh_time= get_time();			xmit_hdr->xh_ipaddr= dest;			eth_pack->acc_ext_link= NULL;			if (ip_port->ip_dl.dl_eth.de_arp_head == NULL)				ip_port->ip_dl.dl_eth.de_arp_head= eth_pack;			else			{				ip_port->ip_dl.dl_eth.de_arp_tail->					acc_ext_link= eth_pack;			}			ip_port->ip_dl.dl_eth.de_arp_tail= eth_pack;			return NW_OK;		}		if (r == EDSTNOTRCH)		{			bf_afree(eth_pack);			return EDSTNOTRCH;		}		assert(r == NW_OK);	}	/* If we have no write in progress, we can try to send the ethernet	 * packet using eth_send. If the IP packet is larger than mtu,	 * enqueue the packet and let ipeth_restart_send deal with it. 	 */	pack_size= bf_bufsize(eth_pack);	if (ip_port->ip_dl.dl_eth.de_frame == NULL && pack_size <=

⌨️ 快捷键说明

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