From 774c3e05ec0a9c298e14681fb662c392842c2ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= Date: Fri, 4 Sep 2015 00:31:49 +0200 Subject: net: parse DHCP options from overloaded file/sname fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Option 52 in the vendor option field signals overloading of the file and/or sname fields, these field may contain additional options. Formatting of file/sname contained options is the same as in the vendor options field, but without the leading magic. Signed-off-by: Stefan BrĂ¼ns Acked-by: Joe Hershberger --- net/bootp.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/net/bootp.c b/net/bootp.c index 9cf0d64025..8aeddb08ea 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -773,14 +773,12 @@ void bootp_request(void) } #if defined(CONFIG_CMD_DHCP) -static void dhcp_process_options(uchar *popt, struct bootp_hdr *bp) +static void dhcp_process_options(uchar *popt, uchar *end) { - uchar *end = popt + BOOTP_HDR_SIZE; int oplen, size; #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) int *to_ptr; #endif - dhcp_option_overload = 0; while (popt < end && *popt != 0xff) { oplen = *(popt + 1); @@ -865,6 +863,35 @@ static void dhcp_process_options(uchar *popt, struct bootp_hdr *bp) } } +static void dhcp_packet_process_options(struct bootp_hdr *bp) +{ + uchar *popt = (uchar *)&bp->bp_vend[4]; + uchar *end = popt + BOOTP_HDR_SIZE; + + if (net_read_u32((u32 *)&bp->bp_vend[0]) != htonl(BOOTP_VENDOR_MAGIC)) + return; + + dhcp_option_overload = 0; + + /* + * The 'options' field MUST be interpreted first, 'file' next, + * 'sname' last. + */ + dhcp_process_options(popt, end); + + if (dhcp_option_overload & OVERLOAD_FILE) { + popt = (uchar *)bp->bp_file; + end = popt + sizeof(bp->bp_file); + dhcp_process_options(popt, end); + } + + if (dhcp_option_overload & OVERLOAD_SNAME) { + popt = (uchar *)bp->bp_sname; + end = popt + sizeof(bp->bp_sname); + dhcp_process_options(popt, end); + } +} + static int dhcp_message_type(unsigned char *popt) { if (net_read_u32((u32 *)popt) != htonl(BOOTP_VENDOR_MAGIC)) @@ -982,14 +1009,11 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, CONFIG_SYS_BOOTFILE_PREFIX, strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) { #endif /* CONFIG_SYS_BOOTFILE_PREFIX */ + dhcp_packet_process_options(bp); debug("TRANSITIONING TO REQUESTING STATE\n"); dhcp_state = REQUESTING; - if (net_read_u32((u32 *)&bp->bp_vend[0]) == - htonl(BOOTP_VENDOR_MAGIC)) - dhcp_process_options((u8 *)&bp->bp_vend[4], bp); - net_set_timeout_handler(5000, bootp_timeout_handler); dhcp_send_request_packet(bp); #ifdef CONFIG_SYS_BOOTFILE_PREFIX @@ -1002,9 +1026,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, debug("DHCP State: REQUESTING\n"); if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) { - if (net_read_u32((u32 *)&bp->bp_vend[0]) == - htonl(BOOTP_VENDOR_MAGIC)) - dhcp_process_options((u8 *)&bp->bp_vend[4], bp); + dhcp_packet_process_options(bp); /* Store net params from reply */ store_net_params(bp); dhcp_state = BOUND; -- cgit v1.2.1