/** * \brief NFQ verdict module packet entry function */ TmEcode VerdictNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { NFQThreadVars *ntv = (NFQThreadVars *)data; /* update counters */ CaptureStatsUpdate(tv, &ntv->stats, p); int ret; /* if this is a tunnel packet we check if we are ready to verdict * already. */ if (IS_TUNNEL_PKT(p)) { SCLogDebug("tunnel pkt: %p/%p %s", p, p->root, p->root ? "upper layer" : "root"); bool verdict = VerdictTunnelPacket(p); /* don't verdict if we are not ready */ if (verdict == true) { ret = NFQSetVerdict(p->root ? p->root : p); if (ret != TM_ECODE_OK) { return ret; } } } else { /* no tunnel, verdict normally */ ret = NFQSetVerdict(p); if (ret != TM_ECODE_OK) { return ret; } } return TM_ECODE_OK; }
/** * \brief Pfring bypass callback function * * \param p a Packet to use information from to trigger bypass * \return 1 if bypass is successful, 0 if not */ static int PfringBypassCallback(Packet *p) { hw_filtering_rule r; /* Only bypass TCP and UDP */ if (!(PKT_IS_TCP(p) || PKT_IS_UDP(p))) { return 0; } /* Bypassing tunneled packets is currently not supported */ if (IS_TUNNEL_PKT(p)) { return 0; } r.rule_family_type = generic_flow_id_rule; r.rule_family.flow_id_rule.action = flow_drop_rule; r.rule_family.flow_id_rule.thread = 0; r.rule_family.flow_id_rule.flow_id = p->pfring_v.flow_id; SCLogDebug("Bypass set for flow ID = %u", p->pfring_v.flow_id); if (pfring_add_hw_rule(p->pfring_v.ptv->pd, &r) < 0) { return 0; } return 1; }
/** * \brief This function handles the Verdict processing * \todo Unit tests are needed for this module. * * * \param tv pointer to ThreadVars * \param p pointer to the Packet * \param data pointer that gets cast into IPFWThreadVars for ptv * \param pq pointer for the Packet Queue access (Not used) */ TmEcode VerdictIPFW(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { IPFWThreadVars *ptv = (IPFWThreadVars *)data; TmEcode retval = TM_ECODE_OK; SCEnter(); /* can't verdict a "fake" packet */ if (p->flags & PKT_PSEUDO_STREAM_END) { SCReturnInt(TM_ECODE_OK); } /* This came from NFQ. * if this is a tunnel packet we check if we are ready to verdict * already. */ if (IS_TUNNEL_PKT(p)) { char verdict = 1; SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex; SCMutexLock(m); /* if there are more tunnel packets than ready to verdict packets, * we won't verdict this one */ if (TUNNEL_PKT_TPR(p) > TUNNEL_PKT_RTV(p)) { SCLogDebug("VerdictIPFW: not ready to verdict yet: " "TUNNEL_PKT_TPR(p) > TUNNEL_PKT_RTV(p) = %" PRId32 " > %" PRId32 "", TUNNEL_PKT_TPR(p), TUNNEL_PKT_RTV(p)); verdict = 0; } SCMutexUnlock(m); /* don't verdict if we are not ready */ if (verdict == 1) { SCLogDebug("Setting verdict on tunnel"); retval = IPFWSetVerdict(tv, ptv, p->root ? p->root : p); } else { TUNNEL_INCR_PKT_RTV(p); } } else { /* no tunnel, verdict normally */ SCLogDebug("Setting verdict on non-tunnel"); retval = IPFWSetVerdict(tv, ptv, p); } /* IS_TUNNEL_PKT end */ SCReturnInt(retval); }
/** * \brief NFQ verdict module packet entry function */ TmEcode VerdictNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { int ret; /* if this is a tunnel packet we check if we are ready to verdict * already. */ if (IS_TUNNEL_PKT(p)) { char verdict = 1; //printf("VerdictNFQ: tunnel pkt: %p %s\n", p, p->root ? "upper layer" : "root"); SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex; SCMutexLock(m); /* if there are more tunnel packets than ready to verdict packets, * we won't verdict this one */ if (TUNNEL_PKT_TPR(p) > TUNNEL_PKT_RTV(p)) { SCLogDebug("not ready to verdict yet: TUNNEL_PKT_TPR(p) > " "TUNNEL_PKT_RTV(p) = %" PRId32 " > %" PRId32, TUNNEL_PKT_TPR(p), TUNNEL_PKT_RTV(p)); verdict = 0; } SCMutexUnlock(m); /* don't verdict if we are not ready */ if (verdict == 1) { //printf("VerdictNFQ: setting verdict\n"); ret = NFQSetVerdict(p->root ? p->root : p); if (ret != TM_ECODE_OK) return ret; } else { TUNNEL_INCR_PKT_RTV(p); } } else { /* no tunnel, verdict normally */ ret = NFQSetVerdict(p); if (ret != TM_ECODE_OK) return ret; } return TM_ECODE_OK; }
/** * \brief bypass callback function for NFQ * * \param p a Packet to use information from to trigger bypass * \return 1 if bypass is successful, 0 if not */ static int NFQBypassCallback(Packet *p) { if (IS_TUNNEL_PKT(p)) { /* real tunnels may have multiple flows inside them, so bypass can't * work for those. Rebuilt packets from IP fragments are fine. */ if (p->flags & PKT_REBUILT_FRAGMENT) { Packet *tp = p->root ? p->root : p; SCMutexLock(&tp->tunnel_mutex); tp->nfq_v.mark = (nfq_config.bypass_mark & nfq_config.bypass_mask) | (tp->nfq_v.mark & ~nfq_config.bypass_mask); tp->flags |= PKT_MARK_MODIFIED; SCMutexUnlock(&tp->tunnel_mutex); return 1; } return 0; } else { /* coverity[missing_lock] */ p->nfq_v.mark = (nfq_config.bypass_mark & nfq_config.bypass_mask) | (p->nfq_v.mark & ~nfq_config.bypass_mask); p->flags |= PKT_MARK_MODIFIED; } return 1; }
void TmqhOutputPacketpool(ThreadVars *t, Packet *p) { bool proot = false; SCEnter(); SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, p->flags & PKT_ALLOC ? "true" : "false"); if (IS_TUNNEL_PKT(p)) { SCLogDebug("Packet %p is a tunnel packet: %s", p,p->root ? "upper layer" : "tunnel root"); /* get a lock to access root packet fields */ SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex; SCMutexLock(m); if (IS_TUNNEL_ROOT_PKT(p)) { SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE"); const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p); SCLogDebug("root pkt: outstanding %u", outstanding); if (outstanding == 0) { SCLogDebug("no tunnel packets outstanding, no more tunnel " "packet(s) depending on this root"); /* if this packet is the root and there are no * more tunnel packets to consider * * return it to the pool */ } else { SCLogDebug("tunnel root Packet %p: outstanding > 0, so " "packets are still depending on this root, setting " "SET_TUNNEL_PKT_VERDICTED", p); /* if this is the root and there are more tunnel * packets, return this to the pool. It's still referenced * by the tunnel packets, and we will return it * when we handle them */ SET_TUNNEL_PKT_VERDICTED(p); PACKET_PROFILING_END(p); SCMutexUnlock(m); SCReturn; } } else { SCLogDebug("NOT IS_TUNNEL_ROOT_PKT, so tunnel pkt"); TUNNEL_INCR_PKT_RTV_NOLOCK(p); const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p); SCLogDebug("tunnel pkt: outstanding %u", outstanding); /* all tunnel packets are processed except us. Root already * processed. So return tunnel pkt and root packet to the * pool. */ if (outstanding == 0 && p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) { SCLogDebug("root verdicted == true && no outstanding"); /* handle freeing the root as well*/ SCLogDebug("setting proot = 1 for root pkt, p->root %p " "(tunnel packet %p)", p->root, p); proot = true; /* fall through */ } else { /* root not ready yet, or not the last tunnel packet, * so get rid of the tunnel pkt only */ SCLogDebug("NOT IS_TUNNEL_PKT_VERDICTED (%s) || " "outstanding > 0 (%u)", (p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) ? "true" : "false", outstanding); /* fall through */ } } SCMutexUnlock(m); SCLogDebug("tunnel stuff done, move on (proot %d)", proot); } /* we're done with the tunnel root now as well */ if (proot == true) { SCLogDebug("getting rid of root pkt... alloc'd %s", p->root->flags & PKT_ALLOC ? "true" : "false"); PACKET_RELEASE_REFS(p->root); p->root->ReleasePacket(p->root); p->root = NULL; } PACKET_PROFILING_END(p); PACKET_RELEASE_REFS(p); p->ReleasePacket(p); SCReturn; }
void SCProfilingAddPacket(Packet *p) { if (p == NULL || p->profile == NULL || p->profile->ticks_start == 0 || p->profile->ticks_end == 0 || p->profile->ticks_start > p->profile->ticks_end) return; pthread_mutex_lock(&packet_profile_lock); { if (profiling_packets_csv_enabled) SCProfilingPrintPacketProfile(p); if (PKT_IS_IPV4(p)) { SCProfilePacketData *pd = &packet_profile_data4[p->proto]; uint64_t delta = p->profile->ticks_end - p->profile->ticks_start; if (pd->min == 0 || delta < pd->min) { pd->min = delta; } if (pd->max < delta) { pd->max = delta; } pd->tot += delta; pd->cnt ++; if (IS_TUNNEL_PKT(p)) { pd = &packet_profile_data4[256]; if (pd->min == 0 || delta < pd->min) { pd->min = delta; } if (pd->max < delta) { pd->max = delta; } pd->tot += delta; pd->cnt ++; } SCProfilingUpdatePacketGenericRecords(p, p->profile->flowworker, packet_profile_flowworker_data, PROFILE_FLOWWORKER_SIZE); SCProfilingUpdatePacketTmmRecords(p); SCProfilingUpdatePacketAppRecords(p); SCProfilingUpdatePacketDetectRecords(p); SCProfilingUpdatePacketLogRecords(p); } else if (PKT_IS_IPV6(p)) { SCProfilePacketData *pd = &packet_profile_data6[p->proto]; uint64_t delta = p->profile->ticks_end - p->profile->ticks_start; if (pd->min == 0 || delta < pd->min) { pd->min = delta; } if (pd->max < delta) { pd->max = delta; } pd->tot += delta; pd->cnt ++; if (IS_TUNNEL_PKT(p)) { pd = &packet_profile_data6[256]; if (pd->min == 0 || delta < pd->min) { pd->min = delta; } if (pd->max < delta) { pd->max = delta; } pd->tot += delta; pd->cnt ++; } SCProfilingUpdatePacketGenericRecords(p, p->profile->flowworker, packet_profile_flowworker_data, PROFILE_FLOWWORKER_SIZE); SCProfilingUpdatePacketTmmRecords(p); SCProfilingUpdatePacketAppRecords(p); SCProfilingUpdatePacketDetectRecords(p); SCProfilingUpdatePacketLogRecords(p); } } pthread_mutex_unlock(&packet_profile_lock); }
void TmqhOutputPacketpool(ThreadVars *t, Packet *p) { int proot = 0; SCEnter(); SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, p->flags & PKT_ALLOC ? "true" : "false"); /** \todo make this a callback * Release tcp segments. Done here after alerting can use them. */ if (p->flow != NULL && p->proto == IPPROTO_TCP) { SCMutexLock(&p->flow->m); StreamTcpPruneSession(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? STREAM_TOSERVER : STREAM_TOCLIENT); SCMutexUnlock(&p->flow->m); } if (IS_TUNNEL_PKT(p)) { SCLogDebug("Packet %p is a tunnel packet: %s", p,p->root ? "upper layer" : "tunnel root"); /* get a lock to access root packet fields */ SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex; SCMutexLock(m); if (IS_TUNNEL_ROOT_PKT(p)) { SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE"); if (TUNNEL_PKT_TPR(p) == 0) { SCLogDebug("TUNNEL_PKT_TPR(p) == 0, no more tunnel packet " "depending on this root"); /* if this packet is the root and there are no * more tunnel packets, return it to the pool */ /* fall through */ } else { SCLogDebug("tunnel root Packet %p: TUNNEL_PKT_TPR(p) > 0, so " "packets are still depending on this root, setting " "p->tunnel_verdicted == 1", p); /* if this is the root and there are more tunnel * packets, return this to the pool. It's still referenced * by the tunnel packets, and we will return it * when we handle them */ SET_TUNNEL_PKT_VERDICTED(p); SCMutexUnlock(m); PACKET_PROFILING_END(p); SCReturn; } } else { SCLogDebug("NOT IS_TUNNEL_ROOT_PKT, so tunnel pkt"); /* the p->root != NULL here seems unnecessary: IS_TUNNEL_PKT checks * that p->tunnel_pkt == 1, IS_TUNNEL_ROOT_PKT checks that + * p->root == NULL. So when we are here p->root can only be * non-NULL, right? CLANG thinks differently. May be a FP, but * better safe than sorry. VJ */ if (p->root != NULL && IS_TUNNEL_PKT_VERDICTED(p->root) && TUNNEL_PKT_TPR(p) == 1) { SCLogDebug("p->root->tunnel_verdicted == 1 && TUNNEL_PKT_TPR(p) == 1"); /* the root is ready and we are the last tunnel packet, * lets enqueue them both. */ TUNNEL_DECR_PKT_TPR_NOLOCK(p); /* handle the root */ SCLogDebug("setting proot = 1 for root pkt, p->root %p " "(tunnel packet %p)", p->root, p); proot = 1; /* fall through */ } else { /* root not ready yet, so get rid of the tunnel pkt only */ SCLogDebug("NOT p->root->tunnel_verdicted == 1 && " "TUNNEL_PKT_TPR(p) == 1 (%" PRIu32 ")", TUNNEL_PKT_TPR(p)); TUNNEL_DECR_PKT_TPR_NOLOCK(p); /* fall through */ } } SCMutexUnlock(m); SCLogDebug("tunnel stuff done, move on (proot %d)", proot); } FlowDeReference(&p->flow); /* we're done with the tunnel root now as well */ if (proot == 1) { SCLogDebug("getting rid of root pkt... alloc'd %s", p->root->flags & PKT_ALLOC ? "true" : "false"); FlowDeReference(&p->root->flow); /* if p->root uses extended data, free them */ if (p->root->ext_pkt) { if (!(p->root->flags & PKT_ZERO_COPY)) { SCFree(p->root->ext_pkt); } p->root->ext_pkt = NULL; } p->root->ReleasePacket(p->root); p->root = NULL; } /* if p uses extended data, free them */ if (p->ext_pkt) { if (!(p->flags & PKT_ZERO_COPY)) { SCFree(p->ext_pkt); } p->ext_pkt = NULL; } PACKET_PROFILING_END(p); p->ReleasePacket(p); SCReturn; }