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

📄 arp.c

📁 COLDFIRE 5282SC的文件
💻 C
字号:
/*
 * File:		arp.c
 * Purpose:		Address Resolution Protocol routines.
 *
 * Notes:
 *
 * Modifications:
 */

#include "src/init/m5282evb.h"
#include "src/ethernet/nif.h"
#include "src/ethernet/tftp/arp.h"
#include "src/ethernet/tftp/ip.h"
#include "src/ethernet/tftp/timer.h"

/********************************************************************/
static uint8 *
arp_find_pair (ARP_INFO *arptab, uint16 protocol, uint8 *hwa, uint8 *pa)
{
	/*
	 * This function searches through the ARP table for the
	 * specified <protocol,hwa> or <protocol,pa> address pair.
	 * If it is found, then a a pointer to the non-specified
	 * address is returned.  Otherwise NULL is returned.
	 * If you pass in <protocol,pa> then you get <hwa> out.
	 * If you pass in <protocol,hwa> then you get <pa> out.
	 */
	int slot, i, match = FALSE;
	uint8 *rvalue, old_ipl;


	if (((hwa == 0) && (pa == 0)) || (arptab == 0))
		return NULL;

	/* Disable interrupts for now */
	old_ipl = (uint8)asm_set_ipl(6);

	rvalue = NULL;

	/* check each protocol address for a match */
	for (slot = 0; slot < arptab->tab_size; slot++)
	{
		if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) &&
			(arptab->table[slot].protocol == protocol))
		{
			match = TRUE;
			if (hwa != 0)
			{
				/* Check the Hardware Address field */
				rvalue = &arptab->table[slot].pa[0];
				for (i = 0; i < arptab->table[slot].hwa_size; i++)
				{
					if (arptab->table[slot].hwa[i] != hwa[i])
					{
						match = FALSE;
						break;
					}
				}
			}
			else
			{
				/* Check the Protocol Address field */
				rvalue = &arptab->table[slot].hwa[0];
				for (i = 0; i < arptab->table[slot].pa_size; i++)
				{
					if (arptab->table[slot].pa[i] != pa[i])
					{
						match = FALSE;
						break;
					}
				}
			}
			if (match)
			{
				break;
			}
		}
	}

	/* Allow interrupts again */
	asm_set_ipl(old_ipl);

	if (match)
		return rvalue;
	else
		return NULL;
}

/********************************************************************/
void
arp_merge (	ARP_INFO *arptab,
			uint16 protocol,
			int hwa_size, uint8 *hwa,
			int pa_size, uint8 *pa,
			int longevity)
{
	/*
	 * This function merges an entry into the ARP table.  If
	 * either piece is NULL, the function exits, otherwise
	 * the entry is merged or added, provided there is space.
	 */
	int i, slot;
	uint8 *ta;

	if ((hwa == NULL) || (pa == NULL) || (arptab == NULL) ||
		((longevity != ARP_ENTRY_TEMP) &&
		(longevity != ARP_ENTRY_PERM)))
	{
		return;
	}

	/* First search ARP table for existing entry */
	if ((ta = arp_find_pair(arptab,protocol,NULL,pa)) != 0)
	{
		/* Update hardware address */
		for (i = 0; i < hwa_size; i++)
			ta[i] = hwa[i];
		return;
	}
	
	/* Next try to find an empty slot */
	slot = -1;
	for (i = 0; i < MAX_ARP_ENTRY; i++)
	{
		if (arptab->table[i].longevity == ARP_ENTRY_EMPTY)
		{
			slot = i;
			break;
		}
	}

	/* if no empty slot was found, pick a temp slot */
	if (slot == -1)
	{
		for (i = 0; i < MAX_ARP_ENTRY; i++)
		{
			if (arptab->table[i].longevity == ARP_ENTRY_TEMP)
			{
				slot = i;
				break;
			}
		}
	}

	/* if after all this, still no slot found, add in last slot */
	if (slot == -1)
		slot = (MAX_ARP_ENTRY -1);

	/* add the entry into the slot */
	arptab->table[slot].protocol = protocol;

	arptab->table[slot].hwa_size = (uint8) hwa_size;
	for (i = 0; i < hwa_size; i++)
		arptab->table[slot].hwa[i] = hwa[i];

	arptab->table[slot].pa_size = (uint8) pa_size;
	for (i = 0; i < pa_size; i++)
		arptab->table[slot].pa[i] = pa[i];

	arptab->table[slot].longevity = longevity;
}

/********************************************************************/
void
arp_remove (ARP_INFO *arptab, uint16 protocol, uint8 *hwa, uint8 *pa)
{
	/*
	 * This function removes an entry from the ARP table.  The
	 * ARP table is searched according to the non-NULL address
	 * that is provided.
	 */
	int slot, i, match;

	if (((hwa == 0) && (pa == 0)) || (arptab == 0))
		return;

	/* check each hardware adress for a match */
	for (slot = 0; slot < arptab->tab_size; slot++)
	{
		if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) &&
			(arptab->table[slot].protocol == protocol))
		{
			match = TRUE;
			if (hwa != 0)
			{
				/* Check Hardware Address field */
				for (i = 0; i < arptab->table[slot].hwa_size; i++)
				{
					if (arptab->table[slot].hwa[i] != hwa[i])
					{
						match = FALSE;
						break;
					}
				}
			}
			else
			{
				/* Check Protocol Address field */
				for (i = 0; i < arptab->table[slot].pa_size; i++)
				{
					if (arptab->table[slot].pa[i] != pa[i])
					{
						match = FALSE;
						break;
					}
				}
			}
			if (match)
			{
				for (i = 0; i < arptab->table[slot].hwa_size; i++)
					arptab->table[slot].hwa[i] = 0;
				for (i = 0; i < arptab->table[slot].pa_size; i++)
					arptab->table[slot].pa[i] = 0;
				arptab->table[slot].longevity = ARP_ENTRY_EMPTY;
				break;
			}
		}
	}
}

/********************************************************************/
void
arp_request (NIF *nif, uint8 *pa, NBUF **ppNbuf)
{
	/*
	 * This function broadcasts an ARP request for the
	 * protocol address pa.  Written only for Ethernet.
 	 *	
	 * This routine accesses shared data!
	 * Interrupts should be disabled by calling funtion 
	 */

	uint8 *addr;
	NBUF *pNbuf;
	arp_frame_hdr *arpframe;
	int i;

	pNbuf = nif->tx_alloc();
	/* Make sure I grabbed a valid Tx buffer */
	if (pNbuf == NULL)
	{
		#if defined(DEBUG_PRINT)
			printf("ARP: arp_request couldn't allocate Tx buffer\n");
		#endif
		return;
	}
	arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET];

	/* Build the ARP request packet */
	arpframe->ar_hrd = ETHERNET;
	arpframe->ar_pro = FRAME_IP;
	arpframe->ar_hln = 6;
	arpframe->ar_pln = 4;
	arpframe->opcode = ARP_REQUEST;

	addr = &nif->hwa[0];
	for (i = 0; i < 6; i++)
		arpframe->ar_sha[i] = addr[i];

	addr = ip_get_myip(nif_get_protocol_info(nif,FRAME_IP));
	for (i = 0; i < 4; i++)
		arpframe->ar_spa[i] = addr[i];

	for (i = 0; i < 6; i++)
		arpframe->ar_tha[i] = 0x00;

	for (i = 0; i < 4; i++)
		arpframe->ar_tpa[i] = pa[i];

	/* Save the length of my packet in the buffer structure */
	pNbuf->length = 28;

	/* Swap my buffer descriptor with the one IP is trying to send
	 * so I come first in the buffer ring */
	nbuf_tx_swap(&pNbuf, ppNbuf);

	nif->send(	nif,
				nif->broadcast,
				nif->hwa,
				FRAME_ARP,
				pNbuf);
}

/********************************************************************/
static int
arp_resolve_pa (NIF *nif, uint16 protocol, uint8 *pa, uint8 **ha)
{
	/*
	 * This function accepts a pointer to a protocol address and
	 * searches the ARP table for a hardware address match.  If no
	 * no match found, FALSE is returned.
	 */
	ARP_INFO *arptab;

	if ((pa == NULL) || (nif == NULL) || (protocol == 0))
		return 0;

	arptab = nif_get_protocol_info (nif,FRAME_ARP);
	*ha = arp_find_pair(arptab,protocol,0,pa);

	if (*ha == NULL)
	{
		/* do ARP request, still not guaranteed to find it! */
		return 0;
	}
	/* else */
	return 1;
}

/********************************************************************/
uint8 *
arp_resolve (NIF *nif, uint16 protocol, uint8 *pa, NBUF **ppNbuf)
{
	int i;
	uint8 *hwa;

	/* First see if it is in table already */
	if (arp_resolve_pa (nif, protocol, pa, &hwa))
		return hwa;

	/* Not in table, try to obtain it */
	for (i = 0; i < 3; i++)
	{
		arp_request (nif, pa, ppNbuf);

		/* Enable interrupts so we can get a packet */
		asm_set_ipl(0);

		timer_set_secs(TIMER_NETWORK, ARP_TIMEOUT);
		while (timer_get_reference(TIMER_NETWORK))
		{
			if (arp_resolve_pa (nif, protocol, pa, &hwa))
			{
				/* Disable interrupts */
				asm_set_ipl(6);

				return hwa;
			}
		}

		/* Disable interrupts */
		asm_set_ipl(6);
	}

	return NULL;
}

/********************************************************************/
void
arp_init (ARP_INFO *arptab)
{
	int slot, i;

	arptab->tab_size = MAX_ARP_ENTRY;
	for (slot = 0; slot < arptab->tab_size; slot++)
	{
		for (i = 0; i < MAX_HWA_SIZE; i++)
			arptab->table[slot].hwa[i] = 0;
		for (i = 0; i < MAX_PA_SIZE; i++)
			arptab->table[slot].pa[i] = 0;
		arptab->table[slot].longevity = ARP_ENTRY_EMPTY;
		arptab->table[slot].hwa_size = 0;
		arptab->table[slot].pa_size = 0;
	}
}

/********************************************************************/
void
arp_handler (NIF *nif, NBUF *pRx_nbuf)
{
	/* ARP protocol handler */
	uint8 *addr;
	ARP_INFO *arptab;
	NBUF *pTx_nbuf;
	int longevity;
	arp_frame_hdr *rx_arpframe, *tx_arpframe;

	arptab = nif_get_protocol_info (nif, FRAME_ARP);
	rx_arpframe = (arp_frame_hdr *)&pRx_nbuf->data[ARP_HDR_OFFSET];

	/* Check for appropriate ARP packet */
	if (	(pRx_nbuf->length < 28) 
		 ||	(rx_arpframe->ar_hrd != ETHERNET)
		 ||	(rx_arpframe->ar_hln != 6)
		 ||	(rx_arpframe->ar_pro != FRAME_IP)
		 ||	(rx_arpframe->ar_pln != 4))
		return;

	/* Check to see if addressed to me */
	addr = ip_get_myip(nif_get_protocol_info(nif,FRAME_IP));
	if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
		(rx_arpframe->ar_tpa[1] == addr[1]) &&
		(rx_arpframe->ar_tpa[2] == addr[2]) &&
		(rx_arpframe->ar_tpa[3] == addr[3]) )
	{
		longevity = ARP_ENTRY_PERM;
	}
	else 
		longevity = ARP_ENTRY_TEMP;

	/* Add ARP info into table. */
	arp_merge (	arptab,
				rx_arpframe->ar_pro,
				rx_arpframe->ar_hln,
				&rx_arpframe->ar_sha[0],
				rx_arpframe->ar_pln,
				&rx_arpframe->ar_spa[0],
				longevity);

	switch (rx_arpframe->opcode)
	{
		case ARP_REQUEST:
			/* Check to see if request is of me! */
			if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
				(rx_arpframe->ar_tpa[1] == addr[1]) &&
				(rx_arpframe->ar_tpa[2] == addr[2]) &&
				(rx_arpframe->ar_tpa[3] == addr[3]) )
			{
				/* Allocate new TX buffer */
				pTx_nbuf = nif->tx_alloc();
				if (pTx_nbuf == NULL)
				{
					#if defined(DEBUG_PRINT)
						printf("ARP: arp_handler couldn't allocate Tx buffer\n");
					#endif

					/* Re-enable interrupts */
					asm_set_ipl(0);

					return;
				}
				
				tx_arpframe = (arp_frame_hdr *)&pTx_nbuf->data[ARP_HDR_OFFSET];

				/* Build new ARP frame from old one */
				tx_arpframe->ar_hrd = ETHERNET;
				tx_arpframe->ar_pro = FRAME_IP;
				tx_arpframe->ar_hln = 6;
				tx_arpframe->ar_pln = 4;
				tx_arpframe->opcode = ARP_REPLY;
				tx_arpframe->ar_tha[0] = rx_arpframe->ar_sha[0];
				tx_arpframe->ar_tha[1] = rx_arpframe->ar_sha[1];
				tx_arpframe->ar_tha[2] = rx_arpframe->ar_sha[2];
				tx_arpframe->ar_tha[3] = rx_arpframe->ar_sha[3];
				tx_arpframe->ar_tha[4] = rx_arpframe->ar_sha[4];
				tx_arpframe->ar_tha[5] = rx_arpframe->ar_sha[5];
				tx_arpframe->ar_tpa[0] = rx_arpframe->ar_spa[0];
				tx_arpframe->ar_tpa[1] = rx_arpframe->ar_spa[1];
				tx_arpframe->ar_tpa[2] = rx_arpframe->ar_spa[2];
				tx_arpframe->ar_tpa[3] = rx_arpframe->ar_spa[3];

				/* now copy in the new information */
				addr = &nif->hwa[0];
				tx_arpframe->ar_sha[0] = addr[0];
				tx_arpframe->ar_sha[1] = addr[1];
				tx_arpframe->ar_sha[2] = addr[2];
				tx_arpframe->ar_sha[3] = addr[3];
				tx_arpframe->ar_sha[4] = addr[4];
				tx_arpframe->ar_sha[5] = addr[5];

				addr = ip_get_myip(nif_get_protocol_info(nif,FRAME_IP));
				tx_arpframe->ar_spa[0] = addr[0];
				tx_arpframe->ar_spa[1] = addr[1];
				tx_arpframe->ar_spa[2] = addr[2];
				tx_arpframe->ar_spa[3] = addr[3];

				/* Save the length of my packet in the buffer structure */
				pTx_nbuf->length = 28;
				
				nif->send(	nif, 
							&tx_arpframe->ar_tha[0], 
							&tx_arpframe->ar_sha[0], 
							FRAME_ARP, 
							pTx_nbuf);
			}
			break;
		case ARP_REPLY:
		default:
			break;
	}
	return;
}

/********************************************************************/

⌨️ 快捷键说明

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