/* get the bit with idx from the ippair */ static XBit *IPPairBitGet(IPPair *h, uint16_t idx) { GenericVar *gv = IPPairGetStorageById(h, ippair_bit_id); for ( ; gv != NULL; gv = gv->next) { if (gv->type == DETECT_XBITS && gv->idx == idx) { return (XBit *)gv; } } return NULL; }
static Expectation *AppLayerExpectationLookup(Flow *f, int direction, IPPair **ipp) { Address ip_src, ip_dst; if (GetFlowAddresses(f, &ip_src, &ip_dst) == -1) return NULL; *ipp = IPPairLookupIPPairFromHash(&ip_src, &ip_dst); if (*ipp == NULL) { return NULL; } return IPPairGetStorageById(*ipp, g_expectation_id); }
/** \retval 1 ippair timed out wrt xbits * \retval 0 ippair still has active (non-expired) xbits */ int IPPairBitsTimedoutCheck(IPPair *h, struct timeval *ts) { GenericVar *gv = IPPairGetStorageById(h, ippair_bit_id); for ( ; gv != NULL; gv = gv->next) { if (gv->type == DETECT_XBITS) { XBit *xb = (XBit *)gv; if (xb->expire > (uint32_t)ts->tv_sec) return 0; } } return 1; }
static void IPPairBitRemove(IPPair *h, uint16_t idx) { XBit *fb = IPPairBitGet(h, idx); if (fb == NULL) return; GenericVar *gv = IPPairGetStorageById(h, ippair_bit_id); if (gv) { GenericVarRemove(&gv, (GenericVar *)fb); IPPairSetStorageById(h, ippair_bit_id, gv); } }
/** * Create an entry in expectation list * * Create a expectation from an existing Flow. Currently, only Flow between * the two original IP addresses are supported. * * \param f a pointer to the original Flow * \param direction the direction of the data in the expectation flow * \param src source port of the expected flow, use 0 for any * \param dst destination port of the expected flow, use 0 for any * \param alproto the protocol that need to be set on the expected flow * \param data pointer to data that will be attached to the expected flow * * \return -1 if error * \return 0 if success */ int AppLayerExpectationCreate(Flow *f, int direction, Port src, Port dst, AppProto alproto, void *data) { Expectation *iexp = NULL; IPPair *ipp; Address ip_src, ip_dst; Expectation *exp = SCCalloc(1, sizeof(*exp)); if (exp == NULL) return -1; exp->sp = src; exp->dp = dst; exp->alproto = alproto; exp->ts = f->lastts; exp->data = data; exp->direction = direction; if (GetFlowAddresses(f, &ip_src, &ip_dst) == -1) goto error; ipp = IPPairGetIPPairFromHash(&ip_src, &ip_dst); if (ipp == NULL) goto error; iexp = IPPairGetStorageById(ipp, g_expectation_id); exp->next = iexp; IPPairSetStorageById(ipp, g_expectation_id, exp); SC_ATOMIC_ADD(expectation_count, 1); /* As we are creating the expectation, we release lock on IPPair without * setting the ref count to 0. This way the IPPair will be kept till * cleanup */ IPPairUnlock(ipp); return 0; error: SCFree(exp); return -1; }
/* add a flowbit to the flow */ static void IPPairBitAdd(IPPair *h, uint16_t idx, uint32_t expire) { XBit *fb = IPPairBitGet(h, idx); if (fb == NULL) { fb = SCMalloc(sizeof(XBit)); if (unlikely(fb == NULL)) return; fb->type = DETECT_XBITS; fb->idx = idx; fb->next = NULL; fb->expire = expire; GenericVar *gv = IPPairGetStorageById(h, ippair_bit_id); GenericVarAppend(&gv, (GenericVar *)fb); IPPairSetStorageById(h, ippair_bit_id, gv); // bit already set, lets update it's timer } else { fb->expire = expire; } }
/* lock before using this */ int IPPairHasBits(IPPair *ippair) { if (ippair == NULL) return 0; return IPPairGetStorageById(ippair, ippair_bit_id) ? 1 : 0; }