PcapLogThreadData *td, PcapLogCompressionData *connp, const Packet *p)
{
uint8_t flag;
- /* check which side is packet */
- if (p->flowflags & FLOW_PKT_TOSERVER) {
- flag = STREAM_DUMP_TOCLIENT;
- } else {
- flag = STREAM_DUMP_TOSERVER;
- }
- flag |= STREAM_DUMP_HEADERS;
+ flag = STREAM_DUMP_HEADERS;
/* Loop on segment from this side */
struct PcapLogCallbackContext data = { td->pcap_log, connp, td->buf };
- StreamSegmentForEach(p, flag, PcapLogSegmentCallback, (void *)&data);
+ StreamSegmentForSession(p, flag, PcapLogSegmentCallback, (void *)&data);
}
/**
#else
PcapLogDumpSegments(td, NULL, p);
#endif
+ /* PcapLogDumpSegment has writtens over the PcapLogData variables so need to update */
+ pl->h->ts.tv_sec = p->ts.tv_sec;
+ pl->h->ts.tv_usec = p->ts.tv_usec;
+ if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ rp = p->root;
+ SCMutexLock(&rp->tunnel_mutex);
+ pl->h->caplen = GET_PKT_LEN(rp);
+ pl->h->len = GET_PKT_LEN(rp);
+ len = sizeof(*pl->h) + GET_PKT_LEN(rp);
+ SCMutexUnlock(&rp->tunnel_mutex);
+ } else {
+ pl->h->caplen = GET_PKT_LEN(p);
+ pl->h->len = GET_PKT_LEN(p);
+ len = sizeof(*pl->h) + GET_PKT_LEN(p);
+ }
}
}
}
/**
- * \brief Run callback function on each TCP segment
+ * \brief Run callback function on each TCP segment in a single direction.
*
* \note when stream engine is running in inline mode all segments are used,
* in IDS/non-inline mode only ack'd segments are iterated.
*
* \note Must be called under flow lock.
+ * \var flag determines the direction to run callback on (either to server or to client).
*
* \return -1 in case of error, the number of segment in case of success
*
return cnt;
}
+/**
+ * \brief Run callback function on each TCP segment in both directions of a session.
+ *
+ * \note when stream engine is running in inline mode all segments are used,
+ * in IDS/non-inline mode only ack'd segments are iterated.
+ *
+ * \note Must be called under flow lock.
+ *
+ * \return -1 in case of error, the number of segment in case of success
+ *
+ */
+int StreamTcpSegmentForSession(
+ const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
+{
+ int ret = 0;
+ int cnt = 0;
+
+ if (p->flow == NULL)
+ return 0;
+
+ TcpSession *ssn = (TcpSession *)p->flow->protoctx;
+
+ if (ssn == NULL) {
+ return -1;
+ }
+
+ TcpStream *server_stream = &(ssn->server);
+ TcpStream *client_stream = &(ssn->client);
+
+ TcpSegment *server_node = RB_ROOT(&(server_stream->seg_tree));
+ TcpSegment *client_node = RB_ROOT(&(client_stream->seg_tree));
+ if (server_node == NULL && client_node == NULL) {
+ return cnt;
+ }
+
+ while (server_node != NULL || client_node != NULL) {
+ const uint8_t *seg_data;
+ uint32_t seg_datalen;
+ if (server_node == NULL) {
+ /*
+ * This means the server side RB Tree has been completely searched,
+ * thus all that remains is to dump the TcpSegments on the client
+ * side.
+ */
+ StreamingBufferSegmentGetData(
+ &client_stream->sb, &client_node->sbseg, &seg_data, &seg_datalen);
+ ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
+ if (ret != 1) {
+ SCLogDebug("Callback function has failed");
+ return -1;
+ }
+ client_node = TCPSEG_RB_NEXT(client_node);
+ } else if (client_node == NULL) {
+ /*
+ * This means the client side RB Tree has been completely searched,
+ * thus all that remains is to dump the TcpSegments on the server
+ * side.
+ */
+ StreamingBufferSegmentGetData(
+ &server_stream->sb, &server_node->sbseg, &seg_data, &seg_datalen);
+ ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
+ if (ret != 1) {
+ SCLogDebug("Callback function has failed");
+ return -1;
+ }
+ server_node = TCPSEG_RB_NEXT(server_node);
+ } else {
+ if (TIMEVAL_EARLIER(
+ client_node->pcap_hdr_storage->ts, server_node->pcap_hdr_storage->ts)) {
+ StreamingBufferSegmentGetData(
+ &client_stream->sb, &client_node->sbseg, &seg_data, &seg_datalen);
+ ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
+ if (ret != 1) {
+ SCLogDebug("Callback function has failed");
+ return -1;
+ }
+ client_node = TCPSEG_RB_NEXT(client_node);
+ } else {
+ StreamingBufferSegmentGetData(
+ &server_stream->sb, &server_node->sbseg, &seg_data, &seg_datalen);
+ ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
+ if (ret != 1) {
+ SCLogDebug("Callback function has failed");
+ return -1;
+ }
+ server_node = TCPSEG_RB_NEXT(server_node);
+ }
+ }
+
+ cnt++;
+ }
+ return cnt;
+}
+
int StreamTcpBypassEnabled(void)
{
return (stream_config.flags & STREAMTCP_INIT_FLAG_BYPASS);
#include "stream-tcp.h"
#include "flow-util.h"
-/** \brief Run callback for all segments
+/** \brief Run callback for all segments in a single direction.
*
* Must be called under flow lock.
+ * \var flag determines the direction to run callback on (either to server or to client).
*
* \return -1 in case of error, the number of segment in case of success
*/
}
return 0;
}
+
+/** \brief Run callback for all segments on both directions of the session
+ *
+ * Must be called under flow lock.
+ *
+ * \return -1 in case of error, the number of segments in case of success.
+ */
+int StreamSegmentForSession(
+ const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
+{
+ switch (p->proto) {
+ case IPPROTO_TCP:
+ return StreamTcpSegmentForSession(p, flag, CallbackFunc, data);
+ break;
+#ifdef DEBUG
+ case IPPROTO_UDP:
+ SCLogWarning(SC_ERR_UNKNOWN_PROTOCOL, "UDP is currently unsupported");
+ break;
+ default:
+ SCLogWarning(SC_ERR_UNKNOWN_PROTOCOL, "This protocol is currently unsupported");
+ break;
+#endif
+ }
+ return 0;
+}