summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorStefan Brüns <stefan.bruens@rwth-aachen.de>2015-09-04 00:31:49 +0200
committerJoe Hershberger <joe.hershberger@ni.com>2015-10-29 14:05:45 -0500
commit774c3e05ec0a9c298e14681fb662c392842c2ced (patch)
tree5c9f682f1b18a786fe74e3764ea89355e42668a2 /net
parentec87b1b39b786cb61c5acc01542119663fb157c0 (diff)
net: parse DHCP options from overloaded file/sname fields
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>
Diffstat (limited to 'net')
-rw-r--r--net/bootp.c42
1 files 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;