|
|
|
@ -125,61 +125,88 @@ static void PayloadAsHex(const uint8_t *data, uint32_t data_len, char *str, size
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void FrameAddPayloadTCP(JsonBuilder *js, const TcpStream *stream, const Frame *frame)
|
|
|
|
|
struct FrameJsonStreamDataCallbackData {
|
|
|
|
|
MemBuffer *payload;
|
|
|
|
|
const Frame *frame;
|
|
|
|
|
uint64_t last_re; /**< used to detect gaps */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int FrameJsonStreamDataCallback(
|
|
|
|
|
void *cb_data, const uint8_t *input, const uint32_t input_len, const uint64_t input_offset)
|
|
|
|
|
{
|
|
|
|
|
uint32_t sb_data_len = 0;
|
|
|
|
|
const uint8_t *data = NULL;
|
|
|
|
|
uint64_t data_offset = 0;
|
|
|
|
|
struct FrameJsonStreamDataCallbackData *cbd = cb_data;
|
|
|
|
|
const Frame *frame = cbd->frame;
|
|
|
|
|
|
|
|
|
|
// TODO consider ACK'd
|
|
|
|
|
uint32_t write_size = input_len;
|
|
|
|
|
int done = 0;
|
|
|
|
|
|
|
|
|
|
if (frame->offset < STREAM_BASE_OFFSET(stream)) {
|
|
|
|
|
if (StreamingBufferGetData(&stream->sb, &data, &sb_data_len, &data_offset) == 0) {
|
|
|
|
|
SCLogDebug("NO DATA1");
|
|
|
|
|
return;
|
|
|
|
|
if (frame->len >= 0) {
|
|
|
|
|
const uint64_t data_re = input_offset + input_len;
|
|
|
|
|
const uint64_t frame_re = frame->offset + (uint64_t)frame->len;
|
|
|
|
|
|
|
|
|
|
/* data entirely after frame, we're done */
|
|
|
|
|
if (input_offset >= frame_re) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
data_offset = (uint64_t)frame->offset;
|
|
|
|
|
SCLogDebug("data_offset %" PRIu64, data_offset);
|
|
|
|
|
if (StreamingBufferGetDataAtOffset(
|
|
|
|
|
&stream->sb, &data, &sb_data_len, (uint64_t)data_offset) == 0) {
|
|
|
|
|
SCLogDebug("NO DATA1");
|
|
|
|
|
return;
|
|
|
|
|
/* make sure to only log data belonging to the frame */
|
|
|
|
|
if (data_re >= frame_re) {
|
|
|
|
|
const uint64_t to_write = frame_re - input_offset;
|
|
|
|
|
if (to_write < (uint64_t)write_size) {
|
|
|
|
|
write_size = (uint32_t)to_write;
|
|
|
|
|
}
|
|
|
|
|
done = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (data == NULL || sb_data_len == 0) {
|
|
|
|
|
SCLogDebug("NO DATA2");
|
|
|
|
|
return;
|
|
|
|
|
if (input_offset > cbd->last_re) {
|
|
|
|
|
MemBufferWriteString(
|
|
|
|
|
cbd->payload, "[%" PRIu64 " bytes missing]", input_offset - cbd->last_re);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frame->len >= 0) {
|
|
|
|
|
sb_data_len = MIN(frame->len, (int32_t)sb_data_len);
|
|
|
|
|
if (write_size > 0) {
|
|
|
|
|
MemBufferWriteRaw(cbd->payload, input, write_size);
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("frame data_offset %" PRIu64 ", data_len %u frame len %" PRIi64, data_offset,
|
|
|
|
|
sb_data_len, frame->len);
|
|
|
|
|
cbd->last_re = input_offset + write_size;
|
|
|
|
|
return done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \internal
|
|
|
|
|
* \brief try to log frame's stream data into payload/payload_printable
|
|
|
|
|
*/
|
|
|
|
|
static void FrameAddPayloadTCP(Flow *f, const TcpSession *ssn, const TcpStream *stream,
|
|
|
|
|
const Frame *frame, JsonBuilder *jb, MemBuffer *buffer)
|
|
|
|
|
{
|
|
|
|
|
MemBufferReset(buffer);
|
|
|
|
|
|
|
|
|
|
/* consider all data, ACK'd and non-ACK'd */
|
|
|
|
|
const uint64_t stream_data_re = StreamDataRightEdge(stream, true);
|
|
|
|
|
bool complete = false;
|
|
|
|
|
if (frame->len > 0) {
|
|
|
|
|
const uint64_t frame_re = frame->offset + (uint64_t)frame->len;
|
|
|
|
|
const uint64_t data_re = data_offset + sb_data_len;
|
|
|
|
|
complete = frame_re <= data_re;
|
|
|
|
|
if (frame->len >= 0 && frame->offset + (uint64_t)frame->len <= stream_data_re) {
|
|
|
|
|
complete = true;
|
|
|
|
|
}
|
|
|
|
|
jb_set_bool(js, "complete", complete);
|
|
|
|
|
|
|
|
|
|
uint32_t data_len = MIN(sb_data_len, 256);
|
|
|
|
|
jb_set_base64(js, "payload", data, data_len);
|
|
|
|
|
struct FrameJsonStreamDataCallbackData cbd = {
|
|
|
|
|
.payload = buffer, .frame = frame, .last_re = frame->offset
|
|
|
|
|
};
|
|
|
|
|
uint64_t unused = 0;
|
|
|
|
|
StreamReassembleLog(
|
|
|
|
|
ssn, stream, FrameJsonStreamDataCallback, &cbd, frame->offset, &unused, false);
|
|
|
|
|
/* if we have all data, but didn't log until the end of the frame, we have a gap at the
|
|
|
|
|
* end of the frame
|
|
|
|
|
* TODO what about not logging due to buffer full? */
|
|
|
|
|
if (complete && frame->len >= 0 && cbd.last_re < frame->offset + (uint64_t)frame->len) {
|
|
|
|
|
MemBufferWriteString(cbd.payload, "[%" PRIu64 " bytes missing]",
|
|
|
|
|
(frame->offset + (uint64_t)frame->len) - cbd.last_re);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t printable_buf[data_len + 1];
|
|
|
|
|
uint32_t o = 0;
|
|
|
|
|
PrintStringsToBuffer(printable_buf, &o, data_len + 1, data, data_len);
|
|
|
|
|
printable_buf[data_len] = '\0';
|
|
|
|
|
jb_set_string(js, "payload_printable", (char *)printable_buf);
|
|
|
|
|
#if 0
|
|
|
|
|
char pretty_buf[data_len * 4 + 1];
|
|
|
|
|
pretty_buf[0] = '\0';
|
|
|
|
|
PayloadAsHex(data, data_len, pretty_buf, data_len * 4 + 1);
|
|
|
|
|
jb_set_string(js, "payload_hex", pretty_buf);
|
|
|
|
|
#endif
|
|
|
|
|
if (cbd.payload->offset) {
|
|
|
|
|
jb_set_base64(jb, "payload", cbd.payload->buffer, cbd.payload->offset);
|
|
|
|
|
uint8_t printable_buf[cbd.payload->offset + 1];
|
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
PrintStringsToBuffer(printable_buf, &offset, sizeof(printable_buf), cbd.payload->buffer,
|
|
|
|
|
cbd.payload->offset);
|
|
|
|
|
jb_set_string(jb, "payload_printable", (char *)printable_buf);
|
|
|
|
|
jb_set_bool(jb, "complete", complete);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void FrameAddPayloadUDP(JsonBuilder *js, const Packet *p, const Frame *frame)
|
|
|
|
@ -223,7 +250,7 @@ static void FrameAddPayloadUDP(JsonBuilder *js, const Packet *p, const Frame *fr
|
|
|
|
|
/** \brief log a single frame
|
|
|
|
|
* \note ipproto argument is passed to assist static code analyzers
|
|
|
|
|
*/
|
|
|
|
|
void FrameJsonLogOneFrame(const uint8_t ipproto, const Frame *frame, const Flow *f,
|
|
|
|
|
void FrameJsonLogOneFrame(const uint8_t ipproto, const Frame *frame, Flow *f,
|
|
|
|
|
const TcpStream *stream, const Packet *p, JsonBuilder *jb, MemBuffer *buffer)
|
|
|
|
|
{
|
|
|
|
|
DEBUG_VALIDATE_BUG_ON(ipproto != p->proto);
|
|
|
|
@ -249,7 +276,7 @@ void FrameJsonLogOneFrame(const uint8_t ipproto, const Frame *frame, const Flow
|
|
|
|
|
} else {
|
|
|
|
|
jb_set_uint(jb, "length", frame->len);
|
|
|
|
|
}
|
|
|
|
|
FrameAddPayloadTCP(jb, stream, frame);
|
|
|
|
|
FrameAddPayloadTCP(f, f->protoctx, stream, frame, jb, buffer);
|
|
|
|
|
} else {
|
|
|
|
|
jb_set_uint(jb, "length", frame->len);
|
|
|
|
|
FrameAddPayloadUDP(jb, p, frame);
|
|
|
|
|