📄 arp.c
字号:
* if there is a gateway with a current ARP, use it.
* if not, arp all of the gateways and return an error. Next call
* will
* probably catch the result of the ARP.
*/
haveg = 0;
for (i = CACHELEN-1; i >= 0; i--)
{
if (arpc[i].gate && arpc[i].valid_entry &&
INT32_CMP((arpc[i].tm + CACHETO), n_clicks()) > 0)
return(i);
}
if(INT32_CMP(n_clicks(), arptime) >= 0)
{
for (i = CACHELEN-1; i >= 0; i--)
{
if (arpc[i].gate)
{
haveg = 1;
arp_request (arpc[i].ip); /* put out a broadcast request */
}
}
if (!haveg) /* blind luck, try ARPing even for */
arp_request(ipn); /* a node not on our net. (proxy ARP)*/
arptime=n_clicks()+ARPTO;
} /* end if */
} /* end else gate */
return (-1);
} /* end cachelook */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* netdlayer */
/* */
/* DESCRIPTION */
/* */
/* Get data layer address for insertion into outgoing packets. */
/* searches based on ip number. If it finds the address, ok, else ... */
/* */
/* Checks to see if the address is on the same network. If it is, */
/* then ARPs the machine to get address. Forces pause between sending */
/* arps to guarantee not saturating network. */
/* */
/* If not on the same network, it needs the ether address of a */
/* gateway. Searches the list of machines for a gateway flag. */
/* Returns the first gateway found with an Ethernet address. */
/* */
/* Returns NULL if not here, or pointer to ether address if here. */
/* If we don't have it, this also sends an ARP request so that the */
/* next time we are called, the ARP reply may be here by then. */
/* */
/* CALLED BY */
/* netusend Send a packet */
/* netxopen Open a network socket */
/* */
/* CALLS */
/* */
/* n_clicks */
/* netsleep */
/* NU_Obtain_Semaphore Grab an instance of a semaphore */
/* NU_Release_Semaphore Release an instance of a semaphore */
/* NU_Relinquish Allow other ready tasks to run */
/* getdlayer Check for the hardware address */
/* */
/*************************************************************************/
uint8 *netdlayer(uint8 *tipnum)
{
int32 t;
uint8 *pc;
t=n_clicks()+CONNWAITTIME; /* some seconds time out */
pc=NU_NULL;
do
{
pc = getdlayer(tipnum);
if (pc == NU_NULL)
{
#ifndef INTERRUPT
netsleep(0); /* can't have deadlock */
#endif /* !INTERRUPT */
/* Release the TCP_Resource so that other tasks can run while
* we are waiting for the ARP message to be received and
* processed. */
#ifdef PLUS
NU_Release_Semaphore(&TCP_Resource);
#else /* !PLUS */
NU_Release_Resource(TCP_Resource);
#endif /* !PLUS */
/* Relinquish control to allow other tasks to run. */
NU_Sleep(1);
/* Get the resource back so that we can continue. */
#ifdef PLUS
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else /* !PLUS */
NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif /* !PLUS */
}
if(INT32_CMP(t, n_clicks()) <= 0)
return(NU_NULL);
} while(pc==NU_NULL);
return(pc);
} /* end netdlayer */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* getdlayer */
/* */
/* DESCRIPTION */
/* */
/* check for the hardware address one time */
/* */
/* CALLED BY */
/* NU_EventsDispatcher */
/* netsleep */
/* netdlayer */
/* */
/* CALLS */
/* */
/* n_clicks */
/* netsleep */
/* NU_Relinquish Allow other ready tasks to run */
/* */
/*************************************************************************/
uint8 *getdlayer(uint8 *tipnum)
{
int16 needgate,i;
needgate=0;
/*
* Check to see if we need to go through a gateway.
* If the machine is on our network, then assume that we can send an ARP
* to that machine, otherwise, send the ARP to the gateway.
*
* Uses internet standard subnet mask method, RFC950
* if subnets are not in use, netmask has been pre-set to the
* appropriate
* network addressing mask.
*/
for(i=3; i>=0; i--)
if((nnmask[i] & tipnum[i])!=(nnmask[i] & nnipnum[i]))
needgate=1;
if(needgate && (0<=(i=cachelook(tipnum,1,1))))
return(arpc[i].hrd);
if(!needgate && (0<=(i=cachelook(tipnum,0,1))))
return(arpc[i].hrd);
return(NU_NULL);
} /* end getdlayer */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* netsetgate */
/* */
/* DESCRIPTION */
/* */
/* Establish an IP number to use as a gateway. */
/* They are added in the order that they arrive and there is a limit on*/
/* the number of gateways equal to CACHELEN/2. */
/* ARPs them as they are added so that the Cache will get pre-filled */
/* with gateways. */
/* */
/* returns 0 if ok, -1 on error(full) */
/* */
/* CALLED BY */
/* Ssetgates Set up gateway mahines and subnet */
/* mask */
/* */
/* CALLS */
/* */
/* arp_request Send out an arp request packet */
/* */
/*************************************************************************/
int16 netsetgate(uint8 *ipn)
{
int16 i;
for(i=CACHELEN-1 ; i>=CACHELEN/2 ; i--) {
if(!arpc[i].gate) {
arpc[i].gate=1;
/* The hardware address has yet to be resolved. So this is not yet
a valid entry.
*/
arpc[i].valid_entry = 0;
memcpy ((void *)arpc[i].ip, (const void *)ipn, 4);
arp_request(ipn);
return(NU_SUCCESS);
}
} /* end for */
return(-1);
} /* end netsetgate */
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* ARP_Init */
/* */
/* DESCRIPTION */
/* */
/* Setup an arp packet -- also sets up an arp cache */
/* */
/* CALLED BY */
/* protinit */
/* */
/* CALLS */
/* */
/* intswap */
/* */
/*************************************************************************/
VOID ARP_Init (VOID)
{
int16 i;
memcpy ((void *)&arp.d, (const void *)&blankd, sizeof(DLAYER));
arp.d.type = intswap (EARP); /* 0x0806 is ARP type */
arp.hrd = intswap (HARDWARE_TYPE); /* Ether = 1 */
arp.pro = intswap (ARPPRO); /* IP protocol = 0x0800 */
arp.hln = DADDLEN; /* Ethernet hardware length */
arp.pln = 4; /* IP length = 4 */
/* sender's hardware addr */
memcpy ((void *)arp.sha, (const void *)nnmyaddr, DADDLEN);
/* target hardware addr */
memcpy ((void *)arp.tha, (const void *)broadaddr, DADDLEN);
/* sender's IP addr */
memcpy ((void *)arp.spa, (const void *)nnipnum, 4);
/* Clear all entries as being invalid. */
for (i = 0; i < CACHELEN; i++)
arpc[i].valid_entry = 0;
arptime = 0L;
/* The resolve list is initially empty. */
ARP_Res_List.ar_head = NU_NULL;
ARP_Res_List.ar_tail = NU_NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -