First attempt to stylize and document DHCP sources.

This commit is contained in:
likewise 2002-12-01 19:49:45 +00:00
parent dfa0369678
commit dcce504ade

View File

@ -37,7 +37,8 @@
* RFC 2131 and RFC 2132.
*
* KNOWN BUG:
* - This client will fail on servers using file/sname field overloading
* - Parsing of DHCP messages which use file/sname field overloading will
* probably fail. Additional support for this must go into dhcp_unfold().
* TODO:
* - Add JavaDoc style documentation (API, internals).
* - Make the unfold routine smarter to handle this
@ -62,10 +63,11 @@
*
* Then, use
* struct dhcp_state *client = dhcp_start(struct netif *netif)
* to start the dhcp client to configure the interface by
* starts a DHCP client instance which configures the interface by
* obtaining an IP address lease and maintaining it.
*
* Use dhcp_stop(client) to stop the lease.
* Use dhcp_release(client) to end the lease and use dhcp_stop(client)
* to remove the DHCP client.
*
*/
#include "lwip/debug.h"
@ -78,12 +80,15 @@
#include "lwipopts.h"
#include "lwip/dhcp.h"
/// transaction identifier, unique over all DHCP client and all DHCP requests
/** find the active DHCP attached to the given network interface */
struct dhcp_state *dhcp_find_client(struct netif *netif);
/** transaction identifier, unique over all DHCP requests */
static u32_t xid = 0xABCD0000;
/// singly-linked list of DHCP clients that are active
/** singly-linked list of DHCP clients that are active */
static struct dhcp_state *client_list = NULL;
/// DHCP client state machine functions
/** DHCP client state machine functions */
static void dhcp_handle_ack(struct dhcp_state *state);
static void dhcp_handle_nak(struct dhcp_state *state);
static void dhcp_handle_offer(struct dhcp_state *state);
@ -96,7 +101,7 @@ static err_t dhcp_rebind(struct dhcp_state *state);
static err_t dhcp_release(struct dhcp_state *state);
static void dhcp_set_state(struct dhcp_state *state, unsigned char new_state);
// receive, unfold, process and free incoming messages
/** receive, unfold, parse and free incoming messages */
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
static err_t dhcp_unfold_reply(struct dhcp_state *state);
static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type);
@ -104,12 +109,18 @@ static u8_t dhcp_get_option_byte(u8_t *ptr);
static u16_t dhcp_get_option_short(u8_t *ptr);
static u32_t dhcp_get_option_long(u8_t *ptr);
static void dhcp_free_reply(struct dhcp_state *state);
/** set the DHCP timers */
static void dhcp_timeout(struct dhcp_state *state);
static void dhcp_t1_timeout(struct dhcp_state *state);
static void dhcp_t2_timeout(struct dhcp_state *state);
void dhcp_arp_reply(struct ip_addr *addr);
// build outgoing messages
#if DHCP_DOES_ARP_CHECK
/** called by ARP to notify us of ARP replies */
void dhcp_arp_reply(struct ip_addr *addr);
#endif
/** build outgoing messages */
static err_t dhcp_create_request(struct dhcp_state *state);
static void dhcp_delete_request(struct dhcp_state *state);
static void dhcp_option(struct dhcp_state *state, u8_t option_type, u8_t option_len);
@ -118,9 +129,13 @@ static void dhcp_option_short(struct dhcp_state *state, u16_t value);
static void dhcp_option_long(struct dhcp_state *state, u32_t value);
static void dhcp_option_trailer(struct dhcp_state *state);
// find a client in the singly-linked list of DHCP clients
struct dhcp_state *dhcp_find_client(struct netif *netif);
/**
* Back-off the DHCP client because of a received NAK. Receiving a
* NAK means the client asked for something non-sensible, for
* example when it tries to renew a lease obtained on another network.
*
* We back-off and will end up restarting a fresh DHCP negotiation later.
*/
static void dhcp_handle_nak(struct dhcp_state *state) {
u16_t msecs = 10 * 1000;
DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak()"));
@ -129,8 +144,13 @@ static void dhcp_handle_nak(struct dhcp_state *state) {
dhcp_set_state(state, DHCP_BACKING_OFF);
}
// checks if the offered address is already in use
// it does so by sending an ARP query
/**
* Checks if the offered address from the server is already in use.
*
* It does so by sending an ARP request for the offered address and
* entering CHECKING state. If no ARP reply is received within a small
* interval, the address is assumed to be free for use by us.
*/
static void dhcp_check(struct dhcp_state *state)
{
struct pbuf *p;
@ -143,8 +163,6 @@ static void dhcp_check(struct dhcp_state *state)
DEBUGF(DHCP_DEBUG, ("dhcp_check(): sending ARP request len %u", p->tot_len));
result = state->netif->linkoutput(state->netif, p);
pbuf_free(p);
//return /*result*/;
}
state->tries++;
msecs = state->tries * 1000;
@ -153,6 +171,10 @@ static void dhcp_check(struct dhcp_state *state)
dhcp_set_state(state, DHCP_CHECKING);
}
/**
* Remember the configuration offered by a DHCP server.
*
*/
static void dhcp_handle_offer(struct dhcp_state *state)
{
u8_t *option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SERVER_ID);
@ -174,7 +196,7 @@ static void dhcp_handle_offer(struct dhcp_state *state)
/**
* Select a DHCP server offer out of all offers.
*
* Simply select the first offer received, ignore others
* Simply select the first offer received.
*/
static err_t dhcp_select(struct dhcp_state *state)
{
@ -223,6 +245,10 @@ static err_t dhcp_select(struct dhcp_state *state)
return result;
}
/**
* The DHCP timer that checks for lease renewal/rebind timeouts.
*
*/
void dhcp_coarse_tmr()
{
struct dhcp_state *list_state = client_list;
@ -249,6 +275,10 @@ void dhcp_coarse_tmr()
}
}
/**
* The DHCP timer that handles DHCP negotiotion transaction timeouts.
*
*/
void dhcp_fine_tmr()
{
struct dhcp_state *list_state = client_list;
@ -268,7 +298,11 @@ void dhcp_fine_tmr()
}
}
// something has timed out, handle this
/**
* A DHCP negotiation transaction, or ARP request, has timed out.
*
*
*/
static void dhcp_timeout(struct dhcp_state *state)
{
DEBUGF(DHCP_DEBUG, ("dhcp_timeout()"));
@ -319,13 +353,17 @@ static void dhcp_timeout(struct dhcp_state *state)
}
else
{
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, release, restart"));
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RELEASING, DISCOVERING"));
dhcp_release(state);
dhcp_discover(state);
}
}
}
/**
* The renewal period has timed out.
*
*/
static void dhcp_t1_timeout(struct dhcp_state *state)
{
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()"));
@ -335,6 +373,11 @@ static void dhcp_t1_timeout(struct dhcp_state *state)
dhcp_renew(state);
}
}
/**
* The rebind period has timed out.
*
*/
static void dhcp_t2_timeout(struct dhcp_state *state)
{
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()"));
@ -352,6 +395,7 @@ static void dhcp_t2_timeout(struct dhcp_state *state)
static void dhcp_handle_ack(struct dhcp_state *state)
{
u8_t *option_ptr;
/* clear options we might not get from the ACK */
state->offered_sn_mask.addr = 0;
state->offered_gw_addr.addr = 0;
state->offered_bc_addr.addr = 0;
@ -363,31 +407,36 @@ static void dhcp_handle_ack(struct dhcp_state *state)
state->offered_t1_renew = state->offered_t0_lease / 2;
state->offered_t2_rebind = state->offered_t0_lease;
}
/* renewal period */
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T1);
if (option_ptr != NULL)
{
state->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
}
/* rebind period */
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T2);
if (option_ptr != NULL)
{
state->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
}
/* (y)our internet address */
ip_addr_set(&state->offered_ip_addr, &state->msg_in->yiaddr);
/* subnet mask */
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SUBNET_MASK);
if (option_ptr != NULL)
{
state->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
}
/* gateway router */
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_ROUTER);
if (option_ptr != NULL)
{
state->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
}
/* broadcast address */
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_BROADCAST);
if (option_ptr != NULL)
{
@ -415,7 +464,14 @@ void dhcp_init(void)
* Start DHCP negotiation for a network interface.
*
* If no DHCP client instance was attached to this interface,
* a new client is created first.
* a new client is created first. If a DHCP client instance
* was already present, it restarts negotiation.
*
* @return The DHCP client state, which must be passed for
* all subsequential dhcp_*() calls. NULL means there is
* no (longer a) DHCP client attached to the interface
* (due to unavailable memory or network resources).
*
*/
struct dhcp_state *dhcp_start(struct netif *netif)
{
@ -425,14 +481,14 @@ struct dhcp_state *dhcp_start(struct netif *netif)
DEBUGF(DHCP_DEBUG, ("dhcp_start()"));
// find the DHCP client attached to the given interface
/* find the DHCP client attached to the given interface */
state = dhcp_find_client(netif);
DEBUGF(DHCP_DEBUG, ("dhcp_start(): finished parsing through list"));
// a DHCP client already attached to this interface
/* a DHCP client already attached to this interface? */
if (state != NULL)
{
DEBUGF(DHCP_DEBUG, ("dhcp_start(): already active on interface"));
// just restart the DHCP negotiation
/* just restart the DHCP negotiation */
result = dhcp_discover(state);
if (result == ERR_OK)
{
@ -464,26 +520,33 @@ struct dhcp_state *dhcp_start(struct netif *netif)
}
DEBUGF(DHCP_DEBUG, ("dhcp_start(): created new udp pcb"));
state->netif = netif;
// enqueue in list of clients
// we are last in list
/* enqueue in list of clients */
/* we are last in list */
state->next = NULL;
// empty list?
/* empty list? */
if (client_list == NULL)
{
// single item at head of list
/* single item at head of list */
client_list = state;
}
else
{
// proceed to the last DHCP client state
/* proceed to the last DHCP client state
while (list_state->next != NULL) list_state = list_state->next;
// { list_state->next == NULL }
list_state->next = state;
}
dhcp_discover(state);
return state;
}
/**
* Inform a DHCP server of our manual configuration.
*
* This informs DHCP servers of our fixed IP address configuration
* by send an INFORM message. It does not involve DHCP address
* configuration, it is just here to be nice.
*
*/
void dhcp_inform(struct netif *netif)
{
struct dhcp_state *state = NULL;
@ -568,7 +631,11 @@ void dhcp_arp_reply(struct ip_addr *addr)
}
}
// decline a
/**
* Decline a
*
*
*/
static err_t dhcp_decline(struct dhcp_state *state)
{
err_t result = ERR_OK;
@ -604,7 +671,7 @@ static err_t dhcp_decline(struct dhcp_state *state)
/**
* Start the DHCP process, discover a server
* Start the DHCP process, discover a DHCP server.
*
*/
static err_t dhcp_discover(struct dhcp_state *state)
@ -658,14 +725,15 @@ static void dhcp_bind(struct dhcp_state *state)
{
struct ip_addr sn_mask, gw_addr;
dhcp_set_state(state, DHCP_BOUND);
if (state->offered_t1_renew != 0xffffffffUL)
{
/* temporary DHCP lease? */
if (state->offered_t1_renew != 0xffffffffUL) {
/* set renewal period timer */
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t1 renewal timer %lu secs", state->offered_t1_renew));
state->t1_timeout = (state->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
if (state->t1_timeout == 0) state->t1_timeout = 1;
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): request timeout %u msecs", state->offered_t1_renew*1000));
}
/* set renewal period timer */
if (state->offered_t2_rebind != 0xffffffffUL)
{
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t2 rebind timer %lu secs", state->offered_t2_rebind));
@ -701,8 +769,10 @@ static void dhcp_bind(struct dhcp_state *state)
netif_set_ipaddr(state->netif, &state->offered_ip_addr);
}
/**
* Renew an existing DHCP lease at the involved DHCP server.
*
*/
err_t dhcp_renew(struct dhcp_state *state)
{
err_t result;
@ -748,6 +818,10 @@ err_t dhcp_renew(struct dhcp_state *state)
return result;
}
/**
* Rebind with a DHCP server for an existing DHCP lease.
*
*/
static err_t dhcp_rebind(struct dhcp_state *state)
{
err_t result;
@ -791,6 +865,10 @@ static err_t dhcp_rebind(struct dhcp_state *state)
return result;
}
/**
* Rebind with a DHCP server for an existing DHCP lease.
*
*/
static err_t dhcp_release(struct dhcp_state *state)
{
err_t result;
@ -825,7 +903,11 @@ static err_t dhcp_release(struct dhcp_state *state)
netif_set_netmask(state->netif, IP_ADDR_ANY);
return result;
}
/**
* Remove the DHCP client from the interface.
*
* @param state The DHCP client state
*/
void dhcp_stop(struct dhcp_state *state)
{
struct dhcp_state *list_state = client_list;
@ -1158,8 +1240,15 @@ static void dhcp_option_trailer(struct dhcp_state *state)
}
}
// return a byte offset into the udp message where the option was found, or
// zero if the given option was not found.
/**
* Find the offset of a DHCP option inside the DHCP message.
*
* @param client DHCP client
* @param option_type
*
* @return a byte offset into the UDP message where the option was found, or
* zero if the given option was not found.
*/
static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type)
{
u8_t overload = DHCP_OVERLOAD_NONE;
@ -1244,12 +1333,28 @@ static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type)
return 0;
}
/**
* Return the byte of DHCP option data.
*
* @param client DHCP client.
* @param ptr pointer obtained by dhcp_get_option_ptr().
*
* @return byte value at the given address.
*/
static u8_t dhcp_get_option_byte(u8_t *ptr)
{
DEBUGF(DHCP_DEBUG, ("option byte value=%u", *ptr));
return *ptr;
}
/**
* Return the 16-bit value of DHCP option data.
*
* @param client DHCP client.
* @param ptr pointer obtained by dhcp_get_option_ptr().
*
* @return byte value at the given address.
*/
static u16_t dhcp_get_option_short(u8_t *ptr)
{
u16_t value;
@ -1259,6 +1364,14 @@ static u16_t dhcp_get_option_short(u8_t *ptr)
return value;
}
/**
* Return the 32-bit value of DHCP option data.
*
* @param client DHCP client.
* @param ptr pointer obtained by dhcp_get_option_ptr().
*
* @return byte value at the given address.
*/
static u32_t dhcp_get_option_long(u8_t *ptr)
{
u32_t value;