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

📄 arp.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		memcpy (arp->a46_spa, &tpa, sizeof(ipaddr_t));		arp->a46_tha= ce->ac_ethaddr;		memcpy (arp->a46_tpa, &ce->ac_ipaddr, sizeof(ipaddr_t));		assert(data->acc_linkC == 1);		data->acc_ext_link= arp_port->ap_sendlist;		arp_port->ap_sendlist= data; data= NULL;		if (!(arp_port->ap_flags & APF_ARP_WR_IP))			setup_write(arp_port);	}}PRIVATE void client_reply (arp_port, ipaddr, ethaddr)arp_port_t *arp_port;ipaddr_t ipaddr;ether_addr_t *ethaddr;{	(*arp_port->ap_arp_func)(arp_port->ap_ip_port, ipaddr, ethaddr);}PRIVATE arp_cache_t *find_cache_ent (arp_port, ipaddr)arp_port_t *arp_port;ipaddr_t ipaddr;{	arp_cache_t *ce;	int i;	unsigned hash;	hash= (ipaddr >> 24) ^ (ipaddr >> 16) ^ (ipaddr >> 8) ^ ipaddr;	hash &= ARP_HASH_MASK;	ce= arp_hash[hash].ahe_row[0];	if (ce && ce->ac_ipaddr == ipaddr && ce->ac_port == arp_port &&		ce->ac_state != ACS_UNUSED)	{		return ce;	}	for (i= 1; i<ARP_HASH_WIDTH; i++)	{		ce= arp_hash[hash].ahe_row[i];		if (!ce || ce->ac_ipaddr != ipaddr || ce->ac_port != arp_port			|| ce->ac_state == ACS_UNUSED)		{			continue;		}		arp_hash[hash].ahe_row[i]= arp_hash[hash].ahe_row[0];		arp_hash[hash].ahe_row[0]= ce;		return ce;	}	for (i=0, ce= arp_cache; i<arp_cache_nr; i++, ce++)	{		if (ce->ac_state != ACS_UNUSED &&			ce->ac_port == arp_port &&			ce->ac_ipaddr == ipaddr)		{			for (i= ARP_HASH_WIDTH-1; i>0; i--)			{				arp_hash[hash].ahe_row[i]=					arp_hash[hash].ahe_row[i-1];			}			assert(i == 0);			arp_hash[hash].ahe_row[0]= ce;			return ce;		}	}	return NULL;}PRIVATE arp_cache_t *alloc_cache_ent(flags)int flags;{	arp_cache_t *cache, *old;	int i;	old= NULL;	for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)	{		if (cache->ac_state == ACS_UNUSED)		{			old= cache;			break;		}		if (cache->ac_state == ACS_INCOMPLETE)			continue;		if (cache->ac_flags & ACF_PERM)			continue;		if (!old || cache->ac_lastuse < old->ac_lastuse)			old= cache;	}	assert(old);	if (!flags)		return old;	/* Get next permanent entry */	for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)	{		if (cache->ac_state == ACS_UNUSED)			break;		if (cache->ac_flags & ACF_PERM)			continue;		break;	}	if (i >= arp_cache_nr/2)		return NULL; /* Too many entries */	if (cache != old)	{		assert(old > cache);		*old= *cache;		old= cache;	}	if (!(flags & ACF_PUB))		return old;	/* Get first nonpublished entry */	for (i=0, cache= arp_cache; i<arp_cache_nr; i++, cache++)	{		if (cache->ac_state == ACS_UNUSED)			break;		if (cache->ac_flags & ACF_PUB)			continue;		break;	}	if (cache != old)	{		assert(old > cache);		*old= *cache;		old= cache;	}	return old;}PUBLIC void arp_set_ipaddr (eth_port, ipaddr)int eth_port;ipaddr_t ipaddr;{	arp_port_t *arp_port;	if (eth_port < 0 || eth_port >= eth_conf_nr)		return;	arp_port= &arp_port_table[eth_port];	arp_port->ap_ipaddr= ipaddr;	arp_port->ap_flags |= APF_INADDR_SET;	arp_port->ap_flags &= ~APF_SUSPEND;	if (arp_port->ap_state == APS_GETADDR)		arp_main(arp_port);}PUBLIC int arp_set_cb(eth_port, ip_port, arp_func)int eth_port;int ip_port;arp_func_t arp_func;{	int i;	arp_port_t *arp_port;	assert(eth_port >= 0);	if (eth_port >= eth_conf_nr)		return ENXIO;	arp_port= &arp_port_table[eth_port];	arp_port->ap_eth_port= eth_port;	arp_port->ap_ip_port= ip_port;	arp_port->ap_state= APS_INITIAL;	arp_port->ap_flags= APF_EMPTY;	arp_port->ap_arp_func= arp_func;	arp_port->ap_sendpkt= NULL;	arp_port->ap_sendlist= NULL;	arp_port->ap_reclist= NULL;	for (i= 0; i<AP_REQ_NR; i++)		arp_port->ap_req[i].ar_entry= -1;	ev_init(&arp_port->ap_event);	arp_main(arp_port);	return NW_OK;}PUBLIC int arp_ip_eth (eth_port, ipaddr, ethaddr)int eth_port;ipaddr_t ipaddr;ether_addr_t *ethaddr;{	int i, ref;	arp_port_t *arp_port;	struct arp_req *reqp;	arp_cache_t *ce;	time_t curr_time;	assert(eth_port >= 0 && eth_port < eth_conf_nr);	arp_port= &arp_port_table[eth_port];	assert(arp_port->ap_state == APS_ARPMAIN ||		(printf("arp[%d]: ap_state= %d\n", arp_port-arp_port_table,		arp_port->ap_state), 0));	curr_time= get_time();	ce= find_cache_ent (arp_port, ipaddr);	if (ce && ce->ac_expire < curr_time)	{		assert(ce->ac_state != ACS_INCOMPLETE);		/* Check whether there is enough space for an ARP		 * request or not.		 */		for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; i++, reqp++)		{			if (reqp->ar_entry < 0)				break;		}		if (i < AP_REQ_NR)		{			/* Okay, expire this entry. */			ce->ac_state= ACS_UNUSED;			ce= NULL;		}		else		{			/* Continue using this entry for a while */			printf("arp[%d]: Overloaded! Keeping entry for ",				arp_port-arp_port_table);			writeIpAddr(ipaddr);			printf("\n");			ce->ac_expire= curr_time+ARP_NOTRCH_EXP_TIME;		}	}	if (ce)	{		/* Found an entry. This entry should be valid, unreachable		 * or incomplete.		 */		ce->ac_lastuse= curr_time;		if (ce->ac_state == ACS_VALID)		{			*ethaddr= ce->ac_ethaddr;			return NW_OK;		}		if (ce->ac_state == ACS_UNREACHABLE)			return EDSTNOTRCH;		assert(ce->ac_state == ACS_INCOMPLETE);		return NW_SUSPEND;	}	/* Find an empty slot for an ARP request */	for (i= 0, reqp= arp_port->ap_req; i<AP_REQ_NR; i++, reqp++)	{		if (reqp->ar_entry < 0)			break;	}	if (i >= AP_REQ_NR)	{		/* We should be able to report that this ARP request		 * cannot be accepted. At the moment we just return SUSPEND.		 */		return NW_SUSPEND;	}	ref= (eth_port*AP_REQ_NR + i);	ce= alloc_cache_ent(ACF_EMPTY);	ce->ac_flags= 0;	ce->ac_state= ACS_INCOMPLETE;	ce->ac_ipaddr= ipaddr;	ce->ac_port= arp_port;	ce->ac_expire= curr_time+ARP_EXP_TIME;	ce->ac_lastuse= curr_time;	reqp->ar_entry= ce-arp_cache;	reqp->ar_req_count= -1;	/* Send the first packet by expiring the timer */	clck_timer(&reqp->ar_timer, 1, arp_timeout, ref);	return NW_SUSPEND;}PUBLIC int arp_ioctl (eth_port, fd, req, get_userdata, put_userdata)int eth_port;int fd;ioreq_t req;get_userdata_t get_userdata;put_userdata_t put_userdata;{	arp_port_t *arp_port;	arp_cache_t *ce, *cache;	acc_t *data;	nwio_arp_t *arp_iop;	int entno, result, ac_flags;	u32_t flags;	ipaddr_t ipaddr;	time_t curr_time;	assert(eth_port >= 0 && eth_port < eth_conf_nr);	arp_port= &arp_port_table[eth_port];	assert(arp_port->ap_state == APS_ARPMAIN ||		(printf("arp[%d]: ap_state= %d\n", arp_port-arp_port_table,		arp_port->ap_state), 0));	switch(req)	{	case NWIOARPGIP:		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);		if (data == NULL)			return EFAULT;		data= bf_packIffLess(data, sizeof(*arp_iop));		arp_iop= (nwio_arp_t *)ptr2acc_data(data);		ipaddr= arp_iop->nwa_ipaddr;		ce= NULL;	/* lint */		for (entno= 0; entno < arp_cache_nr; entno++)		{			ce= &arp_cache[entno];			if (ce->ac_state == ACS_UNUSED ||				ce->ac_port != arp_port)			{				continue;			}			if (ce->ac_ipaddr == ipaddr)				break;		}		if (entno == arp_cache_nr)		{			/* Also report the address of this interface */			if (ipaddr != arp_port->ap_ipaddr)			{				bf_afree(data);				return ENOENT;			}			arp_iop->nwa_entno= arp_cache_nr;			arp_iop->nwa_ipaddr= ipaddr;			arp_iop->nwa_ethaddr= arp_port->ap_ethaddr;			arp_iop->nwa_flags= NWAF_PERM | NWAF_PUB;		}		else		{			arp_iop->nwa_entno= entno+1;			arp_iop->nwa_ipaddr= ce->ac_ipaddr;			arp_iop->nwa_ethaddr= ce->ac_ethaddr;			arp_iop->nwa_flags= 0;			if (ce->ac_state == ACS_INCOMPLETE)				arp_iop->nwa_flags |= NWAF_INCOMPLETE;			if (ce->ac_state == ACS_UNREACHABLE)				arp_iop->nwa_flags |= NWAF_DEAD;			if (ce->ac_flags & ACF_PERM)				arp_iop->nwa_flags |= NWAF_PERM;			if (ce->ac_flags & ACF_PUB)				arp_iop->nwa_flags |= NWAF_PUB;		}		result= (*put_userdata)(fd, 0, data, TRUE);		return result;	case NWIOARPGNEXT:		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);		if (data == NULL)			return EFAULT;		data= bf_packIffLess(data, sizeof(*arp_iop));		arp_iop= (nwio_arp_t *)ptr2acc_data(data);		entno= arp_iop->nwa_entno;		if (entno < 0)			entno= 0;		ce= NULL;	/* lint */		for (; entno < arp_cache_nr; entno++)		{			ce= &arp_cache[entno];			if (ce->ac_state == ACS_UNUSED ||				ce->ac_port != arp_port)			{				continue;			}			break;		}		if (entno == arp_cache_nr)		{			bf_afree(data);			return ENOENT;		}		arp_iop->nwa_entno= entno+1;		arp_iop->nwa_ipaddr= ce->ac_ipaddr;		arp_iop->nwa_ethaddr= ce->ac_ethaddr;		arp_iop->nwa_flags= 0;		if (ce->ac_state == ACS_INCOMPLETE)			arp_iop->nwa_flags |= NWAF_INCOMPLETE;		if (ce->ac_state == ACS_UNREACHABLE)			arp_iop->nwa_flags |= NWAF_DEAD;		if (ce->ac_flags & ACF_PERM)			arp_iop->nwa_flags |= NWAF_PERM;		if (ce->ac_flags & ACF_PUB)			arp_iop->nwa_flags |= NWAF_PUB;		result= (*put_userdata)(fd, 0, data, TRUE);		return result;	case NWIOARPSIP:		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);		if (data == NULL)			return EFAULT;		data= bf_packIffLess(data, sizeof(*arp_iop));		arp_iop= (nwio_arp_t *)ptr2acc_data(data);		ipaddr= arp_iop->nwa_ipaddr;		if (find_cache_ent(arp_port, ipaddr))		{			bf_afree(data);			return EEXIST;		}		flags= arp_iop->nwa_flags;		ac_flags= ACF_EMPTY;		if (flags & NWAF_PERM)			ac_flags |= ACF_PERM;		if (flags & NWAF_PUB)			ac_flags |= ACF_PUB|ACF_PERM;		/* Allocate a cache entry */		ce= alloc_cache_ent(ac_flags);		if (ce == NULL)		{			bf_afree(data);			return ENOMEM;		}		ce->ac_flags= ac_flags;		ce->ac_state= ACS_VALID;		ce->ac_ethaddr= arp_iop->nwa_ethaddr;		ce->ac_ipaddr= arp_iop->nwa_ipaddr;		ce->ac_port= arp_port;		curr_time= get_time();		ce->ac_expire= curr_time+ARP_EXP_TIME;		ce->ac_lastuse= curr_time;		bf_afree(data);		return 0;	case NWIOARPDIP:		data= (*get_userdata)(fd, 0, sizeof(*arp_iop), TRUE);		if (data == NULL)			return EFAULT;		data= bf_packIffLess(data, sizeof(*arp_iop));		arp_iop= (nwio_arp_t *)ptr2acc_data(data);		ipaddr= arp_iop->nwa_ipaddr;		bf_afree(data); data= NULL;		ce= find_cache_ent(arp_port, ipaddr);		if (!ce)			return ENOENT;		if (ce->ac_state == ACS_INCOMPLETE)			return EINVAL;		ac_flags= ce->ac_flags;		if (ac_flags & ACF_PUB)		{			/* Make sure entry is at the end of published			 * entries.			 */			for (entno= 0, cache= arp_cache;				entno<arp_cache_nr; entno++, cache++)			{				if (cache->ac_state == ACS_UNUSED)					break;				if (cache->ac_flags & ACF_PUB)					continue;				break;			}			assert(cache > arp_cache);			cache--;			if (cache != ce)			{				assert(cache > ce);				*ce= *cache;				ce= cache;			}		}		if (ac_flags & ACF_PERM)		{			/* Make sure entry is at the end of permanent			 * entries.			 */			for (entno= 0, cache= arp_cache;				entno<arp_cache_nr; entno++, cache++)			{				if (cache->ac_state == ACS_UNUSED)					break;				if (cache->ac_flags & ACF_PERM)					continue;				break;			}			assert(cache > arp_cache);			cache--;			if (cache != ce)			{				assert(cache > ce);				*ce= *cache;				ce= cache;			}		}		/* Clear entry */		ce->ac_state= ACS_UNUSED;		return 0;	default:		ip_panic(("arp_ioctl: unknown request 0x%lx",			(unsigned long)req));	}	return 0;}PRIVATE void arp_timeout (ref, timer)int ref;timer_t *timer;{	int i, port, reqind, acind;	arp_port_t *arp_port;	arp_cache_t *ce;	struct arp_req *reqp;	time_t curr_time;	acc_t *data;	arp46_t *arp;	u16_t *p;	port= ref / AP_REQ_NR;	reqind= ref % AP_REQ_NR;	assert(port >= 0 && port <eth_conf_nr);	arp_port= &arp_port_table[port];	reqp= &arp_port->ap_req[reqind];	assert (timer == &reqp->ar_timer);	acind= reqp->ar_entry;	assert(acind >= 0 && acind < arp_cache_nr);	ce= &arp_cache[acind];	assert(ce->ac_port == arp_port);	assert(ce->ac_state == ACS_INCOMPLETE);	if (++reqp->ar_req_count >= MAX_ARP_RETRIES)	{		curr_time= get_time();		ce->ac_state= ACS_UNREACHABLE;		ce->ac_expire= curr_time+ ARP_NOTRCH_EXP_TIME;		ce->ac_lastuse= curr_time;		clck_untimer(&reqp->ar_timer);		reqp->ar_entry= -1;		client_reply(arp_port, ce->ac_ipaddr, NULL);		return;	}	data= bf_memreq(sizeof(arp46_t));	arp= (arp46_t *)ptr2acc_data(data);	/* Clear padding */	assert(sizeof(arp->a46_data.a46_dummy) % sizeof(*p) == 0);	for (i= 0, p= (u16_t *)arp->a46_data.a46_dummy;		i < sizeof(arp->a46_data.a46_dummy)/sizeof(*p);		i++, p++)	{		*p= 0xdead;	}	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(ARP_REQUEST);	arp->a46_sha= arp_port->ap_ethaddr;	memcpy (arp->a46_spa, &arp_port->ap_ipaddr, sizeof(ipaddr_t));	memset(&arp->a46_tha, '\0', sizeof(ether_addr_t));	memcpy (arp->a46_tpa, &ce->ac_ipaddr, sizeof(ipaddr_t));	assert(data->acc_linkC == 1);	data->acc_ext_link= arp_port->ap_sendlist;	arp_port->ap_sendlist= data; data= NULL;	if (!(arp_port->ap_flags & APF_ARP_WR_IP))		setup_write(arp_port);	clck_timer(&reqp->ar_timer, get_time() + ARP_TIMEOUT,		arp_timeout, ref);}PRIVATE void arp_buffree(priority)int priority;{	int i;	acc_t *pack, *next_pack;	arp_port_t *arp_port;	for (i= 0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)	{		if (priority == ARP_PRI_REC)		{			next_pack= arp_port->ap_reclist;			while(next_pack && next_pack->acc_ext_link)			{				pack= next_pack;				next_pack= pack->acc_ext_link;				bf_afree(pack);			}			if (next_pack)			{				if (ev_in_queue(&arp_port->ap_event))				{					DBLOCK(1, printf(			"not freeing ap_reclist, ap_event enqueued\n"));				}				else				{					bf_afree(next_pack);					next_pack= NULL;				}			}			arp_port->ap_reclist= next_pack;		}		if (priority == ARP_PRI_SEND)		{			next_pack= arp_port->ap_sendlist;			while(next_pack && next_pack->acc_ext_link)			{				pack= next_pack;				next_pack= pack->acc_ext_link;				bf_afree(pack);			}			if (next_pack)			{				if (ev_in_queue(&arp_port->ap_event))				{					DBLOCK(1, printf(			"not freeing ap_sendlist, ap_event enqueued\n"));				}				else				{					bf_afree(next_pack);					next_pack= NULL;				}			}			arp_port->ap_sendlist= next_pack;		}	}}#ifdef BUF_CONSISTENCY_CHECKPRIVATE void arp_bufcheck(){	int i;	arp_port_t *arp_port;	acc_t *pack;	for (i= 0, arp_port= arp_port_table; i<eth_conf_nr; i++, arp_port++)	{		for (pack= arp_port->ap_reclist; pack;			pack= pack->acc_ext_link)		{			bf_check_acc(pack);		}		for (pack= arp_port->ap_sendlist; pack;			pack= pack->acc_ext_link)		{			bf_check_acc(pack);		}	}}#endif /* BUF_CONSISTENCY_CHECK *//* * $PchId: arp.c,v 1.22 2005/06/28 14:15:06 philip Exp $ */

⌨️ 快捷键说明

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