/** \brief Create a pseudo packet injected into the engine to signal the
* opposing direction of this stream trigger detection/logging.
*
- * \param p real packet
+ * \param parent real packet
* \param pq packet queue to store the new pseudo packet in
* \param dir 0 ts 1 tc
*/
static void StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars *tv,
- StreamTcpThread *stt, Packet *p, TcpSession *ssn, PacketQueue *pq, bool dir)
+ StreamTcpThread *stt, Packet *parent,
+ TcpSession *ssn, PacketQueue *pq, int dir)
{
SCEnter();
+ Flow *f = parent->flow;
- if (p->flags & PKT_PSEUDO_DETECTLOG_FLUSH) {
+ if (parent->flags & PKT_PSEUDO_DETECTLOG_FLUSH) {
SCReturn;
}
- Packet *np = StreamTcpPseudoSetup(p, GET_PKT_DATA(p), GET_PKT_LEN(p));
+ Packet *np = PacketPoolGetPacket();
if (np == NULL) {
- SCLogDebug("The packet received from packet allocation is NULL");
- StatsIncr(tv, stt->counter_tcp_pseudo_failed);
SCReturn;
}
PKT_SET_SRC(np, PKT_SRC_STREAM_TCP_DETECTLOG_FLUSH);
- /* Setup the IP and TCP headers */
- StreamTcpPseudoPacketSetupHeader(np,p);
-
- np->tenant_id = p->flow->tenant_id;
- np->flowflags = p->flowflags;
-
+ np->tenant_id = f->tenant_id;
+ np->datalink = DLT_RAW;
+ np->proto = IPPROTO_TCP;
+ FlowReference(&np->flow, f);
np->flags |= PKT_STREAM_EST;
np->flags |= PKT_HAS_FLOW;
np->flags |= PKT_IGNORE_CHECKSUM;
np->flags |= PKT_PSEUDO_DETECTLOG_FLUSH;
- if (p->flags & PKT_NOPACKET_INSPECTION) {
+ if (f->flags & FLOW_NOPACKET_INSPECTION) {
DecodeSetNoPacketInspectionFlag(np);
}
- if (p->flags & PKT_NOPAYLOAD_INSPECTION) {
+ if (f->flags & FLOW_NOPAYLOAD_INSPECTION) {
DecodeSetNoPayloadInspectionFlag(np);
}
- if (dir == false) {
+ if (dir == 0) {
+ SCLogDebug("pseudo is to_server");
+ np->flowflags |= FLOW_PKT_TOSERVER;
+ } else {
SCLogDebug("pseudo is to_client");
- np->flowflags &= ~(FLOW_PKT_TOSERVER|FLOW_PKT_TOCLIENT);
np->flowflags |= FLOW_PKT_TOCLIENT;
-#ifdef DEBUG
- BUG_ON(!(PKT_IS_TOCLIENT(np)));
- BUG_ON((PKT_IS_TOSERVER(np)));
-#endif
+ }
+ np->flowflags |= FLOW_PKT_ESTABLISHED;
+ np->payload = NULL;
+ np->payload_len = 0;
+
+ if (FLOW_IS_IPV4(f)) {
+ if (dir == 0) {
+ FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->src);
+ FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->dst);
+ np->sp = f->sp;
+ np->dp = f->dp;
+ } else {
+ FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->dst);
+ FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->src);
+ np->sp = f->dp;
+ np->dp = f->sp;
+ }
+
+ /* Check if we have enough room in direct data. We need ipv4 hdr + tcp hdr.
+ * Force an allocation if it is not the case.
+ */
+ if (GET_PKT_DIRECT_MAX_SIZE(np) < 40) {
+ if (PacketCallocExtPkt(np, 40) == -1) {
+ goto error;
+ }
+ }
+ /* set the ip header */
+ np->ip4h = (IPV4Hdr *)GET_PKT_DATA(np);
+ /* version 4 and length 20 bytes for the tcp header */
+ np->ip4h->ip_verhl = 0x45;
+ np->ip4h->ip_tos = 0;
+ np->ip4h->ip_len = htons(40);
+ np->ip4h->ip_id = 0;
+ np->ip4h->ip_off = 0;
+ np->ip4h->ip_ttl = 64;
+ np->ip4h->ip_proto = IPPROTO_TCP;
+ if (dir == 0) {
+ np->ip4h->s_ip_src.s_addr = f->src.addr_data32[0];
+ np->ip4h->s_ip_dst.s_addr = f->dst.addr_data32[0];
+ } else {
+ np->ip4h->s_ip_src.s_addr = f->dst.addr_data32[0];
+ np->ip4h->s_ip_dst.s_addr = f->src.addr_data32[0];
+ }
+
+ /* set the tcp header */
+ np->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(np) + 20);
+
+ SET_PKT_LEN(np, 40); /* ipv4 hdr + tcp hdr */
+
+ } else if (FLOW_IS_IPV6(f)) {
+ if (dir == 0) {
+ FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->src);
+ FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->dst);
+ np->sp = f->sp;
+ np->dp = f->dp;
+ } else {
+ FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->dst);
+ FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->src);
+ np->sp = f->dp;
+ np->dp = f->sp;
+ }
+
+ /* Check if we have enough room in direct data. We need ipv6 hdr + tcp hdr.
+ * Force an allocation if it is not the case.
+ */
+ if (GET_PKT_DIRECT_MAX_SIZE(np) < 60) {
+ if (PacketCallocExtPkt(np, 60) == -1) {
+ goto error;
+ }
+ }
+ /* set the ip header */
+ np->ip6h = (IPV6Hdr *)GET_PKT_DATA(np);
+ /* version 6 */
+ np->ip6h->s_ip6_vfc = 0x60;
+ np->ip6h->s_ip6_flow = 0;
+ np->ip6h->s_ip6_nxt = IPPROTO_TCP;
+ np->ip6h->s_ip6_plen = htons(20);
+ np->ip6h->s_ip6_hlim = 64;
+ if (dir == 0) {
+ np->ip6h->s_ip6_src[0] = f->src.addr_data32[0];
+ np->ip6h->s_ip6_src[1] = f->src.addr_data32[1];
+ np->ip6h->s_ip6_src[2] = f->src.addr_data32[2];
+ np->ip6h->s_ip6_src[3] = f->src.addr_data32[3];
+ np->ip6h->s_ip6_dst[0] = f->dst.addr_data32[0];
+ np->ip6h->s_ip6_dst[1] = f->dst.addr_data32[1];
+ np->ip6h->s_ip6_dst[2] = f->dst.addr_data32[2];
+ np->ip6h->s_ip6_dst[3] = f->dst.addr_data32[3];
+ } else {
+ np->ip6h->s_ip6_src[0] = f->dst.addr_data32[0];
+ np->ip6h->s_ip6_src[1] = f->dst.addr_data32[1];
+ np->ip6h->s_ip6_src[2] = f->dst.addr_data32[2];
+ np->ip6h->s_ip6_src[3] = f->dst.addr_data32[3];
+ np->ip6h->s_ip6_dst[0] = f->src.addr_data32[0];
+ np->ip6h->s_ip6_dst[1] = f->src.addr_data32[1];
+ np->ip6h->s_ip6_dst[2] = f->src.addr_data32[2];
+ np->ip6h->s_ip6_dst[3] = f->src.addr_data32[3];
+ }
+
+ /* set the tcp header */
+ np->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(np) + 40);
+
+ SET_PKT_LEN(np, 60); /* ipv6 hdr + tcp hdr */
+ }
+
+ np->tcph->th_offx2 = 0x50;
+ np->tcph->th_flags |= TH_ACK;
+ np->tcph->th_win = 10;
+ np->tcph->th_urp = 0;
+
+ /* to server */
+ if (dir == 0) {
+ np->tcph->th_sport = htons(f->sp);
+ np->tcph->th_dport = htons(f->dp);
+
+ np->tcph->th_seq = htonl(ssn->client.next_seq);
+ np->tcph->th_ack = htonl(ssn->server.last_ack);
+
+ /* to client */
} else {
- SCLogDebug("pseudo is to_server");
- np->flowflags &= ~(FLOW_PKT_TOCLIENT|FLOW_PKT_TOSERVER);
- np->flowflags |= FLOW_PKT_TOSERVER;
-#ifdef DEBUG
- BUG_ON(!(PKT_IS_TOSERVER(np)));
- BUG_ON((PKT_IS_TOCLIENT(np)));
-#endif
+ np->tcph->th_sport = htons(f->dp);
+ np->tcph->th_dport = htons(f->sp);
+
+ np->tcph->th_seq = htonl(ssn->server.next_seq);
+ np->tcph->th_ack = htonl(ssn->client.last_ack);
}
+ /* use parent time stamp */
+ memcpy(&np->ts, &parent->ts, sizeof(struct timeval));
+
SCLogDebug("np %p", np);
PacketEnqueue(pq, np);
StatsIncr(tv, stt->counter_tcp_pseudo);
SCReturn;
+error:
+ FlowDeReference(&np->flow);
+ SCReturn;
}
/** \brief create packets in both directions to flush out logging