📄 sfportobject.c
字号:
/* Search for the Port Object in the input list, by address */ for(pox =(PortObject*)sflist_firstpos(p->pt_polist,&lpos); pox!=0; pox =(PortObject*)sflist_nextpos(p->pt_polist,&lpos) ) { if( pox == po ) { /* already in list - just return */ return 0; } } /* Save the users port object, if not already in the list */ if( sflist_add_tail(p->pt_polist,po) ) return -1; return 0;}/* Hash routine for hashing PortObjects as Keys p - SFHASHFCN * d - PortObject * n = 4 bytes (sizeof*) - not used Don't use this for type=ANY port objects*/staticunsigned PortObject_hash( SFHASHFCN * p, unsigned char *d, int n ){ unsigned hash = p->seed; PortObjectItem * poi; PortObject * po; SF_LNODE * pos; n = n; /* This quiets a Win32 warning */ po = *(PortObject**) d; /* hash up each item */ for(poi =(PortObjectItem*)sflist_firstpos(po->item_list,&pos); poi!=0; poi =(PortObjectItem*)sflist_nextpos(po->item_list,&pos) ) { switch(poi->type) { case PORT_OBJECT_PORT: hash *= p->scale; hash += poi->lport & 0xff; hash *= p->scale; hash += (poi->lport >> 8) & 0xff; break; case PORT_OBJECT_RANGE: hash *= p->scale; hash += poi->lport & 0xff; hash *= p->scale; hash += (poi->lport >> 8) & 0xff; hash *= p->scale; hash += poi->hport & 0xff; hash *= p->scale; hash += (poi->hport >> 8) & 0xff; break; } } return hash ^ p->hardener;}/* Hash Key Comparisons for treating PortObjects as Keys return values memcmp style*/staticint PortObject_keycmp( const void *a , const void *b, size_t n ){ n = n; return !PortObjectEqual( *(PortObject**)a, *(PortObject**)b );}/* * plx_t is a variable sized array of pointers */typedef struct { int n; void ** p;}plx_t;staticplx_t * plx_new( void * pv[], int n ){ plx_t * p; int i; if(!pv || n < 0) return NULL; p = SnortAlloc(sizeof(plx_t)); p->p = SnortAlloc(n * sizeof(void*)); p->n = n; for(i=0;i<n;i++) { p->p[i] = pv[i]; } return p;}void plx_free(void * p ){ plx_t * plx=(plx_t*)p; if( !plx ) return; if( plx->p ) free(plx->p); free( p );}#ifdef DEBUGstaticvoid plx_print(plx_t * p){ DEBUG_WRAP( int i; DebugMessage(DEBUG_PORTLISTS, "plx-n=%d\n", p->n); for(i=0;i<p->n;i++) DebugMessage(DEBUG_PORTLISTS, "plx[%d]=%lu\n", i, p->p[i]); );}#endif/* * hash function for plx_t types */staticunsigned plx_hash( SFHASHFCN * p, unsigned char *d, int n ){ unsigned hash = p->seed; int i,k; plx_t * plx; n = n; /* To silence a Win32 warning */ plx = *(plx_t**)d; for(i=0;i<plx->n;i++) { unsigned char * pc = (unsigned char*)&plx->p[i]; for(k=0;k<sizeof(void*);k++) { hash *= p->scale; hash += pc[k]; } } return hash ^ p->hardener;}/* for sorting an array of pointers */static INLINEint p_keycmp( const void *a , const void *b ){ if( *(unsigned long**)a < *(unsigned long**)b ) return -1; if( *(unsigned long**)a > *(unsigned long**)b ) return 1; return 0; /* they are equal */}/* Hash Key Comparisons for treating plx_t types as Keys return values memcmp style this only needs to produce 0 => exact match, otherwise not. -1, and +1 are not strictly needed, they could both return a non zero value foe the purposes of hashing and searching.*/staticint plx_keycmp( const void *a , const void *b, size_t n ){ int i, cmp; plx_t * pla = *(plx_t**)a; plx_t * plb = *(plx_t**)b; n = n; /* To silence a Win32 warning */ if( pla->n < plb->n ) return -1; if( pla->n > plb->n ) return 1; for(i=0;i<pla->n;i++) { if((cmp = p_keycmp(&pla->p[i], &plb->p[i]))) return cmp; } return 0; /* they are equal */}/* * Merge multiple PortObjects into a final PortObject2, * this merges ports and rules. * * merge po's in pol, find a previous instance add it. * * This is done as follows: * 1) check if it's in the plx table-mhashx, this uses the list of * addresses of the Input PortObjects as it's key, not the ports. * This is quick and does not require assembling/merging the port * objects intoa PortObject2 1st. * 2) if found were done, otherwise * 3) make a merged PortObejct2 * 4) Try adding the PortObejct2 to it's table - mhash * a) if it adds go on, else * b) if it's already in the table * 1) get the one in the table * 2) add any ports in the just created one * 3) free the one just created * 5) Create a plx object * 6) Add the plx object to the plx Table * 1) if it's already in the object - fail this contradicts 1) * 7) return the create PortObject2, or the one retrived from the * PortObject table. * * pol - list of input PortObject pointers * pol_cnt- count in 'pol' * mhash - stores the merged ports, using the merged port objects port list as a key. * mhashx - stores plx keys, and PortObject2 *'s as data for the final merged port objects, * the plx keys provide a quicker way to compare port lists to ensure if two ports * are using the same set of rules (port objects). * mhash and mhashx reference the same port objects as data, but use different keys for lookup * purposes. Once we perform a merge we store the results, using the 'plx' as the key for future lookup. * plx - key to use to lookup and store the merged port object * * */staticPortObject2 * _merge_N_pol( SFGHASH * mhash, SFGHASH * mhashx, PortObject * pol[], int pol_cnt, plx_t * plx ){ PortObject2 * ponew; PortObject2 * pox; plx_t * plx_tmp; int stat; int i; /* * Check for the merged port object in the plx table */ DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "++++n=%d sfghash_find-mhashx\n",pol_cnt);); ponew = sfghash_find( mhashx, &plx ); if( ponew ) { DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "n=%d ponew found in mhashx\n",pol_cnt);); return ponew; } DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "n=%d posnew not found in mhashx\n",pol_cnt);); /* * Merge the port objects together - ports and rules */ /* Dup the 1st port objects rules and ports */ ponew = PortObjectDup2( pol[0] ); if( !ponew ) { FatalError("Could not Dup2\n"); } /* Merge in all the other por object rules and ports */ if( pol_cnt > 1 ) { for(i=1;i<pol_cnt;i++) { DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"*** %d rules in object %d\n", pol[i]->rule_list->count,i);); PortObjectAppendEx2( ponew, pol[i] ); DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "*** merged port-object[%d], %d rules\n", i,ponew->rule_hash->count);); } PortObjectNormalize( (PortObject*)ponew ); } DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "*** merged %d port objects, %d rules\n", pol_cnt,ponew->rule_hash->count);); DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"*** merged ponew - follows: \n");); // PortObjectPrint2(ponew); /* * Add the Merged PortObject2 to tha PortObject2 hash table * keyed by ports. */ DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"n=%d sfghash_add-mhash\n",pol_cnt);); stat =sfghash_add( mhash, &ponew, ponew ); if( stat != SFGHASH_OK ) { /* This is possible since PLX hash on a different key */ if( stat == SFGHASH_INTABLE ) { DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"n=%d sfghash_add-mhash ponew in table\n",pol_cnt);); DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"n=%d sfghash_find-mhash ponew\n",pol_cnt);); pox = sfghash_find(mhash,&ponew); if( pox ) { PortObjectAppendRules3(pox,ponew); DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"sfportobject.c: merge_N_pol() line=%d SFGHASH_INTABLE\n",__LINE__);); PortObjectFree2( ponew ); ponew = pox; DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"n=%d sfghash_find-mhash ponew found, new rules merged\n",pol_cnt);); } else { FatalError("mhash add/find error n=1 \n",pol_cnt); } } else { FatalError("Could not add ponew to hash table- error\n"); } } DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"***%d ports merged object added to mhash table\n",pol_cnt);); /* * Create a plx node and add it to plx table * as the key with the merged port object as the data */ plx_tmp = plx_new( (void**)pol, pol_cnt); if(!plx_tmp) { FatalError("plx_new: memory alloc error\n"); } /* * Add the plx node to the PLX hash table */ DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"n=%d sfghash_add-mhashx\n",pol_cnt);); stat = sfghash_add( mhashx, &plx_tmp, ponew ); if( stat != SFGHASH_OK ) { if( stat == SFGHASH_INTABLE ) { FatalError("Could not add merged plx to PLX HASH table-INTABLE\n"); } else { FatalError("Could not add merged plx to PLX HASH table\n"); } } DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"Added-%d Merged Rule Groups to PLX HASH\n",pol_cnt);); /* * Validate hash table entry */ if( sfghash_find( mhashx, &plx_tmp ) != ponew ) { FatalError("Find after add failed on PLX HASH table key\n"); } return ponew;}/* * Merge Input Port Objects into rule collections that are particular to * each port. We store the results as objects and point to these in the * pt_port_object[MAX_PORTS] array. * * We use plx_t types to manage tracking and testing for merged large * rule groups, and merged small port groups. * * mhash - table of merged port objects ( built and used here ) * mhashx - table of plx_t objects ( built and used here ) * pol - list of input port objects touching the current port * pol_cnt - number of port obejcts in port list * lcnt - large rule count * */staticPortObject2 * PortTableCompileMergePortObjectList2(SFGHASH * mhash, SFGHASH * mhashx, PortObject * pol[], int pol_cnt, int lcnt ){ PortObject2 * ponew = NULL; PortObject2 * posnew = NULL; static PortObject * polarge[SFPO_MAX_LPORTS]; static PortObject * posmall[SFPO_MAX_LPORTS]; int nlarge = 0; int nsmall = 0; plx_t plx_small; plx_t plx_large; int largest; int i; /* * Find the largest rule count of all of the port objects */ largest = 0; for(i=0;i<pol_cnt;i++) { if( pol[i]->rule_list->count >= lcnt ) { if( pol[i]->rule_list->count > largest ) largest = pol[i]->rule_list->count; } } /* * Classify PortObjects as large or small based on rule set size * and copy them into separte lists */ for(i=0;i<pol_cnt;i++) { if( pol[i]->rule_list->count >= lcnt ) { if( nlarge < SFPO_MAX_LPORTS ) polarge[ nlarge++ ] = pol[i]; } else { if( nsmall < SFPO_MAX_LPORTS ) posmall[ nsmall++ ] = pol[i]; } } DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"*** %d small rule groups, %d large rule groups\n",nsmall,nlarge);); /* * Sort the pointers to the input port objects so * we always get them in the same order for key comparsions */ if( nlarge > 1 ) qsort( polarge, nlarge, sizeof(void*), p_keycmp ); if( nsmall > 1 ) qsort( posmall, nsmall, sizeof(void*), p_keycmp ); DEBUG_WRAP( for(i=0;i<nsmall;i++) DebugMessage(DEBUG_PORTLISTS, "posmall[%d]=%lu\n",i,posmall[i]); for(i=0;i<nlarge;i++) DebugMessage(DEBUG_PORTLISTS, "polarge[%d]=%lu\n",i,polarge[i]); ); /* * Setup plx_t representation of port list pointers */ plx_small.n = nsmall; plx_small.p = (void**)&posmall[0]; plx_large.n = nlarge; plx_large.p = (void**)&polarge[0]; #ifdef DEBUG DEBUG_WRAP( if( nlarge ){ DebugMessage(DEBUG_PORTLISTS, "large "); plx_print(&plx_large); } if( nsmall ){ DebugMessage(DEBUG_PORTLISTS, "small "); plx_print(&plx_small); } );#endif /* * Merge Large PortObjects */ if( nlarge ) { DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"***nlarge=%d \n",nlarge);); ponew = _merge_N_pol( mhash, mhashx, polarge, nlarge, &plx_large ); } /* * Merge Small PortObjects */ if( nsmall ) { DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"***nsmall=%d \n",nsmall);); posnew = _merge_N_pol( mhash, mhashx, posmall, nsmall, &plx_small); } /* * Merge Large and Small (rule groups) PortObject2's together * append small port object rule sets to the large port objects, * remove the large port objects ports from the smaller port objects */ if( nlarge && nsmall ) { DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"*** appending small rules to larger rule group\n");); /* Append small port object, just the rules */ PortObjectAppendRules3( ponew, posnew ); /* Remove Ports in ponew from posnew */ PortObjectRemovePorts( (PortObject*)posnew, (PortObject*)ponew ); DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS,"*** final - using small+large rule group \n");); } else if( nsmall ) { /* Only a small port object */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -