diff options
author | Shao Miller <shao.miller@yrdsb.edu.on.ca> | 2009-10-22 16:51:43 -0400 |
---|---|---|
committer | Marty Connor <mdc@etherboot.org> | 2010-01-14 11:14:24 -0500 |
commit | cf5e79adc952fc514bb280482fdc59e7deda8023 (patch) | |
tree | 1673dec8db5c2e0482dc9cd793a3d039b6d93f5b | |
parent | 9de525c34cad0252fe6ff823ee7e18240e472298 (diff) | |
download | ipxe-cf5e79adc952fc514bb280482fdc59e7deda8023.tar.gz |
[dhcp] Append new DHCP options versus prepend
Change the behaviour for adding DHCP options into a DHCP packet so
that we now append options, rather than insert them in front of
whatever options might already be present.
Apparently, the DHCP relay logic on a Nortel 470-48T layer 2 switch
cares about the order of DHCP options. If we build a DHCP packet
pre-populated with some options, their order will now be preserved,
except for encapsulated options.
Signed-off-by: Marty Connor <mdc@etherboot.org>
-rw-r--r-- | src/net/dhcpopts.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/net/dhcpopts.c b/src/net/dhcpopts.c index c1940f1f5..6482c627b 100644 --- a/src/net/dhcpopts.c +++ b/src/net/dhcpopts.c @@ -103,7 +103,7 @@ static unsigned int dhcp_option_len ( struct dhcp_option *option ) { * DHCP option block. Encapsulated options may be searched for by * using DHCP_ENCAP_OPT() to construct the tag value. * - * If the option is encapsulated, and @c encapsulator is non-NULL, it + * If the option is encapsulated, and @c encap_offset is non-NULL, it * will be filled in with the offset of the encapsulating option. * * This routine is designed to be paranoid. It does not assume that @@ -136,8 +136,15 @@ static int find_dhcp_option_with_encap ( struct dhcp_options *options, if ( remaining < 0 ) break; /* Check for explicit end marker */ - if ( option->tag == DHCP_END ) - break; + if ( option->tag == DHCP_END ) { + if ( tag == DHCP_END ) + /* Special case where the caller is interested + * in whether we have this marker or not. + */ + return offset; + else + break; + } /* Check for matching tag */ if ( option->tag == tag ) { DBGC ( options, "DHCPOPT %p found %s (length %d)\n", @@ -256,7 +263,7 @@ static int set_dhcp_option ( struct dhcp_options *options, unsigned int tag, static const uint8_t empty_encapsulator[] = { DHCP_END }; int offset; int encap_offset = -1; - int creation_offset = 0; + int creation_offset; struct dhcp_option *option; unsigned int encap_tag = DHCP_ENCAPSULATOR ( tag ); size_t old_len = 0; @@ -267,6 +274,10 @@ static int set_dhcp_option ( struct dhcp_options *options, unsigned int tag, if ( tag == DHCP_PAD ) return -ENOTTY; + creation_offset = find_dhcp_option_with_encap ( options, DHCP_END, + NULL ); + if ( creation_offset < 0 ) + creation_offset = options->len; /* Find old instance of this option, if any */ offset = find_dhcp_option_with_encap ( options, tag, &encap_offset ); if ( offset >= 0 ) { |