return ponew;
}
+static inline void add_port_object(Port port, PortObject* po, SF_LIST** parray)
+{
+ if ( !parray[port] )
+ {
+ parray[port] = sflist_new();
+ assert(parray[port]);
+ }
+
+ if ( parray[port]->tail && parray[port]->tail->ndata == po )
+ return;
+
+ sflist_add_tail(parray[port], po);
+}
+
+// Update port object lists
+static inline void update_port_lists(PortObject* po, SF_LIST** parray)
+{
+ bool not_flag_set = false;
+
+ PortObjectItem* poi;
+ SF_LNODE* lpos;
+ for ( poi = (PortObjectItem*)sflist_first(po->item_list, &lpos);
+ poi;
+ poi = (PortObjectItem*)sflist_next(&lpos) )
+ {
+ if( poi->any())
+ return;
+
+ else if( poi->one() )
+ {
+ if (poi->negate )
+ {
+ not_flag_set = true;
+ break;
+ }
+
+ add_port_object(poi->lport, po, parray);
+ }
+ else
+ {
+ if (poi->negate )
+ {
+ not_flag_set = true;
+ break;
+ }
+
+ for( int port = poi->lport; port <= poi->hport; port++ )
+ {
+ add_port_object(port, po, parray);
+ }
+ }
+
+ add_port_object(poi->lport, po, parray);
+ }
+
+ if (not_flag_set)
+ {
+ for( int port = 0; port < SFPO_MAX_PORTS; port++ )
+ {
+ add_port_object(port, po, parray);
+ }
+ }
+}
+
+// Create optimized port lists per port
+static inline SF_LIST** create_port_lists(PortTable* p)
+{
+ SF_LIST** parray = (SF_LIST**)snort_calloc(sizeof(SF_LIST*), SFPO_MAX_PORTS);
+ assert(parray);
+
+ PortObject* po;
+ SF_LNODE* lpos;
+ for ( po = (PortObject*)sflist_first(p->pt_polist, &lpos);
+ po;
+ po = (PortObject*)sflist_next(&lpos) )
+ {
+ update_port_lists(po, parray);
+ }
+
+ return parray;
+}
+
+static inline void delete_port_lists(SF_LIST** parray)
+{
+ for ( int port = 0; port < SFPO_MAX_PORTS; port++ )
+ {
+ SF_LIST* list = parray[port];
+ if (list)
+ sflist_free(list);
+ }
+}
+
+
static int PortTableCompileMergePortObjects(PortTable* p)
{
DebugMessage(DEBUG_PORTLISTS, "***\n***Merging PortObjects->PortObjects2\n***\n");
SF_LIST* plx_list = sflist_new();
+ SF_LIST** optimized_pl = create_port_lists(p);
+
/*
* For each port, merge rules from all port objects that touch the port
* into an optimal object, that may be shared with other ports.
PortObject* po;
SF_LNODE* lpos;
- for (po = (PortObject*)sflist_first(p->pt_polist, &lpos);
+ for (po = (PortObject*)sflist_first(optimized_pl[i], &lpos);
po;
po = (PortObject*)sflist_next(&lpos) )
{
- if ( PortObjectHasPort (po, i) )
+ if (pol_cnt < SFPO_MAX_LPORTS )
{
- if ( pol_cnt < SFPO_MAX_LPORTS )
- {
- pol[ pol_cnt++ ] = po;
- }
+ pol[ pol_cnt++ ] = po;
}
}
p->pt_port_object[i] = 0;
DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "\n"); fflush(stdout); );
}
+ delete_port_lists(optimized_pl);
+ snort_free(optimized_pl);
+
/*
* Normalize the Ports so they indicate only the ports that
* reference the composite port object
}
#ifdef DEBUG
+/* Verify all rules in 'po' list are in 'po2' hash
+ *
+ * return 0 - OK
+ * !0 - a rule in po is not in po2
+ */
+static int _po2_include_po_rules(PortObject2* po2, PortObject* po)
+{
+ SF_LNODE* rpos;
+
+ /* get each rule in po */
+ for ( int* pid = (int*)sflist_first(po->rule_list, &rpos);
+ pid;
+ pid = (int*)sflist_next(&rpos) )
+ {
+ /* find it in po2 */
+ int* id = (int*)sfghash_find(po2->rule_hash, pid);
+
+ /* make sure it's in po2 */
+ if ( !id )
+ return 1; /* error */
+ }
+
+ return 0;
+}
+
// consistency check - part 1
// make sure each port is only in one composite port object
static bool PortTableConsistencyCheck(PortTable* p)
return true;
}
-/*
- * Verify all rules in 'po' list are in 'po2' hash
- * return 0 - OK; !0 - a rule in po is not in po2
- */
-static int _po2_include_po_rules(PortObject2* po2, PortObject* po)
-{
- SF_LNODE* rpos;
-
- /* get each rule in po */
- for ( int* pid = (int*)sflist_first(po->rule_list, &rpos);
- pid;
- pid = (int*)sflist_next(&rpos) )
- {
- /* find it in po2 */
- int* id = (int*)sfghash_find(po2->rule_hash, pid);
-
- /* make sure it's in po2 */
- if ( !id )
- return 1; /* error */
- }
-
- return 0;
-}
-
// consistency check - part 2
/*
* This phase checks the Input port object rules/ports against
assert(PortTableConsistencyCheck2(p));
#endif
+#ifdef DEBUG_MSGS
+ if ( Debug::enabled(DEBUG_PORTLISTS) )
+ PortTablePrintPortGroups(p);
+#endif
+
return 0;
}
}
}
+
+/*
+ * Get Next State-NFA, using direct index to speed up search
+ */
+static int List_GetNextStateOpt( ACSM_STRUCT2 * acsm,
+ trans_node_t **acsmTransTableOpt, int state, int input )
+{
+ int index = state * acsm->acsmAlphabetSize + input;
+ trans_node_t * t = acsmTransTableOpt[index];
+
+ if ( t )
+ return t->next_state;
+
+ if( state == 0 )
+ return 0;
+
+ return ACSM_FAIL_STATE2; /* Fail state ??? */
+}
+
+
/*
* Get Next State-NFA
*/
return 0; /* default state */
}
+/*
+ * Put Next State - Head insertion, and transition updates
+ */
+static int List_PutNextStateOpt( ACSM_STRUCT2 * acsm, trans_node_t **acsmTransTableOpt,
+ int state, int input, int next_state )
+{
+ int index = state * acsm->acsmAlphabetSize + input;
+
+ trans_node_t *t = acsmTransTableOpt[index];
+
+ if ( t )
+ {
+ t->next_state = next_state;
+ return 0;
+ }
+
+ /* Definitely not an existing transition - add it */
+ trans_node_t * tnew = (trans_node_t*)AC_MALLOC(sizeof(trans_node_t),
+ ACSM2_MEMORY_TYPE__TRANSTABLE);
+
+ if( !tnew )
+ return -1;
+
+ tnew->key = input;
+ tnew->next_state = next_state;
+ tnew->next = acsm->acsmTransTable[state];
+ acsm->acsmTransTable[state] = tnew;
+ acsm->acsmNumTrans++;
+
+ acsmTransTableOpt[index] = tnew;
+
+ return 0;
+}
+
/*
* Put Next State - Head insertion, and transition updates
*/
return 0;
}
-/*
-*
-*/
-/*
-static int List_FreeList( trans_node_t * t )
-{
- int tcnt=0;
-
- trans_node_t *p;
-
- while( t )
- {
- p = t->next;
- snort_free(t);
- t = p;
- acsm2_total_memory -= sizeof(trans_node_t);
- tcnt++;
- }
-
- return tcnt;
-}
-*/
/*
* Converts row of states from list to a full vector format
*/
-static int List_ConvToFull(ACSM_STRUCT2* acsm, acstate_t state, acstate_t* full)
+static inline int List_ConvToFull(ACSM_STRUCT2* acsm, acstate_t state, acstate_t* full)
{
int tcnt = 0;
trans_node_t* t = acsm->acsmTransTable[state];
- memset(full, 0, acsm->sizeofstate * acsm->acsmAlphabetSize);
-
if (t == NULL)
return 0;
{
acstate_t* FailState = acsm->acsmFailState;
ACSM_PATTERN2** MatchList = acsm->acsmMatchList;
- ACSM_PATTERN2* mlist,* px;
+ ACSM_PATTERN2* mlist, * px;
std::list<int> queue;
+ bool* queue_array = (bool*) snort_calloc( acsm->acsmNumStates, sizeof(bool) );
+
/* Add the state 0 transitions 1st, the states at depth 1, fail to state 0 */
for (int i = 0; i < acsm->acsmAlphabetSize; i++)
{
if ( s )
{
- queue.push_back(s);
+ if ( !queue_array[s] )
+ {
+ queue.push_back(s);
+ queue_array[s] = true;
+ }
FailState[s] = 0;
}
}
/* Build the fail state successive layer of transitions */
for ( auto r : queue )
{
+ queue_array[r] = false;
+
/* Find Final States for any Failure */
for (int i = 0; i < acsm->acsmAlphabetSize; i++)
{
if ( (acstate_t)s != ACSM_FAIL_STATE2 )
{
- queue.push_back(s);
+ if ( !queue_array[s] )
+ {
+ queue.push_back(s);
+ queue_array[s] = true;
+ }
int fs = FailState[r];
/*
* Locate the next valid state for 'i' starting at fs
*/
- while ((acstate_t)(next = List_GetNextState(acsm,fs,i))
- == ACSM_FAIL_STATE2 )
+ while ((acstate_t)(next = List_GetNextState(acsm,fs,i)) == ACSM_FAIL_STATE2 )
{
fs = FailState[fs];
}
}
}
}
+
+ snort_free(queue_array);
}
/*
acstate_t* FailState = acsm->acsmFailState;
std::list<int> queue;
+ bool* queue_array = (bool*) snort_calloc( acsm->acsmNumStates, sizeof(bool) );
+ trans_node_t** acsmTransTableOpt = (trans_node_t**)
+ snort_calloc( acsm->acsmAlphabetSize * acsm->acsmNumStates, sizeof(trans_node_t*) );
+
+ for ( int i = 0; i < acsm->acsmNumStates; i++ )
+ {
+ trans_node_t* t = acsm->acsmTransTable[i];
+ while ( t )
+ {
+ int index = i * acsm->acsmAlphabetSize + t->key;
+ acsmTransTableOpt[index] = t;
+ t = t->next;
+ }
+ }
/* Add the state 0 transitions 1st */
for (int i=0; i<acsm->acsmAlphabetSize; i++)
{
- if ( int s = List_GetNextState(acsm,0,i) )
- queue.push_back(s);
+ if ( int s = List_GetNextStateOpt(acsm, acsmTransTableOpt, 0, i) )
+ {
+ if ( !queue_array[s] )
+ {
+ queue.push_back(s);
+ queue_array[s] = true;
+ }
+ }
}
/* Start building the next layer of transitions */
for ( auto r : queue )
{
+ queue_array[r] = false;
+
/* Process this states layer */
for (int i = 0; i < acsm->acsmAlphabetSize; i++)
{
- int s = List_GetNextState(acsm,r,i);
+ int s = List_GetNextStateOpt(acsm, acsmTransTableOpt, r, i);
- if ( (acstate_t)s != ACSM_FAIL_STATE2 && s!= 0)
+ if ( (acstate_t)s != ACSM_FAIL_STATE2 && s != 0 )
{
- queue.push_back(s);
+ if ( !queue_array[s] )
+ {
+ queue.push_back(s);
+ queue_array[s] = true;
+ }
}
else
{
- cFailState = List_GetNextState(acsm,FailState[r],i);
+ cFailState = List_GetNextStateOpt(acsm, acsmTransTableOpt, FailState[r], i);
if ( cFailState != 0 && (acstate_t)cFailState != ACSM_FAIL_STATE2 )
{
- List_PutNextState(acsm,r,i,cFailState);
+ List_PutNextStateOpt(acsm, acsmTransTableOpt, r, i, cFailState);
}
}
}
}
+
+ snort_free(queue_array);
+ snort_free(acsmTransTableOpt);
}
/*
{
cnt=0;
+ memset(full, 0, acsm->sizeofstate * acsm->acsmAlphabetSize);
List_ConvToFull(acsm, (acstate_t)k, full);
for (i = 0; i < acsm->acsmAlphabetSize; i++)
for (k=0; k<acsm->acsmNumStates; k++)
{
+ memset(full, 0, acsm->sizeofstate * acsm->acsmAlphabetSize);
List_ConvToFull(acsm, (acstate_t)k, full);
first=-1;
for (k=0; k<acsm->acsmNumStates; k++)
{
+ memset(full, 0, acsm->sizeofstate * acsm->acsmAlphabetSize);
List_ConvToFull(acsm, (acstate_t)k, full);
nbands = calcSparseBands(full, band_begin, band_end, acsm->acsmAlphabetSize, zcnt);