📄 dhcpclnt.c
字号:
int i;
#endif /* DHC_MAXDNSRVS */
/* first, clear the options */
dhc_states[iface].snmask = 0;
dhc_states[iface].defgw = 0;
dhc_states[iface].lease = 0;
#if defined(DHC_MAXDNSRVS) && (DHC_MAXDNSRVS > 0)
MEMSET(dhc_states[iface].dnsrv, 0, sizeof(dhc_states[iface].dnsrv));
#endif /* DHC_MAXDNSRVS */
/* then fill them in from the DHCP data */
while (opts <= end)
{
switch (*opts++)
{
case DHOP_PAD:
break;
case DHOP_END:
return 0; /* only good exit point */
case DHOP_SNMASK:
opts++;
dhc_states[iface].snmask = dh_getlong(opts);
opts += 4;
break;
case DHOP_ROUTER:
optlen = *opts++;
if (optlen >= 4)
dhc_states[iface].defgw = dh_getlong(opts);
opts += optlen;
break;
case DHOP_LEASE:
opts++;
dhc_states[iface].lease = htonl(dh_getlong(opts));
opts += 4;
break;
case DHOP_DNSRV:
optlen = *opts++;
#if defined(DHC_MAXDNSRVS) && (DHC_MAXDNSRVS > 0)
i = 0;
while ((optlen >= 4) && (i < DHC_MAXDNSRVS))
{
dhc_states[iface].dnsrv[i] = dh_getlong(opts);
optlen -= 4;
opts += 4;
i++;
}
#endif /* DHC_MAXDNSRVS */
opts += optlen;
break;
default:
opts += ((*opts) + 1);
break;
}
}
dtrap("dhcpclnt 11\n");
return -1;
}
/* dhc_stats() - print dhcp client statistics. Returns 0 if ok, else
* non-zero error.
*/
#ifdef NET_STATS
/* FUNCTION: dhc_stats()
*
* PARAM1: void *pio
*
* RETURNS:
*/
int
dhc_stats(void *pio)
{
int i;
ns_printf(pio ,"dhcp client stats:\n");
ns_printf(pio ,"all errors: %lu\n", dsc_errors);
ns_printf(pio ,"discover sent: %lu\n", dsc_discovers);
ns_printf(pio ,"offers rcvd: %lu\n", dsc_offers);
ns_printf(pio ,"requests sent: %lu\n", dsc_requests);
ns_printf(pio ,"acks received: %lu\n", dsc_acks);
ns_printf(pio ,"bootp replys: %lu\n", dsc_bpreplys);
ns_printf(pio ,"declines sent: %lu\n", dsc_declines);
ns_printf(pio ,"releases sent: %lu\n", dsc_releases);
ns_printf(pio ,"naks received: %lu\n", dsc_naks);
ns_printf(pio ,"renew req sent: %lu\n", dsc_renew);
ns_printf(pio ,"rebind req sent: %lu\n", dsc_rebind);
ns_printf(pio ,"relay agent errs:%lu\n", dsc_rlyerrs);
for ( i=0 ; i < MAXNETS ; i++ )
{
ns_printf(pio ,"Interface %d state = %s\n",i+1,
dhc_state_str[ dhc_states[i].state ] );
if ( dhc_states[i].state == DHCS_UNUSED )
continue;
else
{
ns_printf(pio ," tries=%d, xid=%lu, secs=%d\n",
dhc_states[i].tries,dhc_states[i].xid,dhc_states[i].secs);
ns_printf(pio ," lease=%lu, t1=%lu, t2=%lu\n",
dhc_states[i].lease,dhc_states[i].t1,dhc_states[i].t2);
ns_printf(pio ,
" ip=%u.%u.%u.%u, snmask=%u.%u.%u.%u, gw=%u.%u.%u.%u\n",
PUSH_IPADDR(dhc_states[i].ipaddr),
PUSH_IPADDR(dhc_states[i].snmask),
PUSH_IPADDR(dhc_states[i].defgw) );
ns_printf(pio , " serverip=%u.%u.%u.%u\n",
PUSH_IPADDR(dhc_states[i].srv_ipaddr) );
#if defined(DHC_MAXDNSRVS) && (DHC_MAXDNSRVS > 0)
{
int dnsindex;
for (dnsindex=0; dnsindex < DHC_MAXDNSRVS ; dnsindex++ )
{
ns_printf(pio , " DNS%d=%u.%u.%u.%u\n", dnsindex+1,
PUSH_IPADDR(dhc_states[i].dnsrv[dnsindex]) );
}
}
#endif
}
}
return 0;
}
#endif /* NET_STATS */
/* FUNCTION: dhc_second()
*
* dhc_second() - dhcp client timer. system should call this once a
* second for retries, lease renewal, etc.
*
*
* PARAM1: void
*
* RETURNS: Returns 0 or ENP_ error code
*/
int
dhc_second(void)
{
int iface;
int tries;
int e;
u_long half_time;
for (iface = 0; iface < MAXNETS; iface++)
{
switch (dhc_states[iface].state)
{
case DHCS_INIT: /* Send a discover packet */
e = dhc_discover(iface);
/* Error while sending a discover packet */
if (e)
{
dtrap("dhcpclnt 12\n");
return e;
}
dhc_set_state(iface,DHCS_SELECTING);
break;
case DHCS_INITREBOOT: /* Send a request packet */
e = dhc_reclaim(iface);
if (e)
{
dtrap("dhcpclnt 13\n");
return e;
}
dhc_set_state(iface,DHCS_REBOOTING);
break;
case DHCS_SELECTING:
/* Send discover packet on timeout */
case DHCS_REBOOTING:
case DHCS_REQUESTING:
/* Discovery timeout = DHC_RETRY_TMO secs * (2 ** retries), max 64 */
tries = dhc_states[iface].tries ;
/* Set the exponential count */
if ( tries >= DHC_MAX_TRIES)
tries= DHC_MAX_TRIES;
if ( cticks > (dhc_states[iface].last_tick +
(((u_long) (DHC_RETRY_TMO*TPS)) << tries ) ) )
{
/* Timeout while waiting for a OFFER/ACK/NAK. Retransmit */
switch(dhc_states[iface].state)
{
case DHCS_SELECTING:
dhc_discover(iface);
break;
case DHCS_REQUESTING:
dhc_request(iface,FALSE);
break;
case DHCS_REBOOTING:
dhc_reclaim(iface);
break;
default:
dtrap("dhcpclnt 14\n"); /* bogus state */
break;
}
}
if ( tries == DHC_MAX_TRIES &&
(dhc_states[iface].state !=DHCS_SELECTING) )
{
/* We have tried enough. Restart from INIT state */
dhc_set_state(iface,DHCS_RESTARTING);
dhc_resetip(iface);
dhc_set_state(iface,DHCS_INIT);
}
break;
case DHCS_REBINDING:
/* Check for timeout. Retry if we didn't get a ACK/NAK response. */
if ( (dhc_states[iface].lease*TPS+dhc_states[iface].lease_start) > cticks )
{
/* See if we need to retransmit. If we have waiting for
* half the time between last transmit and lease, then we
* need to retransmit. Also the minimum retransmit
* interval is 60 secs.
*/
half_time = (dhc_states[iface].lease_start +
dhc_states[iface].lease*TPS -
dhc_states[iface].last_tick)/2;
if ( half_time < 60*TPS )
half_time = 60*TPS;
if ( dhc_states[iface].last_tick + half_time < cticks )
{
dhc_request(iface,FALSE);
}
}
else
{
/* Lease has expired. We didn't receive a ACK/NAK. Hence restart*/
dhc_set_state(iface,DHCS_RESTARTING);
dhc_resetip(iface);
dhc_set_state(iface,DHCS_INIT);
}
break;
case DHCS_BOUND:
/* Test for lease expiry. The RENEW timer. */
if ( (dhc_states[iface].t1 != DHC_INFINITY) &&
(((dhc_states[iface].t1*TPS)+dhc_states[iface].lease_start) < cticks ) )
{
/* Time to renew. Send a UNICAST to the DHCP server */
dhc_set_state(iface,DHCS_RENEWING);
e = dhc_reclaim(iface); /* unicast */
if (e)
{
dtrap("dhcpclnt 15\n");
return e;
}
dsc_renew++;
}
break;
case DHCS_RENEWING:
/* Test for lease expiry. The REBIND timer. */
if ( (dhc_states[iface].t2*TPS+dhc_states[iface].lease_start) > cticks )
{
/* See if we need to retransmit. If we have waiting for
* half the time between last transmit and t2, then we
* need to retransmit. Also the minimum retransmit
* interval is 60 secs.
*/
half_time = (dhc_states[iface].lease_start +
dhc_states[iface].t2*TPS -
dhc_states[iface].last_tick)/2;
if ( half_time < 60*TPS )
half_time = 60*TPS;
if ( dhc_states[iface].last_tick + half_time < cticks )
{
dhc_request(iface,FALSE);
}
}
else
{
/* No Response has come from the Server that assigned our
* IP. Hence send a broadcast packet to see if we can
* lease this IP from some other server
*/
dhc_set_state(iface,DHCS_REBINDING);
e = dhc_request(iface,TRUE); /* broadcast */
if (e)
{
dtrap("dhcpclnt 16\n");
return e;
}
dsc_rebind++;
}
break;
case DHCS_UNUSED:
default:
continue;
}
}
return 0;
}
/* FUNCTION: dhc_halt()
*
* dhc_halt() - stop dhcp all client activity for the passed iface.
*
*
* PARAM1: int iface
*
* RETURNS: void
*/
void
dhc_halt(int iface)
{
if (iface < 0 || iface > MAXNETS)
{
dtrap("dhcpclnt 17\n");
return;
}
/* clear dhc_states entry - (kills retrys) */
MEMSET(&dhc_states[iface], 0, sizeof(struct dhc_state));
dhc_states[iface].state = DHCS_UNUSED;
}
/* FUNCTION: dhc_reclaim()
*
* dhc_reclaim() - send a "request" for the address currently in the
* passed interface. This is an alternative to dhc_discover() for
* machines which have previously been assigned an address via DHCP,
* saved it in flash, been through a power cycle, and now want to try
* to reclaim previous address from the server. This works by setting
* parameters of dhc_states[] and calling dhc_request()
*
*
* PARAM1: int iface
*
* RETURNS: Returns 0 if DHCP request was sent OK, else non-zero error.
*/
int
dhc_reclaim(int iface)
{
/* punt if IP address is not set */
if (nets[iface]->n_ipaddr == 0L)
{
dtrap("dhcpclnt 18\n"); /* programming bug? */
return ENP_LOGIC;
}
dhc_states[iface].ipaddr = nets[iface]->n_ipaddr;
dhc_states[iface].snmask = nets[iface]->snmask;
dhc_states[iface].defgw = nets[iface]->n_defgw;
#ifdef IP_ROUTING
/* If the DHCP Server is on other network, route the request
* from the same DHCP relay agent. To do that, add a route.
*/
if (dhc_states[iface].rly_ipaddr)
{
if (dhc_states[iface].srv_ipaddr)
{
/* yes, earlier negotiation was done via a relay agent */
if ( !add_route(dhc_states[iface].srv_ipaddr, 0xFFFFFFFF,
dhc_states[iface].rly_ipaddr, iface, IPRP_LOCAL))
{
/* route was not added. check this case */
dtrap("dhcpclnt 19\n");
}
}
else
{
/* DHCP relay IP address is set, but DHCP Server IP address is
* not set ! How can this happen ?
*/
dtrap("dhcpclnt 20\n");
}
}
#else
/* IP_ROUTING is disabled. Hence we can't add route. */
#endif
/* send the request */
return(dhc_request(iface,TRUE));
}
/* FUNCTION: dhc_state_init()
*
* dhc_state_init() : Initiate the DHCP Client for a interface into a
* starting state. Either INIT or INITREBOOT. If the DHCP Client is
* in INIT state, it would start by sending a DISCOVER packet. If it
* is in INITREBOOT state, it would try to use the earlier IP address
* by sending a REQUEST packet. Returns nothing.
*
* PARAM1: int iface
* PARAM2: int init_flag
*
* RETURNS: void
*/
void
dhc_state_init(int iface,int init_flag)
{
if ( init_flag == TRUE )
dhc_set_state(iface,DHCS_INIT);
else
dhc_set_state(iface,DHCS_INITREBOOT);
}
/* FUNCTION: dhc_alldone()
*
* dhc_alldone() : Check if DHCP activities on all interfaces is done
* or not.
*
* PARAM1: void
*
* RETURNS: Return TRUE if all valid interfaces are done. Return FALSE
* otherwise.
*/
int
dhc_alldone(void)
{
int i;
for ( i=0 ; i < MAXNETS ; i++ )
{
if ( ( dhc_states[i].state == DHCS_UNUSED ) ||
( dhc_states[i].state == DHCS_BOUND ) )
{
continue ;
}
else
{
return FALSE ;
}
}
return TRUE ;
}
/* FUNCTION: dhc_ifacedone()
*
* dhc_ifacedone() : Check if DHCP activities on a interface is done
* or not. Return TRUE if done (or if DHCP Client is not used on the
* interface). Return FALSE otherwise.
*
*
* PARAM1: int iface
*
* RETURNS:
*/
int
dhc_ifacedone(int iface)
{
if ( ( dhc_states[iface].state == DHCS_UNUSED ) ||
( dhc_states[iface].state == DHCS_BOUND ) )
{
return TRUE ;
}
else
{
return FALSE ;
}
}
/* FUNCTION: dhc_set_state()
*
* dhc_set_state() : Set the new state for the interface and call the
* callback routine. That way applications can track about the state
* of DHCP Client
*
*
* PARAM1: int iface
* PARAM2: int state
*
* RETURNS:
*/
void dhc_set_state(int iface, int state)
{
dhc_states[iface].state = state; /* Set the new state */
dhc_states[iface].tries = 0; /* Reset the number of tries */
/* If callback is set, call it */
if (dhc_states[iface].callback)
dhc_states[iface].callback(iface,state);
}
#endif /* DHCP_CLIENT - ifdef out whole file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -