udhcpc: fix 6rd option formatting (was using 4 more bytes than there is)

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2011-10-20 12:29:18 +02:00
parent 42816c204d
commit 1dff672335

View File

@ -161,8 +161,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
int len, type, optlen; int len, type, optlen;
char *dest, *ret; char *dest, *ret;
/* option points to OPT_DATA, need to go back and get OPT_LEN */ /* option points to OPT_DATA, need to go back to get OPT_LEN */
len = option[OPT_LEN - OPT_DATA]; len = option[-OPT_DATA + OPT_LEN];
type = optflag->flags & OPTION_TYPE_MASK; type = optflag->flags & OPTION_TYPE_MASK;
optlen = dhcp_option_lengths[type]; optlen = dhcp_option_lengths[type];
@ -252,39 +252,29 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
return ret; return ret;
} }
case OPTION_6RD: { case OPTION_6RD:
/* Option binary format (see RFC 5969): /* Option binary format (see RFC 5969):
* 0 1 2 3 * 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen | * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | 6rdPrefix | * | 6rdPrefix |
* | (16 octets) | * ... (16 octets) ...
* | |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 6rdBRIPv4Address(es) | * ... 6rdBRIPv4Address(es) ...
* . .
* . .
* . .
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* We convert it to a string * We convert it to a string
* "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..." * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..."
*/ *
* Sanity check: ensure that our length is at least 22 bytes, that
/* Sanity check: ensure that our length is at least 22 bytes, that
* IPv4MaskLen <= 32, * IPv4MaskLen <= 32,
* 6rdPrefixLen <= 128, * 6rdPrefixLen <= 128,
* 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128
* (2nd condition need no check - it follows from 1st and 3rd). * (2nd condition need no check - it follows from 1st and 3rd).
* If any of these requirements is not fulfilled, return with empty * Else, return envvar with empty value ("optname=")
* value.
*/ */
if (len >= 22 if (len >= (1 + 1 + 16 + 4)
&& option[0] <= 32 && option[0] <= 32
&& (option[1] + 32 - option[0]) <= 128 && (option[1] + 32 - option[0]) <= 128
) { ) {
@ -295,19 +285,20 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
/* 6rdPrefix */ /* 6rdPrefix */
dest += sprint_nip6(dest, /* "", */ option); dest += sprint_nip6(dest, /* "", */ option);
option += 16; option += 16;
len -= 1 + 1 + 16; len -= 1 + 1 + 16 + 4;
/* 6rdBRIPv4Address(es) */ /* "+ 4" above corresponds to the length of IPv4 addr
* we consume in the loop below */
while (1) { while (1) {
/* 6rdBRIPv4Address(es) */
dest += sprint_nip(dest, " ", option); dest += sprint_nip(dest, " ", option);
option += 4; option += 4;
len -= 4; len -= 4; /* do we have yet another 4+ bytes? */
if (len < 0) if (len < 0)
break; break; /* no */
} }
} }
return ret; return ret;
}
#if ENABLE_FEATURE_UDHCP_RFC3397 #if ENABLE_FEATURE_UDHCP_RFC3397
case OPTION_DNS_STRING: case OPTION_DNS_STRING:
/* unpack option into dest; use ret for prefix (i.e., "optname=") */ /* unpack option into dest; use ret for prefix (i.e., "optname=") */
@ -347,6 +338,10 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
return ret; return ret;
#endif #endif
} /* switch */ } /* switch */
/* If we are here, try to format any remaining data
* in the option as another, similarly-formatted option
*/
option += optlen; option += optlen;
len -= optlen; len -= optlen;
// TODO: it can be a list only if (optflag->flags & OPTION_LIST). // TODO: it can be a list only if (optflag->flags & OPTION_LIST).
@ -356,7 +351,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
break; break;
*dest++ = ' '; *dest++ = ' ';
*dest = '\0'; *dest = '\0';
} } /* while */
return ret; return ret;
} }