This commit is contained in:
roy 2012-12-06 11:16:47 +00:00
parent b84abd3f0f
commit a6e5712818

View File

@ -253,7 +253,7 @@ int make_option_mask(uint8_t *mask, const char *opts, int add)
} }
static int static int
valid_length(uint8_t option, int dl, int *type) validate_length(uint8_t option, int dl, int *type)
{ {
const struct dhcp_opt *opt; const struct dhcp_opt *opt;
ssize_t sz; ssize_t sz;
@ -270,10 +270,13 @@ valid_length(uint8_t option, int dl, int *type)
if (opt->type == 0 || if (opt->type == 0 ||
opt->type & (STRING | RFC3442 | RFC5969)) opt->type & (STRING | RFC3442 | RFC5969))
return 0; return dl;
if (opt->type & IPV4 && opt->type & ARRAY) if (opt->type & IPV4 && opt->type & ARRAY) {
return (dl % sizeof(uint32_t) == 0 ? 0 : -1); if (dl < (int)sizeof(uint32_t))
return -1;
return dl - (dl % sizeof(uint32_t));
}
sz = 0; sz = 0;
if (opt->type & (UINT32 | IPV4)) if (opt->type & (UINT32 | IPV4))
@ -283,17 +286,20 @@ valid_length(uint8_t option, int dl, int *type)
if (opt->type & UINT8) if (opt->type & UINT8)
sz = sizeof(uint8_t); sz = sizeof(uint8_t);
/* If we don't know the size, assume it's valid */ /* If we don't know the size, assume it's valid */
return (sz == 0 || dl == sz ? 0 : -1); if (sz == 0)
return dl;
return (dl < sz ? -1 : sz);
} }
/* unknown option, so let it pass */ /* unknown option, so let it pass */
return 0; return dl;
} }
#ifdef DEBUG_MEMORY #ifdef DEBUG_MEMORY
static void static void
free_option_buffer(void) free_option_buffer(void)
{ {
free(opt_buffer); free(opt_buffer);
} }
#endif #endif
@ -309,7 +315,7 @@ get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
uint8_t overl = 0; uint8_t overl = 0;
uint8_t *bp = NULL; uint8_t *bp = NULL;
const uint8_t *op = NULL; const uint8_t *op = NULL;
int bl = 0; ssize_t bl = 0;
while (p < e) { while (p < e) {
o = *p++; o = *p++;
@ -358,7 +364,9 @@ get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
} }
exit: exit:
if (valid_length(opt, bl, type) == -1) {
bl = validate_length(opt, bl, type);
if (bl == -1) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
@ -431,10 +439,14 @@ get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
ssize_t ssize_t
decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p) decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p)
{ {
const char *start;
ssize_t start_len;
const uint8_t *r, *q = p; const uint8_t *r, *q = p;
int count = 0, l, hops; int count = 0, l, hops;
uint8_t ltype; uint8_t ltype;
start = out;
start_len = len;
while (q - p < pl) { while (q - p < pl) {
r = NULL; r = NULL;
hops = 0; hops = 0;
@ -474,15 +486,19 @@ decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p)
} }
} }
/* change last dot to space */ /* change last dot to space */
if (out) if (out && out != start)
*(out - 1) = ' '; *(out - 1) = ' ';
if (r) if (r)
q = r; q = r;
} }
/* change last space to zero terminator */ /* change last space to zero terminator */
if (out) if (out) {
*(out - 1) = 0; if (out != start)
*(out - 1) = '\0';
else if (start_len > 0)
*out = '\0';
}
return count; return count;
} }
@ -1177,7 +1193,7 @@ read_lease(const struct interface *iface)
return dhcp; return dhcp;
} }
static ssize_t ssize_t
print_string(char *s, ssize_t len, int dl, const uint8_t *data) print_string(char *s, ssize_t len, int dl, const uint8_t *data)
{ {
uint8_t c; uint8_t c;