int add_detection_option(option_type_t type, void *option_data, void **existing_data) { SnortConfig *sc = snort_conf_for_parsing; detection_option_key_t key; if (sc == NULL) { FatalError("%s(%d) Snort config is NULL.\n", __FILE__, __LINE__); } if (sc->detection_option_hash_table == NULL) sc->detection_option_hash_table = DetectionHashTableNew(); if (!option_data) { /* No option data, no conflict to resolve. */ return DETECTION_OPTION_EQUAL; } key.option_type = type; key.option_data = option_data; *existing_data = sfxhash_find(sc->detection_option_hash_table, &key); if (*existing_data) { return DETECTION_OPTION_EQUAL; } sfxhash_add(sc->detection_option_hash_table, &key, option_data); return DETECTION_OPTION_NOT_EQUAL; }
/** * * @param sip - source IP address * @param dip - destination IP address * @param sport - server sport number * @param file_sig - file signature * @param expiry - session expiry in seconds. */ int file_resume_block_add_file(void *pkt, uint32_t file_sig, uint32_t timeout, File_Verdict verdict, uint32_t file_type_id, uint8_t *signature) { FileHashKey hashKey; SFXHASH_NODE *hash_node = NULL; FileNode *node; FileNode new_node; snort_ip_p srcIP; snort_ip_p dstIP; Packet *p = (Packet *)pkt; time_t now = p->pkth->ts.tv_sec; srcIP = GET_SRC_IP(p); dstIP = GET_DST_IP(p); IP_COPY_VALUE(hashKey.dip, dstIP); IP_COPY_VALUE(hashKey.sip, srcIP); hashKey.file_sig = file_sig; hash_node = sfxhash_find_node(fileHash, &hashKey); if (hash_node) { if (!(node = hash_node->data)) sfxhash_free_node(fileHash, hash_node); } else node = NULL; if (node) { node->expires = now + timeout; updateFileNode(node, verdict, file_type_id, signature); } else { DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Adding file node\n");); updateFileNode(&new_node, verdict, file_type_id, signature); /* * use the time that we keep files around * since this info would effectively be invalid * after that anyway because the file that * caused this will be gone. */ new_node.expires = now + timeout; /* Add it to the table */ if (sfxhash_add(fileHash, &hashKey, &new_node) != SFXHASH_OK) { /* Uh, shouldn't get here... * There is already a node or couldn't alloc space * for key. This means bigger problems, but fail * gracefully. */ DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Failed to add file node to hash table\n"););
int server_stats_add_ipv4(SERVER_STATS *ssp, u_int8_t ip_proto, u_int32_t address, u_int16_t port, u_int32_t *retcount) { SERVER_KEY *kp = &s_key; u_int32_t one = 1; u_int32_t *hitcountp = NULL; int ret; #ifdef DEBUG u_int32_t hostaddress = ntohl(address); #endif /* DEBUG */ if(ssp == NULL || retcount == NULL) return FLOW_ENULL; /* calls to this subsystem should only be made if we are really watching this. */ FLOWASSERT(ipset_contains(ssp->ipv4_watch, &hostaddress, IPV4_FAMILY)); /* make the key */ kp->address = address; kp->port = port; kp->protocol = ip_proto; /* find the key, add 1 to it or add a new node to the table */ ret = sfxhash_add(ssp->ipv4_table, kp, &one); switch(ret) { case SFXHASH_NOMEM: /* NOMEM means that we would add it if we could but we're * hard-core out of space. So, just assume we added it. */ case SFXHASH_OK: *retcount = 1; break; case SFXHASH_INTABLE: hitcountp = (u_int32_t *) sfxhash_mru(ssp->ipv4_table); /* never let us wrap around to less hits */ if(!hitcountp) { /* this is an odd error! */ return FLOW_BADJUJU; } else { if((*hitcountp) < SERVER_STATS_MAX_HITCOUNT) { (*hitcountp)++; } } break; } return FLOW_SUCCESS; }
int scoreboard_add(SCOREBOARD *sbp, u_int32_t *address, SCORE_ENTRY **sepp) { int ret; int hash_add_ret; if(!sbp) { return FLOW_ENULL; } hash_add_ret = sfxhash_add(sbp->ipv4_table, address, &s_init_entry); switch(hash_add_ret) { case SFXHASH_OK: if(scoreboard_mru(sbp,sepp) != FLOW_SUCCESS) { /* something's wrong because we just added this thing!\n */ flow_printf("sba: Unable to find a key I just added!\n"); ret = FLOW_BADJUJU; } else { ret = FLOW_SUCCESS; } break; case SFXHASH_NOMEM: ret = FLOW_ENOMEM; break; case SFXHASH_INTABLE: default: ret = FLOW_EINVALID; break; } return ret; }
void checkSessionForAFIndicator(SFSnortPacket *p, int dir, const tAppIdConfig *pConfig, tAppId indicator) { AFElement *ind_element; if (!(ind_element = (AFElement*)sfxhash_find(pConfig->AF_indicators, &indicator))) return; rekeyMasterAFActKey(p, dir, ind_element->forecast); AFActVal *test_active_value; if ((test_active_value = (AFActVal*)sfxhash_find(pConfig->AF_actives, &master_key))) { test_active_value->last = GetPacketRealTime; test_active_value->target = ind_element->target; return; } AFActVal new_active_value; new_active_value.target = ind_element->target; new_active_value.last = GetPacketRealTime; sfxhash_add(pConfig->AF_actives, &master_key, &new_active_value); }
/** ** Get a tracker node by either finding one or starting a new one. We may ** return NULL, in which case we wait till the next packet. */ static int ps_tracker_get(PS_TRACKER **ht, PS_HASH_KEY *key) { int iRet; *ht = (PS_TRACKER *)sfxhash_find(portscan_hash, (void *)key); if(!(*ht)) { iRet = sfxhash_add(portscan_hash, (void *)key, NULL); if(iRet == SFXHASH_OK) { *ht = (PS_TRACKER *)sfxhash_mru(portscan_hash); if(!(*ht)) return -1; ps_tracker_init(*ht); } else { return -1; } } return 0; }
/* * Test a global thresholding object */ static inline int sfthd_test_global( SFXHASH *global_hash, THD_NODE * sfthd_node, unsigned gen_id, /* from current event */ unsigned sig_id, /* from current event */ snort_ip_p sip, /* " */ snort_ip_p dip, /* " */ time_t curtime ) { THD_IP_GNODE_KEY key; THD_IP_NODE data, *sfthd_ip_node; int status=0; snort_ip_p ip; tSfPolicyId policy_id = getRuntimePolicy(); #ifdef THD_DEBUG printf("THD_DEBUG-GLOBAL: gen_id=%u, sig_id=%u\n",gen_id,sig_id); printf("THD_DEBUG: Global THD_NODE IP=%s,",printIP((unsigned)sfthd_node->ip_address) ); printf(" MASK=%s\n",printIP((unsigned)sfthd_node->ip_mask) ); printf("THD_DEBUG: PKT SIP=%s\n",printIP((unsigned)sip) ); printf("THD_DEBUG: PKT DIP=%s\n",printIP((unsigned)dip) ); fflush(stdout); #endif /* -1 means don't do any limit or thresholding */ if ( sfthd_node->count == THD_NO_THRESHOLD) { #ifdef THD_DEBUG printf("\n...No Threshold applied for this object\n"); fflush(stdout); #endif return 0; } /* Get The correct IP */ if (sfthd_node->tracking == THD_TRK_SRC) ip = sip; else ip = dip; /* Check for and test Suppression of this event to this IP */ if( sfthd_node->type == THD_TYPE_SUPPRESS ) { #ifdef THD_DEBUG printf("THD_DEBUG: G-SUPPRESS NODE Testing...\n");fflush(stdout); #endif return sfthd_test_suppress(sfthd_node, ip); } /* * Go on and do standard thresholding */ /* Set up the key */ key.ip = IP_VAL(ip); key.gen_id = sfthd_node->gen_id; key.sig_id = sig_id; key.policyId = policy_id; /* Set up a new data element */ data.count = 1; data.prev = 0; data.tstart = data.tlast = curtime; /* Event time */ /* Check for any Permanent sig_id objects for this gen_id or add this one ... */ status = sfxhash_add(global_hash, (void*)&key, &data); if (status == SFXHASH_INTABLE) { /* Already in the table */ sfthd_ip_node = global_hash->cnode->data; /* Increment the event count */ sfthd_ip_node->count++; } else if (status != SFXHASH_OK) { /* hash error */ return 1; /* check the next threshold object */ } else { /* Was not in the table - it was added - work with our copy of the data */ sfthd_ip_node = &data; } return sfthd_test_non_suppress(sfthd_node, sfthd_ip_node, curtime); }
int flowcache_newflow(FLOWCACHE *flowcachep, FLOWKEY *keyp, FLOW **flowpp) { static int run_once = 1; #ifdef FLOW_PERF_FIX FLOW *newflow = NULL; SFXHASH_NODE *new_node = NULL; #else static FLOW zeroflow; #endif static FLOWKEY searchkey; int ret; if(!flowcachep || !keyp || !flowpp) { return FLOW_ENULL; } FCS_new(flowcachep, keyp); if(run_once) { /* all the time that we're running this, we're actually going to be filling in the key, and having zero'd out counters */ #ifndef FLOW_PERF_FIX memset(&zeroflow, 0, sizeof(FLOW)); #endif memset(&searchkey, 0, sizeof(FLOWKEY)); run_once = 0; } flowkey_normalize(&searchkey, keyp); #ifdef FLOW_PERF_FIX /* This just eliminates a memcpy. */ /* Since we're using auto node recovery, we should get a node back * here that has a data pointer. */ /* flow_init resets the internal key & stats to zero. */ new_node = sfxhash_get_node(flowcachep->ipv4_table, &searchkey); if (new_node && new_node->data) { newflow = new_node->data; if(flow_init(newflow, keyp->protocol, keyp->init_address, keyp->init_port, keyp->resp_address, keyp->resp_port)) { return FLOW_ENULL; } ret = SFXHASH_OK; } else { ret = SFXHASH_NOMEM; } #else if(flow_init(&zeroflow, keyp->protocol, keyp->init_address, keyp->init_port, keyp->resp_address, keyp->resp_port)) { return FLOW_ENULL; } ret = sfxhash_add(flowcachep->ipv4_table, &searchkey, &zeroflow); #endif switch(ret) { case SFXHASH_OK: if(flowcache_mru(flowcachep,flowpp) != FLOW_SUCCESS) { /* something's wrong because we just added this thing!\n */ flow_printf("Unable to find a key I just added!\n"); return FLOW_BADJUJU; } if(init_flowdata(flowcachep, *flowpp)) { return FLOW_BADJUJU; } return FLOW_SUCCESS; case SFXHASH_NOMEM: return FLOW_ENOMEM; case SFXHASH_INTABLE: default: return FLOW_EINVALID; } }
/** * load a server stats file * * fmt: * * 1 char for the family * hex network representation of the IP (8 chars) * hex network representation of the port (2 chars) * 1 char for the ip_proto (1 char) * hex network representation of the hit count (4 chars) * * yes this record format is hard to use but it's easy to parse! :> * * @param ssp server stats pointer * @param filename filename to load * * @return FLOW_SUCCESS on sucess */ int server_stats_load(SERVER_STATS *ssp, char *filename) { SERVER_KEY *kp = &s_key; size_t rsize; unsigned char buf[STATSREC_SIZE]; int fd; if(!filename || !ssp) return FLOW_ENULL; fd = open(filename, O_RDONLY); if(fd < 0) { return FLOW_NOTFOUND; } /* this is a crappy parser... that's par for the course */ while((rsize = read(fd, &buf, STATSREC_SIZE) == STATSREC_SIZE) > 0) { u_int8_t family; u_int32_t ipv4_address; u_int16_t port; u_int8_t protocol; u_int32_t count; if(rsize != STATSREC_SIZE) { /* this record was truncated */ close(fd); return FLOW_EINVALID; } memcpy(&family, buf + FAMILY_OFFSET, FAMILY_SIZE); memcpy(&ipv4_address, buf + IPV4_OFFSET, IPV4_SIZE); memcpy(&port, buf + PORT_OFFSET, PORT_SIZE); memcpy(&protocol, buf + IP_PROTO_OFFSET, IP_PROTO_SIZE); memcpy(&count, buf + COUNT_OFFSET, COUNT_SIZE); /* make sure that we're reading a format we understand */ if(family != '4') { close(fd); return FLOW_EINVALID; } kp->protocol = ntohs(protocol); kp->address = ntohl(ipv4_address); kp->port = ntohs(port); count = ntohl(count); if(sfxhash_add(ssp->ipv4_table, kp, &count) != 0) { close(fd); return FLOW_BADJUJU; } } close(fd); return FLOW_SUCCESS; }
/* * Hash test program : use 'sfxhash 1000 50000' to stress the Auto_NodeRecover feature */ int main ( int argc, char ** argv ) { int i; SFXHASH * t; SFXHASH_NODE * n; char strkey[256], strdata[256], * p; int num = 100; int mem = 0; memset(strkey,0,20); memset(strdata,0,20); if( argc > 1 ) { num = atoi(argv[1]); } if( argc > 2 ) { mem = atoi(argv[2]); } /* Create a Hash Table */ t = sfxhash_new( 100, /* one row per element in table, when possible */ 20, /* key size : padded with zeros */ 20, /* data size: padded with zeros */ mem, /* max bytes, 0=no max */ 1, /* enable AutoNodeRecovery */ anrfree, /* provide a function to let user know we want to kill a node */ usrfree, /* provide a function to release user memory */ 1); /* Recycle nodes */ if(!t) { printf("Low Memory!\n"); exit(0); } /* Add Nodes to the Hash Table */ for(i=0;i<num;i++) { snprintf(strkey, sizeof(strkey), "KeyWord%5.5d",i+1); strkey[sizeof(strkey) - 1] = '\0'; snprintf(strdata, sizeof(strdata), "KeyWord%5.5d",i+1); strdata[sizeof(strdata) - 1] = '\0'; //strupr(strdata); sfxhash_add( t, strkey /* user key */ , strdata /* user data */ ); } /* Find and Display Nodes in the Hash Table */ printf("\n** FIND KEY TEST\n"); for(i=0;i<num;i++) { snprintf(strkey, sizeof(strkey) - 1, "KeyWord%5.5d",i+1); strkey[sizeof(strkey) - 1] = '\0'; p = (char*) sfxhash_find( t, strkey ); if(p)printf("Hash-key=%*s, data=%*s\n", strlen(strkey),strkey, strlen(strkey), p ); } /* Show memcap memory */ printf("\n...******\n"); sfmemcap_showmem(&t->mc); printf("...******\n"); /* Display All Nodes in the Hash Table findfirst/findnext */ printf("\n...FINDFIRST / FINDNEXT TEST\n"); for( n = sfxhash_findfirst(t); n != 0; n = sfxhash_findnext(t) ) { printf("hash-findfirst/next: n=%x, key=%s, data=%s\n", n, n->key, n->data ); /* remove node we are looking at, this is first/next safe. */ if( sfxhash_remove(t,n->key) ) { printf("...ERROR: Could not remove the key node!\n"); } else { printf("...key node removed\n"); } } printf("...Auto-Node-Recovery: %d recycle attempts, %d completions.\n",t->anr_tries,t->anr_count); /* Free the table and it's user data */ printf("...sfxhash_delete\n"); sfxhash_delete( t ); printf("\nnormal pgm finish\n\n"); return 0; }
/** * * @param sip - source IP address * @param dip - destination IP address * @param sport - server sport number * @param file_sig - file signature * @param expiry - session expiry in seconds. */ int file_resume_block_add_file(void *pkt, uint32_t file_sig, uint32_t timeout, File_Verdict verdict, uint32_t file_type_id, uint8_t *signature) { FileHashKey hashKey; SFXHASH_NODE *hash_node = NULL; FileNode *node; FileNode new_node; sfaddr_t* srcIP; sfaddr_t* dstIP; Packet *p = (Packet*)pkt; time_t now = p->pkth->ts.tv_sec; srcIP = GET_SRC_IP(p); dstIP = GET_DST_IP(p); sfaddr_copy_to_raw(&hashKey.dip, dstIP); sfaddr_copy_to_raw(&hashKey.sip, srcIP); hashKey.file_sig = file_sig; #ifdef HAVE_DAQ_DP_ADD_DC { DAQ_DC_Params params; memset(¶ms, 0, sizeof(params)); params.flags = DAQ_DC_ALLOW_MULTIPLE | DAQ_DC_PERSIST; params.timeout_ms = 5 * 60 * 1000; /* 5 minutes */ if (p->packet_flags & PKT_FROM_CLIENT) DAQ_Add_Dynamic_Protocol_Channel(p, srcIP, 0, dstIP, p->dp, GET_IPH_PROTO(p), ¶ms); else if (p->packet_flags & PKT_FROM_SERVER) DAQ_Add_Dynamic_Protocol_Channel(p, dstIP, 0, srcIP, p->sp, GET_IPH_PROTO(p), ¶ms); } #endif hash_node = sfxhash_find_node(fileHash, &hashKey); if (hash_node) { if (!(node = hash_node->data)) sfxhash_free_node(fileHash, hash_node); } else node = NULL; if (node) { node->expires = now + timeout; updateFileNode(node, verdict, file_type_id, signature); } else { DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Adding file node\n");); updateFileNode(&new_node, verdict, file_type_id, signature); /* * use the time that we keep files around * since this info would effectively be invalid * after that anyway because the file that * caused this will be gone. */ new_node.expires = now + timeout; /* Add it to the table */ if (sfxhash_add(fileHash, &hashKey, &new_node) != SFXHASH_OK) { /* Uh, shouldn't get here... * There is already a node or couldn't alloc space * for key. This means bigger problems, but fail * gracefully. */ DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Failed to add file node to hash table\n"););