summaryrefslogtreecommitdiff
path: root/gdhcp
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2012-05-03 13:28:40 (GMT)
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-05-04 09:53:14 (GMT)
commit1d1a22fe586a455935483708fbe8eaeada79df7f (patch)
treeaf62888249abb19a68ea75b277199985e23d6ccb /gdhcp
parenta5f540db7354b76bcabd0a05d8eb8ba2bff4e911 (diff)
downloadconnman-1d1a22fe586a455935483708fbe8eaeada79df7f.zip
connman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.gz
connman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.bz2
gdhcp: Fix packet length checking
Fix packet length checking where payload length could have been zero. Also check that we don't set the option pointer beyond the end of the packet payload.
Diffstat (limited to 'gdhcp')
-rw-r--r--gdhcp/common.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/gdhcp/common.c b/gdhcp/common.c
index 91c428c..8d5c284 100644
--- a/gdhcp/common.c
+++ b/gdhcp/common.c
@@ -155,14 +155,16 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
rem = pkt_len - 1 - 3;
if (rem <= 0)
- /* Bad packet */
- return NULL;
+ goto bad_packet;
while (1) {
opt_code = optionptr[0] << 8 | optionptr[1];
opt_len = len = optionptr[2] << 8 | optionptr[3];
len += 2 + 2; /* skip code and len */
+ if (len < 4)
+ goto bad_packet;
+
rem -= len;
if (rem < 0)
break;
@@ -170,7 +172,10 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
if (opt_code == code) {
if (option_len != NULL)
*option_len = opt_len;
- found = optionptr + 2 + 2;
+ if (rem == 0)
+ found = NULL;
+ else
+ found = optionptr + 2 + 2;
count++;
}
@@ -184,6 +189,13 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
*option_count = count;
return found;
+
+bad_packet:
+ if (option_len != NULL)
+ *option_len = 0;
+ if (option_count != NULL)
+ *option_count = 0;
+ return NULL;
}
uint8_t *dhcpv6_get_sub_option(unsigned char *option, uint16_t max_len,