130 |
static void dhcp_option_trailer(struct dhcp_state *state); |
static void dhcp_option_trailer(struct dhcp_state *state); |
131 |
|
|
132 |
/** |
/** |
133 |
|
* Back-off the DHCP client (because of a received NAK response). |
134 |
|
* |
135 |
* Back-off the DHCP client because of a received NAK. Receiving a |
* Back-off the DHCP client because of a received NAK. Receiving a |
136 |
* NAK means the client asked for something non-sensible, for |
* NAK means the client asked for something non-sensible, for |
137 |
* example when it tries to renew a lease obtained on another network. |
* example when it tries to renew a lease obtained on another network. |
138 |
* |
* |
139 |
* We back-off and will end up restarting a fresh DHCP negotiation later. |
* We back-off and will end up restarting a fresh DHCP negotiation later. |
140 |
|
* |
141 |
|
* @param state pointer to DHCP state structure |
142 |
*/ |
*/ |
143 |
static void dhcp_handle_nak(struct dhcp_state *state) { |
static void dhcp_handle_nak(struct dhcp_state *state) { |
144 |
u16_t msecs = 10 * 1000; |
u16_t msecs = 10 * 1000; |
161 |
err_t result; |
err_t result; |
162 |
u16_t msecs; |
u16_t msecs; |
163 |
DEBUGF(DHCP_DEBUG, ("dhcp_check()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_check()")); |
164 |
|
/* create an ARP query for the offered IP address, expecting that no host |
165 |
|
responds, as the IP address should not be in use. */ |
166 |
p = etharp_query(state->netif, &state->offered_ip_addr, NULL); |
p = etharp_query(state->netif, &state->offered_ip_addr, NULL); |
167 |
if(p != NULL) |
if(p != NULL) |
168 |
{ |
{ |
181 |
/** |
/** |
182 |
* Remember the configuration offered by a DHCP server. |
* Remember the configuration offered by a DHCP server. |
183 |
* |
* |
184 |
|
* @param state pointer to DHCP state structure |
185 |
*/ |
*/ |
186 |
static void dhcp_handle_offer(struct dhcp_state *state) |
static void dhcp_handle_offer(struct dhcp_state *state) |
187 |
{ |
{ |
188 |
|
/* obtain the server address */ |
189 |
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); |
190 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
191 |
{ |
{ |
206 |
* Select a DHCP server offer out of all offers. |
* Select a DHCP server offer out of all offers. |
207 |
* |
* |
208 |
* Simply select the first offer received. |
* Simply select the first offer received. |
209 |
|
* |
210 |
|
* @param state pointer to DHCP state structure |
211 |
|
* @return lwIP specific error (see error.h) |
212 |
*/ |
*/ |
213 |
static err_t dhcp_select(struct dhcp_state *state) |
static err_t dhcp_select(struct dhcp_state *state) |
214 |
{ |
{ |
242 |
|
|
243 |
pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len); |
pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len); |
244 |
|
|
245 |
|
/* TODO: we really should bind to a specific local interface here |
246 |
|
but we cannot specify an unconfigured netif as it is addressless */ |
247 |
udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); |
udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); |
248 |
|
/* listen to broadcast traffic from a DHCP server */ |
249 |
udp_connect(state->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT); |
udp_connect(state->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT); |
250 |
udp_send(state->pcb, state->p_out); |
udp_send(state->pcb, state->p_out); |
251 |
// reconnect to any (or to server here?!) |
// reconnect to any (or to server here?!) |
263 |
/** |
/** |
264 |
* The DHCP timer that checks for lease renewal/rebind timeouts. |
* The DHCP timer that checks for lease renewal/rebind timeouts. |
265 |
* |
* |
266 |
|
* @param state pointer to DHCP state structure |
267 |
*/ |
*/ |
268 |
void dhcp_coarse_tmr() |
void dhcp_coarse_tmr() |
269 |
{ |
{ |
299 |
{ |
{ |
300 |
struct dhcp_state *list_state = client_list; |
struct dhcp_state *list_state = client_list; |
301 |
// DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr():")); |
// DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr():")); |
302 |
// loop through clients |
/* loop through clients */ |
303 |
while (list_state != NULL) |
while (list_state != NULL) |
304 |
{ |
{ |
305 |
// timer is active (non zero), and triggers (zeroes) now |
/* timer is active (non zero), and triggers (zeroes) now */ |
306 |
if (list_state->request_timeout-- == 1) |
if (list_state->request_timeout-- == 1) |
307 |
{ |
{ |
308 |
DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr(): request timeout")); |
DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr(): request timeout")); |
309 |
// this clients' request timeout triggered |
/* this clients' request timeout triggered */ |
310 |
dhcp_timeout(list_state); |
dhcp_timeout(list_state); |
311 |
} |
} |
312 |
// proceed to next client |
/* proceed to next client */ |
313 |
list_state = list_state->next; |
list_state = list_state->next; |
314 |
} |
} |
315 |
} |
} |
317 |
/** |
/** |
318 |
* A DHCP negotiation transaction, or ARP request, has timed out. |
* A DHCP negotiation transaction, or ARP request, has timed out. |
319 |
* |
* |
320 |
|
* The timer that was started with the DHCP or ARP request has |
321 |
|
* timed out, indicating no response was received. |
322 |
|
* |
323 |
|
* @param state pointer to DHCP state structure |
324 |
* |
* |
325 |
*/ |
*/ |
326 |
static void dhcp_timeout(struct dhcp_state *state) |
static void dhcp_timeout(struct dhcp_state *state) |
327 |
{ |
{ |
328 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout()")); |
329 |
|
/* back-off period has passed, or server selection timed out */ |
330 |
if ((state->state == DHCP_BACKING_OFF) || (state->state == DHCP_SELECTING)) |
if ((state->state == DHCP_BACKING_OFF) || (state->state == DHCP_SELECTING)) |
331 |
{ |
{ |
332 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): restarting discovery")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): restarting discovery")); |
333 |
dhcp_discover(state); |
dhcp_discover(state); |
334 |
} |
} |
335 |
|
/* receiving the requested lease timed out */ |
336 |
else if (state->state == DHCP_REQUESTING) |
else if (state->state == DHCP_REQUESTING) |
337 |
{ |
{ |
338 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, DHCP request timed out")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, DHCP request timed out")); |
347 |
dhcp_discover(state); |
dhcp_discover(state); |
348 |
} |
} |
349 |
} |
} |
350 |
|
/* received no ARP reply for the offered address (which is good) */ |
351 |
else if (state->state == DHCP_CHECKING) |
else if (state->state == DHCP_CHECKING) |
352 |
{ |
{ |
353 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): CHECKING, ARP request timed out")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): CHECKING, ARP request timed out")); |
355 |
{ |
{ |
356 |
dhcp_check(state); |
dhcp_check(state); |
357 |
} |
} |
358 |
// no ARP replies on the offered address, |
/* no ARP replies on the offered address, |
359 |
// looks like the IP address is indeed free |
looks like the IP address is indeed free */ |
360 |
else |
else |
361 |
{ |
{ |
362 |
|
/* bind the interface to the offered address */ |
363 |
dhcp_bind(state); |
dhcp_bind(state); |
364 |
} |
} |
365 |
} |
} |
366 |
|
/* did not get response to renew request? */ |
367 |
else if (state->state == DHCP_RENEWING) |
else if (state->state == DHCP_RENEWING) |
368 |
{ |
{ |
369 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RENEWING, DHCP request timed out")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RENEWING, DHCP request timed out")); |
370 |
|
/* just retry renewal */ |
371 |
|
/* note that the rebind timer will eventually time-out if renew does not work */ |
372 |
dhcp_renew(state); |
dhcp_renew(state); |
373 |
} |
} |
374 |
|
/* did not get response to rebind request? */ |
375 |
else if (state->state == DHCP_REBINDING) |
else if (state->state == DHCP_REBINDING) |
376 |
{ |
{ |
377 |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, DHCP request timed out")); |
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, DHCP request timed out")); |
391 |
/** |
/** |
392 |
* The renewal period has timed out. |
* The renewal period has timed out. |
393 |
* |
* |
394 |
|
* @param state pointer to DHCP state structure |
395 |
*/ |
*/ |
396 |
static void dhcp_t1_timeout(struct dhcp_state *state) |
static void dhcp_t1_timeout(struct dhcp_state *state) |
397 |
{ |
{ |
398 |
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()")); |
399 |
if ((state->state == DHCP_REQUESTING) || (state->state == DHCP_BOUND) || (state->state == DHCP_RENEWING)) |
if ((state->state == DHCP_REQUESTING) || (state->state == DHCP_BOUND) || (state->state == DHCP_RENEWING)) |
400 |
{ |
{ |
401 |
|
/* just retry to renew */ |
402 |
|
/* note that the rebind timer will eventually time-out if renew does not work */ |
403 |
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout(): must renew")); |
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout(): must renew")); |
404 |
dhcp_renew(state); |
dhcp_renew(state); |
405 |
} |
} |
414 |
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()")); |
415 |
if ((state->state == DHCP_REQUESTING) || (state->state == DHCP_BOUND) || (state->state == DHCP_RENEWING)) |
if ((state->state == DHCP_REQUESTING) || (state->state == DHCP_BOUND) || (state->state == DHCP_RENEWING)) |
416 |
{ |
{ |
417 |
|
/* just retry to rebind */ |
418 |
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout(): must rebind")); |
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout(): must rebind")); |
419 |
dhcp_rebind(state); |
dhcp_rebind(state); |
420 |
} |
} |
423 |
/** |
/** |
424 |
* Extract options from the server ACK message. |
* Extract options from the server ACK message. |
425 |
* |
* |
426 |
|
* @param state pointer to DHCP state structure |
427 |
*/ |
*/ |
428 |
static void dhcp_handle_ack(struct dhcp_state *state) |
static void dhcp_handle_ack(struct dhcp_state *state) |
429 |
{ |
{ |
433 |
state->offered_gw_addr.addr = 0; |
state->offered_gw_addr.addr = 0; |
434 |
state->offered_bc_addr.addr = 0; |
state->offered_bc_addr.addr = 0; |
435 |
|
|
436 |
|
/* lease time given? */ |
437 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_LEASE_TIME); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_LEASE_TIME); |
438 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
439 |
{ |
{ |
440 |
|
/* remember offered lease time */ |
441 |
state->offered_t0_lease = dhcp_get_option_long(option_ptr + 2); |
state->offered_t0_lease = dhcp_get_option_long(option_ptr + 2); |
442 |
|
/* calculate safe periods for renewal and rebinding */ |
443 |
state->offered_t1_renew = state->offered_t0_lease / 2; |
state->offered_t1_renew = state->offered_t0_lease / 2; |
444 |
state->offered_t2_rebind = state->offered_t0_lease; |
state->offered_t2_rebind = state->offered_t0_lease; |
445 |
} |
} |
446 |
/* renewal period */ |
/* renewal period given? */ |
447 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T1); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T1); |
448 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
449 |
{ |
{ |
450 |
|
/* remember given renewal period */ |
451 |
state->offered_t1_renew = dhcp_get_option_long(option_ptr + 2); |
state->offered_t1_renew = dhcp_get_option_long(option_ptr + 2); |
452 |
} |
} |
453 |
/* rebind period */ |
/* renewal period given? */ |
454 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T2); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T2); |
455 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
456 |
{ |
{ |
457 |
|
/* remember given rebind period */ |
458 |
state->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2); |
state->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2); |
459 |
} |
} |
460 |
/* (y)our internet address */ |
/* (y)our internet address */ |
462 |
|
|
463 |
/* subnet mask */ |
/* subnet mask */ |
464 |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SUBNET_MASK); |
option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SUBNET_MASK); |
465 |
|
/* subnet mask given? */ |
466 |
if (option_ptr != NULL) |
if (option_ptr != NULL) |
467 |
{ |
{ |
468 |
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])); |
506 |
* a new client is created first. If a DHCP client instance |
* a new client is created first. If a DHCP client instance |
507 |
* was already present, it restarts negotiation. |
* was already present, it restarts negotiation. |
508 |
* |
* |
509 |
|
* @param netif The lwIP network interface |
510 |
* @return The DHCP client state, which must be passed for |
* @return The DHCP client state, which must be passed for |
511 |
* all subsequential dhcp_*() calls. NULL means there is |
* all subsequential dhcp_*() calls. NULL means there is |
512 |
* no (longer a) DHCP client attached to the interface |
* no (longer a) DHCP client attached to the interface |
583 |
* Inform a DHCP server of our manual configuration. |
* Inform a DHCP server of our manual configuration. |
584 |
* |
* |
585 |
* This informs DHCP servers of our fixed IP address configuration |
* This informs DHCP servers of our fixed IP address configuration |
586 |
* by send an INFORM message. It does not involve DHCP address |
* by sending an INFORM message. It does not involve DHCP address |
587 |
* configuration, it is just here to be nice. |
* configuration, it is just here to be nice to the network. |
588 |
|
* |
589 |
|
* @param netif The lwIP network interface |
590 |
* |
* |
591 |
*/ |
*/ |
592 |
void dhcp_inform(struct netif *netif) |
void dhcp_inform(struct netif *netif) |
610 |
} |
} |
611 |
DEBUGF(DHCP_DEBUG, ("dhcp_inform(): created new udp pcb")); |
DEBUGF(DHCP_DEBUG, ("dhcp_inform(): created new udp pcb")); |
612 |
state->netif = netif; |
state->netif = netif; |
613 |
// we are last in list |
/* we are last in list */ |
614 |
state->next = NULL; |
state->next = NULL; |
615 |
// create and initialize the DHCP message header |
/* create and initialize the DHCP message header */ |
616 |
result = dhcp_create_request(state); |
result = dhcp_create_request(state); |
617 |
if (result == ERR_OK) |
if (result == ERR_OK) |
618 |
{ |
{ |
643 |
} |
} |
644 |
|
|
645 |
#if DHCP_DOES_ARP_CHECK |
#if DHCP_DOES_ARP_CHECK |
646 |
|
/** |
647 |
|
* Match an ARP reply with the offered IP address. |
648 |
|
* |
649 |
|
* @param addr The IP address we received a reply from |
650 |
|
* |
651 |
|
*/ |
652 |
void dhcp_arp_reply(struct ip_addr *addr) |
void dhcp_arp_reply(struct ip_addr *addr) |
653 |
{ |
{ |
654 |
struct dhcp_state *list_state = client_list; |
struct dhcp_state *list_state = client_list; |
655 |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply()")); |
656 |
// loop through clients |
/* loop through clients */ |
657 |
while (list_state != NULL) |
while (list_state != NULL) |
658 |
{ |
{ |
659 |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): list_state %p", list_state)); |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): list_state %p", list_state)); |
660 |
// is this DHCP client doing an ARP check? |
/* is this DHCP client doing an ARP check? */ |
661 |
if (list_state->state == DHCP_CHECKING) |
if (list_state->state == DHCP_CHECKING) |
662 |
{ |
{ |
663 |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx", addr->addr)); |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx", addr->addr)); |
664 |
// does a host respond with the address we |
/* does a host respond with the address we |
665 |
// were offered by the DHCP server? |
were offered by the DHCP server? */ |
666 |
if (ip_addr_cmp(addr, &list_state->offered_ip_addr)) |
if (ip_addr_cmp(addr, &list_state->offered_ip_addr)) |
667 |
{ |
{ |
668 |
// we will not accept the offered address |
/* we will not accept the offered address */ |
669 |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): arp reply matched with offered address, declining")); |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): arp reply matched with offered address, declining")); |
670 |
dhcp_decline(list_state); |
dhcp_decline(list_state); |
671 |
} |
} |
674 |
{ |
{ |
675 |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): NOT CHECKING")); |
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): NOT CHECKING")); |
676 |
} |
} |
677 |
// proceed to next timer |
/* proceed to next timer */ |
678 |
list_state = list_state->next; |
list_state = list_state->next; |
679 |
} |
} |
680 |
} |
} |
681 |
|
|
682 |
/** |
/** |
683 |
* Decline a |
* Decline an offered lease. |
|
* |
|
684 |
* |
* |
685 |
|
* Tell the DHCP server we do not accept the offered address. |
686 |
|
* One reason to decline the lease is when we find out the address |
687 |
|
* is already in use by another host (through ARP). |
688 |
*/ |
*/ |
689 |
static err_t dhcp_decline(struct dhcp_state *state) |
static err_t dhcp_decline(struct dhcp_state *state) |
690 |
{ |
{ |
692 |
u16_t msecs; |
u16_t msecs; |
693 |
DEBUGF(DHCP_DEBUG, ("dhcp_decline()")); |
DEBUGF(DHCP_DEBUG, ("dhcp_decline()")); |
694 |
dhcp_set_state(state, DHCP_BACKING_OFF); |
dhcp_set_state(state, DHCP_BACKING_OFF); |
695 |
// create and initialize the DHCP message header |
/* create and initialize the DHCP message header */ |
696 |
result = dhcp_create_request(state); |
result = dhcp_create_request(state); |
697 |
if (result == ERR_OK) |
if (result == ERR_OK) |
698 |
{ |
{ |
793 |
} |
} |
794 |
|
|
795 |
ip_addr_set(&sn_mask, &state->offered_sn_mask); |
ip_addr_set(&sn_mask, &state->offered_sn_mask); |
796 |
// subnet mask not given |
|
797 |
|
/* subnet mask not given? */ |
798 |
|
/* TODO: this is not a valid check. what if the network mask is 0??!! */ |
799 |
if (sn_mask.addr == 0) |
if (sn_mask.addr == 0) |
800 |
{ |
{ |
801 |
// choose a safe subnet mask given the network class |
/* choose a safe subnet mask given the network class */ |
802 |
u8_t first_octet = ip4_addr1(&sn_mask); |
u8_t first_octet = ip4_addr1(&sn_mask); |
803 |
if (first_octet <= 127) sn_mask.addr = htonl(0xff000000); |
if (first_octet <= 127) sn_mask.addr = htonl(0xff000000); |
804 |
else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00); |
else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00); |
808 |
netif_set_netmask(state->netif, &sn_mask); |
netif_set_netmask(state->netif, &sn_mask); |
809 |
|
|
810 |
ip_addr_set(&gw_addr, &state->offered_gw_addr); |
ip_addr_set(&gw_addr, &state->offered_gw_addr); |
811 |
// gateway address not given |
/* gateway address not given? */ |
812 |
if (gw_addr.addr == 0) |
if (gw_addr.addr == 0) |
813 |
{ |
{ |
814 |
gw_addr.addr &= sn_mask.addr; |
gw_addr.addr &= sn_mask.addr; |
1005 |
} |
} |
1006 |
} |
} |
1007 |
|
|
1008 |
|
/* |
1009 |
|
* Set the DHCP state of a DHCP client. |
1010 |
|
* |
1011 |
|
* If the state changed, reset the number of tries. |
1012 |
|
* |
1013 |
|
* TODO: we might also want to reset the timeout here? |
1014 |
|
*/ |
1015 |
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) |
1016 |
{ |
{ |
1017 |
if (new_state != state->state) |
if (new_state != state->state) |
1021 |
} |
} |
1022 |
} |
} |
1023 |
|
|
1024 |
|
/* |
1025 |
|
* Concatenate an option type and length field to the outgoing |
1026 |
|
* DHCP message. |
1027 |
|
* |
1028 |
|
*/ |
1029 |
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) |
1030 |
{ |
{ |
1031 |
LWIP_ASSERT("dhcp_option_short: state->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", state->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN); |
LWIP_ASSERT("dhcp_option_short: state->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", state->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN); |
1032 |
state->msg_out->options[state->options_out_len++] = option_type; |
state->msg_out->options[state->options_out_len++] = option_type; |
1033 |
state->msg_out->options[state->options_out_len++] = option_len; |
state->msg_out->options[state->options_out_len++] = option_len; |
1034 |
} |
} |
1035 |
|
/* |
1036 |
|
* Concatenate a single byte to the outgoing DHCP message. |
1037 |
|
* |
1038 |
|
*/ |
1039 |
static void dhcp_option_byte(struct dhcp_state *state, u8_t value) |
static void dhcp_option_byte(struct dhcp_state *state, u8_t value) |
1040 |
{ |
{ |
1041 |
LWIP_ASSERT("dhcp_option_short: state->options_out_len < DHCP_OPTIONS_LEN", state->options_out_len < DHCP_OPTIONS_LEN); |
LWIP_ASSERT("dhcp_option_short: state->options_out_len < DHCP_OPTIONS_LEN", state->options_out_len < DHCP_OPTIONS_LEN); |
1059 |
/** |
/** |
1060 |
* Extract the dhcp_msg and options each into linear pieces of memory. |
* Extract the dhcp_msg and options each into linear pieces of memory. |
1061 |
* |
* |
1062 |
|
* |
1063 |
|
* |
1064 |
*/ |
*/ |
1065 |
static err_t dhcp_unfold_reply(struct dhcp_state *state) |
static err_t dhcp_unfold_reply(struct dhcp_state *state) |
1066 |
{ |
{ |
1070 |
u16_t j = 0; |
u16_t j = 0; |
1071 |
state->msg_in = NULL; |
state->msg_in = NULL; |
1072 |
state->options_in = NULL; |
state->options_in = NULL; |
1073 |
// options present? |
/* options present? */ |
1074 |
if (state->p->tot_len > sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN) |
if (state->p->tot_len > sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN) |
1075 |
{ |
{ |
1076 |
state->options_in_len = state->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); |
state->options_in_len = state->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); |
1091 |
} |
} |
1092 |
|
|
1093 |
ptr = (u8_t *)state->msg_in; |
ptr = (u8_t *)state->msg_in; |
1094 |
// proceed through struct dhcp_msg |
/* proceed through struct dhcp_msg */ |
1095 |
for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++) |
for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++) |
1096 |
{ |
{ |
1097 |
*ptr++ = ((u8_t *)p->payload)[j++]; |
*ptr++ = ((u8_t *)p->payload)[j++]; |
1098 |
// reached end of pbuf? |
/* reached end of pbuf? */ |
1099 |
if (j == p->len) |
if (j == p->len) |
1100 |
{ |
{ |
1101 |
// proceed to next pbuf in chain |
/* proceed to next pbuf in chain */ |
1102 |
p = p->next; |
p = p->next; |
1103 |
j = 0; |
j = 0; |
1104 |
} |
} |
1107 |
if (state->options_in != NULL) |
if (state->options_in != NULL) |
1108 |
{ |
{ |
1109 |
ptr = (u8_t *)state->options_in; |
ptr = (u8_t *)state->options_in; |
1110 |
// proceed through options |
/* proceed through options */ |
1111 |
for (i = 0; i < state->options_in_len; i++) |
for (i = 0; i < state->options_in_len; i++) |
1112 |
{ |
{ |
1113 |
*ptr++ = ((u8_t *)p->payload)[j++]; |
*ptr++ = ((u8_t *)p->payload)[j++]; |
1114 |
// reached end of pbuf? |
/* reached end of pbuf? */ |
1115 |
if (j == p->len) |
if (j == p->len) |
1116 |
{ |
{ |
1117 |
// proceed to next pbuf in chain |
/* proceed to next pbuf in chain */ |
1118 |
p = p->next; |
p = p->next; |
1119 |
j = 0; |
j = 0; |
1120 |
} |
} |
1125 |
} |
} |
1126 |
|
|
1127 |
/** |
/** |
1128 |
* Extract the dhcp_msg and options into linear pieces of memory. |
* Free the incoming DHCP message including contiguous copy of |
1129 |
|
* its DHCP options. |
1130 |
* |
* |
1131 |
*/ |
*/ |
1132 |
static void dhcp_free_reply(struct dhcp_state *state) |
static void dhcp_free_reply(struct dhcp_state *state) |