/** \brief Get Flow for packet * * Hash retrieval function for flows. Looks up the hash bucket containing the * flow pointer. Then compares the packet with the found flow to see if it is * the flow we need. If it isn't, walk the list until the right flow is found. * * If the flow is not found or the bucket was emtpy, a new flow is taken from * the queue. FlowDequeue() will alloc new flows as long as we stay within our * memcap limit. * * The p->flow pointer is updated to point to the flow. * * \param tv thread vars * \param dtv decode thread vars (for flow log api thread data) * * \retval f *LOCKED* flow or NULL */ Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p, Flow **dest) { Flow *f = NULL; /* get our hash bucket and lock it */ const uint32_t hash = p->flow_hash; FlowBucket *fb = &flow_hash[hash % flow_config.hash_size]; FBLOCK_LOCK(fb); SCLogDebug("fb %p fb->head %p", fb, fb->head); /* see if the bucket already has a flow */ if (fb->head == NULL) { f = FlowGetNew(tv, dtv, p); if (f == NULL) { FBLOCK_UNLOCK(fb); return NULL; } /* flow is locked */ fb->head = f; fb->tail = f; /* got one, now lock, initialize and return */ FlowInit(f, p); f->flow_hash = hash; f->fb = fb; FlowUpdateState(f, FLOW_STATE_NEW); FlowReference(dest, f); FBLOCK_UNLOCK(fb); return f; } /* ok, we have a flow in the bucket. Let's find out if it is our flow */ f = fb->head; /* see if this is the flow we are looking for */ if (FlowCompare(f, p) == 0) { Flow *pf = NULL; /* previous flow */ while (f) { pf = f; f = f->hnext; if (f == NULL) { f = pf->hnext = FlowGetNew(tv, dtv, p); if (f == NULL) { FBLOCK_UNLOCK(fb); return NULL; } fb->tail = f; /* flow is locked */ f->hprev = pf; /* initialize and return */ FlowInit(f, p); f->flow_hash = hash; f->fb = fb; FlowUpdateState(f, FLOW_STATE_NEW); FlowReference(dest, f); FBLOCK_UNLOCK(fb); return f; } if (FlowCompare(f, p) != 0) { /* we found our flow, lets put it on top of the * hash list -- this rewards active flows */ if (f->hnext) { f->hnext->hprev = f->hprev; } if (f->hprev) { f->hprev->hnext = f->hnext; } if (f == fb->tail) { fb->tail = f->hprev; } f->hnext = fb->head; f->hprev = NULL; fb->head->hprev = f; fb->head = f; /* found our flow, lock & return */ FLOWLOCK_WRLOCK(f); if (unlikely(TcpSessionPacketSsnReuse(p, f, f->protoctx) == 1)) { f = TcpReuseReplace(tv, dtv, fb, f, hash, p); if (f == NULL) { FBLOCK_UNLOCK(fb); return NULL; } } FlowReference(dest, f); FBLOCK_UNLOCK(fb); return f; } } } /* lock & return */ FLOWLOCK_WRLOCK(f); if (unlikely(TcpSessionPacketSsnReuse(p, f, f->protoctx) == 1)) { f = TcpReuseReplace(tv, dtv, fb, f, hash, p); if (f == NULL) { FBLOCK_UNLOCK(fb); return NULL; } } FlowReference(dest, f); FBLOCK_UNLOCK(fb); return f; }
/* FlowGetFlowFromHash * * Hash retrieval function for flows. Looks up the hash bucket containing the * flow pointer. Then compares the packet with the found flow to see if it is * the flow we need. If it isn't, walk the list until the right flow is found. * * If the flow is not found or the bucket was emtpy, a new flow is taken from * the queue. FlowDequeue() will alloc new flows as long as we stay within our * memcap limit. * * The p->flow pointer is updated to point to the flow. * * returns a *LOCKED* flow or NULL */ Flow *FlowGetFlowFromHash(const Packet *p) { Flow *f = NULL; FlowHashCountInit; /* get the key to our bucket */ uint32_t key = FlowGetKey(p); /* get our hash bucket and lock it */ FlowBucket *fb = &flow_hash[key]; FBLOCK_LOCK(fb); SCLogDebug("fb %p fb->head %p", fb, fb->head); FlowHashCountIncr; /* see if the bucket already has a flow */ if (fb->head == NULL) { f = FlowGetNew(p); if (f == NULL) { FBLOCK_UNLOCK(fb); FlowHashCountUpdate; return NULL; } /* flow is locked */ fb->head = f; fb->tail = f; /* got one, now lock, initialize and return */ FlowInit(f, p); f->fb = fb; FBLOCK_UNLOCK(fb); FlowHashCountUpdate; return f; } /* ok, we have a flow in the bucket. Let's find out if it is our flow */ f = fb->head; /* see if this is the flow we are looking for */ if (FlowCompare(f, p) == 0) { Flow *pf = NULL; /* previous flow */ while (f) { FlowHashCountIncr; pf = f; f = f->hnext; if (f == NULL) { f = pf->hnext = FlowGetNew(p); if (f == NULL) { FBLOCK_UNLOCK(fb); FlowHashCountUpdate; return NULL; } fb->tail = f; /* flow is locked */ f->hprev = pf; /* initialize and return */ FlowInit(f, p); f->fb = fb; FBLOCK_UNLOCK(fb); FlowHashCountUpdate; return f; } if (FlowCompare(f, p) != 0) { /* we found our flow, lets put it on top of the * hash list -- this rewards active flows */ if (f->hnext) { f->hnext->hprev = f->hprev; } if (f->hprev) { f->hprev->hnext = f->hnext; } if (f == fb->tail) { fb->tail = f->hprev; } f->hnext = fb->head; f->hprev = NULL; fb->head->hprev = f; fb->head = f; /* found our flow, lock & return */ FLOWLOCK_WRLOCK(f); FBLOCK_UNLOCK(fb); FlowHashCountUpdate; return f; } } } /* lock & return */ FLOWLOCK_WRLOCK(f); FBLOCK_UNLOCK(fb); FlowHashCountUpdate; return f; }
int detection_option_key_compare_func(const void *k1, const void *k2, size_t n) { int ret = DETECTION_OPTION_NOT_EQUAL; const detection_option_key_t *key1 = (detection_option_key_t*)k1; const detection_option_key_t *key2 = (detection_option_key_t*)k2; #ifdef KEEP_THEM_ALLOCATED return DETECTION_OPTION_NOT_EQUAL; #endif if (!key1 || !key2) return DETECTION_OPTION_NOT_EQUAL; if (key1->option_type != key2->option_type) return DETECTION_OPTION_NOT_EQUAL; switch (key1->option_type) { /* Call compare function specific to the key type */ case RULE_OPTION_TYPE_LEAF_NODE: /* Leaf node always not equal. */ break; case RULE_OPTION_TYPE_ASN1: ret = Asn1Compare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_BYTE_TEST: ret = ByteTestCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_BYTE_JUMP: ret = ByteJumpCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_FLOW: ret = FlowCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_CVS: ret = CvsCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_DSIZE: ret = DSizeCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_FLOWBIT: ret = FlowBitsCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_FTPBOUNCE: break; case RULE_OPTION_TYPE_ICMP_CODE: ret = IcmpCodeCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_ICMP_ID: ret = IcmpIdCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_ICMP_SEQ: ret = IcmpSeqCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_ICMP_TYPE: ret = IcmpTypeCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_FRAGBITS: ret = IpFragBitsCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_FRAG_OFFSET: ret = IpFragOffsetCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_ID: ret = IpIdCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_OPTION: ret = IpOptionCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_PROTO: ret = IpProtoCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_SAME: ret = IpSameCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IP_TOS: ret = IpTosCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_IS_DATA_AT: ret = IsDataAtCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_CONTENT: case RULE_OPTION_TYPE_CONTENT_URI: ret = PatternMatchCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_PCRE: ret = PcreCompare(key1->option_data, key2->option_data); break; #ifdef ENABLE_REACT case RULE_OPTION_TYPE_REACT: ret = ReactCompare(key1->option_data, key2->option_data); break; #endif #ifdef ENABLE_RESPOND case RULE_OPTION_TYPE_RESPOND: ret = RespondCompare(key1->option_data, key2->option_data); break; #endif case RULE_OPTION_TYPE_RPC_CHECK: ret = RpcCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_SESSION: ret = SessionCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_TCP_ACK: ret = TcpAckCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_TCP_FLAG: ret = TcpFlagCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_TCP_SEQ: ret = TcpSeqCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_TCP_WIN: ret = TcpWinCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_TTL: ret = TtlCheckCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_URILEN: ret = UriLenCheckCompare(key1->option_data, key2->option_data); break; #ifdef DYNAMIC_PLUGIN case RULE_OPTION_TYPE_HDR_OPT_CHECK: ret = HdrOptCheckCompare(key1->option_data, key2->option_data); case RULE_OPTION_TYPE_PREPROCESSOR: ret = PreprocessorRuleOptionCompare(key1->option_data, key2->option_data); break; case RULE_OPTION_TYPE_DYNAMIC: ret = DynamicRuleCompare(key1->option_data, key2->option_data); break; #endif } return ret; }