diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c index 4a6d091db..372ee2353 100644 --- a/netutils/dhcpc/dhcpc.c +++ b/netutils/dhcpc/dhcpc.c @@ -326,52 +326,98 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult, /* Get subnet mask in network order */ - memcpy(&presult->netmask.s_addr, optptr + 2, 4); + if (optptr + 6 <= end) + { + memcpy(&presult->netmask.s_addr, optptr + 2, 4); + } + else + { + nerr("Packet too short (netmask missing)\n"); + } break; case DHCP_OPTION_ROUTER: /* Get the default router address in network order */ - memcpy(&presult->default_router.s_addr, optptr + 2, 4); + if (optptr + 6 <= end) + { + memcpy(&presult->default_router.s_addr, optptr + 2, 4); + } + else + { + nerr("Packet too short (router address missing)\n"); + } break; case DHCP_OPTION_DNS_SERVER: /* Get the DNS server address in network order */ - memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4); + if (optptr + 6 <= end) + { + memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4); + } + else + { + nerr("Packet too short (DNS address missing)\n"); + } break; case DHCP_OPTION_MSG_TYPE: /* Get message type */ - type = *(optptr + 2); + if (optptr + 3 <= end) + { + type = *(optptr + 2); + } + else + { + nerr("Packet too short (type missing)\n"); + } break; case DHCP_OPTION_SERVER_ID: /* Get server address in network order */ - memcpy(&presult->serverid.s_addr, optptr + 2, 4); + if (optptr + 6 <= end) + { + memcpy(&presult->serverid.s_addr, optptr + 2, 4); + } + else + { + nerr("Packet too short (server address missing)\n"); + } break; case DHCP_OPTION_LEASE_TIME: - { + /* Get lease time (in seconds) in host order */ - uint16_t tmp[2]; - memcpy(tmp, optptr + 2, 4); - presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 | - (uint32_t)ntohs(tmp[1]); - } + if (optptr + 6 <= end) + { + uint16_t tmp[2]; + memcpy(tmp, optptr + 2, 4); + presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 | + (uint32_t)ntohs(tmp[1]); + } + else + { + nerr("Packet too short (lease time missing)\n"); + } break; case DHCP_OPTION_END: return type; } + if (optptr + 1 >= end) + { + break; + } + optptr += optptr[1] + 2; } @@ -385,13 +431,15 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult, static uint8_t dhcpc_parsemsg(FAR struct dhcpc_state_s *pdhcpc, int buflen, FAR struct dhcpc_state *presult) { - if (pdhcpc->packet.op == DHCP_REPLY && + if (buflen >= 44 && pdhcpc->packet.op == DHCP_REPLY && memcmp(pdhcpc->packet.xid, xid, sizeof(xid)) == 0 && memcmp(pdhcpc->packet.chaddr, pdhcpc->ds_macaddr, pdhcpc->ds_maclen) == 0) { memcpy(&presult->ipaddr.s_addr, pdhcpc->packet.yiaddr, 4); - return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4], buflen); + return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4], + buflen - + (offsetof(struct dhcp_msg, options) + 4)); } return 0;