📄 arp.c
字号:
ARP_Res_Count = 0;
} /* end ARP_Init */
#if RARP_INCLUDED
/******************************************************************************/
/* FUNCTION */
/* */
/* NU_Rarp */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for resolving the IP address of this host. */
/* It is the entry point for applications that need to use RARP (Reverse */
/* Address Resolution Protocol). RARP is typically required by disk-less */
/* workstations. Such workstations have no means to store their IP */
/* address locally. */
/* */
/* AUTHOR */
/* */
/* Glen Johnson, Accelerated Technology Inc. */
/* */
/* CALLED BY */
/* */
/* Applications */
/* */
/* CALLS */
/* */
/* NU_Obtain_Semaphore Grab the semaphore. */
/* NU_Release_Semaphore Release the semaphore. */
/* NU_Allocate_Memory Allocate a block of memory. */
/* NU_Deallocate_Memory Deallocate a block of memory. */
/* NU_Suspend_Task Suspend a task. */
/* NU_Current_Task_Pointer Get a pointer to the current TCB. */
/* dll_dequeue Remove the first item from a list. */
/* dll_remove Remove an item from anywhere in a list. */
/* dll_enqueue Add an item to the tail of a list. */
/* NET_Send Send a packet. */
/* Stimerset Create a timer event. */
/* */
/* INPUTS */
/* */
/* */
/* OUTPUTS */
/* */
/* NU_MEM_ALLOC Memory allocation failure. */
/* NU_NO_BUFFERS No buffers a re available to build the pkt in.*/
/* NU_RARP_INIT_FAILED A response was not received to the request. */
/* NU_SUCCESS The IP was successfully resolved. */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* Glen Johnson 06/04/97 Created initial version. */
/* */
/******************************************************************************/
STATUS NU_Rarp(VOID)
{
BUFFER *buf_ptr;
ARPKT *arp_pkt;
STATUS stat;
ARP_RESOLVE_ENTRY *ar_entry;
/* Don't let any other users in until we are done. */
#ifdef PLUS
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif
/* Allocate a buffer to place the arp packet in. */
if ((buf_ptr = (BUFFER *)dll_dequeue((tqe_t *)&buffer_freelist))==NU_NULL)
return NU_NO_BUFFERS;
/* Initialize each field in the allocated buffer. */
buf_ptr->data_len = sizeof(ARPKT);
buf_ptr->next = (struct pqueue *)NU_NULL;
buf_ptr->previous = (struct pqueue *)NU_NULL;
buf_ptr->seqnum = 0;
/* Set up a pointer to the packet. */
arp_pkt = (ARPKT *)buf_ptr->packet;
/* Copy in the dlayer header. */
memcpy((void *)&arp_pkt->d, (const void *)&blankd, sizeof(DLAYER));
/* Set up the target hardware address, this will be a broadcast packet. */
memcpy((void *)arp_pkt->d.dest, (const void *)broadaddr, DADDLEN);
/* Set the type to an ARP packet. */
arp_pkt->d.type = intswap (ERARP);
arp_pkt->hrd = intswap (HARDWARE_TYPE); /* Ether = 1 */
arp_pkt->pro = intswap (ARPPRO); /* IP protocol = 0x0800 */
arp_pkt->hln = DADDLEN; /* Ethernet hardware length */
arp_pkt->pln = 4; /* IP length = 4 */
/* For an RARP request both the target and source hardware addresses should
be set to my own. */
memcpy((void *)arp_pkt->sha, (const void *)nnmyaddr, DADDLEN);
memcpy((void *)arp_pkt->tha, (const void *)nnmyaddr, DADDLEN);
/* Both our own and the server's IP address is unknown. Set them both to
the broadcast address. */
memcpy((void *)arp_pkt->spa, (const void *)nullip, 4);
memcpy((void *)arp_pkt->tpa, (const void *)nullip, 4);
/* This is a RARP request. */
arp_pkt->op = intswap(RARPQ);
/* Allocate memory for an ARP resolve entry. This structure is used to keep
track of this resolution attempt. */
if (NU_Allocate_Memory(&System_Memory, (VOID **)&ar_entry,
sizeof(*ar_entry),
(UNSIGNED)NU_NO_SUSPEND) != NU_SUCCESS)
{
/* Free the buffer that was allocated above. */
dll_enqueue((tqe_t *)&buffer_freelist, (tqe_t *)buf_ptr);
return (NU_MEM_ALLOC);
}
/* Order is not important. Simply add the new entry to the end of the
list. */
dll_enqueue((tqe_t *)&ARP_Res_List, (tqe_t *)ar_entry);
/* Initialize the entry structure. */
ar_entry->ar_id = ARP_Res_Count++;
ar_entry->ar_send_count = 0;
ar_entry->ar_task = NU_Current_Task_Pointer();
ar_entry->ar_buf_ptr = buf_ptr;
ar_entry->ar_pkt_type = RARPQ;
/* Continue to periodically retransmit the RARP request until either the IP
address is resolved or until it's time to give up.
*/
while ( (*(uint32 *)nnipnum == NU_NULL) &&
(ar_entry->ar_send_count < RARP_MAX_ATTEMPTS) )
{
/* Send the RARP Request. */
/* IMPORTANT: I know that this is not a TCP_DATA_PKT, but by claiming
that it is we can reuse the same packet for retransmits. The
alternative would be to allocate a new buffer and re-build the packet
each time.
*/
NET_Send(buf_ptr, sizeof(ARPKT), TCP_DATA_PKT);
/* Increment the number of attempts made so far. */
ar_entry->ar_send_count++;
/* Transmit the next one in a second. */
Stimerset (CONCLASS, RARP_REQUEST, ar_entry->ar_id, TICKSPERSEC, 0);
/* Suspend this task pending the resolution of our IP address or a
timeout. */
#ifdef PLUS
NU_Release_Semaphore(&TCP_Resource);
NU_Suspend_Task(NU_Current_Task_Pointer());
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
NU_Release_Resource(TCP_Resource);
NU_Stop(NU_Current_Task_ID());
NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif
}
/* Free the buffer that was allocated above. */
dll_enqueue((tqe_t *)&buffer_freelist, (tqe_t *)buf_ptr);
/* Deallocate the ARP resolve entry structure. */
dll_remove((tqe_t *)&ARP_Res_List, (tqe_t *)ar_entry);
NU_Deallocate_Memory(ar_entry);
#ifdef PLUS
NU_Release_Semaphore(&TCP_Resource);
#else
NU_Release_Resource(TCP_Resource);
#endif
/* Did we find the IP address. */
if (*(uint32 *)nnipnum)
return (NU_SUCCESS);
else
return (NU_RARP_INIT_FAILED);
} /* end NU_Rarp */
/******************************************************************************/
/* FUNCTION */
/* */
/* ARP_Event */
/* */
/* DESCRIPTION */
/* */
/* This function is called from the events dispatcher to process events */
/* associated with ARP and RARP. */
/* */
/* AUTHOR */
/* */
/* Glen Johnson, Accelerated Technology Inc. */
/* */
/* CALLED BY */
/* */
/* NU_EventsDispatcher */
/* */
/* CALLS */
/* */
/* NU_Resume_Task Resume a suspended task. */
/* */
/* INPUTS */
/* */
/* id Identifies the ARP entry structure we are */
/* interested in. */
/* */
/* OUTPUTS */
/* */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* Glen Johnson 06/04/97 Created initial version. */
/* */
/******************************************************************************/
VOID ARP_Event(uint16 id)
{
ARP_RESOLVE_ENTRY *ar_entry;
/* Search the ARP_Res_List for a match. */
for(ar_entry = ARP_Res_List.ar_head;
ar_entry != NU_NULL;
ar_entry = ar_entry->ar_next)
{
/* We have a match when the ID's match. */
if (ar_entry->ar_id == id)
break;
}
/* If a match was found, start the pending task. */
if (ar_entry)
{
NU_Resume_Task(ar_entry->ar_task);
}
} /* ARP_Event */
#endif /* RARP_INCLUDED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -