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

📄 arp.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				if (result != EINTR)					 ip_warning((				"arp.c: read error on port %d: error %d\n", 								fd, result ));				return NW_OK;			}			port->ap_flags &= ~APF_RARP_RD_IP;			if (port->ap_flags & APF_INADDR_SET)				ipaddr_set(port);			else if (port->ap_flags & APF_RARP_RD_SP)				rarp_read_setup(port);			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(rarp46_t));		rarp= (rarp46_t *)ptr2acc_data(data);		if ((data->acc_length >= sizeof(rarp46_t)) &&			(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_REPLY)) &&			(rarp->a46_tha.ea_addr[5] ==				port->ap_ethaddr.ea_addr[5]) &&			(rarp->a46_tha.ea_addr[4] ==				port->ap_ethaddr.ea_addr[4]) &&			(rarp->a46_tha.ea_addr[3] ==				port->ap_ethaddr.ea_addr[3]) &&			(rarp->a46_tha.ea_addr[2] ==				port->ap_ethaddr.ea_addr[2]) &&			(rarp->a46_tha.ea_addr[1] ==				port->ap_ethaddr.ea_addr[1]) &&			(rarp->a46_tha.ea_addr[0] ==				port->ap_ethaddr.ea_addr[0]) &&			!(port->ap_flags & APF_INADDR_SET))		{			memcpy (&port->ap_ipaddr, rarp->a46_tpa,				sizeof(ipaddr_t));			port->ap_flags |= APF_INADDR_SET;#if DEBUG & 256 { unsigned char *a; where();  a=(unsigned char *)&port->ap_ipaddr; 	printf("arp.c: got ip address: %d.%d.%d.%d\n", 	a[0], a[1], a[2], a[3]); }#endif		}		bf_afree(data);		return NW_OK;	}	switch (port->ap_state & APS_STATMASK)	{	case APS_GETADDR:		if (!data)		{			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;		}		compare (bf_bufsize(data), ==, sizeof(*ethstat));		data= bf_packIffLess(data, sizeof(*ethstat));		compare (data->acc_length, ==, sizeof(*ethstat));		ethstat= (struct nwio_ethstat *)ptr2acc_data(data);		port->ap_ethaddr= ethstat->nwes_addr;		bf_afree(data);		return NW_OK;	default:		printf("arp_putdata(%d, 0x%d, 0x%lx) called but ap_state=0x%x\n",			fd, offset, (unsigned long)data, port->ap_state);		break;	}	return EGENERIC;}PRIVATE void rarp_timeout (fd, timer)int fd;timer_t *timer;{	arp_port_t *port;#if DEBUG & 256 { where(); printf("in rarp_timeout()\n"); }#endif	port= &arp_port_table[fd];	assert (timer == &port->ap_timer);	arp_main(port);}PRIVATE void ipaddr_set (port)arp_port_t *port;{	if (port->ap_flags & APF_RARPREQ)	{		port->ap_flags &= ~APF_RARPREQ;		(*port->ap_rarp_func)(port->ap_rarp_ref, port->ap_ipaddr);	}	if (port->ap_state & APS_RARPWAIT)	{		clck_untimer(&port->ap_timer);		port->ap_state= (port->ap_state &			 ~(APS_STATMASK|APS_SUSPEND)) | APS_ARPSTART;		arp_main(port);	}}PRIVATE void setup_read(port)arp_port_t *port;{	int result;	while (!(port->ap_flags & APF_ARP_RD_IP))	{		port->ap_flags |= APF_ARP_RD_IP;		result= eth_read (port->ap_eth_fd, ETH_MAX_PACK_SIZE);		if (result == NW_SUSPEND)			port->ap_flags |= APF_ARP_RD_SP;		if (result<0)		{#if DEBUG if (result != NW_SUSPEND)  { where(); printf("arp.c: eth_read(..,%d)=%d\n", ETH_MAX_PACK_SIZE, result); }#endif			return;		}	}}PRIVATE void setup_write(port)arp_port_t *port;{	int i, result;	while (port->ap_flags & APF_MORE2WRITE)	{		if (port->ap_flags & APF_CLIENTWRITE)		{			port->ap_flags &= ~APF_CLIENTWRITE;			port->ap_write_ipaddr= port->ap_req_ipaddr;			port->ap_write_code= ARP_REQUEST;			clck_timer(&port->ap_timer, get_time() + ARP_TIMEOUT,				arp_timeout, port-arp_port_table);		}		else		{			arp_cache_t *cache;			cache= arp_cache;			for (i=0; i<ARP_CACHE_NR; i++, cache++)				if ((cache->ac_flags & ACF_NETREQ) &&					cache->ac_eth_port ==					port->ap_eth_port)				{					cache->ac_flags &= ~ACF_NETREQ;					port->ap_write_ethaddr= cache->						ac_ethaddr;					port->ap_write_ipaddr= cache->						ac_ipaddr;					port->ap_write_code= ARP_REPLY;					break;				}			if (i>=ARP_CACHE_NR)			{				port->ap_flags &= ~APF_MORE2WRITE;				break;			}		}		port->ap_flags= (port->ap_flags & ~APF_ARP_WR_SP) |			APF_ARP_WR_IP;#if DEBUG & 256 { where(); printf("doing eth_write\n"); }#endif		result= eth_write(port->ap_eth_fd, sizeof(arp46_t));		if (result == NW_SUSPEND)			port->ap_flags |= APF_ARP_WR_SP;		if (result<0)		{#if DEBUG if (result != NW_SUSPEND) { where(); printf("arp.c: eth_write(..,%d)=%d\n", sizeof(rarp46_t), result); }#endif			return;		}	}}PRIVATE void process_arp_req (port, data)arp_port_t *port;acc_t *data;{	arp46_t *arp;	arp_cache_t *prim, *sec;	int level;	time_t curr_tim;	ipaddr_t spa, tpa;#if DEBUG & 256 { where(); printf("process_arp_req(...)\n"); }#endif#if DEBUG & 256 { where(); print_arp_cache(); }#endif	arp= (arp46_t *)ptr2acc_data(data);	memcpy(&spa, arp->a46_spa, sizeof(ipaddr_t));	memcpy(&tpa, arp->a46_tpa, sizeof(ipaddr_t));#if DEBUG & 256 {  if (arp->a46_hdr == htons(ARP_ETHERNET))   { where(); printf("arp.c: a46_hdr OK\n"); }  if (arp->a46_hln == 6)   { where(); printf("arp.c: a46_hln OK\n"); }  if (arp->a46_pro == htons(ETH_IP_PROTO))   { where(); printf("arp.c: a46_pro OK\n"); }  if (arp->a46_pln == 4)   { where(); printf("arp.c: a46_pln OK\n"); } }#endif	if (arp->a46_hdr != htons(ARP_ETHERNET) ||		arp->a46_hln != 6 ||		arp->a46_pro != htons(ETH_IP_PROTO) ||		arp->a46_pln != 4)		return;#if DEBUG & 256 { where(); printf("arp.c: a46_tpa= 0x%lx, ap_ipaddr= 0x%lx\n",	arp->a46_tpa, port->ap_ipaddr); }#endif	if ((port->ap_flags & APF_CLIENTREQ) && (spa == port->ap_req_ipaddr))		level= ARP_TYPE3;	else if (arp->a46_op == htons(ARP_REQUEST) && (tpa ==		port->ap_ipaddr))		level= ARP_TYPE2;	else		level= ARP_TYPE1;#if DEBUG & 256 { where(); printf("arp.c: level= %d\n", level); }#endif	prim= find_cache_ent(port->ap_eth_port, spa, level, &sec);	if (!prim)	{		prim= sec;		prim->ac_flags= ACF_EMPTY;		prim->ac_ipaddr= spa;		prim->ac_eth_port= port->ap_eth_port;	}	else if (prim->ac_type < level)	{		sec->ac_type= prim->ac_type;		prim->ac_type= level;	}	prim->ac_ethaddr= arp->a46_sha;	curr_tim= get_time();	prim->ac_expire= curr_tim+ ARP_EXP_TIME;	if (curr_tim > prim->ac_lastuse)		prim->ac_lastuse= curr_tim;	prim->ac_flags &= ~ACF_NOTRCH;	if (level== ARP_TYPE2)	{		prim->ac_flags |= ACF_NETREQ;		port->ap_flags |= APF_MORE2WRITE;		if (!(port->ap_flags & APF_ARP_WR_IP))			setup_write(port);	} else if (level== ARP_TYPE3)	{		prim->ac_lastuse= curr_tim + ARP_INUSE_OFFSET;		client_reply(port, &arp->a46_sha);	}#if DEBUG & 256 { where(); print_arp_cache(); }#endif}PRIVATE void client_reply (port, ethaddr)arp_port_t *port;ether_addr_t *ethaddr;{	port->ap_flags &= ~(APF_CLIENTREQ|APF_CLIENTWRITE);	clck_untimer(&port->ap_timer);	(*port->ap_req_func)(port->ap_req_ref, ethaddr);}PRIVATE arp_cache_t *find_cache_ent (eth_port, ipaddr, level, new_ent)int eth_port;ipaddr_t ipaddr;int level;arp_cache_t **new_ent;{	arp_cache_t *cache, *prim, *sec;	int i;	cache= arp_cache;	prim= 0;	sec= 0;	for (i=0; i<ARP_CACHE_NR; i++, cache++)	{		if (cache->ac_eth_port == eth_port &&			cache->ac_ipaddr == ipaddr)			prim= cache;		if (cache->ac_type == level && (!sec || cache->ac_lastuse <			sec->ac_lastuse))			sec= cache;	}	assert(sec);	*new_ent= sec;	return prim;}PRIVATE void rarp_read_setup (port)arp_port_t *port;{	int result;	while (!(port->ap_flags & (APF_RARP_RD_IP|APF_INADDR_SET)))	{		port->ap_flags= (port->ap_flags & ~ APF_RARP_RD_SP) |			APF_RARP_RD_IP;		result= eth_read (port->ap_eth_fd, ETH_MAX_PACK_SIZE);		if (result == NW_SUSPEND)			port->ap_flags |= APF_RARP_RD_SP;		if (result<0)		{#if DEBUG if (result != NW_SUSPEND) { where(); printf("arp.c: eth_read(..,%d)=%d\n", ETH_MAX_PACK_SIZE, result); }#endif			return;		}		if ((port->ap_state & APS_STATMASK) != APS_RARPPROTO)			return;	}}PUBLIC int rarp_req(eth_port, ref, func)int eth_port;int ref;rarp_func_t func;{	arp_port_t *port;	int i;	port= arp_port_table;	for (i=0; i<ARP_PORT_NR; i++, port++)		if (port->ap_eth_port == eth_port)			break;	if (i>=ARP_PORT_NR)		return EGENERIC;	if (port->ap_flags & APF_INADDR_SET)	{		(*func)(ref, port->ap_ipaddr);		return NW_OK;	}	port->ap_flags |= APF_RARPREQ;	port->ap_rarp_ref= ref;	port->ap_rarp_func= func;	return NW_SUSPEND;}PUBLIC void set_ipaddr (eth_port, ipaddr)int eth_port;ipaddr_t ipaddr;{	arp_port_t *port;	int i;	port= arp_port_table;	for (i=0; i<ARP_PORT_NR; i++, port++)		if (port->ap_eth_port == eth_port)			break;	assert (i < ARP_PORT_NR);	port->ap_ipaddr= ipaddr;	port->ap_flags |= APF_INADDR_SET;	ipaddr_set(port);}PUBLIC int arp_ip_eth (eth_port, ref, ipaddr, func)int eth_port;int ref;ipaddr_t ipaddr;arp_req_func_t func;{	arp_port_t *port;	int i;	arp_cache_t *prim, *sec;#if DEBUG & 256 { where(); printf("sending arp_req for: "); writeIpAddr(ipaddr);	printf("\n"); }#endif	port= arp_port_table;	for (i=0; i<ARP_PORT_NR; i++, port++)		if (port->ap_eth_port == eth_port)			break;	if (i>=ARP_PORT_NR)		return EGENERIC;	if ((port->ap_state & APS_STATMASK) != APS_ARPMAIN)	{		port->ap_flags |= APF_CLIENTREQ|APF_MORE2WRITE |			APF_CLIENTWRITE;		port->ap_req_func= func;		port->ap_req_ref= ref;		port->ap_req_ipaddr= ipaddr;		port->ap_req_count= 0;		return NW_SUSPEND;	}	prim= find_cache_ent (eth_port, ipaddr, ARP_TYPE3, &sec);	if (prim)	{		if (prim->ac_type < ARP_TYPE3)		{			sec->ac_type= prim->ac_type;			prim->ac_type= ARP_TYPE3;		}		if (prim->ac_expire < get_time())			prim= 0;	}	if (!prim)	{		port->ap_flags |= APF_CLIENTREQ|APF_MORE2WRITE|APF_CLIENTWRITE;		port->ap_req_func= func;		port->ap_req_ref= ref;		port->ap_req_ipaddr= ipaddr;		port->ap_req_count= 0;		if (!(port->ap_flags & APF_ARP_WR_IP))			setup_write(port);		return NW_SUSPEND;	}	prim->ac_lastuse= get_time();	if (prim->ac_flags & ACF_NOTRCH)		return EDSTNOTRCH;	else	{		client_reply (port, &prim->ac_ethaddr);		return NW_OK;	}}PUBLIC int arp_ip_eth_nonbl (eth_port, ipaddr, ethaddr)int eth_port;ipaddr_t ipaddr;ether_addr_t *ethaddr;{	arp_port_t *port;	int i;	arp_cache_t *prim, *sec;#if DEBUG & 256 { where(); printf("got a arp_ip_eth_nonbl(%d, ", eth_port);	writeIpAddr(ipaddr); printf(", ...)\n");  }#endif	port= arp_port_table;	for (i=0; i<ARP_PORT_NR; i++, port++)		if (port->ap_eth_port == eth_port)			break;	if (i>=ARP_PORT_NR)		return EGENERIC;	if ((port->ap_state & APS_STATMASK) != APS_ARPMAIN)	{#if DEBUG { where(); printf("replying NW_SUSPEND\n"); }#endif		return NW_SUSPEND;	}	prim= find_cache_ent (eth_port, ipaddr, ARP_TYPE3, &sec);	if (prim)	{		if (prim->ac_type < ARP_TYPE3)		{			sec->ac_type= prim->ac_type;			prim->ac_type= ARP_TYPE3;		}		if (prim->ac_expire < get_time())			prim= 0;	}	if (!prim)	{#if DEBUG & 256 { where(); printf("replying NW_SUSPEND\n"); }#endif		return NW_SUSPEND;	}	if (prim->ac_flags & ACF_NOTRCH)	{#if DEBUG { where(); printf("replying EDSTNOTRCH\n"); }#endif		return EDSTNOTRCH;	}	else	{		prim->ac_lastuse= get_time();		if (ethaddr)			*ethaddr= prim->ac_ethaddr;#if DEBUG & 256 { where(); printf("replying NW_OK (\n"); writeEtherAddr(&prim->ac_ethaddr);	printf(")\n"); }#endif		return NW_OK;	}}PRIVATE void arp_timeout (fd, timer)int fd;timer_t *timer;{	arp_port_t *port;	arp_cache_t *prim, *sec;	int level;	time_t curr_tim;	port= &arp_port_table[fd];	assert (timer == &port->ap_timer);	if (++port->ap_req_count < MAX_ARP_RETRIES)	{		port->ap_flags |= APF_CLIENTWRITE|APF_MORE2WRITE;		if (!(port->ap_flags & APF_ARP_WR_IP))			setup_write(port);	}	else	{		level= ARP_TYPE3;		prim= find_cache_ent(port->ap_eth_port, port->ap_req_ipaddr,			level, &sec);		if (!prim)		{			prim= sec;			prim->ac_flags= ACF_EMPTY;			prim->ac_ipaddr= port->ap_req_ipaddr;		}		else if (prim->ac_type < level)		{			sec->ac_type= prim->ac_type;			prim->ac_type= level;		}		curr_tim= get_time();		prim->ac_expire= curr_tim+ ARP_NOTRCH_EXP_TIME;		prim->ac_lastuse= curr_tim + ARP_INUSE_OFFSET;		prim->ac_flags |= ACF_NOTRCH;		(*port->ap_req_func)(port->ap_req_ref,			(ether_addr_t *)0);	}}PRIVATE void print_arp_cache(){	int i;	arp_cache_t *ci;	for (i=0, ci= arp_cache; i< ARP_CACHE_NR; i++, ci++)	{		if (!ci->ac_expire)			continue;		printf("%d %d ", ci->ac_flags, ci->ac_type);		writeEtherAddr(&ci->ac_ethaddr);		printf(" ");		writeIpAddr(ci->ac_ipaddr);		printf(" %d %ld %ld\n", ci->ac_eth_port, ci->ac_expire,			ci->ac_lastuse);	}}

⌨️ 快捷键说明

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