From 28d9415e375b96a102b0cd07fc14b48b8e38555d Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 23 Oct 2008 17:31:08 +0200 Subject: [PATCH] New approach to tunnel decoding. --- src/decode-ipv4.c | 21 ++++++++++------ src/decode.h | 32 ++++++++++++++++-------- src/packet-queue.c | 39 +++++++++++++++++++++++++++++ src/source-nfq.c | 45 +++++++++++++++++++++++++--------- src/source-nfq.h | 4 +-- src/vips.c | 61 +++++----------------------------------------- 6 files changed, 116 insertions(+), 86 deletions(-) diff --git a/src/decode-ipv4.c b/src/decode-ipv4.c index ee3dfe3cca..d99e536ab8 100644 --- a/src/decode-ipv4.c +++ b/src/decode-ipv4.c @@ -95,14 +95,19 @@ void DecodeIPV4(ThreadVars *t, Packet *p, u_int8_t *pkt, u_int16_t len) return(DecodeICMPV4(t, p, pkt + IPV4_GET_HLEN(p), len - IPV4_GET_HLEN(p))); break; case IPPROTO_IPV6: - //printf("DecodeIPV4: next layer is IPV6\n"); - //printf("DecodeIPV4: we are p %p\n", p); - - /* spawn off tunnel packet */ - SetupTunnelPkt(t, p, pkt + IPV4_GET_HLEN(p), len - IPV4_GET_HLEN(p), IPV4_GET_IPPROTO(p)); - /* this is now a tunnel packet */ - SET_TUNNEL_PKT(p); - break; + { + //printf("DecodeIPV4: next layer is IPV6\n"); + //printf("DecodeIPV4: we are p %p\n", p); + + /* spawn off tunnel packet */ + Packet *tp = TunnelPktSetup(t, p, pkt + IPV4_GET_HLEN(p), len - IPV4_GET_HLEN(p), IPV4_GET_IPPROTO(p)); + /* send that to the Tunnel decoder */ + DecodeTunnel(t, tp, tp->pkt, tp->pktlen); + + /* the current packet is now a tunnel packet */ + SET_TUNNEL_PKT(p); + break; + } } return; diff --git a/src/decode.h b/src/decode.h index e7a4798512..5d27d094be 100644 --- a/src/decode.h +++ b/src/decode.h @@ -180,6 +180,9 @@ typedef struct _Packet Port sp; Port dp; u_int8_t proto; + u_int8_t recursion_level; +/* XXX make sure we can't be attacked on when the tunneled packet + * has the exact same tuple as the lower levels */ struct timeval ts; @@ -192,18 +195,17 @@ typedef struct _Packet /* tunnel packet ref count */ u_int8_t tpr_cnt; pthread_mutex_t mutex_rtv_cnt; - + /* tunnel stuff */ + u_int8_t tunnel_proto; /* tunnel XXX convert to bitfield*/ - int tunnel_pkt; + char tunnel_pkt; + char tunnel_verdicted; /* nfq stuff */ #ifdef NFQ NFQPacketVars nfq_v; #endif /* NFQ */ - /* tunnel stuff */ - u_int8_t tunnel_proto; - /* storage */ u_int8_t pkt[65536]; u_int16_t pktlen; @@ -295,22 +297,32 @@ typedef struct _Packet #define REJECT_PACKET_DST(p) ((p)->root ? ((p)->root->action = ACTION_REJECT_DST) : ((p)->action = ACTION_REJECT_DST)) #define REJECT_PACKET_BOTH(p) ((p)->root ? ((p)->root->action = ACTION_REJECT_BOTH) : ((p)->action = ACTION_REJECT_BOTH)) -#define INCR_PKT_RTV(p) \ +#define TUNNEL_INCR_PKT_RTV(p) \ { \ mutex_lock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \ ((p)->root ? (p)->root->rtv_cnt++ : (p)->rtv_cnt++); \ mutex_unlock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \ } -#define INCR_PKT_TPR(p) \ +#define TUNNEL_INCR_PKT_TPR(p) \ { \ mutex_lock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \ ((p)->root ? (p)->root->tpr_cnt++ : (p)->tpr_cnt++); \ mutex_unlock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \ } +#define TUNNEL_DECR_PKT_TPR(p) \ +{ \ + mutex_lock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \ + ((p)->root ? (p)->root->tpr_cnt-- : (p)->tpr_cnt--); \ + mutex_unlock((p)->root ? &(p)->root->mutex_rtv_cnt : &(p)->mutex_rtv_cnt); \ +} +#define TUNNEL_DECR_PKT_TPR_NOLOCK(p) \ +{ \ + ((p)->root ? (p)->root->tpr_cnt-- : (p)->tpr_cnt--); \ +} -#define PKT_RTV(p) ((p)->root ? (p)->root->rtv_cnt : (p)->rtv_cnt) -#define PKT_TPR(p) ((p)->root ? (p)->root->tpr_cnt : (p)->tpr_cnt) +#define TUNNEL_PKT_RTV(p) ((p)->root ? (p)->root->rtv_cnt : (p)->rtv_cnt) +#define TUNNEL_PKT_TPR(p) ((p)->root ? (p)->root->tpr_cnt : (p)->tpr_cnt) #define IS_TUNNEL_ROOT_PKT(p) (((p)->root == NULL && (p)->tunnel_pkt == 1)) #define IS_TUNNEL_PKT(p) (((p)->tunnel_pkt == 1)) @@ -328,7 +340,7 @@ void DecodeUDP(ThreadVars *, Packet *, u_int8_t *, u_int16_t); void DecodeHTTP(ThreadVars *, Packet *, u_int8_t *, u_int16_t); Packet *SetupPkt (void); -void SetupTunnelPkt(ThreadVars *, Packet *, u_int8_t *, u_int16_t, u_int8_t); +Packet *TunnelPktSetup(ThreadVars *, Packet *, u_int8_t *, u_int16_t, u_int8_t); #define DECODER_SET_EVENT(p, e) ((p)->events[(e/8)] |= (1<<(e%8))) #define DECODER_ISSET_EVENT(p, e) ((p)->events[(e/8)] & (1<<(e%8))) diff --git a/src/packet-queue.c b/src/packet-queue.c index b98c9fc8da..32effe860e 100644 --- a/src/packet-queue.c +++ b/src/packet-queue.c @@ -3,8 +3,47 @@ #include "vips.h" #include "decode.h" #include "packet-queue.h" +#include "threads.h" void PacketEnqueue (PacketQueue *q, Packet *p) { + if (IS_TUNNEL_PKT(p)) { + /* get a lock */ + pthread_mutex_t *m = p->root ? &p->root->mutex_rtv_cnt : &p->mutex_rtv_cnt; + mutex_lock(m); + + if (IS_TUNNEL_ROOT_PKT(p)) { + if (TUNNEL_PKT_TPR(p) == 0) { + /* if this packet is the root and there are no + * more tunnel packets, enqueue it */ + + /* fall through */ + } else { + /* if this is the root and there are more tunnel + * packets, don't add this. It's still referenced + * by the tunnel packets, and we will enqueue it + * when we handle them */ + p->tunnel_verdicted = 1; + mutex_unlock(m); + return; + } + } else { + if (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 */ + PacketEnqueue(q,p->root); + + /* fall through */ + } else { + TUNNEL_DECR_PKT_TPR_NOLOCK(p); + /* fall through */ + } + } + mutex_unlock(m); + } + /* more packets in queue */ if (q->top != NULL) { p->next = q->top; diff --git a/src/source-nfq.c b/src/source-nfq.c index 8a1e9633d9..47f32a9e34 100644 --- a/src/source-nfq.c +++ b/src/source-nfq.c @@ -67,12 +67,13 @@ void NFQSetupPkt (Packet *p, void *data) struct nfq_data *tb = (struct nfq_data *)data; int ret; char *pktdata; + struct nfqnl_msg_packet_hdr *ph; - p->nfq_v.ph = nfq_get_msg_packet_hdr(tb); - if (p->nfq_v.ph != NULL) { - p->nfq_v.id = ntohl(p->nfq_v.ph->packet_id); + ph = nfq_get_msg_packet_hdr(tb); + if (ph != NULL) { + p->nfq_v.id = ntohl(ph->packet_id); //p->nfq_v.hw_protocol = ntohs(p->nfq_v.ph->hw_protocol); - p->nfq_v.hw_protocol = p->nfq_v.ph->hw_protocol; + p->nfq_v.hw_protocol = ph->hw_protocol; } p->nfq_v.mark = nfq_get_nfmark(tb); p->nfq_v.ifi = nfq_get_indev(tb); @@ -265,7 +266,8 @@ int VerdictNFQThreadDeinit(ThreadVars *tv, void *data) { void NFQRecvPkt(NFQThreadVars *t) { int rv, ret; char buf[70000]; -/* XXX what happens on rv == 0? */ + + /* XXX what happens on rv == 0? */ rv = recv(t->fd, buf, sizeof(buf), 0); if (rv < 0) { if (errno == EINTR || errno == EWOULDBLOCK) { @@ -306,14 +308,14 @@ void NFQSetVerdict(NFQThreadVars *t, Packet *p) { int ret; u_int32_t verdict; - if(p->action == ACTION_ALERT){ + if (p->action == ACTION_ALERT) { verdict = NF_ACCEPT; - } else if(p->action == ACTION_PASS){ + } else if (p->action == ACTION_PASS) { verdict = NF_ACCEPT; - } else if(p->action == ACTION_DROP){ + } else if (p->action == ACTION_DROP) { verdict = NF_DROP; - } else if(p->action == ACTION_REJECT||p->action == ACTION_REJECT_DST|| - p->action == ACTION_REJECT_BOTH){ + } else if (p->action == ACTION_REJECT || p->action == ACTION_REJECT_DST || + p->action == ACTION_REJECT_BOTH){ verdict = NF_DROP; } else { /* a verdict we don't know about, drop to be sure */ @@ -331,7 +333,28 @@ void NFQSetVerdict(NFQThreadVars *t, Packet *p) { int VerdictNFQ(ThreadVars *tv, Packet *p, void *data) { NFQThreadVars *ntv = (NFQThreadVars *)data; - NFQSetVerdict(ntv, p); + /* if this is a tunnel packet we check if we are ready to verdict + * already. */ + if (IS_TUNNEL_PKT(p)) { + char verdict = 1; + + pthread_mutex_t *m = p->root ? &p->root->mutex_rtv_cnt : &p->mutex_rtv_cnt; + mutex_lock(m); + /* if there are more tunnel packets than ready to verdict packets, + * we won't verdict this one */ + if ((TUNNEL_PKT_TPR(p)+1) > TUNNEL_PKT_RTV(p)) { + verdict = 0; + } + mutex_unlock(m); + + /* don't verdict if we are not ready */ + if (verdict == 1) { + NFQSetVerdict(ntv, p); + } + } else { + /* no tunnel, verdict normally */ + NFQSetVerdict(ntv, p); + } return 0; } diff --git a/src/source-nfq.h b/src/source-nfq.h index 01d9fa5572..96e50c1f1a 100644 --- a/src/source-nfq.h +++ b/src/source-nfq.h @@ -14,11 +14,11 @@ typedef struct _NFQPacketVars { - struct nfqnl_msg_packet_hdr *ph; + int id; /* this nfq packets id */ + u_int32_t mark; u_int32_t ifi; u_int32_t ifo; - int id; u_int16_t hw_protocol; } NFQPacketVars; diff --git a/src/vips.c b/src/vips.c index 9bbfe7949a..df4b623992 100644 --- a/src/vips.c +++ b/src/vips.c @@ -90,12 +90,13 @@ Packet *SetupPkt (void) return p; } -void SetupTunnelPkt(ThreadVars *t, Packet *parent, u_int8_t *pkt, u_int16_t len, u_int8_t proto) +Packet *TunnelPktSetup(ThreadVars *t, Packet *parent, u_int8_t *pkt, u_int16_t len, u_int8_t proto) { /* get us a packet */ mutex_lock(&packet_q.mutex_q); Packet *p = PacketDequeue(&packet_q); mutex_unlock(&packet_q.mutex_q); + CLEAR_PACKET(p); /* set the root ptr to the lowest layer */ @@ -109,24 +110,10 @@ void SetupTunnelPkt(ThreadVars *t, Packet *parent, u_int8_t *pkt, u_int16_t len, p->pktlen = len; memcpy(&p->pkt, pkt, len); - /* copy queue id's */ -/* XXX review how to insert tunnel packets into the queue decoders use */ - p->pickup_q_id = parent->pickup_q_id; - p->verdict_q_id = parent->verdict_q_id; - /* set tunnel flags */ SET_TUNNEL_PKT(p); - INCR_PKT_TPR(p); - - /* enqueue the packet in the pickup_q */ - PacketQueue *pq = &trans_q[p->pickup_q_id]; - - /* lock mutex and add the packet to the queue */ - mutex_lock(&pq->mutex_q); - PacketEnqueue(pq, p); - pthread_cond_signal(&pq->cond_q); - mutex_unlock(&pq->mutex_q); - return; + TUNNEL_INCR_PKT_TPR(p); + return p; } /* this function should only be called for tunnel packets @@ -146,6 +133,7 @@ void SetupTunnelPkt(ThreadVars *t, Packet *parent, u_int8_t *pkt, u_int16_t len, * one. * */ +#if 0 static Packet * VerdictTunnelPacket(Packet *p) { char verdict = 1; Packet *vp = NULL; @@ -189,44 +177,8 @@ static Packet * VerdictTunnelPacket(Packet *p) { mutex_unlock(&packet_q.mutex_q); return vp; } +#endif #if 0 -void *DecoderThread(void *td) { - ThreadVars *th_v = (ThreadVars *)td; - int run = 1; - u_int32_t cnt = 0; - - printf("DecoderThread[%d] started...\n", th_v->tid); - - while(run) { - Packet *p = th_v->tmqh_in(th_v); - if (p == NULL) { - if (threadflags & VIPS_KILLDECODE) - run = 0; - } else { -#ifdef COUNTERS - cnt++; -#endif /* COUNTERS */ - - if ((IS_TUNNEL_PKT(p))) { - DecodeTunnel(th_v, p, p->pkt, p->pktlen); - } - else { -#ifdef NFQ - DecodeNFQ(th_v, p); -#endif /* NFQ */ - } - - /* lock mutex and add the packet to the queue */ - th_v->tmqh_out(th_v,p); - } - } - - printf("DecoderThread[%d] cnt %u\n", th_v->tid, cnt); - - printf("DecoderThread[%d] ended...\n", th_v->tid); - pthread_exit((void *) 0); -} - void *DetectThread(void *td) { ThreadVars *th_v = (ThreadVars *)td; int run = 1; @@ -268,7 +220,6 @@ void *DetectThread(void *td) { } #endif -//ThreadVars th_v[NUM_THREADS]; int main(int argc, char **argv) {