Check length of packet before decoding it (#168)
Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+86
-63
@@ -268,6 +268,14 @@ static bool bvlc_send_result(struct ip_addr *addr, uint16_t result_code)
|
|||||||
return bip_send_mpdu(addr, BIP_Port, pkt);
|
return bip_send_mpdu(addr, BIP_Port, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** LwIP BACnet service callback
|
||||||
|
*
|
||||||
|
* @param arg [in] optional argument from service
|
||||||
|
* @param upcb [in] UDP control block
|
||||||
|
* @param pkt [in] UDP packet - PBUF
|
||||||
|
* @param addr [in] UDP source address
|
||||||
|
* @param port [in] UDP port number
|
||||||
|
*/
|
||||||
void bip_server_callback(void *arg,
|
void bip_server_callback(void *arg,
|
||||||
struct udp_pcb *upcb,
|
struct udp_pcb *upcb,
|
||||||
struct pbuf *pkt,
|
struct pbuf *pkt,
|
||||||
@@ -283,73 +291,88 @@ void bip_server_callback(void *arg,
|
|||||||
uint8_t *pdu = (uint8_t *)pkt->payload;
|
uint8_t *pdu = (uint8_t *)pkt->payload;
|
||||||
|
|
||||||
/* the signature of a BACnet/IP packet */
|
/* the signature of a BACnet/IP packet */
|
||||||
if (pdu[0] != BVLL_TYPE_BACNET_IP) {
|
if ((pkt->tot_len >= 2) &&
|
||||||
return;
|
(pdu[0] == BVLL_TYPE_BACNET_IP)) {
|
||||||
}
|
function = pdu[1];
|
||||||
function = pdu[1];
|
if ((function == BVLC_ORIGINAL_UNICAST_NPDU) ||
|
||||||
if ((function == BVLC_ORIGINAL_UNICAST_NPDU) ||
|
(function == BVLC_ORIGINAL_BROADCAST_NPDU)) {
|
||||||
(function == BVLC_ORIGINAL_BROADCAST_NPDU)) {
|
/* ignore messages from me */
|
||||||
/* ignore messages from me */
|
if ((addr->addr == BIP_Address.s_addr) && (port == BIP_Port)) {
|
||||||
if ((addr->addr == BIP_Address.s_addr) && (port == BIP_Port)) {
|
pdu_len = 0;
|
||||||
pdu_len = 0;
|
} else if (pkt->tot_len >= 4) {
|
||||||
} else {
|
/* data in src->mac[] is in network format */
|
||||||
/* data in src->mac[] is in network format */
|
src.mac_len = 6;
|
||||||
src.mac_len = 6;
|
bip_addr_to_mac(&src.mac[0], addr);
|
||||||
bip_addr_to_mac(&src.mac[0], addr);
|
memcpy(&src.mac[4], &port, 2);
|
||||||
memcpy(&src.mac[4], &port, 2);
|
/* decode the length of the PDU
|
||||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
length is inclusive of BVLC */
|
||||||
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
||||||
/* subtract off the BVLC header */
|
if (pdu_len > pkt->tot_len) {
|
||||||
pdu_len -= 4;
|
/* BVLC length is too long - someone is lying */
|
||||||
pdu_offset = 4;
|
pdu_len = 0;
|
||||||
|
} else {
|
||||||
|
/* subtract off the BVLC header */
|
||||||
|
pdu_len -= 4;
|
||||||
|
pdu_offset = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (function == BVLC_FORWARDED_NPDU) {
|
||||||
|
if (pkt->tot_len >= 10) {
|
||||||
|
IP4_ADDR(&sin_addr, pdu[4], pdu[5], pdu[6], pdu[7]);
|
||||||
|
decode_unsigned16(&pdu[8], &sin_port);
|
||||||
|
if ((sin_addr.addr == BIP_Address.s_addr) &&
|
||||||
|
(sin_port == BIP_Port)) {
|
||||||
|
/* ignore forwarded messages from me */
|
||||||
|
pdu_len = 0;
|
||||||
|
} else {
|
||||||
|
/* data in src->mac[] is in network format */
|
||||||
|
src.mac_len = 6;
|
||||||
|
bip_addr_to_mac(&src.mac[0], &sin_addr);
|
||||||
|
memcpy(&src.mac[4], &sin_port, 2);
|
||||||
|
/* decode the length of the PDU
|
||||||
|
length is inclusive of BVLC */
|
||||||
|
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
||||||
|
if (pdu_len > pkt->tot_len) {
|
||||||
|
/* BVLC length is too long - someone is lying */
|
||||||
|
pdu_len = 0;
|
||||||
|
} else {
|
||||||
|
/* subtract off the BVLC header */
|
||||||
|
pdu_len -= 10;
|
||||||
|
pdu_offset = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (function == BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE) {
|
||||||
|
bvlc_send_result(
|
||||||
|
addr, BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||||
|
} else if (function == BVLC_READ_BROADCAST_DIST_TABLE) {
|
||||||
|
bvlc_send_result(
|
||||||
|
addr, BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||||
|
} else if (function == BVLC_REGISTER_FOREIGN_DEVICE) {
|
||||||
|
bvlc_send_result(addr, BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK);
|
||||||
|
} else if (function == BVLC_READ_FOREIGN_DEVICE_TABLE) {
|
||||||
|
bvlc_send_result(addr, BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
|
||||||
|
} else if (function == BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY) {
|
||||||
|
bvlc_send_result(
|
||||||
|
addr, BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
|
||||||
|
} else if (function == BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK) {
|
||||||
|
bvlc_send_result(addr, BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
|
||||||
}
|
}
|
||||||
} else if (function == BVLC_FORWARDED_NPDU) {
|
if (pdu_len) {
|
||||||
IP4_ADDR(&sin_addr, pdu[4], pdu[5], pdu[6], pdu[7]);
|
BIP_STATS_INC(recv);
|
||||||
decode_unsigned16(&pdu[8], &sin_port);
|
if ((function == BVLC_ORIGINAL_BROADCAST_NPDU) &&
|
||||||
if ((sin_addr.addr == BIP_Address.s_addr) && (sin_port == BIP_Port)) {
|
(npdu_confirmed_service(&pdu[pdu_offset], pdu_len))) {
|
||||||
/* ignore forwarded messages from me */
|
/* BTL test: verifies that the IUT will quietly discard any
|
||||||
pdu_len = 0;
|
Confirmed-Request-PDU, whose destination address is a
|
||||||
|
multicast or broadcast address, received from the
|
||||||
|
network layer. */
|
||||||
|
} else {
|
||||||
|
npdu_handler(&src, &pdu[pdu_offset], pdu_len);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* data in src->mac[] is in network format */
|
BIP_STATS_INC(rxdrop);
|
||||||
src.mac_len = 6;
|
|
||||||
bip_addr_to_mac(&src.mac[0], &sin_addr);
|
|
||||||
memcpy(&src.mac[4], &sin_port, 2);
|
|
||||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
|
||||||
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
|
||||||
/* subtract off the BVLC header */
|
|
||||||
pdu_len -= 10;
|
|
||||||
pdu_offset = 10;
|
|
||||||
}
|
}
|
||||||
} else if (function == BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE) {
|
|
||||||
bvlc_send_result(
|
|
||||||
addr, BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
|
||||||
} else if (function == BVLC_READ_BROADCAST_DIST_TABLE) {
|
|
||||||
bvlc_send_result(
|
|
||||||
addr, BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
|
||||||
} else if (function == BVLC_REGISTER_FOREIGN_DEVICE) {
|
|
||||||
bvlc_send_result(addr, BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK);
|
|
||||||
} else if (function == BVLC_READ_FOREIGN_DEVICE_TABLE) {
|
|
||||||
bvlc_send_result(addr, BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
|
|
||||||
} else if (function == BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY) {
|
|
||||||
bvlc_send_result(
|
|
||||||
addr, BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
|
|
||||||
} else if (function == BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK) {
|
|
||||||
bvlc_send_result(addr, BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
|
|
||||||
}
|
}
|
||||||
if (pdu_len) {
|
|
||||||
BIP_STATS_INC(recv);
|
|
||||||
npdu_handler(&src, &pdu[pdu_offset], pdu_len);
|
|
||||||
} else {
|
|
||||||
BIP_STATS_INC(drop);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* prepare for next packet */
|
|
||||||
udp_disconnect(upcb);
|
|
||||||
udp_bind(upcb, IP_ADDR_ANY, BIP_Port);
|
|
||||||
/* Set a receive callback for the upcb */
|
|
||||||
udp_recv(upcb, bip_server_callback, NULL);
|
|
||||||
#endif
|
|
||||||
/* free our packet */
|
/* free our packet */
|
||||||
pbuf_free(pkt);
|
pbuf_free(pkt);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user