]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
net: parse DHCP options from overloaded file/sname fields
authorStefan Brüns <stefan.bruens@rwth-aachen.de>
Thu, 3 Sep 2015 22:31:49 +0000 (00:31 +0200)
committerJoe Hershberger <joe.hershberger@ni.com>
Thu, 29 Oct 2015 19:05:45 +0000 (14:05 -0500)
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 <stefan.bruens@rwth-aachen.de>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
net/bootp.c

index 9cf0d640259b9545d3bc002e03265f2a2918befb..8aeddb08ea83f0bf1094d9cb72938df4357801dc 100644 (file)
@@ -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;