Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tunnel/v8 #10597

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -1021,8 +1021,9 @@ void DecodeUnregisterCounters(void);
/** Packet is modified by the stream engine, we need to recalc the csum and \
reinject/replace */
#define PKT_STREAM_MODIFIED BIT_U32(10)
/** Packet mark is modified */
#define PKT_MARK_MODIFIED BIT_U32(11)

// vacancy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shift here as well?


/** Exclude packet from pcap logging as it's part of a stream that has reassembly \
depth reached. */
#define PKT_STREAM_NOPCAPLOG BIT_U32(12)
Expand Down
9 changes: 7 additions & 2 deletions src/detect-mark.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,15 @@ static int DetectMarkPacket(DetectEngineThreadCtx *det_ctx, Packet *p,
const DetectMarkData *nf_data = (const DetectMarkData *)ctx;
if (nf_data->mask) {
if (PacketIsNotTunnel(p)) {
/* for a non-tunnel packet we don't need a lock,
* and if we're here we can't turn into a tunnel
* packet anymore. */

/* coverity[missing_lock] */
p->nfq_v.mark = (nf_data->mark & nf_data->mask)
| (p->nfq_v.mark & ~(nf_data->mask));
p->flags |= PKT_MARK_MODIFIED;
/* coverity[missing_lock] */
p->nfq_v.mark_modified = true;
} else {
/* real tunnels may have multiple flows inside them, so marking
* might 'mark' too much. Rebuilt packets from IP fragments
Expand All @@ -242,7 +247,7 @@ static int DetectMarkPacket(DetectEngineThreadCtx *det_ctx, Packet *p,
SCSpinLock(&tp->persistent.tunnel_lock);
tp->nfq_v.mark = (nf_data->mark & nf_data->mask)
| (tp->nfq_v.mark & ~(nf_data->mask));
tp->flags |= PKT_MARK_MODIFIED;
tp->nfq_v.mark_modified = true;
SCSpinUnlock(&tp->persistent.tunnel_lock);
}
}
Expand Down
101 changes: 66 additions & 35 deletions src/source-nfq.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ static TmEcode DecodeNFQ(ThreadVars *, Packet *, void *);
static TmEcode DecodeNFQThreadInit(ThreadVars *, const void *, void **);
static TmEcode DecodeNFQThreadDeinit(ThreadVars *tv, void *data);

static TmEcode NFQSetVerdict(Packet *p);
static TmEcode NFQSetVerdict(Packet *p, const uint32_t mark_value, const bool mark_modified);
static void NFQReleasePacket(Packet *p);

typedef enum NFQMode_ {
Expand Down Expand Up @@ -324,7 +324,8 @@ static void NFQVerdictCacheFlush(NFQQueueVars *t)
#endif
}

static int NFQVerdictCacheAdd(NFQQueueVars *t, Packet *p, uint32_t verdict)
static int NFQVerdictCacheAdd(NFQQueueVars *t, Packet *p, const uint32_t verdict,
const uint32_t mark_value, const bool mark_modified)
{
#ifdef HAVE_NFQ_SET_VERDICT_BATCH
if (t->verdict_cache.maxlen == 0)
Expand All @@ -333,13 +334,13 @@ static int NFQVerdictCacheAdd(NFQQueueVars *t, Packet *p, uint32_t verdict)
if (p->flags & PKT_STREAM_MODIFIED || verdict == NF_DROP)
goto flush;

if (p->flags & PKT_MARK_MODIFIED) {
if (mark_modified) {
if (!t->verdict_cache.mark_valid) {
if (t->verdict_cache.len)
goto flush;
t->verdict_cache.mark_valid = 1;
t->verdict_cache.mark = p->nfq_v.mark;
} else if (t->verdict_cache.mark != p->nfq_v.mark) {
t->verdict_cache.mark = mark_value;
} else if (t->verdict_cache.mark != mark_value) {
goto flush;
}
} else if (t->verdict_cache.mark_valid) {
Expand Down Expand Up @@ -439,6 +440,7 @@ static int NFQSetupPkt (Packet *p, struct nfq_q_handle *qh, void *data)
p->ReleasePacket = NFQReleasePacket;
p->nfq_v.ifi = nfq_get_indev(tb);
p->nfq_v.ifo = nfq_get_outdev(tb);
/* coverity[missing_lock] */
p->nfq_v.verdicted = false;

#ifdef NFQ_GET_PAYLOAD_SIGNED
Expand Down Expand Up @@ -481,9 +483,28 @@ static int NFQSetupPkt (Packet *p, struct nfq_q_handle *qh, void *data)

static void NFQReleasePacket(Packet *p)
{
if (unlikely(!p->nfq_v.verdicted)) {
PacketDrop(p, ACTION_DROP, PKT_DROP_REASON_NFQ_ERROR);
NFQSetVerdict(p);
if (PacketIsNotTunnel(p)) {
if (unlikely(!p->nfq_v.verdicted)) {
PacketDrop(p, ACTION_DROP, PKT_DROP_REASON_NFQ_ERROR);
/* coverity[missing_lock] */
NFQSetVerdict(p, p->nfq_v.mark, p->nfq_v.mark_modified);
/* coverity[missing_lock] */
p->nfq_v.verdicted = true;
}
} else {
Packet *root_p = p->root ? p->root : p;
SCSpinlock *lock = &root_p->persistent.tunnel_lock;
SCSpinLock(lock);
const bool verdicted = p->nfq_v.verdicted;
// taken from root packet
const bool mark_modified = root_p->nfq_v.mark_modified;
const uint32_t mark_value = root_p->nfq_v.mark;
root_p->nfq_v.verdicted = true;
SCSpinUnlock(lock);
if (!verdicted) {
PacketDrop(p, ACTION_DROP, PKT_DROP_REASON_NFQ_ERROR);
NFQSetVerdict(p, mark_value, mark_modified);
}
}
PacketFreeOrRelease(p);
}
Expand All @@ -504,7 +525,7 @@ static int NFQBypassCallback(Packet *p)
SCSpinLock(&tp->persistent.tunnel_lock);
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;
tp->nfq_v.mark_modified = true;
SCSpinUnlock(&tp->persistent.tunnel_lock);
return 1;
}
Expand All @@ -513,7 +534,8 @@ static int NFQBypassCallback(Packet *p)
/* 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;
/* coverity[missing_lock] */
p->nfq_v.mark_modified = true;
}

return 1;
Expand Down Expand Up @@ -1073,15 +1095,14 @@ static inline void UpdateCounters(NFQQueueVars *t, const Packet *p)

/** \internal
* \brief NFQ verdict function
* \param p Packet to work with. Will be the tunnel root packet in case of tunnel.
*/
static TmEcode NFQSetVerdict(Packet *p)
static TmEcode NFQSetVerdict(Packet *p, const uint32_t mark_value, const bool mark_modified)
{
int iter = 0;
/* we could also have a direct pointer but we need to have a ref count in this case */
NFQQueueVars *t = g_nfq_q + p->nfq_v.nfq_index;

p->nfq_v.verdicted = true;

/* can't verdict a "fake" packet */
if (PKT_IS_PSEUDOPKT(p)) {
return TM_ECODE_OK;
Expand All @@ -1101,7 +1122,7 @@ static TmEcode NFQSetVerdict(Packet *p)
UpdateCounters(t, p);
#endif /* COUNTERS */

int ret = NFQVerdictCacheAdd(t, p, verdict);
int ret = NFQVerdictCacheAdd(t, p, verdict, mark_value, mark_modified);
if (ret == 0) {
NFQMutexUnlock(t);
return TM_ECODE_OK;
Expand All @@ -1112,26 +1133,21 @@ static TmEcode NFQSetVerdict(Packet *p)
default:
case NFQ_ACCEPT_MODE:
case NFQ_ROUTE_MODE:
if (p->flags & PKT_MARK_MODIFIED) {
if (mark_modified) {
#ifdef HAVE_NFQ_SET_VERDICT2
if (p->flags & PKT_STREAM_MODIFIED) {
ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
p->nfq_v.mark,
ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, mark_value,
GET_PKT_LEN(p), GET_PKT_DATA(p));
} else {
ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
p->nfq_v.mark,
0, NULL);
ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, mark_value, 0, NULL);
}
#else /* fall back to old function */
if (p->flags & PKT_STREAM_MODIFIED) {
ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
htonl(p->nfq_v.mark),
ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict, htonl(mark_value),
GET_PKT_LEN(p), GET_PKT_DATA(p));
} else {
ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
htonl(p->nfq_v.mark),
0, NULL);
ret = nfq_set_verdict_mark(
t->qh, p->nfq_v.id, verdict, htonl(mark_value), 0, NULL);
}
#endif /* HAVE_NFQ_SET_VERDICT2 */
} else {
Expand All @@ -1141,28 +1157,29 @@ static TmEcode NFQSetVerdict(Packet *p)
} else {
ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict, 0, NULL);
}

}
break;
case NFQ_REPEAT_MODE:
#ifdef HAVE_NFQ_SET_VERDICT2
if (p->flags & PKT_STREAM_MODIFIED) {
ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
(nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask),
(nfq_config.mark & nfq_config.mask) | (mark_value & ~nfq_config.mask),
GET_PKT_LEN(p), GET_PKT_DATA(p));
} else {
ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
(nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask),
(nfq_config.mark & nfq_config.mask) | (mark_value & ~nfq_config.mask),
0, NULL);
}
#else /* fall back to old function */
if (p->flags & PKT_STREAM_MODIFIED) {
ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)),
htonl((nfq_config.mark & nfq_config.mask) |
(mark_value & ~nfq_config.mask)),
GET_PKT_LEN(p), GET_PKT_DATA(p));
} else {
ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)),
htonl((nfq_config.mark & nfq_config.mask) |
(mark_value & ~nfq_config.mask)),
0, NULL);
}
#endif /* HAVE_NFQ_SET_VERDICT2 */
Expand All @@ -1186,19 +1203,33 @@ TmEcode VerdictNFQ(ThreadVars *tv, Packet *p, void *data)
{
/* if this is a tunnel packet we check if we are ready to verdict
* already. */
if (p->ttype != PacketTunnelNone) {
if (PacketIsTunnel(p)) {
Packet *root_p = p->root ? p->root : p;

SCLogDebug("tunnel pkt: %p/%p %s", p, p->root, p->root ? "upper layer" : "root");
bool verdict = VerdictTunnelPacket(p);

SCSpinlock *lock = &root_p->persistent.tunnel_lock;
SCSpinLock(lock);
const bool do_verdict = VerdictTunnelPacketInternal(p);
// taken from root packet
const bool mark_modified = root_p->nfq_v.mark_modified;
const uint32_t mark_value = root_p->nfq_v.mark;
root_p->nfq_v.verdicted = do_verdict;
SCSpinUnlock(lock);
/* don't verdict if we are not ready */
if (verdict == true) {
int ret = NFQSetVerdict(p->root ? p->root : p);
if (do_verdict == true) {
int ret = NFQSetVerdict(root_p, mark_value, mark_modified);
if (ret != TM_ECODE_OK) {
return ret;
}
}
} else {
/* no tunnel, verdict normally */
int ret = NFQSetVerdict(p);

/* coverity[missing_lock] */
p->nfq_v.verdicted = true;

int ret = NFQSetVerdict(p, p->nfq_v.mark, p->nfq_v.mark_modified);
if (ret != TM_ECODE_OK) {
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions src/source-nfq.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef struct NFQPacketVars_
int id; /* this nfq packets id */
uint16_t nfq_index; /* index in NFQ array */
bool verdicted;
bool mark_modified;

uint32_t mark;
uint32_t ifi;
Expand Down
Loading