Give each packet explicit tunnel type `ttype`: none, root, child.
Assigning happens when a (tunnel) packet is set up and is thread
safe.
p->livedev = parent->livedev;
/* set the root ptr to the lowest layer */
- if (parent->root != NULL)
+ if (parent->root != NULL) {
p->root = parent->root;
- else
+ BUG_ON(parent->ttype != PacketTunnelChild);
+ } else {
p->root = parent;
-
+ parent->ttype = PacketTunnelRoot;
+ }
/* tell new packet it's part of a tunnel */
- SET_TUNNEL_PKT(p);
+ p->ttype = PacketTunnelChild;
ret = DecodeTunnel(tv, dtv, p, GET_PKT_DATA(p),
GET_PKT_LEN(p), proto);
{
/* Not a (valid) tunnel packet */
SCLogDebug("tunnel packet is invalid");
-
p->root = NULL;
- UNSET_TUNNEL_PKT(p);
TmqhOutputPacketpool(tv, p);
SCReturnPtr(NULL, "Packet");
}
-
- /* tell parent packet it's part of a tunnel */
- SET_TUNNEL_PKT(parent);
-
- /* increment tunnel packet refcnt in the root packet */
+ /* Update tunnel settings in parent */
+ if (parent->root == NULL) {
+ parent->ttype = PacketTunnelRoot;
+ }
TUNNEL_INCR_PKT_TPR(p);
/* disable payload (not packet) inspection on the parent, as the payload
}
/* set the root ptr to the lowest layer */
- if (parent->root != NULL)
+ if (parent->root != NULL) {
p->root = parent->root;
- else
+ BUG_ON(parent->ttype != PacketTunnelChild);
+ } else {
p->root = parent;
+ // we set parent->ttype later
+ }
+ /* tell new packet it's part of a tunnel */
+ p->ttype = PacketTunnelChild;
/* copy packet and set length, proto */
if (pkt && len) {
p->ts = parent->ts;
p->datalink = DLT_RAW;
p->tenant_id = parent->tenant_id;
- /* tell new packet it's part of a tunnel */
- SET_TUNNEL_PKT(p);
memcpy(&p->vlan_id[0], &parent->vlan_id[0], sizeof(p->vlan_id));
p->vlan_idx = parent->vlan_idx;
p->livedev = parent->livedev;
void PacketDefragPktSetupParent(Packet *parent)
{
/* tell parent packet it's part of a tunnel */
- SET_TUNNEL_PKT(parent);
+ if (parent->ttype == PacketTunnelNone)
+ parent->ttype = PacketTunnelRoot;
/* increment tunnel packet refcnt in the root packet */
TUNNEL_INCR_PKT_TPR(parent);
PKT_DROP_REASON_MAX,
};
+enum PacketTunnelType {
+ PacketTunnelNone,
+ PacketTunnelRoot,
+ PacketTunnelChild,
+};
+
/* forward declaration since Packet struct definition requires this */
struct PacketQueue_;
* hash size still */
uint32_t flow_hash;
+ /* tunnel type: none, root or child */
+ enum PacketTunnelType ttype;
+
SCTime_t ts;
union {
/* enum PacketDropReason::PKT_DROP_REASON_* as uint8_t for compactness */
uint8_t drop_reason;
- /* has tunnel been verdicted? */
+ /** has verdict on this tunneled packet been issued? */
bool tunnel_verdicted;
/* tunnel/encapsulation handling */
/** lock to protect access to:
* - tunnel_rtv_cnt
* - tunnel_tpr_cnt
- * - nfq_v.mark
- * - flags
+ * - tunnel_verdicted
+ * - nfq_v.mark (if p->ttype != PacketTunnelNone)
*/
SCSpinlock tunnel_lock;
} persistent;
#define TUNNEL_PKT_RTV(p) ((p)->root ? (p)->root->tunnel_rtv_cnt : (p)->tunnel_rtv_cnt)
#define TUNNEL_PKT_TPR(p) ((p)->root ? (p)->root->tunnel_tpr_cnt : (p)->tunnel_tpr_cnt)
-#define IS_TUNNEL_PKT(p) (((p)->flags & PKT_TUNNEL))
-#define SET_TUNNEL_PKT(p) ((p)->flags |= PKT_TUNNEL)
-#define UNSET_TUNNEL_PKT(p) ((p)->flags &= ~PKT_TUNNEL)
-#define IS_TUNNEL_ROOT_PKT(p) (IS_TUNNEL_PKT(p) && (p)->root == NULL)
-
-#define IS_TUNNEL_PKT_VERDICTED(p) (p)->tunnel_verdicted
-#define SET_TUNNEL_PKT_VERDICTED(p) (p)->tunnel_verdicted = true
+static inline bool PacketTunnelIsVerdicted(const Packet *p)
+{
+ return p->tunnel_verdicted;
+}
+static inline void PacketTunnelSetVerdicted(Packet *p)
+{
+ p->tunnel_verdicted = true;
+}
enum DecodeTunnelProto {
DECODE_TUNNEL_ETHERNET,
depth reached. */
#define PKT_STREAM_NOPCAPLOG BIT_U32(12)
-#define PKT_TUNNEL BIT_U32(13)
-// vacancy
+// vacancy 2x
/** Packet checksum is not computed (TX packet for example) */
#define PKT_IGNORE_CHECKSUM BIT_U32(15)
p->flags |= PKT_NOPACKET_INSPECTION;
}
+static inline bool PacketIsTunnelRoot(const Packet *p)
+{
+ return (p->ttype == PacketTunnelRoot);
+}
+
+static inline bool PacketIsTunnelChild(const Packet *p)
+{
+ return (p->ttype == PacketTunnelChild);
+}
+
+static inline bool PacketIsTunnel(const Packet *p)
+{
+ return (p->ttype != PacketTunnelNone);
+}
+
+static inline bool PacketIsNotTunnel(const Packet *p)
+{
+ return (p->ttype == PacketTunnelNone);
+}
+
/** \brief return true if *this* packet needs to trigger a verdict.
*
* If we have the root packet, and we have none outstanding,
SCLogDebug("tunnel: outstanding %u", outstanding);
/* if there are packets outstanding, we won't verdict this one */
- if (IS_TUNNEL_ROOT_PKT(p) && !IS_TUNNEL_PKT_VERDICTED(p) && !outstanding) {
+ if (PacketIsTunnelRoot(p) && !PacketTunnelIsVerdicted(p) && !outstanding) {
// verdict
SCLogDebug("root %p: verdict", p);
- } else if (!IS_TUNNEL_ROOT_PKT(p) && outstanding == 1 && p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) {
+ } else if (PacketIsTunnelChild(p) && outstanding == 1 && p->root &&
+ PacketTunnelIsVerdicted(p->root)) {
// verdict
SCLogDebug("tunnel %p: verdict", p);
} else {
r = Defrag4Reassemble(tv, tracker, p);
if (r != NULL && tv != NULL && dtv != NULL) {
StatsIncr(tv, dtv->counter_defrag_ipv4_reassembled);
- if (DecodeIPV4(tv, dtv, r, (void *)r->ip4h,
- IPV4_GET_IPLEN(r)) != TM_ECODE_OK) {
-
- UNSET_TUNNEL_PKT(r);
+ if (DecodeIPV4(tv, dtv, r, (void *)r->ip4h, IPV4_GET_IPLEN(r)) != TM_ECODE_OK) {
r->root = NULL;
TmqhOutputPacketpool(tv, r);
r = NULL;
if (r != NULL && tv != NULL && dtv != NULL) {
StatsIncr(tv, dtv->counter_defrag_ipv6_reassembled);
if (DecodeIPV6(tv, dtv, r, (uint8_t *)r->ip6h,
- IPV6_GET_PLEN(r) + IPV6_HEADER_LEN)
- != TM_ECODE_OK) {
-
- UNSET_TUNNEL_PKT(r);
+ IPV6_GET_PLEN(r) + IPV6_HEADER_LEN) != TM_ECODE_OK) {
r->root = NULL;
TmqhOutputPacketpool(tv, r);
r = NULL;
#ifdef NFQ
const DetectMarkData *nf_data = (const DetectMarkData *)ctx;
if (nf_data->mask) {
- if (!(IS_TUNNEL_PKT(p))) {
+ if (PacketIsNotTunnel(p)) {
/* coverity[missing_lock] */
p->nfq_v.mark = (nf_data->mark & nf_data->mask)
| (p->nfq_v.mark & ~(nf_data->mask));
return false;
}
- if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ if (p->ttype == PacketTunnelChild) {
return false;
}
return true;
PCAPLOG_PROFILE_START;
int datalink = p->datalink;
- if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ if (p->ttype == PacketTunnelChild) {
Packet *real_p = p->root;
datalink = real_p->datalink;
}
pl->pkt_cnt++;
pl->h->ts.tv_sec = SCTIME_SECS(p->ts);
pl->h->ts.tv_usec = SCTIME_USECS(p->ts);
- if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ if (p->ttype == PacketTunnelChild) {
rp = p->root;
pl->h->caplen = GET_PKT_LEN(rp);
pl->h->len = GET_PKT_LEN(rp);
/* PcapLogDumpSegment has written over the PcapLogData variables so need to update */
pl->h->ts.tv_sec = SCTIME_SECS(p->ts);
pl->h->ts.tv_usec = SCTIME_USECS(p->ts);
- if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ if (p->ttype == PacketTunnelChild) {
rp = p->root;
pl->h->caplen = GET_PKT_LEN(rp);
pl->h->len = GET_PKT_LEN(rp);
}
}
- if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ if (p->ttype == PacketTunnelChild) {
rp = p->root;
#ifdef HAVE_LIBLZ4
ret = PcapWrite(pl, comp, GET_PKT_DATA(rp), len);
/* alert */
AlertJsonHeader(json_output_ctx, p, pa, jb, json_output_ctx->flags, &addr, xff_buffer);
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
AlertJsonTunnel(p, jb);
}
p->vlan_id[0] = 0;
p->vlan_id[1] = 0;
p->vlan_idx = 0;
+ p->ttype = PacketTunnelNone;
SCTIME_INIT(p->ts);
p->datalink = 0;
p->drop_reason = 0;
return TM_ECODE_OK;
}
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
return TM_ECODE_OK;
}
/* Bypassing tunneled packets is currently not supported
* because we can't discard the inner packet only due to
* primitive parsing in eBPF */
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
return 0;
}
if (PKT_IS_IPV4(p)) {
/* Bypassing tunneled packets is currently not supported
* because we can't discard the inner packet only due to
* primitive parsing in eBPF */
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
return 0;
}
if (PKT_IS_IPV4(p)) {
}
/* This came from NFQ.
- * if this is a tunnel packet we check if we are ready to verdict
- * already. */
- if (IS_TUNNEL_PKT(p)) {
+ * If this is a tunnel packet we check if we are ready to verdict already. */
+ if (PacketIsTunnel(p)) {
bool verdict = VerdictTunnelPacket(p);
/* don't verdict if we are not ready */
/* no tunnel, verdict normally */
SCLogDebug("Setting verdict on non-tunnel");
retval = IPFWSetVerdict(tv, ptv, p);
- } /* IS_TUNNEL_PKT end */
+ }
SCReturnInt(retval);
}
*/
static int NFQBypassCallback(Packet *p)
{
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(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) {
{
/* if this is a tunnel packet we check if we are ready to verdict
* already. */
- if (IS_TUNNEL_PKT(p)) {
+ if (p->ttype != PacketTunnelNone) {
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 */
}
/* Bypassing tunneled packets is currently not supported */
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
return 0;
}
/* we can't verdict tunnel packets without ensuring all encapsulated
* packets are verdicted */
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
bool finalVerdict = VerdictTunnelPacket(p);
if (!finalVerdict) {
SCReturnInt(TM_ECODE_OK);
return;
}
- if (IS_TUNNEL_PKT(p) && !IS_TUNNEL_ROOT_PKT(p)) {
+ if (PacketIsTunnelChild(p)) {
Packet *rp = p->root;
StreamTcpSegmentAddPacketDataDo(seg, rp, p);
} else {
SCEnter();
SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, BOOL2STR(p->pool == NULL));
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
SCLogDebug("Packet %p is a tunnel packet: %s",
p,p->root ? "upper layer" : "tunnel root");
SCSpinlock *lock = p->root ? &p->root->persistent.tunnel_lock : &p->persistent.tunnel_lock;
SCSpinLock(lock);
- if (IS_TUNNEL_ROOT_PKT(p)) {
+ if (PacketIsTunnelRoot(p)) {
SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE");
- CaptureStatsUpdate(t, p);
+ CaptureStatsUpdate(t, p); // TODO move out of lock
const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p);
SCLogDebug("root pkt: outstanding %u", outstanding);
* 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);
+ PacketTunnelSetVerdicted(p);
PACKET_PROFILING_END(p);
SCSpinUnlock(lock);
/* 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))
- {
+ if (outstanding == 0 && p->root && PacketTunnelIsVerdicted(p->root)) {
SCLogDebug("root verdicted == true && no outstanding");
/* handle freeing the root as well*/
* 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 > 0 (%u)",
+ (p->root && PacketTunnelIsVerdicted(p->root)) ? "true" : "false",
outstanding);
/* fall through */
}
SCLogDebug("[packet %p][%s] %s", p,
- IS_TUNNEL_PKT(p) ? IS_TUNNEL_ROOT_PKT(p) ? "tunnel::root" : "tunnel::leaf"
- : "no tunnel",
+ PacketIsTunnel(p) ? PacketIsTunnelRoot(p) ? "tunnel::root" : "tunnel::leaf"
+ : "no tunnel",
(p->action & ACTION_DROP) ? "DROP" : "no drop");
/* we're done with the tunnel root now as well */
pd->tot += delta;
pd->cnt ++;
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
pd = &packet_profile_data4[256];
if (pd->min == 0 || delta < pd->min) {
pd->tot += delta;
pd->cnt ++;
- if (IS_TUNNEL_PKT(p)) {
+ if (PacketIsTunnel(p)) {
pd = &packet_profile_data6[256];
if (pd->min == 0 || delta < pd->min) {