📄 spp_conversation.c
字号:
if(p->pkth->ts.tv_sec >= (conv_data.prune_time.tv_sec + conv_data.timeout)) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "Prune time quanta exceeded, pruning " "conversation cache\n");); PruneConvCache(p->pkth->ts.tv_sec, 0, NULL); conv_data.prune_time.tv_sec = p->pkth->ts.tv_sec; }}/* Function: StateRecord* ConvAlloc(unsigned long cur_time) * * Purpose: get a new state record from * Args: * * Returns:n */ StateRecord* ConvAlloc(unsigned long cur_time){ MemBucket* bp; StateRecord *sr; DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "Getting free state\n");); bp = mempool_alloc(&conv_data.state_records); if(bp == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "State Table is full! used: %u max: %u\n", conv_data.max_convs);); return NULL; } /* the container has to know what bucket it came from */ sr = bp->data; sr->bucket = bp; return sr; }void ConvDelete(StateRecord *sr){ /* * need to have a set of call back functions that occur when a * conversation is deleted. * * Eventually, stream4 will be able to delete conversations as * well as this one so that someone using the same pair of ports * all the time will be detected. That's why the function is * exported. */ MemBucket *mb; mb = sr->bucket; ubi_sptRemove(conv_data.cachePtr, (ubi_btNodePtr) sr); mempool_free(&conv_data.state_records, mb);}/* Function: static INLINE void FillConvStats(StateRecord *s, Packet* p) * * Purpose: populate the packet data statistics for this conversation * Args: * * Returns: */ static INLINE void FillConvStats(StateRecord *s, Packet *p){ if(PACKET_FORWARD(p)) { s->bytes_sent += p->caplen; s->dsize_sent += p->dsize; s->pkts_sent++; } else { s->bytes_recv += p->caplen; s->dsize_recv += p->dsize; s->pkts_recv++; }}/*********************************************** * Fills the state record with info ***********************************************/static INLINE void FillStateRecord(StateRecord* s, Packet* p){ /* always store things the same way so that when we have to look up a session, we only have to look them up one way. */ s->ip_proto = p->iph->ip_proto; if(PACKET_FORWARD(p)) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "going forward!\n");); s->sip = p->iph->ip_src.s_addr; s->dip = p->iph->ip_dst.s_addr; s->sport = p->sp; s->dport = p->dp; } else { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "going switcheroo ninja style!\n");); s->sip = p->iph->ip_dst.s_addr; s->dip = p->iph->ip_src.s_addr; s->sport = p->dp; s->dport = p->sp; } DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "s->sip: %X, s->dip: %X " "s->sport: %d s->dport: %d s->ip_proto: %d\n", s->sip, s->dip, s->sport,s->dport,s->ip_proto);); DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "p->iph->ip_src.s_addr: %X, p->iph->ip_dst.s_addr: %X " "p->sp: %d p->dp: %d p->iph->ip_proto: %d\n", (u_int32_t) p->iph->ip_src.s_addr, (u_int32_t) p->iph->ip_dst.s_addr, p->sp,p->dp,p->iph->ip_proto););}/*********************************************** * Find a session from the hash. * returns a pointer to that session. * allocates a new session if not found ***********************************************/static StateRecord* ConvGetSession(Packet* p){ /* We should probably only do the look up once and obliterate the original session */ StateRecord tmp; MemBucket *mb = NULL; StateRecord *ret = NULL; /* FIXME -- this shouldn't be needed */ bzero(&tmp, sizeof(StateRecord)); /* Searches it's own junk */ FillStateRecord(&tmp, p); DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "tmp.sip: %X, tmp.dip: %X " "tmp.sport: %d tmp.dport: %d tmp.ip_proto: %d\n", tmp.sip, tmp.dip, tmp.sport,tmp.dport,tmp.ip_proto);); ret = (StateRecord *) ubi_sptFind(conv_data.cachePtr, (ubi_btItemPtr) &tmp); DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "ret from the sptFind is %p\n", ret);); if(ret == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "Conversation not found... allocating a new one\n");); mb = mempool_alloc(&conv_data.state_records); if(mb == NULL) { /* return NULL, free up some conversations, try to assign again */ DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "mempool is out of state records\n");); return NULL; } DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "allocated: %p\n", mb->data);); ret = (StateRecord *) mb->data; ret->bucket = mb; FillStateRecord(ret, p); if(ubi_sptInsert(conv_data.cachePtr, (ubi_btNodePtr) ret, (ubi_btNodePtr) ret, NULL) == ubi_trFALSE) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "insertion into splay tree failed for ret==%p\n", ret);); return NULL; } DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "insertion into splay tree succeed for ret==%p\n", ret);); /* * When we assign new conversation ID, the greater IP is * always declared to be "sip". This flag check allows us to * know who was the first talker. */ if(PACKET_FORWARD(p)) { ret->conv_flags |= CONV_FORWARD; } else { ret->conv_flags |= CONV_REVERSED; } } else /* ret != NULL */ { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "Conversation found @ %p\n", ret);); ret->conv_flags |= CONV_MULIPACKETS; } return ret;}/* Returns -1 if A < B Returns 1 if A > B Returns 0 if A = B */static int ConvCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr){ StateRecord *A = (StateRecord *) ItemPtr; StateRecord *B = (StateRecord *) NodePtr;#ifdef DEBUG #define IPLEN 256 char sip[IPLEN]; strncpy(sip, inet_ntoa(*(struct in_addr *) &A->sip), IPLEN); DebugMessage(DEBUG_PORTSCAN2,"A %d %s:%d -> %s:%d\n", A->ip_proto, sip, A->sport, inet_ntoa(*(struct in_addr *) &A->dip), A->dport); strncpy(sip, inet_ntoa(*(struct in_addr *) &B->sip), IPLEN); DebugMessage(DEBUG_PORTSCAN2,"B %d %s:%d -> %s:%d\n", B->ip_proto, sip, B->sport, inet_ntoa(*(struct in_addr *) &B->dip), B->dport); #undef IPLEN#endif /* DEBUG */ if(A->sip > B->sip) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,"returning 1\n");); return 1; } if(A->sip < B->sip) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,"returning -1\n");); return -1; } if(A->dip > B->dip) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,"returning 1\n");); return 1; } if(A->dip < B->dip) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,"returning -1\n");); return -1; } /* ok the IPs are equal */ if(A->sport > B->sport) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,"returning 1\n");); return 1; } if(A->sport < B->sport) { DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,"returning -1, count: %u\n", ubi_trCount(conv_data.cachePtr) );); return -1; } if(A->dport > B->dport) return 1; if(A->dport < B->dport) return -1; /* now lets check the protocol, maybe this should be first but I think that most networks only see tcp traffic with a little DNS -- cmg */ if(A->ip_proto > B->ip_proto) return 1; if(A->ip_proto < B->ip_proto) return -1;#ifdef DEBUG DebugMessage(DEBUG_CONVERSATION, "returning 0 for session equalness\n"); DebugMessage(DEBUG_CONVERSATION, "A->sip: %u B->sip: %u A->sport: %d" "B->dport: %d A->ip_proto %d B->ip_proto: %d\n", A->sip, B->sip, A->sport, B->sport, A->ip_proto, B->ip_proto );#endif /* DEBUG */ return 0;}static int PruneConvCache(u_int32_t now, int tokill, StateRecord *keeper){ StateRecord *idx; u_int32_t pruned = 0; if(ubi_trCount(conv_data.cachePtr) <= 1) { return 0; } /* Number of things that need to be deleted */ if(tokill == 0) { idx = (StateRecord *) ubi_btFirst((ubi_btNodePtr)conv_data.cachePtr->root); if(idx == NULL) { return 0; } do { if(idx == keeper) { idx = (StateRecord *) ubi_btNext((ubi_btNodePtr)idx); continue; } if((idx->last_time.tv_sec+conv_data.timeout) < now) { StateRecord *savidx = idx; if(ubi_trCount(conv_data.cachePtr) > 1) { idx = (StateRecord *) ubi_btNext((ubi_btNodePtr)idx); DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION, "pruning stale conversation\n");); ConvDelete(savidx); pruned++; } else { ConvDelete(savidx); pruned++; return pruned; } } else { if(idx != NULL && ubi_trCount(conv_data.cachePtr)) { idx = (StateRecord *) ubi_btNext((ubi_btNodePtr)idx); } else { return pruned; } } } while(idx != NULL); return pruned; } else { while(tokill-- && ubi_trCount(conv_data.cachePtr) > 1) { idx = (StateRecord *) ubi_btLeafNode((ubi_btNodePtr)conv_data.cachePtr); if(idx != keeper) ConvDelete(idx); }#ifdef DEBUG if(tokill > 0) { DebugMessage(DEBUG_STREAM, "Emptied out the conversation cache" "completely tokill: %d\n", tokill); }#endif /* DEBUG */ return 0; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -