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

📄 arp.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*arp.c*/#include "inet.h"#include "arp.h"#include "assert.h"#include "buf.h"#include "clock.h"#include "eth.h"#include "io.h"#include "sr.h"#include "type.h"INIT_PANIC();#define ARP_PORT_NR	1#define ARP_CACHE1_NR	8#define ARP_CACHE2_NR	8#define ARP_CACHE3_NR	16#define ARP_CACHE_NR	(ARP_CACHE1_NR+ARP_CACHE2_NR+ARP_CACHE3_NR)#define ARP_TYPE1	1#define ARP_TYPE2	2#define ARP_TYPE3	3#define MAX_RARP_RETRIES	5#define MAX_ARP_RETRIES		5#define RARP_TIMEOUT		(1*HZ)#define ARP_TIMEOUT		(HZ/2+1)	/* .5 seconds */#define ARP_EXP_TIME		(20L*60L*HZ)	/* 20 minutes */#define ARP_NOTRCH_EXP_TIME	(2L*60L*HZ)	/* 2 minutes */#define ARP_INUSE_OFFSET	(60*HZ)	/* an entry in the cache can be deleted					   if its not used for 1 minute */typedef struct arp46{	ether_addr_t a46_dstaddr;	ether_addr_t a46_srcaddr;	ether_type_t a46_ethtype;	union	{		struct		{			u16_t a_hdr, a_pro;			u8_t a_hln, a_pln;			u16_t a_op;			ether_addr_t a_sha;			u8_t a_spa[4];			ether_addr_t a_tha;			u8_t a_tpa[4];		} a46_data;		char    a46_dummy[ETH_MIN_PACK_SIZE-ETH_HDR_SIZE];	} a46_data;} arp46_t, rarp46_t;#define a46_hdr a46_data.a46_data.a_hdr#define a46_pro a46_data.a46_data.a_pro#define a46_hln a46_data.a46_data.a_hln#define a46_pln a46_data.a46_data.a_pln#define a46_op a46_data.a46_data.a_op#define a46_sha a46_data.a46_data.a_sha#define a46_spa a46_data.a46_data.a_spa#define a46_tha a46_data.a46_data.a_tha#define a46_tpa a46_data.a46_data.a_tpatypedef struct arp_cache{	int ac_flags;	int ac_type;	ether_addr_t ac_ethaddr;	ipaddr_t ac_ipaddr;	int ac_eth_port;	time_t ac_expire;	time_t ac_lastuse;} arp_cache_t;#define ACF_EMPTY	0#define ACF_NETREQ	1#define ACF_NOTRCH	2typedef struct arp_port{	int ap_flags;	int ap_state;	int ap_eth_port;	int ap_eth_fd;	int ap_rarp_retries;	ether_addr_t ap_ethaddr;	ipaddr_t ap_ipaddr;	timer_t ap_timer;	ether_addr_t ap_write_ethaddr;	ipaddr_t ap_write_ipaddr;	int ap_write_code;	ipaddr_t ap_req_ipaddr;	arp_req_func_t ap_req_func;	int ap_req_ref;	int ap_req_count;	rarp_func_t ap_rarp_func;	int ap_rarp_ref;} arp_port_t;#define APF_EMPTY	0#define APF_RARP_RD_IP	0x1#define APF_RARP_RD_SP	0x2#define APF_ARP_RD_IP	0x4#define APF_ARP_RD_SP	0x8#define APF_ARP_WR_IP	0x10#define APF_ARP_WR_SP	0x20#define APF_INADDR_SET	0x100#define APF_MORE2WRITE	0x200#define APF_CLIENTREQ	0x400#define APF_RARPREQ	0x800#define APF_CLIENTWRITE	0x1000#define APS_EMPTY	0#define APS_STATMASK	0xff#define		APS_GETADDR	0x1#define		APS_RARPPROTO	0x2#define		APS_RARPWRITE	0x4#define		APS_RARPWAIT	0x8#define		APS_ARPSTART	0x10#define		APS_ARPPROTO	0x20#define		APS_ARPMAIN	0x40#define		APS_ERROR	0x80#define APS_SUSPEND	0x400FORWARD acc_t *arp_getdata ARGS(( int fd, size_t offset,	size_t count, int for_ioctl ));FORWARD int arp_putdata ARGS(( int fd, size_t offset,	acc_t *data, int for_ioctl ));FORWARD void arp_main ARGS(( arp_port_t *port ));FORWARD void arp_timeout ARGS(( int fd, timer_t *timer ));FORWARD void rarp_timeout ARGS(( int fd, timer_t *timer ));FORWARD void ipaddr_set ARGS(( arp_port_t *port ));FORWARD void setup_write ARGS(( arp_port_t *port ));FORWARD void setup_read ARGS(( arp_port_t *port ));FORWARD void process_arp_req ARGS(( arp_port_t *port, acc_t *data ));FORWARD void client_reply ARGS(( arp_port_t *port,	ether_addr_t *ethaddr ));FORWARD arp_cache_t *find_cache_ent ARGS(( int eth_port, ipaddr_t ipaddr,	int level, arp_cache_t **new_ent ));FORWARD void rarp_read_setup ARGS(( arp_port_t *port ));FORWARD void print_arp_cache ARGS(( void ));PRIVATE arp_port_t arp_port_table[ARP_PORT_NR];PRIVATE arp_port_t *arp_port;PRIVATE	arp_cache_t arp_cache[ARP_CACHE_NR];PUBLIC void arp_init(){	int i;	assert (BUF_S >= sizeof(struct nwio_ethstat));	assert (BUF_S >= sizeof(struct nwio_ethopt));	assert (BUF_S >= sizeof(rarp46_t));	assert (BUF_S >= sizeof(arp46_t));	arp_port_table[0].ap_eth_port= ETH0;	for (i=0, arp_port= arp_port_table; i<ARP_PORT_NR; i++, arp_port++)	{		arp_port->ap_state= APS_EMPTY;		arp_port->ap_flags= APF_EMPTY;		arp_main(arp_port);	}}PRIVATE void arp_main(port)arp_port_t *port;{	int result;#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n", port->ap_state &	APS_STATMASK); }#endif	switch (port->ap_state & APS_STATMASK)	{	case APS_EMPTY:		port->ap_rarp_retries= 0;		port->ap_eth_fd= eth_open(port->ap_eth_port,			port-arp_port_table, arp_getdata, arp_putdata);		if (port->ap_eth_fd<0)		{	printf("arp.c: unable to open ethernet\n");			return;		}		port->ap_state= (port->ap_state &			 ~(APS_STATMASK|APS_SUSPEND)) | APS_GETADDR;		result= eth_ioctl (port->ap_eth_fd, NWIOGETHSTAT);		if (result==NW_SUSPEND)			port->ap_state |= APS_SUSPEND;		if (result<0)		{#if DEBUG if (result != NW_SUSPEND) { where(); printf("arp.c: eth_ioctl(..,NWIOGETHSTAT)=%d\n", result); }#endif			return;		}		if ((port->ap_state & APS_STATMASK) != APS_GETADDR)			return;		/* drop through */	case APS_GETADDR:#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n", port->ap_state & APS_STATMASK); }#endif		port->ap_state= (port->ap_state &			~(APS_STATMASK|APS_SUSPEND)) | APS_RARPPROTO;		result= eth_ioctl (port->ap_eth_fd, NWIOSETHOPT);		if (result==NW_SUSPEND)			port->ap_state |= APS_SUSPEND;		if (result<0)		{#if DEBUG if (result != NW_SUSPEND) { printf("arp.c: eth_ioctl(..,NWIOSETHOPT)=%d\n", result); }#endif			return;		}		if ((port->ap_state & APS_STATMASK) != APS_RARPPROTO)			return;		/* drop through */	case APS_RARPWAIT:#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n",	port->ap_state & APS_STATMASK); }#endif		if (port->ap_flags & APF_INADDR_SET)		{			port->ap_state= (port->ap_state &				~(APS_STATMASK|APS_SUSPEND)) | APS_ARPSTART;			arp_main(port);			return;		}		/* drop through */	case APS_RARPPROTO:#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n",	port->ap_state & APS_STATMASK); }#endif		rarp_read_setup(port);		port->ap_state= (port->ap_state &			~(APS_STATMASK|APS_SUSPEND)) | APS_RARPWRITE;#if DEBUG & 256 { where(); printf("doing eth_write\n"); }#endif		result= eth_write (port->ap_eth_fd, sizeof(rarp46_t));		if (result == NW_SUSPEND)			port->ap_state |= APS_SUSPEND;		if (result<0)		{#if DEBUG & 256 if (result != NW_SUSPEND) { where();  printf("arp.c: eth_write(..,%d)=%d\n", sizeof(rarp46_t), result); }#endif			return;		}		if ((port->ap_state & APS_STATMASK) != APS_RARPWRITE)			return;		/* drop through */	case APS_RARPWRITE:#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n",	port->ap_state & APS_STATMASK); }#endif		port->ap_state= (port->ap_state &			~(APS_STATMASK|APS_SUSPEND)) | APS_RARPWAIT;		if (port->ap_rarp_retries>=MAX_RARP_RETRIES)			return;#if DEBUG & 256 { where(); printf("port->ap_rarp_retries= %d\n",	port->ap_rarp_retries); }#endif		port->ap_rarp_retries++;		clck_timer(&port->ap_timer, get_time() + RARP_TIMEOUT,			rarp_timeout, port-arp_port_table);		return;	case APS_ARPSTART:#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n",	port->ap_state & APS_STATMASK); }#endif		if (port->ap_flags & APF_RARP_RD_IP)		{			eth_cancel(port->ap_eth_fd, SR_CANCEL_READ);			port->ap_flags &= ~(APF_RARP_RD_IP|APF_RARP_RD_SP);		}		port->ap_state= (port->ap_state &			~(APS_STATMASK|APS_SUSPEND)) | APS_ARPPROTO;		{			arp_cache_t *cache;			int i;			cache= arp_cache;			for (i=0; i<ARP_CACHE_NR; i++, cache++)			{				cache->ac_flags= ACF_EMPTY;				cache->ac_expire= 0;				cache->ac_lastuse= 0;			}			cache= arp_cache;			for (i=0; i<ARP_CACHE1_NR; i++, cache++)				cache->ac_type= 1;			for (i=0; i<ARP_CACHE2_NR; i++, cache++)				cache->ac_type= 2;			for (i=0; i<ARP_CACHE3_NR; i++, cache++)				cache->ac_type= 3;		}		result= eth_ioctl (port->ap_eth_fd, NWIOSETHOPT);		if (result==NW_SUSPEND)			port->ap_state |= APS_SUSPEND;		if (result<0)		{#if DEBUG { where(); printf("arp.c: /* arp */ eth_ioctl(..,NWIOSETHOPT)=%d\n",	result); }#endif			return;		}		if ((port->ap_state & APS_STATMASK) != APS_ARPPROTO)			return;		/* drop through */	case APS_ARPPROTO:#if DEBUG & 256 { where(); printf("in arp_main with status: %d\n",	port->ap_state & APS_STATMASK); }#endif		port->ap_state= (port->ap_state &			~(APS_STATMASK|APS_SUSPEND)) | APS_ARPMAIN;		if (port->ap_flags & APF_MORE2WRITE)			setup_write(port);		setup_read(port);		return;	default:		ip_panic((		 "arp_main(&arp_port_table[%d]) called but ap_state=0x%x\n",			port-arp_port_table, port->ap_state ));	}}PRIVATE acc_t *arp_getdata (fd, offset, count, for_ioctl)int fd;size_t offset;size_t count;int for_ioctl;{	arp_port_t *port;	rarp46_t *rarp;	arp46_t *arp;	acc_t *data;	int result;#if DEBUG & 256 { where(); printf("arp_getdata (fd= %d, offset= %d, count= %d)\n", fd,	offset, count); }#endif	port= &arp_port_table[fd];	switch (port->ap_state & APS_STATMASK)	{	case APS_RARPPROTO:		if (!count)		{			result= (int)offset;			if (result<0)			{				port->ap_state= (port->ap_state &					 ~(APS_STATMASK|APS_SUSPEND))|					 APS_ERROR;				break;			}			if (port->ap_state & APS_SUSPEND)				arp_main(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_TYPESPEC;			ethopt->nweo_type= htons(ETH_RARP_PROTO);			return acc;		}	case APS_RARPWRITE:		if (!count)		{			result= (int)offset;			if (result<0)			{#if DEBUG if (result != NW_SUSPEND) { where(); printf("arp.c: write error on port %d: error %d\n", fd, result); }#endif				port->ap_state= (port->ap_state &					 ~(APS_STATMASK|APS_SUSPEND))|					 APS_ERROR;				break;			}			if (port->ap_state & APS_SUSPEND)				arp_main(port);			return NW_OK;		}		assert (offset+count <= sizeof(rarp46_t));		data= bf_memreq(sizeof(rarp46_t));		rarp= (rarp46_t *)ptr2acc_data(data);		data->acc_offset += offset;		data->acc_length= count;		rarp->a46_dstaddr.ea_addr[0]= 0xff;		rarp->a46_dstaddr.ea_addr[1]= 0xff;		rarp->a46_dstaddr.ea_addr[2]= 0xff;		rarp->a46_dstaddr.ea_addr[3]= 0xff;		rarp->a46_dstaddr.ea_addr[4]= 0xff;		rarp->a46_dstaddr.ea_addr[5]= 0xff;		rarp->a46_hdr= htons(ARP_ETHERNET);		rarp->a46_pro= htons(ETH_IP_PROTO);		rarp->a46_hln= 6;		rarp->a46_pln= 4;		rarp->a46_op= htons(RARP_REQUEST);		rarp->a46_sha= port->ap_ethaddr;		rarp->a46_tha= port->ap_ethaddr;		return data;	case APS_ARPPROTO:		if (!count)		{			result= (int)offset;			if (result<0)			{				port->ap_state= (port->ap_state &					 ~(APS_STATMASK|APS_SUSPEND))|					 APS_ERROR;				break;			}			if (port->ap_state & APS_SUSPEND)				arp_main(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_TYPESPEC;			ethopt->nweo_type= htons(ETH_ARP_PROTO);			return acc;		}	case APS_ARPMAIN:		assert (port->ap_flags & APF_ARP_WR_IP);		if (!count)		{			result= (int)offset;			if (result<0)			{#if DEBUG if (result != NW_SUSPEND) { where(); printf("arp.c: write error on port %d: error %d\n", fd, result); }#endif				port->ap_state= (port->ap_state &					 ~(APS_STATMASK|APS_SUSPEND))|					 APS_ERROR;				break;			}			port->ap_flags &= ~APF_ARP_WR_IP;			if (port->ap_flags & APF_ARP_WR_SP)				setup_write(port);			return NW_OK;		}		assert (offset+count <= sizeof(arp46_t));		data= bf_memreq(sizeof(arp46_t));		arp= (arp46_t *)ptr2acc_data(data);		data->acc_offset += offset;		data->acc_length= count;		if (port->ap_write_code == ARP_REPLY)			arp->a46_dstaddr= port->ap_write_ethaddr;		else		{			arp->a46_dstaddr.ea_addr[0]= 0xff;			arp->a46_dstaddr.ea_addr[1]= 0xff;			arp->a46_dstaddr.ea_addr[2]= 0xff;			arp->a46_dstaddr.ea_addr[3]= 0xff;			arp->a46_dstaddr.ea_addr[4]= 0xff;			arp->a46_dstaddr.ea_addr[5]= 0xff;		}		arp->a46_hdr= htons(ARP_ETHERNET);		arp->a46_pro= htons(ETH_IP_PROTO);		arp->a46_hln= 6;		arp->a46_pln= 4;		arp->a46_op= htons(port->ap_write_code);		arp->a46_sha= port->ap_ethaddr;		memcpy (arp->a46_spa, &port->ap_ipaddr, sizeof(ipaddr_t));		arp->a46_tha= port->ap_write_ethaddr;		memcpy (arp->a46_tpa, &port->ap_write_ipaddr, sizeof(ipaddr_t));		return data;	default:		printf("arp_getdata(%d, 0x%d, 0x%d) called but ap_state=0x%x\n",			fd, offset, count, port->ap_state);		break;	}	return 0;}PRIVATE int arp_putdata (fd, offset, data, for_ioctl)int fd;size_t offset;acc_t *data;int for_ioctl;{	arp_port_t *port;	int result;	struct nwio_ethstat *ethstat;	rarp46_t *rarp;#if DEBUG & 256 { where(); printf("arp_putdata (fd= %d, offset= %d, data= 0x%x)\n",	fd, offset, data); }#endif	port= &arp_port_table[fd];	if (port->ap_flags & APF_ARP_RD_IP)	{		if (!data)		{			result= (int)offset;			if (result<0)			{#if DEBUG if (result != NW_SUSPEND) { where(); printf("arp.c: read error on port %d: error %d\n", fd, result); }#endif				return NW_OK;			}			if (port->ap_flags & APF_ARP_RD_SP)			{				port->ap_flags &= ~(APF_ARP_RD_IP|					APF_ARP_RD_SP);				setup_read(port);			}			else				port->ap_flags &= ~(APF_ARP_RD_IP|					APF_ARP_RD_SP);			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. */		data= bf_packIffLess(data, sizeof(arp46_t));		if (data->acc_length >= sizeof(arp46_t))			process_arp_req(port,data);		bf_afree(data);		return NW_OK;	}	if (port->ap_flags & APF_RARP_RD_IP)	{		if (!data)		{			result= (int)offset;			if (result<0)			{

⌨️ 快捷键说明

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