📄 snort_stream5_session.c
字号:
if (hnode && hnode->data) { /* This is a unique hnode, since the sfxhash finds the * same key before returning this node. */ returned = (Stream5LWSession *)hnode->data; } return returned;}void FreeLWApplicationData(Stream5LWSession *ssn){ Stream5AppData *tmpData, *appData = ssn->appDataList; while (appData) { if (appData->freeFunc && appData->dataPointer) { appData->freeFunc(appData->dataPointer); } tmpData = appData->next; free(appData); appData = tmpData; } ssn->appDataList = NULL;}int RemoveLWSession(Stream5SessionCache *sessionCache, Stream5LWSession *ssn){ mempool_free(&s5FlowMempool, ssn->flowdata); ssn->flowdata = NULL; return sfxhash_remove(sessionCache->hashTable, &(ssn->key));}int DeleteLWSession(Stream5SessionCache *sessionCache, Stream5LWSession *ssn, char *delete_reason){ int ret; /* Save the current mem in use before pruning */ u_int32_t old_mem_in_use = s5_global_config.mem_in_use; /* And save some info on that session */#ifdef SUP_IP6 sfip_t client_ip; sfip_t server_ip;#else struct in_addr client_ip; struct in_addr server_ip;#endif u_int16_t client_port = ntohs(ssn->client_port); u_int16_t server_port = ntohs(ssn->server_port); u_int16_t lw_session_state = ssn->session_state; u_int32_t lw_session_flags = ssn->session_flags;#ifdef TARGET_BASED int16_t app_proto_id = ssn->application_protocol;#endif#ifdef SUP_IP6 sfip_set_ip(&client_ip, &ssn->client_ip); sfip_set_ip(&server_ip, &ssn->server_ip);#else client_ip.s_addr = ssn->client_ip; server_ip.s_addr = ssn->server_ip;#endif /* * Call callback to cleanup the protocol (TCP/UDP/ICMP) * specific session details */ if (sessionCache->cleanup_fcn) sessionCache->cleanup_fcn(ssn); FreeLWApplicationData(ssn); ret = RemoveLWSession(sessionCache, ssn); /* If we're pruning and we clobbered some large amount, log a * message about that session. */ if (s5_global_config.prune_log_max && ((old_mem_in_use - s5_global_config.mem_in_use ) > s5_global_config.prune_log_max)) { char *client_ip_str, *server_ip_str;#ifdef SUP_IP6 client_ip_str = SnortStrdup(inet_ntoa(&client_ip)); server_ip_str = SnortStrdup(inet_ntoa(&server_ip));#else client_ip_str = SnortStrdup(inet_ntoa(client_ip)); server_ip_str = SnortStrdup(inet_ntoa(server_ip));#endif LogMessage("S5: Pruned session from cache that was " "using %d bytes (%s). %s %d --> %s %d "#ifdef TARGET_BASED "(%d) "#endif ": LWstate 0x%x LWFlags 0x%x\n", old_mem_in_use - s5_global_config.mem_in_use, delete_reason, client_ip_str, client_port, server_ip_str, server_port,#ifdef TARGET_BASED app_proto_id,#endif lw_session_state, lw_session_flags); free(client_ip_str); free(server_ip_str); } return ret;}int PurgeLWSessionCache(Stream5SessionCache *sessionCache){ int retCount = 0; Stream5LWSession *idx; SFXHASH_NODE *hnode; if (!sessionCache) return 0; /* Remove all sessions from the hash table. */ hnode = sfxhash_mru_node(sessionCache->hashTable); while (hnode) { idx = (Stream5LWSession *)hnode->data; if (!idx) { sfxhash_free_node(sessionCache->hashTable, hnode); } else { idx->session_flags |= SSNFLAG_PRUNED; DeleteLWSession(sessionCache, idx, "purge whole cache"); } hnode = sfxhash_mru_node(sessionCache->hashTable); retCount++; } return retCount;}int DeleteLWSessionCache(Stream5SessionCache *sessionCache){ int retCount = 0; if (!sessionCache) return 0; retCount = PurgeLWSessionCache(sessionCache); sfxhash_delete(sessionCache->hashTable); free(sessionCache); return retCount;}int PruneLWSessionCache(Stream5SessionCache *sessionCache, u_int32_t thetime, Stream5LWSession *save_me, int memCheck){ Stream5LWSession *idx; u_int32_t pruned = 0; if (thetime != 0) { /* Pruning, look for sessions that have time'd out */ char got_one; idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable); if(idx == NULL) { return 0; } do { got_one = 0; if(idx == save_me) { SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionCache->hashTable); sfxhash_gmovetofront(sessionCache->hashTable, lastNode); lastNode = sfxhash_lru_node(sessionCache->hashTable); if ((lastNode) && (lastNode->data != idx)) { idx = (Stream5LWSession *)lastNode->data; continue; } else { return pruned; } } if((idx->last_data_seen+sessionCache->timeout) < thetime) { Stream5LWSession *savidx = idx; if(sfxhash_count(sessionCache->hashTable) > 1) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n");); savidx->session_flags |= SSNFLAG_TIMEDOUT; DeleteLWSession(sessionCache, savidx, "stale/timeout"); idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable); pruned++; got_one = 1; } else { savidx->session_flags |= SSNFLAG_TIMEDOUT; DeleteLWSession(sessionCache, savidx, "stale/timeout/last ssn"); pruned++; return pruned; } } else { return pruned; } if (pruned > sessionCache->cleanup_sessions) { /* Don't bother cleaning more than 'n' at a time */ break; } } while ((idx != NULL) && (got_one == 1)); return pruned; } else { /* Free up 'n' sessions at a time until we get under the * memcap or free enough sessions to be able to create * new ones. */ unsigned int session_count;#define s5_sessions_in_table() \ ((session_count = sfxhash_count(sessionCache->hashTable)) > 1)#define s5_over_session_limit() \ (session_count > (sessionCache->max_sessions - sessionCache->cleanup_sessions))#define s5_havent_pruned_yet() \ (pruned == 0)#define s5_over_memcap() \ (s5_global_config.mem_in_use > s5_global_config.memcap) while (s5_sessions_in_table() && ((!memCheck && (s5_over_session_limit() || s5_havent_pruned_yet())) || (memCheck && s5_over_memcap() ))) { unsigned int i; DEBUG_WRAP( DebugMessage(DEBUG_STREAM, "S5: Pruning session cache by %d ssns for %s: %d/%d\n", sessionCache->cleanup_sessions, memCheck ? "memcap" : "hash limit", s5_global_config.mem_in_use, s5_global_config.memcap);); idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable); for (i=0;i<sessionCache->cleanup_sessions && (sfxhash_count(sessionCache->hashTable) >= 1); i++) { if(idx != save_me) { idx->session_flags |= SSNFLAG_PRUNED; DeleteLWSession(sessionCache, idx, memCheck ? "memcap/check" : "memcap/stale"); pruned++; idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable); } else { SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionCache->hashTable); sfxhash_gmovetofront(sessionCache->hashTable, lastNode); lastNode = sfxhash_lru_node(sessionCache->hashTable); if ((lastNode) && (lastNode->data == idx)) { /* Okay, this session is the only one left */ break; } idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable); i--; /* Didn't clean this one */ } } /* Nothing (or the one we're working with) in table, couldn't * kill it */ if (!memCheck && (pruned == 0)) { break; } } } if (memCheck && pruned) { LogMessage("S5: Pruned %d sessions from cache for memcap. %d ssns remain. memcap: %d/%d\n", pruned, sfxhash_count(sessionCache->hashTable), s5_global_config.mem_in_use, s5_global_config.memcap); DEBUG_WRAP( if (sfxhash_count(sessionCache->hashTable) == 1) { DebugMessage(DEBUG_STREAM, "S5: Pruned, one session remains\n"); } ); } return pruned;}Stream5LWSession *NewLWSession(Stream5SessionCache *sessionCache, Packet *p, SessionKey *key){ Stream5LWSession *retSsn = NULL; SFXHASH_NODE *hnode; StreamFlowData *flowdata; hnode = sfxhash_get_node(sessionCache->hashTable, key); if (!hnode) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, clean it\n");); if (!PruneLWSessionCache(sessionCache, p->pkth->ts.tv_sec, NULL, 0)) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, no timeouts, clean it\n");); PruneLWSessionCache(sessionCache, 0, NULL, 0); } /* Should have some freed nodes now */ hnode = sfxhash_get_node(sessionCache->hashTable, key);#ifdef DEBUG if (!hnode) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Problem, no freed nodes\n");); }#endif } if (hnode && hnode->data) { retSsn = hnode->data; /* Zero everything out */ memset(retSsn, 0, sizeof(Stream5LWSession)); /* Save the session key for future use */ memcpy(&(retSsn->key), key, sizeof(SessionKey)); retSsn->protocol = key->protocol; retSsn->last_data_seen = p->pkth->ts.tv_sec; retSsn->flowdata = mempool_alloc(&s5FlowMempool); flowdata = retSsn->flowdata->data; boInitStaticBITOP(&(flowdata->boFlowbits), giFlowbitSize, flowdata->flowb); } return retSsn;}u_int32_t HashFunc(SFHASHFCN *p, unsigned char *d, int n) { u_int32_t a,b,c;#ifdef MPLS u_int32_t tmp = 0;#endif #ifdef SUP_IP6 a = *(u_int32_t*)d; /* IPv6 lo[0] */ b = *(u_int32_t*)(d+4); /* IPv6 lo[1] */ c = *(u_int32_t*)(d+8); /* IPv6 lo[2] */ mix(a,b,c); a += *(u_int32_t*)(d+12); /* IPv6 lo[3] */ b += *(u_int32_t*)(d+16); /* IPv6 hi[0] */ c += *(u_int32_t*)(d+20); /* IPv6 hi[1] */ mix(a,b,c); a += *(u_int32_t*)(d+24); /* IPv6 hi[2] */ b += *(u_int32_t*)(d+28); /* IPv6 hi[3] */ c += *(u_int32_t*)(d+32); /* port lo & port hi */ mix(a,b,c); a += *(u_int32_t*)(d+36); /* vlan, protocol, & pad */#ifdef MPLS tmp = *(u_int32_t *)(d+40); if( tmp ) { b += tmp; /* mpls label */ } mix(a,b,c);#endif#else a = *(u_int32_t*)d; /* IPv4 lo */ b = *(u_int32_t*)(d+4); /* IPv4 hi */ c = *(u_int32_t*)(d+8); /* port lo & port hi */ mix(a,b,c); a += *(u_int32_t*)(d+12); /* vlan, protocol, & pad */#ifdef MPLS tmp = *(u_int32_t *)(d+16); if( tmp ) { b += tmp; /* mpls label */ } mix(a,b,c);#endif#endif final(a,b,c); return c;} int HashKeyCmp(const void *s1, const void *s2, size_t n) { UINT64 *a,*b; a = (UINT64*)s1; b = (UINT64*)s2; if(*a - *b) return 1; /* Compares IPv4 lo/hi */ /* SUP_IP6 Compares IPv6 low[0,1] */ a++; b++; if(*a - *b) return 1; /* Compares port lo/hi, vlan, protocol, pad */ /* SUP_IP6 Compares IPv6 low[2,3] */#ifdef SUP_IP6 a++; b++; if(*a - *b) return 1; /* SUP_IP6 Compares IPv6 hi[0,1] */ a++; b++; if(*a - *b) return 1; /* SUP_IP6 Compares IPv6 hi[2,3] */ a++; b++; if(*a - *b) return 1; /* SUP_IP6 Compares port lo/hi, vlan, protocol, pad */#endif#ifdef MPLS a++; b++; if(*a - *b) return 1; /* mpls label and pad */ #endif return 0;}Stream5SessionCache *InitLWSessionCache(int max_sessions, u_int32_t session_timeout, u_int32_t cleanup_sessions, u_int32_t cleanup_percent, Stream5SessionCleanup cleanup_fcn){ Stream5SessionCache *sessionCache = NULL; /* Rule of thumb, size should be 1.4 times max to avoid * collisions. */ int hashTableSize = max_sessions;// int hashTableSize = sfxhash_calcrows((int) (max_sessions * 1.4)); /* Memory required for 1 node: LW Session + Session Key + * Node + NodePtr. */ //int maxSessionMem = max_sessions * ( // sizeof(Stream5LWSession) + // sizeof(SFXHASH_NODE) + // sizeof(SessionKey) + // sizeof(SFXHASH_NODE *)); /* Memory required for table entries */ //int tableMem = (hashTableSize +1) * sizeof(SFXHASH_NODE*); sessionCache = SnortAlloc(sizeof(Stream5SessionCache)); if (sessionCache) { sessionCache->timeout = session_timeout; sessionCache->max_sessions = max_sessions; if (cleanup_percent) { sessionCache->cleanup_sessions = max_sessions * cleanup_percent/100; } else { sessionCache->cleanup_sessions = cleanup_sessions; } if (sessionCache->cleanup_sessions == 0) { sessionCache->cleanup_sessions = 1; } sessionCache->cleanup_fcn = cleanup_fcn; /* Okay, now create the table */ sessionCache->hashTable = sfxhash_new( hashTableSize, sizeof(SessionKey), sizeof(Stream5LWSession), //maxSessionMem + tableMem, 0, NULL, NULL, 1); 0, 0, NULL, NULL, 1); sfxhash_set_max_nodes(sessionCache->hashTable, max_sessions);//#ifdef SUP_IP6 sfxhash_set_keyops(sessionCache->hashTable, HashFunc, HashKeyCmp);//#endif } return sessionCache;}void PrintLWSessionCache(Stream5SessionCache *sessionCache){ DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "%lu sessions active\n", sfxhash_count(sessionCache->hashTable)););}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -