37 |
* RFC 2131 and RFC 2132. |
* RFC 2131 and RFC 2132. |
38 |
* |
* |
39 |
* KNOWN BUG: |
* KNOWN BUG: |
40 |
* - This client will fail on servers using file/sname field overloading |
* - Parsing of DHCP messages which use file/sname field overloading will |
41 |
|
* probably fail. Additional support for this must go into dhcp_unfold(). |
42 |
* TODO: |
* TODO: |
43 |
* - Add JavaDoc style documentation (API, internals). |
* - Add JavaDoc style documentation (API, internals). |
44 |
* - Make the unfold routine smarter to handle this |
* - Make the unfold routine smarter to handle this |
63 |
* |
* |
64 |
* Then, use |
* Then, use |
65 |
* struct dhcp_state *client = dhcp_start(struct netif *netif) |
* struct dhcp_state *client = dhcp_start(struct netif *netif) |
66 |
* to start the dhcp client to configure the interface by |
* starts a DHCP client instance which configures the interface by |
67 |
* obtaining an IP address lease and maintaining it. |
* obtaining an IP address lease and maintaining it. |
68 |
* |
* |
69 |
* Use dhcp_stop(client) to stop the lease. |
* Use dhcp_release(client) to end the lease and use dhcp_stop(client) |
70 |
|
* to remove the DHCP client. |
71 |
* |
* |
72 |
*/ |
*/ |
73 |
#include "lwip/debug.h" |
#include "lwip/debug.h" |
80 |
#include "lwipopts.h" |
#include "lwipopts.h" |
81 |
#include "lwip/dhcp.h" |
#include "lwip/dhcp.h" |
82 |
|
|
83 |
/// transaction identifier, unique over all DHCP client and all DHCP requests |
/** find the active DHCP attached to the given network interface */ |
84 |
|
struct dhcp_state *dhcp_find_client(struct netif *netif); |
85 |
|
|
86 |
|
/** transaction identifier, unique over all DHCP requests */ |
87 |
static u32_t xid = 0xABCD0000; |
static u32_t xid = 0xABCD0000; |
88 |
/// singly-linked list of DHCP clients that are active |
/** singly-linked list of DHCP clients that are active */ |
89 |
static struct dhcp_state *client_list = NULL; |
static struct dhcp_state *client_list = NULL; |
90 |
|
|
91 |
/// DHCP client state machine functions |
/** DHCP client state machine functions */ |
92 |
static void dhcp_handle_ack(struct dhcp_state *state); |
static void dhcp_handle_ack(struct dhcp_state *state); |
93 |
static void dhcp_handle_nak(struct dhcp_state *state); |
static void dhcp_handle_nak(struct dhcp_state *state); |
94 |
static void dhcp_handle_offer(struct dhcp_state *state); |
static void dhcp_handle_offer(struct dhcp_state *state); |
101 |
static err_t dhcp_release(struct dhcp_state *state); |
static err_t dhcp_release(struct dhcp_state *state); |
102 |
static void dhcp_set_state(struct dhcp_state *state, unsigned char new_state); |
static void dhcp_set_state(struct dhcp_state *state, unsigned char new_state); |
103 |
|
|
104 |
// receive, unfold, process and free incoming messages |
/** receive, unfold, parse and free incoming messages */ |
105 |
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); |
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); |
106 |
static err_t dhcp_unfold_reply(struct dhcp_state *state); |
static err_t dhcp_unfold_reply(struct dhcp_state *state); |
107 |
static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type); |
static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type); |
109 |
static u16_t dhcp_get_option_short(u8_t *ptr); |
static u16_t dhcp_get_option_short(u8_t *ptr); |
110 |
static u32_t dhcp_get_option_long(u8_t *ptr); |
static u32_t dhcp_get_option_long(u8_t *ptr); |
111 |
static void dhcp_free_reply(struct dhcp_state *state); |
static void dhcp_free_reply(struct dhcp_state *state); |
112 |
|
|
113 |
|
/** set the DHCP timers */ |
114 |
static void dhcp_timeout(struct dhcp_state *state); |
static void dhcp_timeout(struct dhcp_state *state); |
115 |
static void dhcp_t1_timeout(struct dhcp_state *state); |
static void dhcp_t1_timeout(struct dhcp_state *state); |
116 |
static void dhcp_t2_timeout(struct dhcp_state *state); |
static void dhcp_t2_timeout(struct dhcp_state *state); |
117 |
|
|
118 |
|
#if DHCP_DOES_ARP_CHECK |
119 |
|
/** called by ARP to notify us of ARP replies */ |
120 |
void dhcp_arp_reply(struct ip_addr *addr); |
void dhcp_arp_reply(struct ip_addr *addr); |
121 |
|
#endif |
122 |
|
|
123 |
// build outgoing messages |
/** build outgoing messages */ |
124 |
static err_t dhcp_create_request(struct dhcp_state *state); |
static err_t dhcp_create_request(struct dhcp_state *state); |
125 |
static void dhcp_delete_request(struct dhcp_state *state); |
static void dhcp_delete_request(struct dhcp_state *state); |
126 |
static void dhcp_option(struct dhcp_state *state, u8_t option_type, u8_t option_len); |
static void dhcp_option(struct dhcp_state *state, u8_t option_type, u8_t option_len); |
129 |
static void dhcp_option_long(struct dhcp_state *state, u32_t value); |
static void dhcp_option_long(struct dhcp_state *state, u32_t value); |
130 |
static void dhcp_option_trailer(struct dhcp_state *state); |
static void dhcp_option_trailer(struct dhcp_state *state); |
131 |
|
|
132 |
// find a client in the singly-linked list of DHCP clients |
/** |
133 |
struct dhcp_state *dhcp_find_client(struct netif *netif); |
* Back-off the DHCP client because of a received NAK. Receiving a |
134 |
|
* NAK means the client asked for something non-sensible, for |
135 |
|
* example when it tries to renew a lease obtained on another network. |
136 |
|
* |
137 |
|
* We back-off and will end up restarting a fresh DHCP negotiation later. |
138 |
|
*/ |
139 |
static void dhcp_handle_nak(struct dhcp_state *state) { |
static void dhcp_handle_nak(struct dhcp_state *state) { |
140 |
u16_t msecs = 10 * 1000; |
u16_t msecs = 10 * 1000; |
141 |
DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak()")); |
144 |
dhcp_set_state(state, DHCP_BACKING_OFF); |
dhcp_set_state(state, DHCP_BACKING_OFF); |
145 |
} |
} |
146 |
|
|
147 |
// checks if the offered address is already in use |
/** |
148 |
// it does so by sending an ARP query |
* Checks if the offered address from the server is already in use. |
149 |
|
* |
150 |
|
* It does so by sending an ARP request for the offered address and |
151 |
|
* entering CHECKING state. If no ARP reply is received within a small |
152 |
|
* interval, the address is assumed to be free for use by us. |
153 |
|
*/ |
154 |
static void dhcp_check(struct dhcp_state *state) |
static void dhcp_check(struct dhcp_state *state) |
155 |
{ |
{ |
156 |
struct pbuf *p; |
struct pbuf *p; |
163 |
DEBUGF(DHCP_DEBUG, ("dhcp_check(): sending ARP request len %u", p->tot_len)); |
DEBUGF(DHCP_DEBUG, ("dhcp_check(): sending ARP request len %u", p->tot_len)); |
164 |
result = state->netif->linkoutput(state->netif, p); |
result = state->netif->linkoutput(state->netif, p); |
165 |
pbuf_free(p); |
pbuf_free(p); |
|
|
|
|
//return /*result*/; |
|
166 |
} |
} |
167 |
state->tries++; |
state->tries++; |
168 |
msecs = state->tries * 1000; |
msecs = state->tries * 1000; |
171 |
dhcp_set_state(state, DHCP_CHECKING); |
dhcp_set_state(state, DHCP_CHECKING); |
172 |
} |
} |
173 |
|
|
174 |
|
/** |
175 |
|
* Remember the configuration offered by a DHCP server. |
176 |
|
* |
177 |
|
*/ |
178 |
static void dhcp_handle_offer(struct dhcp_state *state) |
static void dhcp_handle_offer(struct dhcp_state *state) |
179 |
{ |
{ |
180 |
u8_t *option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SERVER_ID); |
u8_t *option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SERVER_ID); |
196 |
/** |
/** |
197 |
* Select a DHCP server offer out of all offers. |
* Select a DHCP server offer out of all offers. |
198 |
* |
* |
199 |
* Simply select the first offer received, ignore others |
* Simply select the first offer received. |
200 |
*/ |
*/ |
201 |
static err_t dhcp_select(struct dhcp_state *state) |
static err_t dhcp_select(struct dhcp_state *state) |
202 |
{ |
{ |
245 |
return result; |
return result; |
246 |
} |
} |
247 |
|
|
248 |
|
/** |
249 |
|
* The DHCP timer that checks for lease renewal/rebind timeouts. |
250 |
|
* |
251 |
|
*/ |
252 |
void dhcp_coarse_tmr() |
void dhcp_coarse_tmr() |
253 |
{ |
{ |
254 |
struct dhcp_state *list_state = client_list; |
struct dhcp_state *list_state = client_list; |
275 |
} |
} |
276 |
} |
} |
277 |
|
|
278 |
|
/** |
279 |
|
* The DHCP timer that handles DHCP negotiotion transaction timeouts. |
280 |
|
* |
281 |
|
*/ |
282 |
void dhcp_fine_tmr() |
void dhcp_fine_tmr() |
283 |
{ |
{ |
284 |
struct dhcp_state *list_state = client_list; |
struct dhcp_state *list_state = client_list; |
298 |
} |
} |
299 |
} |
} |
300 |
|
|
301 |
// something has timed out, handle this |
/** |
302 |
|
* A DHCP negotiation transaction, or ARP request, has timed out. |
303 |
|
* |
304 |
|
* |
305 |
|
*/ |
306 |
static void dhcp_timeout(struct dhcp_state *state) |
static void dhcp_timeout(struct dhcp_state *state) |
307 |
{ |
{ |
308 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout()")); |
353 |
} |
} |
354 |
else |
else |
355 |
{ |
{ |
356 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, release, restart")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RELEASING, DISCOVERING")); |
357 |
dhcp_release(state); |
dhcp_release(state); |
358 |
dhcp_discover(state); |
dhcp_discover(state); |
359 |
} |
} |
360 |
} |
} |
361 |
} |
} |
362 |
|
|
363 |
|
/** |
364 |
|
* The renewal period has timed out. |
365 |
|
* |
366 |
|
*/ |
367 |
static void dhcp_t1_timeout(struct dhcp_state *state) |
static void dhcp_t1_timeout(struct dhcp_state *state) |
368 |
{ |
{ |
369 |
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()")); |
373 |
dhcp_renew(state); |
dhcp_renew(state); |
374 |
} |
} |
375 |
} |
} |
376 |
|
|
377 |
|
/** |
378 |
|
* The rebind period has timed out. |
379 |
|
* |
380 |
|
*/ |
381 |
static void dhcp_t2_timeout(struct dhcp_state *state) |
static void dhcp_t2_timeout(struct dhcp_state *state) |
382 |
{ |
{ |
383 |
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()")); |
395 |
static void dhcp_handle_ack(struct dhcp_state *state) |
static void dhcp_handle_ack(struct dhcp_state *state) |
396 |
{ |
{ |
397 |
u8_t *option_ptr; |
u8_t *option_ptr; |
398 |
|
/* clear options we might not get from the ACK */ |
399 |
state->offered_sn_mask.addr = 0; |
state->offered_sn_mask.addr = 0; |
400 |
state->offered_gw_addr.addr = 0; |
state->offered_gw_addr.addr = 0; |
401 |
state->offered_bc_addr.addr = 0; |
state->offered_bc_addr.addr = 0; |
407 |
state->offered_t1_renew = state->offered_t0_lease / 2; |
state->offered_t1_renew = state->offered_t0_lease / 2; |
408 |
state->offered_t2_rebind = state->offered_t0_lease; |
state->offered_t2_rebind = state->offered_t0_lease; |
409 |
} |
} |
410 |
|
/* renewal period */ |
411 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T1); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T1); |
412 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
413 |
{ |
{ |
414 |
state->offered_t1_renew = dhcp_get_option_long(option_ptr + 2); |
state->offered_t1_renew = dhcp_get_option_long(option_ptr + 2); |
415 |
} |
} |
416 |
|
/* rebind period */ |
417 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T2); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T2); |
418 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
419 |
{ |
{ |
420 |
state->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2); |
state->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2); |
421 |
} |
} |
422 |
|
/* (y)our internet address */ |
423 |
ip_addr_set(&state->offered_ip_addr, &state->msg_in->yiaddr); |
ip_addr_set(&state->offered_ip_addr, &state->msg_in->yiaddr); |
424 |
|
|
425 |
|
/* subnet mask */ |
426 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SUBNET_MASK); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SUBNET_MASK); |
427 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
428 |
{ |
{ |
429 |
state->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2])); |
state->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2])); |
430 |
} |
} |
431 |
|
|
432 |
|
/* gateway router */ |
433 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_ROUTER); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_ROUTER); |
434 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
435 |
{ |
{ |
436 |
state->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); |
state->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); |
437 |
} |
} |
438 |
|
|
439 |
|
/* broadcast address */ |
440 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_BROADCAST); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_BROADCAST); |
441 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
442 |
{ |
{ |
464 |
* Start DHCP negotiation for a network interface. |
* Start DHCP negotiation for a network interface. |
465 |
* |
* |
466 |
* If no DHCP client instance was attached to this interface, |
* If no DHCP client instance was attached to this interface, |
467 |
* a new client is created first. |
* a new client is created first. If a DHCP client instance |
468 |
|
* was already present, it restarts negotiation. |
469 |
|
* |
470 |
|
* @return The DHCP client state, which must be passed for |
471 |
|
* all subsequential dhcp_*() calls. NULL means there is |
472 |
|
* no (longer a) DHCP client attached to the interface |
473 |
|
* (due to unavailable memory or network resources). |
474 |
|
* |
475 |
*/ |
*/ |
476 |
struct dhcp_state *dhcp_start(struct netif *netif) |
struct dhcp_state *dhcp_start(struct netif *netif) |
477 |
{ |
{ |
481 |
|
|
482 |
DEBUGF(DHCP_DEBUG, ("dhcp_start()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_start()")); |
483 |
|
|
484 |
// find the DHCP client attached to the given interface |
/* find the DHCP client attached to the given interface */ |
485 |
state = dhcp_find_client(netif); |
state = dhcp_find_client(netif); |
486 |
DEBUGF(DHCP_DEBUG, ("dhcp_start(): finished parsing through list")); |
DEBUGF(DHCP_DEBUG, ("dhcp_start(): finished parsing through list")); |
487 |
// a DHCP client already attached to this interface |
/* a DHCP client already attached to this interface? */ |
488 |
if (state != NULL) |
if (state != NULL) |
489 |
{ |
{ |
490 |
DEBUGF(DHCP_DEBUG, ("dhcp_start(): already active on interface")); |
DEBUGF(DHCP_DEBUG, ("dhcp_start(): already active on interface")); |
491 |
// just restart the DHCP negotiation |
/* just restart the DHCP negotiation */ |
492 |
result = dhcp_discover(state); |
result = dhcp_discover(state); |
493 |
if (result == ERR_OK) |
if (result == ERR_OK) |
494 |
{ |
{ |
520 |
} |
} |
521 |
DEBUGF(DHCP_DEBUG, ("dhcp_start(): created new udp pcb")); |
DEBUGF(DHCP_DEBUG, ("dhcp_start(): created new udp pcb")); |
522 |
state->netif = netif; |
state->netif = netif; |
523 |
// enqueue in list of clients |
/* enqueue in list of clients */ |
524 |
// we are last in list |
/* we are last in list */ |
525 |
state->next = NULL; |
state->next = NULL; |
526 |
// empty list? |
/* empty list? */ |
527 |
if (client_list == NULL) |
if (client_list == NULL) |
528 |
{ |
{ |
529 |
// single item at head of list |
/* single item at head of list */ |
530 |
client_list = state; |
client_list = state; |
531 |
} |
} |
532 |
else |
else |
533 |
{ |
{ |
534 |
// proceed to the last DHCP client state |
/* proceed to the last DHCP client state |
535 |
while (list_state->next != NULL) list_state = list_state->next; |
while (list_state->next != NULL) list_state = list_state->next; |
|
// { list_state->next == NULL } |
|
536 |
list_state->next = state; |
list_state->next = state; |
537 |
} |
} |
538 |
dhcp_discover(state); |
dhcp_discover(state); |
539 |
return state; |
return state; |
540 |
} |
} |
541 |
|
|
542 |
|
/** |
543 |
|
* Inform a DHCP server of our manual configuration. |
544 |
|
* |
545 |
|
* This informs DHCP servers of our fixed IP address configuration |
546 |
|
* by send an INFORM message. It does not involve DHCP address |
547 |
|
* configuration, it is just here to be nice. |
548 |
|
* |
549 |
|
*/ |
550 |
void dhcp_inform(struct netif *netif) |
void dhcp_inform(struct netif *netif) |
551 |
{ |
{ |
552 |
struct dhcp_state *state = NULL; |
struct dhcp_state *state = NULL; |
631 |
} |
} |
632 |
} |
} |
633 |
|
|
634 |
// decline a |
/** |
635 |
|
* Decline a |
636 |
|
* |
637 |
|
* |
638 |
|
*/ |
639 |
static err_t dhcp_decline(struct dhcp_state *state) |
static err_t dhcp_decline(struct dhcp_state *state) |
640 |
{ |
{ |
641 |
err_t result = ERR_OK; |
err_t result = ERR_OK; |
671 |
|
|
672 |
|
|
673 |
/** |
/** |
674 |
* Start the DHCP process, discover a server |
* Start the DHCP process, discover a DHCP server. |
675 |
* |
* |
676 |
*/ |
*/ |
677 |
static err_t dhcp_discover(struct dhcp_state *state) |
static err_t dhcp_discover(struct dhcp_state *state) |
725 |
{ |
{ |
726 |
struct ip_addr sn_mask, gw_addr; |
struct ip_addr sn_mask, gw_addr; |
727 |
dhcp_set_state(state, DHCP_BOUND); |
dhcp_set_state(state, DHCP_BOUND); |
728 |
|
/* temporary DHCP lease? */ |
729 |
if (state->offered_t1_renew != 0xffffffffUL) |
if (state->offered_t1_renew != 0xffffffffUL) { |
730 |
{ |
/* set renewal period timer */ |
731 |
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t1 renewal timer %lu secs", state->offered_t1_renew)); |
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t1 renewal timer %lu secs", state->offered_t1_renew)); |
732 |
state->t1_timeout = (state->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; |
state->t1_timeout = (state->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; |
733 |
if (state->t1_timeout == 0) state->t1_timeout = 1; |
if (state->t1_timeout == 0) state->t1_timeout = 1; |
734 |
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): request timeout %u msecs", state->offered_t1_renew*1000)); |
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): request timeout %u msecs", state->offered_t1_renew*1000)); |
735 |
} |
} |
736 |
|
/* set renewal period timer */ |
737 |
if (state->offered_t2_rebind != 0xffffffffUL) |
if (state->offered_t2_rebind != 0xffffffffUL) |
738 |
{ |
{ |
739 |
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t2 rebind timer %lu secs", state->offered_t2_rebind)); |
DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t2 rebind timer %lu secs", state->offered_t2_rebind)); |
769 |
netif_set_ipaddr(state->netif, &state->offered_ip_addr); |
netif_set_ipaddr(state->netif, &state->offered_ip_addr); |
770 |
} |
} |
771 |
|
|
772 |
|
/** |
773 |
|
* Renew an existing DHCP lease at the involved DHCP server. |
774 |
|
* |
775 |
|
*/ |
776 |
err_t dhcp_renew(struct dhcp_state *state) |
err_t dhcp_renew(struct dhcp_state *state) |
777 |
{ |
{ |
778 |
err_t result; |
err_t result; |
818 |
return result; |
return result; |
819 |
} |
} |
820 |
|
|
821 |
|
/** |
822 |
|
* Rebind with a DHCP server for an existing DHCP lease. |
823 |
|
* |
824 |
|
*/ |
825 |
static err_t dhcp_rebind(struct dhcp_state *state) |
static err_t dhcp_rebind(struct dhcp_state *state) |
826 |
{ |
{ |
827 |
err_t result; |
err_t result; |
865 |
return result; |
return result; |
866 |
} |
} |
867 |
|
|
868 |
|
/** |
869 |
|
* Rebind with a DHCP server for an existing DHCP lease. |
870 |
|
* |
871 |
|
*/ |
872 |
static err_t dhcp_release(struct dhcp_state *state) |
static err_t dhcp_release(struct dhcp_state *state) |
873 |
{ |
{ |
874 |
err_t result; |
err_t result; |
903 |
netif_set_netmask(state->netif, IP_ADDR_ANY); |
netif_set_netmask(state->netif, IP_ADDR_ANY); |
904 |
return result; |
return result; |
905 |
} |
} |
906 |
|
/** |
907 |
|
* Remove the DHCP client from the interface. |
908 |
|
* |
909 |
|
* @param state The DHCP client state |
910 |
|
*/ |
911 |
void dhcp_stop(struct dhcp_state *state) |
void dhcp_stop(struct dhcp_state *state) |
912 |
{ |
{ |
913 |
struct dhcp_state *list_state = client_list; |
struct dhcp_state *list_state = client_list; |
1240 |
} |
} |
1241 |
} |
} |
1242 |
|
|
1243 |
// return a byte offset into the udp message where the option was found, or |
/** |
1244 |
// zero if the given option was not found. |
* Find the offset of a DHCP option inside the DHCP message. |
1245 |
|
* |
1246 |
|
* @param client DHCP client |
1247 |
|
* @param option_type |
1248 |
|
* |
1249 |
|
* @return a byte offset into the UDP message where the option was found, or |
1250 |
|
* zero if the given option was not found. |
1251 |
|
*/ |
1252 |
static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type) |
static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type) |
1253 |
{ |
{ |
1254 |
u8_t overload = DHCP_OVERLOAD_NONE; |
u8_t overload = DHCP_OVERLOAD_NONE; |
1333 |
return 0; |
return 0; |
1334 |
} |
} |
1335 |
|
|
1336 |
|
/** |
1337 |
|
* Return the byte of DHCP option data. |
1338 |
|
* |
1339 |
|
* @param client DHCP client. |
1340 |
|
* @param ptr pointer obtained by dhcp_get_option_ptr(). |
1341 |
|
* |
1342 |
|
* @return byte value at the given address. |
1343 |
|
*/ |
1344 |
static u8_t dhcp_get_option_byte(u8_t *ptr) |
static u8_t dhcp_get_option_byte(u8_t *ptr) |
1345 |
{ |
{ |
1346 |
DEBUGF(DHCP_DEBUG, ("option byte value=%u", *ptr)); |
DEBUGF(DHCP_DEBUG, ("option byte value=%u", *ptr)); |
1347 |
return *ptr; |
return *ptr; |
1348 |
} |
} |
1349 |
|
|
1350 |
|
/** |
1351 |
|
* Return the 16-bit value of DHCP option data. |
1352 |
|
* |
1353 |
|
* @param client DHCP client. |
1354 |
|
* @param ptr pointer obtained by dhcp_get_option_ptr(). |
1355 |
|
* |
1356 |
|
* @return byte value at the given address. |
1357 |
|
*/ |
1358 |
static u16_t dhcp_get_option_short(u8_t *ptr) |
static u16_t dhcp_get_option_short(u8_t *ptr) |
1359 |
{ |
{ |
1360 |
u16_t value; |
u16_t value; |
1364 |
return value; |
return value; |
1365 |
} |
} |
1366 |
|
|
1367 |
|
/** |
1368 |
|
* Return the 32-bit value of DHCP option data. |
1369 |
|
* |
1370 |
|
* @param client DHCP client. |
1371 |
|
* @param ptr pointer obtained by dhcp_get_option_ptr(). |
1372 |
|
* |
1373 |
|
* @return byte value at the given address. |
1374 |
|
*/ |
1375 |
static u32_t dhcp_get_option_long(u8_t *ptr) |
static u32_t dhcp_get_option_long(u8_t *ptr) |
1376 |
{ |
{ |
1377 |
u32_t value; |
u32_t value; |