/* System includes */ #include #include #include #include #include #include #include /* Our includes */ #include "constants.h" #include "conn_table.h" #include "transaction.h" extern int CHECKID; extern int nt, numapps; /* Table of packets */ struct hash_table* ConnTable; /* Hash related functions we need to define */ int conn_clean(struct conn_stats* data) { /* Never clean unless explicitly demanded */ return 0; } int conn_compare(struct conn_key* k1, struct conn_key* k2) { if (k1 == NULL || k2 == NULL) return 0; if (k1->srcIP == k2->srcIP && k1->dstIP == k2->dstIP && k1->srcport == k2->srcport && k1->dstport == k2->dstport) return 1; else return 0; } unsigned long conn_hash1(struct conn_key* k, unsigned long size) { /* Here we just hash sum of fields */ return (k->srcIP % size + k->dstIP % size + k->srcport + k->dstport) % size; } unsigned long conn_hash2(struct conn_key* k, unsigned long size) { /* Here we just hash sum of fields */ return (1+conn_hash1(k,size-1)); } void create_conntable() { /* Create hash with same min and max size to avoid rehashing since we did not use locks for any operation */ create_hash(&ConnTable, CONN_TABLE_SIZE, CONN_TABLE_SIZE, CONN_TABLE_SIZE, 1, 0, sizeof(struct conn_key), sizeof(struct conn_stats), (int (*)(void*))conn_clean, (int (*)(void*,void*))conn_compare, (unsigned long (*)(void*,unsigned long))conn_hash1); } /* Utility functions that mask hash structure */ /* Get connection's data */ struct conn_stats* get_cdata(int index) { return (struct conn_stats*)(ConnTable->entries[index].data); } /* Get connection's key */ struct conn_key* get_ckey(int index) { return (struct conn_key*)(ConnTable->entries[index].key); } /* Insert new good connection */ long insert_connection(unsigned int address1, unsigned int address2, unsigned short port1, unsigned short port2) { struct conn_key key; struct conn_stats* data; int index, outcome; key.srcIP = address1; key.srcport = port1; key.dstIP = address2; key.dstport = port2; index = insert(&key, ConnTable,&outcome); if (index != NOT_FOUND && outcome == NEW) { data = (struct conn_stats*)ConnTable->entries[index].data; data->nt = 0; return index; } else if (index != NOT_FOUND && outcome == EXISTING) { data = (struct conn_stats*)ConnTable->entries[index].data; return FOUND; } return NOT_FOUND; } int insertTransaction(struct conn_stats* cs, double time, enum type ttype, enum app tapp, enum trans ttrans, unsigned int sIP, int sport, unsigned int dIP, int dport, int tid) { if (cs->nt < MAX_T) { createTransaction(&cs->trans[cs->nt], time, ttype, tapp, ttrans, sIP, sport, dIP, dport, tid); cs->t = cs->trans[cs->nt]; cs->nt++; return TRUE; } return FALSE; } void removeTransaction(struct conn_stats* cs, double time, struct transaction* t) { int i; for(i=0;int;i++) if (cs->trans[i] == t) break; if (i != cs->nt) { int r=i; closeTransaction(&cs->trans[i], time); for(i;int-1;i++) cs->trans[i] = cs->trans[i+1]; if (t == cs->t) cs->t = 0; cs->nt--; } } int isMatchApp(enum app tapp1, enum app tapp2) { if (tapp1 == tapp2) return TRUE; else if ((tapp1 == FTPData || tapp1 == Telnet || tapp1 == FTPTelnet) && (tapp2 == FTPData || tapp2 == Telnet || tapp2 == FTPTelnet)) return TRUE; else return FALSE; } int setActiveTransaction(struct conn_stats* cs, enum app tapp, int identification) { int i; for(i=0;int;i++) { struct transaction* t = cs->trans[i]; if (isMatchApp(t->tapp, tapp) && ((t->ID == identification) || (!CHECKID && t->replyStart == 0 && t->requestStart != 0))) { cs->t = cs->trans[i]; return TRUE; } } return FALSE; } /* Find conneciton and return its index in hash*/ unsigned long find_connection(unsigned int address1, unsigned int address2, unsigned short port1, unsigned short port2) { struct conn_key key; key.srcIP = address1; key.srcport = port1; key.dstIP = address2; key.dstport = port2; return find(&key,ConnTable); } /* Remove packets for a given flow whose inference has ended */ void clean_packets(unsigned int address) { int i; for(i=0;isize;i++) { if(ConnTable->entries[i].state == VALID) { struct conn_key* key = (struct conn_key*)ConnTable->entries[i].key; if (key->srcIP == address || key->dstIP == address) delete(key,ConnTable); } } } /* Remove all records from the table */ void reset_conntable() { int i; for(i=0;isize;i++) { if(ConnTable->entries[i].state == VALID) { struct conn_stats* cs = (struct conn_stats*)ConnTable->entries[i].data; int i; for (i=0; int;i++) free(cs->trans[i]); cs->nt = 0; cs->t = 0; } } reset_table(ConnTable); } /* Remove connection from hash */ void delete_connection(unsigned int address1, unsigned int address2, unsigned short port1, unsigned short port2) { struct conn_key key; int index; struct conn_stats* cs; key.srcIP = address1; key.srcport = port1; key.dstIP = address2; key.dstport = port2; index = find_connection(address1, address2, port1, port2); if (index != NOT_FOUND) { int i; cs = (struct conn_stats*)ConnTable->entries[index].data; for (i=0; int;i++) free(cs->trans[i]); cs->nt = 0; cs->t = 0; delete(&key,ConnTable); } } /* Delete hash table on exit */ void delete_conntable() { int i; if (ConnTable == NULL || ConnTable->entries == NULL) return; for(i=0;isize;i++) { if(ConnTable->entries[i].state == VALID) { int j; struct conn_stats* cs; free(ConnTable->entries[i].key); ConnTable->entries[i].key = NULL; cs = (struct conn_stats*)ConnTable->entries[i].data; for (j=0; jnt;j++) free(cs->trans[j]); cs->nt = 0; cs->t = 0; free(ConnTable->entries[i].data); ConnTable->entries[i].data = NULL; } } free(ConnTable->entries); ConnTable->entries = NULL; free(ConnTable); ConnTable = NULL; }