size_t packet_len, in_buffer;
decode_fail_t reason;
+ /*
+ * We may hvae read multiple packets in the previous read. In which case the buffer may already
+ * have packets remaining. In that case, we can return packets directly from the buffer, and
+ * skip the read().
+ */
+ if (*leftover >= RADIUS_HEADER_LENGTH) {
+ packet_len = fr_nbo_to_uint16(buffer + 2);
+
+ if (packet_len <= *leftover) {
+ data_size = 0;
+ goto have_packet;
+ }
+
+ /*
+ * Else we don't have a full packet, try to read more data from the network.
+ */
+ }
+
/*
* Read data into the buffer.
*/
#endif
case EAGAIN:
/*
- * We didn't read any data leave the buffers alone.
+ * We didn't read any data; leave the buffers alone.
*
* i.e. if we had a partial packet in the buffer and we didn't read any data,
* then the partial packet is still left in the buffer.
break;
}
- PDEBUG2("proto_radius_tcp got read error %zd", data_size);
+ PDEBUG2("proto_radius_tcp got read error (%zd) - %s", data_size, fr_syserror(errno));
return data_size;
}
return -1;
}
+have_packet:
/*
* We MUST always start with a known RADIUS packet.
*/
/*
* Not enough for one packet. Tell the caller that we need to read more.
*/
- if (in_buffer < 20) {
+ if (in_buffer < RADIUS_HEADER_LENGTH) {
*leftover = in_buffer;
return 0;
}
ssize_t data_size, packet_len;
size_t in_buffer;
+ /*
+ * We may hvae read multiple packets in the previous read. In which case the buffer may already
+ * have packets remaining. In that case, we can return packets directly from the buffer, and
+ * skip the read().
+ */
+ if (*leftover >= FR_HEADER_LENGTH) {
+ packet_len = fr_tacacs_length(buffer, *leftover);
+ if (packet_len < 0) goto invalid;
+
+ if (packet_len <= *leftover) {
+ data_size = 0;
+ goto have_packet;
+ }
+
+ /*
+ * Else we don't have a full packet, try to read more data from the network.
+ */
+ }
+
/*
* Read data into the buffer.
*/
return -1;
}
+have_packet:
/*
* Represents all the data we've read since we last
* decoded a complete packet.
*/
packet_len = fr_tacacs_length(buffer, in_buffer);
if (packet_len < 0) {
+ invalid:
PERROR("Invalid TACACS packet");
return -1; /* Malformed, close the socket */
}