From 30d69d68e331353af6721d265290dee7574de173 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Tue, 2 Feb 2010 18:26:40 +0000 Subject: [PATCH] Fix handling of zero-padding and parse file before sname field (if overloaded, according to the RFC) --- src/core/dhcp.c | 54 ++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/core/dhcp.c b/src/core/dhcp.c index 907ea044..ae7c80e7 100644 --- a/src/core/dhcp.c +++ b/src/core/dhcp.c @@ -1304,7 +1304,8 @@ dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) u16_t options_idx; u16_t options_idx_max; struct pbuf *q; - u8_t file_overloaded = 0; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; /* clear received options */ dhcp_clear_all_options(dhcp); @@ -1353,11 +1354,13 @@ again: /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ decode_len = len; switch(op) { + /* case(DHCP_OPTION_END): handled above */ case(DHCP_OPTION_PAD): /* special option: no len encoded */ decode_len = len = 0; /* will be increased below */ offset--; + break; case(DHCP_OPTION_SUBNET_MASK): LWIP_ASSERT("len == 4", len == 4); decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; @@ -1433,6 +1436,7 @@ decode_next: offset -= q->len; offset_max -= q->len; q = q->next; + options = (u8_t*)q->payload; } } /* is this an overloaded message? */ @@ -1440,38 +1444,42 @@ decode_next: u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); if (overload == DHCP_OVERLOAD_FILE) { - file_overloaded = 1; + parse_file_as_options = 1; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); - options_idx = DHCP_FILE_OFS; - options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; - goto again; } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); - options_idx = DHCP_SNAME_OFS; - options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; - goto again; } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { - file_overloaded = 1; + parse_sname_as_options = 1; + parse_file_as_options = 1; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); - /* @todo: parse file first and then sname (RFC 2131 ch. 4.1) */ - options_idx = DHCP_SNAME_OFS; - options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN + DHCP_FILE_LEN; - goto again; } else { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); } - } #if LWIP_DHCP_BOOTP_FILE - if (!file_overloaded) { - /* only do this for ACK messages */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && - (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) - /* copy bootp file name, don't care for sname (server hostname) */ - pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); - /* make sure the string is really NULL-terminated */ - dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; - } + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } #endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } return ERR_OK; }