summaryrefslogtreecommitdiff
path: root/gdhcp
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2012-05-03 16:28:40 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-05-04 12:53:14 +0300
commit1d1a22fe586a455935483708fbe8eaeada79df7f (patch)
treeaf62888249abb19a68ea75b277199985e23d6ccb /gdhcp
parenta5f540db7354b76bcabd0a05d8eb8ba2bff4e911 (diff)
downloadconnman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.gz
connman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.bz2
connman-1d1a22fe586a455935483708fbe8eaeada79df7f.zip
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 91c428c1..8d5c284b 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,