Example #1
0
/** 
 * Print out the entirety of the server cache.
 * 
 * @param ssp server stats pointer
 */
void server_stats_dump(SERVER_STATS *ssp)
{
    SFXHASH_NODE *nodep;
    
    if(ssp && ssp->ipv4_table)
    {
        for( nodep = sfxhash_ghead(ssp->ipv4_table);
             nodep != NULL;
             nodep = sfxhash_gnext(nodep) )
        {
            SERVER_KEY *kp = (SERVER_KEY *) nodep->key;
            u_int32_t count = *(u_int32_t *) nodep->data;
            
            flow_printf("hits: %u proto: %3u port: %5u ip: %s\n",
                        count,
                        kp->protocol,
                        kp->port,
                        inet_ntoa(*(struct in_addr *)&kp->address));
        }
    }
    else
    {
        flow_printf("nothing to dump!\n");
    }
}
Example #2
0
/** 
 * print out a key to a file stream
 * 
 * @param key what to print
 * 
 * @return 0 on sucess
 */
int flowkey_print(FLOWKEY *key)
{
    flow_printf(" Protocol   : %d", key->protocol);
    flow_printf(" InitAddress: %s", inet_ntoa(*(struct in_addr *) &key->init_address));
    flow_printf(" InitPort   : %d", key->init_port);
    flow_printf(" RespAddress: %s", inet_ntoa(*(struct in_addr *) &key->resp_address));
    flow_printf(" RespPort   : %d", key->resp_port);
    return 0;
}
Example #3
0
int flow_init(FLOW *flow,
              char protocol,
              u_int32_t init_address,
              u_int16_t init_port,
              u_int32_t resp_address,
              u_int16_t resp_port)
{
    if(flow == NULL)
    {
        return FLOW_ENULL;
    }

    flow->key.protocol = protocol;
    flow->key.init_address = init_address;
    flow->key.init_port = init_port;
    flow->key.resp_address = resp_address;
    flow->key.resp_port = resp_port;

    if(flowstat_clear(&flow->stats))
    {
        flow_printf("unable to clear flow stats\n");
        return FLOW_EINVALID;
    }

    /** have not done anything with the flow->data section yet */
    return FLOW_SUCCESS;
}
/** 
 * See if the flow needs to be shutdown and remove it from the
 * cache. This function should be placed AFTER all detection type
 * components.
 * 
 * @param p packet
 * 
 * @return 0 on success
 */
int CheckFlowShutdown(Packet *p)
{
    FLOWCACHE *fcache = &s_fcache;
    FLOW *flowp = (FLOW *) p->flow;
    PROFILE_VARS;
   
    /* Use TMPSTART to not add to 'checks' */
    PREPROC_PROFILE_TMPSTART(flowPerfStats);
    if(flowp != NULL)
    {
        if(flow_checkflag(flowp, FLOW_CLOSEME))
        {
            /* allow all the submodules to trigger their final stand */            
            flow_callbacks(FLOW_SHUTDOWN, flowp, FROM_INITIATOR, p);
            
            if(flowcache_releaseflow(fcache, &flowp) != FLOW_SUCCESS)
            {
                flow_printf("Can't release flow %p\n", p->flow);
                PREPROC_PROFILE_TMPEND(flowPerfStats);
                return FLOW_BADJUJU;
            }
        }
    }

    p->flow = NULL;

    PREPROC_PROFILE_TMPEND(flowPerfStats);
    return FLOW_SUCCESS;
}
/** 
 * Printout a score entry
 * 
 * @param ps_score score entry to printf
 * 
 * @return FLOW_SUCCESS on success
 */
int flowps_score_print(PS_SCORE *ps_score)
{
    flow_printf(" score: %u start: %u end: %u",
                ps_score->score,
                (unsigned int) ps_score->start,
                (unsigned int) ps_score->ends);
    
    return FLOW_SUCCESS;
}
static int FlowParseArgs(SPPFLOW_CONFIG *config, char *args)
{
    char *key, *value;
    char *myargs = NULL;
    const char *delim = " \t";
    
    if(args)
    {
        if(s_debug > 5)
            flow_printf("I'm parsing %s!\n", args);
        
        myargs = strdup(args);

        if(myargs == NULL)
            FatalError("Out of memory parsing flow arguments\n");
    }
    else
    {
        if(s_debug > 5)
            flow_printf("nothing to parse for this flow!\n");
        
        return 0;
    }

    key = strtok(myargs, delim);

    while(key != NULL)
    {
        value = strtok(NULL, delim);

        if(!value)
        {
            FatalError("%s(%d) key %s has no value\n", file_name, file_line, key); 
        }

        FlowParseOption(config, file_name, file_line, key, value);                
        key = strtok(NULL, delim);
    }

    if(myargs)
        free(myargs);
    
    return 0;
}
void flowps_stats(PS_TRACKER *pstp)
{
    int dumpall = pstp->config.dumpall;
        
    flow_printf("+---[ Flow-portscan Stats ]----------------+\n");
    scoreboard_stats(&pstp->table_active, dumpall);
    scoreboard_stats(&pstp->table_scanner, dumpall);
    ut_stats(&pstp->unique_tracker, dumpall);
    server_stats(&pstp->server_stats, dumpall);
}
Example #8
0
void server_stats(SERVER_STATS *ssp, int dumpall)
{
    unsigned total, fail, success, nodes, anr, overhead, memcap;

    memcap = overhead = nodes = anr = total = fail = success = 0;
    
    if(ssp && ssp->ipv4_table)
    {
        total    = sfxhash_find_total(ssp->ipv4_table);
        fail     = sfxhash_find_fail(ssp->ipv4_table);
        success  = sfxhash_find_success(ssp->ipv4_table);
        nodes    = sfxhash_count(ssp->ipv4_table);
        anr      = sfxhash_anr_count(ssp->ipv4_table);
        memcap   = server_stats_memcap(ssp);
        overhead = server_stats_overhead_bytes(ssp);
    }    

    flow_printf(",-----[SERVER STATS]------------\n");
    flow_printf("   Memcap: %u  Overhead Bytes: %u\n",
                memcap, overhead);
    
    flow_printf("   Finds: %u (Sucessful: %u(%%%lf) Unsucessful: %u(%%%lf))\n",
                total,
                success, calc_percent(success,total),
                fail, calc_percent(fail,total));

    flow_printf("   Nodes: %u\n", nodes);
    
    flow_printf("   Recovered Nodes: %u\n", anr);
    flow_printf("`-------------------------------\n");

    if(dumpall)
        server_stats_dump(ssp);
}
Example #9
0
/** 
 * Create a new scoreboard for tracking nodes.
 * 
 * @param sbp scoreboard to initialize
 * @param at_thr active talker thresholds
 * @param sc_thr scanner thresholds (may not be needed)
 * @param kind tracker location for this table 
 * @param description table description
 * @param rows number of rows to populate the initial HASHTABLE() with
 * @param memcap bytes we can spend on this scoreboard
 * 
 * @return FLOW_SUCCESS on success, else failure
 */
int scoreboard_init(SCOREBOARD *sbp,
                    char *description,
                    TRACKER_POSITION kind,
                    unsigned int rows,
                    int memcap)
{
    
    if(!sbp || !description)
    {
        return FLOW_ENULL;
    }
    
    if(rows < 1)
        return FLOW_EINVALID;

    if(memcap < (sizeof(SCORE_ENTRY) + sizeof(SFXHASH_NODE)))
        return FLOW_EINVALID;

    /* initialize s_init_entry*/
    sb_init_entry();

    memset(sbp, 0, sizeof(SCOREBOARD));

    snprintf(sbp->description, SDESC_SIZE - 1, description);
    sbp->description[SDESC_SIZE - 1] = '\0';
     
    /* what size should we do? */
    sbp->ipv4_table = sfxhash_new(rows,               /* # of rows in HT*/
                                  sizeof(u_int32_t),    /* size of the key  */
                                  sizeof(SCORE_ENTRY), /* data size */
                                  memcap,              /* how much memory is alloted */
                                  1,                   /* auto recover nodes */
                                  scoreboard_anrfree, /* autorecovery function */
                                  scoreboard_usrfree, /* free function for the data */
                                  1);                 /* recycle old nodes */

    if(sbp->ipv4_table == NULL)
    {
        flow_printf("Unable to create scoreboard table!\n");
        return FLOW_ENOMEM;
    }

    sbp->kind = kind;

    return FLOW_SUCCESS;
}
Example #10
0
/** 
 * Print out the entirety of the scoreboard
 * 
 * @param ssp unique tracker
 */
void scoreboard_dump(SCOREBOARD *ssp)
{
    SFXHASH_NODE *nodep;

    if(ssp && ssp->ipv4_table)
    {
        for( nodep = sfxhash_ghead(ssp->ipv4_table);
             nodep != NULL;
             nodep = sfxhash_gnext(nodep) )
        {
            u_int32_t  *address = (u_int32_t *) nodep->key;
            SCORE_ENTRY *entry = (SCORE_ENTRY *) nodep->data;
            flowps_entry_print(entry, address);
        }
    }
    else
    {
        flow_printf("nothing to dump!\n");
    }
}
Example #11
0
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;    
}
Example #12
0
void scoreboard_stats(SCOREBOARD *sbp, int dumpall)
{
    unsigned total = sfxhash_find_total(sbp->ipv4_table);
    unsigned fail = sfxhash_find_fail(sbp->ipv4_table);
    unsigned success = sfxhash_find_success(sbp->ipv4_table);
    
    flow_printf("SCOREBOARD_STATS: %s\n", (char *) sbp->description);
    flow_printf("   Memcap: %u  Overhead Bytes: %u\n",
                sbp->ipv4_table->mc.memcap,
                sfxhash_overhead_bytes(sbp->ipv4_table));
    
    flow_printf("   Finds: %u (Sucessful: %u(%%%f) Unsucessful: %u(%%%f))\n",
                total,
                success, calc_percent(success,total),
                fail, calc_percent(fail,total));

    flow_printf("   Nodes: %u\n", sfxhash_count(sbp->ipv4_table));
    
    flow_printf("   Recovered Nodes: %u\n", sfxhash_anr_count(sbp->ipv4_table));
    flow_printf("   Score Entry Size:: %u\n", sizeof(SCORE_ENTRY));

    if(dumpall)
        scoreboard_dump(sbp);
}
Example #13
0
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;
    }
}
/** 
 * The runtime entry point for the flow module from snort
 *
 * 1) Assign each packet a flow
 * 2) Perform various callbacks based on the parameters for the flow
 * 
 * @param p packet to process
 */
static void FlowPreprocessor(Packet *p, void *context)
{
    int flow_class; /**< addressing scheme to use */
    int direction; /**< which way does the flow go */
    static time_t last_output = 0;
    FLOWKEY search_key;
    FLOW *fp;
    FLOWCACHE *fcache = &s_fcache;
    FLOWPACKET *pkt = (FLOWPACKET *) p;
    PROFILE_VARS;
        
    if(!FlowPacket(p))
    {
        return;
    }

    PREPROC_PROFILE_START(flowPerfStats);
    
    /* first find the addressing schema */
    if(flow_classifier(pkt, &flow_class) != FLOW_SUCCESS)
    {
        //LogMessage("Error classifying packet\n");
        return;
    }

    switch(flow_class)
    {
    case FLOW_IPV4:
        if(flowkey_make(&search_key, pkt) != FLOW_SUCCESS)
        {
            ErrorMessage("Unable to make a search key\n");
            PREPROC_PROFILE_END(flowPerfStats);
            return;
        }
        break;
    default:
        ErrorMessage("Unknown Flow Type: %d\n", flow_class);
        PREPROC_PROFILE_END(flowPerfStats);
        return;
    }

    /** this should return a direction too for the key */
    //printf("flowkey: "); flowkey_fprint(stdout, &search_key); printf("\n");
    
    if(flowcache_find(fcache, &search_key, &fp, &direction) == FLOW_SUCCESS)
    {
        /*
        **  We set flows for rebuilt pkts if there is one, otherwise
        **  we just bail.
        */
        if(p->packet_flags & PKT_REBUILT_STREAM)
        {
            p->flow = fp;
            PREPROC_PROFILE_END(flowPerfStats);
            return;
        }

        if(direction == FROM_RESPONDER && fp->stats.packets_recv == 0)
        {
            /* this is the first packet back from the guy */           
            flow_callbacks(FLOW_FIRST_BIDIRECTIONAL, fp, direction, p);
        }

        flow_callbacks(FLOW_ADDITIONAL, fp, direction, pkt);
    }
    else
    {
        /*
        **  If there's no flow for a rebuilt stream, then we don't
        **  care because something is screwed up.
        */
        if(p->packet_flags & PKT_REBUILT_STREAM)
        {
            PREPROC_PROFILE_END(flowPerfStats);
            return;
        }

        if(flowcache_newflow(fcache, &search_key, &fp) != FLOW_SUCCESS)
        {
            flow_printf("***ERROR: "); flowkey_print(&search_key); flow_printf("\n");
        }

        direction = FROM_INITIATOR;

        flow_callbacks(FLOW_NEW, fp, FROM_INITIATOR, pkt);
    }

    fp->stats.direction = direction;

    /* printout some verbose statistics */
    if(s_config.stats_interval  &&
       ((last_output + s_config.stats_interval) <= p->pkth->ts.tv_sec))
    {
        last_output =  p->pkth->ts.tv_sec;

        if(!pv.quiet_flag)
            flowcache_stats(stdout, fcache);
    }

    p->flow = fp;

    PREPROC_PROFILE_END(flowPerfStats);
}
Example #15
0
static void FlowPSParseOption(PS_CONFIG *config,
                              char *fname, int lineno,
                              char *key, char *value)
{
    int ivalue;

    if(!key || !value)
    {
        FatalError("%s:(%d) Invalid command line arguments!\n");
    }

    if(s_debug > 1)
        flow_printf("key: %s value: %s\n", key, value);
    
    if(!strcasecmp(key, "scoreboard-memcap-talker"))
    {
        ivalue = atoi(value);
        config->sb_memcap_talker = ivalue;
    }
    else if(!strcasecmp(key, "scoreboard-memcap-scanner"))
    {
        ivalue = atoi(value);
        config->sb_memcap_scanner = ivalue;
    }
    else if(!strcasecmp(key,"unique-memcap"))
    {
        ivalue = atoi(value);
        config->ut_memcap = ivalue;
    }
    else if(!strcasecmp(key,"server-memcap"))
    {
        ivalue = atoi(value);
        config->server_memcap = ivalue;
    }
    else if(!strcasecmp(key, "scoreboard-rows-talker"))
    {
        ivalue = atoi(value);
        config->sb_rows_talker = ivalue;
    }
    else if(!strcasecmp(key, "scoreboard-rows-scanner"))
    {
        ivalue = atoi(value);
        config->sb_rows_scanner = ivalue;
    }
    else if(!strcasecmp(key,"unique-rows"))
    {
        ivalue = atoi(value);
        config->ut_rows = ivalue;
    }
    else if(!strcasecmp(key,"server-rows"))
    {
        ivalue = atoi(value);
        config->server_rows = ivalue;
    }
    else if(!strcasecmp(key, "server-watchnet"))
    {
        IPSET *ipset = ipset_new(IPV4_FAMILY);

        if(!ipset || ip4_setparse(ipset, value) !=0)
        {
            FatalError("%s(%d) Unable to create an IPSet from %s\n",
                            file_name,file_line,value);
        }

        config->server_watchnet_ipv4 = ipset;        
    }
    else if(!strcasecmp(key, "src-ignore-net"))
    {
        IPSET *ipset = ipset_new(IPV4_FAMILY);

        if(!ipset || ip4_setparse(ipset, value) !=0)
        {
            FatalError("%s(%d) Unable to create an IPSet from %s\n",
                            file_name,file_line,value);
        }

        config->src_ignore_ipv4 = ipset;        
    }
    else if(!strcasecmp(key, "dst-ignore-net"))
    {
        IPSET *ipset = ipset_new(IPV4_FAMILY);

        if(!ipset || ip4_setparse(ipset, value) !=0)
        {
            FatalError("%s(%d) Unable to create an IPSet from %s\n",
                       file_name,file_line,value);
        }

        config->dst_ignore_ipv4 = ipset;        
    }
    else if(!strcasecmp(key, "tcp-penalties"))
    {
        if(toggle_option(key, value, &config->tcp_penalties))
        {
            FatalError("%s(%d) Error processing %s directive (value = %s)\n",
                       file_name,file_line,key,value);
        }
    }
    else if(!strcasecmp(key, "server-learning-time"))
    {
        ivalue = atoi(value);
        config->server_learning_time = ivalue;
    }   
    else if(!strcasecmp(key, "server-ignore-limit"))
    {
        ivalue = atoi(value);
        config->server_ignore_limit = ivalue;
    }
    else if(!strcasecmp(key, "server-scanner-limit"))
    {
        ivalue = atoi(value);
        config->server_scanner_limit = ivalue;
    }
    else if(!strcasecmp(key, "talker-fixed-threshold"))
    {
        ivalue = atoi(value);
        config->limit_talker.fixed = ivalue;
    }
    else if(!strcasecmp(key, "talker-sliding-threshold"))
    {
        ivalue = atoi(value);
        config->limit_talker.sliding = ivalue;
    }
    else if(!strcasecmp(key, "talker-fixed-window"))
    {
        ivalue = atoi(value);
        config->limit_talker.fixed_size = ivalue;
    }
    else if(!strcasecmp(key, "talker-sliding-window"))
    {
        ivalue = atoi(value);
        config->limit_talker.sliding_size = ivalue;
    }
    else if(!strcasecmp(key, "talker-sliding-scale-factor"))
    {
        config->limit_talker.window_scale = (float)strtod(value, NULL);
    }
    else if(!strcasecmp(key, "scanner-fixed-threshold"))
    {
        ivalue = atoi(value);
        config->limit_scanner.fixed = ivalue;
    }
    else if(!strcasecmp(key, "scanner-sliding-threshold"))
    {
        ivalue = atoi(value);
        config->limit_scanner.sliding = ivalue;
    }
    else if(!strcasecmp(key, "scanner-fixed-window"))
    {
        ivalue = atoi(value);
        config->limit_scanner.fixed_size = ivalue;
    }
    else if(!strcasecmp(key, "scanner-sliding-window"))
    {
        ivalue = atoi(value);
        config->limit_scanner.sliding_size = ivalue;
    }
    else if(!strcasecmp(key, "scanner-sliding-scale-factor"))
    {
        config->limit_scanner.window_scale = (float)strtod(value, NULL);
    }
    else if(!strcasecmp(key, "base-score"))
    {
        config->base_score = atoi(value);
    }
    else if(!strcasecmp(key, "dumpall"))
    {
        config->dumpall = atoi(value);
    }
    else if(!strcasecmp(key, "alert-mode"))
    {
        if(!strcasecmp(value, "once"))
        {
            config->alert_once = 1;
        }
        else if(!strcasecmp(value, "all"))
        {
            config->alert_once = 0;
        }
        else
        {
            FatalError("%s(%d) Bad option to %s => %s\n",
                       file_name, file_line, key, value);
        }
    }
    else if(!strcasecmp(key, "output-mode"))
    {
        if(!strcasecmp(value, "msg"))
        {
            config->output_mode = VARIABLEMSG;
        }
        else if(!strcasecmp(value, "pktkludge"))
        {
            config->output_mode = PKTKLUDGE;
        }
        else
        {
            FatalError("%s(%d) Bad option to %s => %s\n",
                       file_name, file_line, key, value);
        }
    }
    else        
    {
        FatalError("%s(%d) Unknown Arguments: key(%s) value(%s)\n",
                   fname, lineno, key, value);
    }
    
}
Example #16
0
void flowcache_stats(FILE *stream, FLOWCACHE *flowcachep)
{
    int could_hold;
    int i;
    time_t low_time = 0, high_time = 0, diff_time = 0;    
    int diff_hours = 0, diff_min = 0, diff_sec = 0;
    int diff_blocks = 0;
    FLOW *flow_mrup, *flow_lrup;

#ifdef INDEPTH_DEBUG
    printf("table max depth: %u\n",
           sfxhash_maxdepth(flowcachep->ipv4_table));
#endif /* INDEPTH_DEBUG */
        
    if((flowcache_mru(flowcachep, &flow_mrup) == FLOW_SUCCESS) &&
       (flowcache_lru(flowcachep, &flow_lrup) == FLOW_SUCCESS))
    {
        low_time = flow_lrup->stats.last_packet;
        high_time = flow_mrup->stats.last_packet;

        diff_time = high_time - low_time;

        diff_hours = diff_time / 3600;
        diff_min = (diff_time - (3600 * diff_hours)) / 60;
        diff_sec = diff_time % 60;
    }

    diff_blocks = flowcachep->ipv4_table->mc.nblocks -
        flowcache_overhead_blocks(flowcachep);


    //could_hold = flowcachep->ipv4_table->mc.memcap /
    //    (sizeof(FLOW) + sizeof(FLOWKEY) + sizeof(SFXHASH_NODE));

    /* this is a bad calculation -- should clean this up */
    if(diff_blocks > 0)
    {
        could_hold = (flowcachep->ipv4_table->mc.memused - flowcache_overhead_bytes(flowcachep)) / diff_blocks;
        could_hold = flowcachep->ipv4_table->mc.memcap / could_hold;
    }
    else
    {
        could_hold = diff_blocks;
    }

    flow_printf(",----[ FLOWCACHE STATS ]----------\n");
    flow_printf("Memcap: %u Overhead Bytes %u used(%%%f)/blocks (%u/%u)\nOverhead blocks: %u Could Hold: (%u)\n",
                flowcachep->ipv4_table->mc.memcap,
                flowcache_overhead_bytes(flowcachep),
                calc_percent(flowcachep->ipv4_table->mc.memused,
                             flowcachep->ipv4_table->mc.memcap),
                flowcachep->ipv4_table->mc.memused,
                flowcachep->ipv4_table->mc.nblocks,
                flowcache_overhead_blocks(flowcachep),
                could_hold);
    
    flow_printf("IPV4 count: %u frees: %u\nlow_time: %u, high_time: %u,"
                " diff: %dh:%02d:%02ds\n",
                sfxhash_count(flowcachep->ipv4_table),
                sfxhash_anr_count(flowcachep->ipv4_table),
                (unsigned) low_time,
                (unsigned) high_time,
                diff_hours,diff_min,diff_sec);
    

    flow_printf("    finds: " STDu64 " reversed: " STDu64 "(%%%f) \n    find_success: " STDu64 " "
                "find_fail: " STDu64 "\npercent_success: (%%%f) new_flows: " STDu64 "\n",
                flowcachep->total.find_ops,
                flowcachep->total.reversed_ops,
                calc_percent64(flowcachep->total.reversed_ops,
                             flowcachep->total.find_ops),
                flowcachep->total.find_success,
                flowcachep->total.find_fail,
                calc_percent64(flowcachep->total.find_success,
                             flowcachep->total.find_ops),
                flowcachep->total.new_flows);
    
    for(i=0;i<256;i++)
    {
        if(flowcachep->per_proto[i].find_ops > 0)
        {
            flow_printf(" Protocol: %d (%%%f)\n"
                        "   finds: " STDu64 "\n"
                        "   reversed: " STDu64 "(%%%f)\n"
                        "   find_success: " STDu64 "\n"
                        "   find_fail: " STDu64 "\n"
                        "   percent_success: (%%%f)\n"
                        "   new_flows: " STDu64 "\n",
                        i,
                        calc_percent64(flowcachep->per_proto[i].find_ops,
                                     flowcachep->total.find_ops),
                        flowcachep->per_proto[i].find_ops,
                        flowcachep->per_proto[i].reversed_ops,
                        calc_percent64(flowcachep->per_proto[i].reversed_ops,
                                     flowcachep->per_proto[i].find_ops),
                        flowcachep->per_proto[i].find_success,
                        flowcachep->per_proto[i].find_fail,
                        calc_percent64(flowcachep->per_proto[i].find_success,
                                     flowcachep->per_proto[i].find_ops),
                        flowcachep->per_proto[i].new_flows);
        }
    }
}
int flowps_entry_print(SCORE_ENTRY *entry, u_int32_t *address)
{
    char *c_position = "TRACKER_ACTIVE";
    u_int32_t i;
    if(entry->position == TRACKER_SCANNER)
        c_position = "TRACKER_SCANNER";

    flow_printf(",-----------------------------------------------------\n");
    flow_printf("| Score entry for %s@%p Flags: %x\n",
            inet_ntoa(*(struct in_addr *) address), entry, entry->flags);


    flow_printf("|   Alerts: FT: %u ST: %u FS: %u SS: %u",
            (entry->flags & ALERT_FIXED_TALKER),
            (entry->flags & ALERT_SLIDING_TALKER),
            (entry->flags & ALERT_FIXED_SCANNER),
            (entry->flags & ALERT_SLIDING_SCANNER));
    
    flowps_score_print(&entry->fixed_talker);
    
    flow_printf("\n| Position: %s\n", c_position);
    flow_printf("|   Fixed Talker:");
    flowps_score_print(&entry->fixed_talker);
    
    flow_printf("\n| Sliding Talker:");
    flowps_score_print(&entry->sliding_talker);
    
    flow_printf("\n|   Fixed Scanner:");
    flowps_score_print(&entry->fixed_scanner);

    flow_printf("\n| Sliding Scanner:");
    flowps_score_print(&entry->sliding_scanner);

    flow_printf("\n| Connections Seen: %u", entry->connections_seen);

    /* as long as we have a postive # of connections, pump out the info */
    for(i=0; i < entry->connections_seen && i < FLOWPS_HOSTS_SIZE; i++)
    {
        CONN_ENTRY *cp = &entry->last_hosts[i];
        if(cp->protocol == 6)
        {
            flow_printf("\n|        proto: %d %s:%d th_flags: %s",
                        cp->protocol,
                        inet_ntoa(*(struct in_addr*) &cp->ip),
                        cp->port,
                        mktcpflag_str(cp->cflags));
        }
        else
        {
            flow_printf("\n|        proto: %d %s:%d cflags: %d",
                        cp->protocol,
                        inet_ntoa(*(struct in_addr*) &cp->ip),
                        cp->port,
                        cp->cflags);

        }
    }
    flow_printf("\n`----------------------------------------------------\n");

    return 0;
}
Example #18
0
/** 
 * Display what the underlying tidbits think the config is
 * 
 * @param trackerp grab the configuration info from the portscan tracker
 */
static void FlowPSOutputConfig(PS_TRACKER *trackerp)
{
    if(pv.quiet_flag)
        return;

    flow_printf(",-----------[flow-portscan config]-------------\n");
    flow_printf("| TCP Penalties:  %s\n", trackerp->config.tcp_penalties ? "On": "Off");
    flow_printf("|    Ouput Mode:  %s\n",
                (trackerp->config.output_mode == VARIABLEMSG) ? "msg" : "pktkludge");
    flow_printf("|    Base Score:  %d\n", trackerp->config.base_score);
    
    flow_printf("+----------------------------------------------\n");
    flow_printf("| Scoreboard:  ACTIVE         PORTSCANNER\n");
    flow_printf("|     memcap:  %-8d         %-8d\n",
                scoreboard_memcap(&trackerp->table_active),
                scoreboard_memcap(&trackerp->table_scanner));
    flow_printf("|       rows:  %-8d         %-8d\n",
                scoreboard_row_count(&trackerp->table_active),
                scoreboard_row_count(&trackerp->table_scanner));
    flow_printf("|   overhead:  %-8d(%%%.02lf) %-8d(%%%.02lf)\n",
                scoreboard_overhead_bytes(&trackerp->table_active),
                calc_percent(scoreboard_overhead_bytes(&trackerp->table_active),
                             scoreboard_memcap(&trackerp->table_active)),
                scoreboard_overhead_bytes(&trackerp->table_scanner),
                calc_percent(scoreboard_overhead_bytes(&trackerp->table_scanner),
                             scoreboard_memcap(&trackerp->table_scanner)));

    flow_printf("|      fixed-size:    %-4ds        %-4ds\n",
                trackerp->config.limit_talker.fixed_size,
                trackerp->config.limit_scanner.fixed_size);
    flow_printf("|    sliding-size:    %-4ds        %-4ds\n",
                trackerp->config.limit_talker.sliding_size,
                trackerp->config.limit_scanner.sliding_size);
    flow_printf("| threshold-fixed:    %-4u         %-4u\n",
                trackerp->config.limit_talker.fixed,
                trackerp->config.limit_scanner.fixed);
    flow_printf("| threshold-sliding:  %-4u         %-4u\n",
                trackerp->config.limit_talker.sliding,
                trackerp->config.limit_scanner.sliding);
    flow_printf("|      window scale:  %-.2lf         %-.2lf\n",
                trackerp->config.limit_talker.window_scale,
                trackerp->config.limit_scanner.window_scale);
    
    
    flow_printf("+----------------------------------------------\n");
    flow_printf("|   Uniqueness:  memcap: %8d rows: %8d\n",
               ut_memcap(&trackerp->unique_tracker),
               ut_row_count(&trackerp->unique_tracker));
    flow_printf("|      overhead: %d (%%%.02lf)\n",               
                ut_overhead_bytes(&trackerp->unique_tracker),
                calc_percent(ut_overhead_bytes(&trackerp->unique_tracker),
                             ut_memcap(&trackerp->unique_tracker)));
    
    if(flowps_server_stats_enabled(trackerp) == FLOW_SUCCESS)
    {
        flow_printf("+----------------------------------------------\n");        
        flow_printf("| Server Stats:  memcap: %8d rows: %8d\n",
                    server_stats_memcap(&trackerp->server_stats),
                    server_stats_row_count(&trackerp->server_stats));
        flow_printf("|      overhead: %d (%%%.02lf)\n",               
                    server_stats_overhead_bytes(&trackerp->server_stats),
                    calc_percent(server_stats_overhead_bytes(&trackerp->server_stats),
                                 server_stats_memcap(&trackerp->server_stats)));
        flow_printf("|   learning time: %d\n",
                    trackerp->config.server_learning_time);
        flow_printf("|    ignore limit: %u\n",
                    trackerp->config.server_ignore_limit);
        flow_printf("|   scanner limit: %u\n",
                    trackerp->config.server_scanner_limit);
        
        
    }
    else
    {
        flow_printf("| Server Stats: Disabled\n");
    }

    flow_printf("`----------------------------------------------\n");
}
/** 
 * Get the score and the type of connection this is
 *
 * If the score is 0, this is an already existing connection and can
 * be successfully ignored.
 *
 * @param pstp portscan tracker
 * @param flowp flow to aquire a score for *
 * @param cur current time
 * @flags packet related flags that can be used to modify the score
 * @param score return value for the score
 * @param type return value for the type of connection
 * 
 * @return FLOW_SUCCESS on success and sets the score and type
 */
int flowps_get_score(PS_TRACKER *pstp, FLOW *flowp,
                     time_t cur, u_int32_t flags,
                     int *score, TRACKER_POSITION *type)
{
    UT_TYPE unique;
    u_int32_t hitcount = 1;
    int base_score;
    
    
    if(!flowp || !score || !type)
    {
        return FLOW_ENULL;
    }

    /* save off a default base score */
    base_score = pstp->config.base_score;
    *score     = pstp->config.base_score;

    /* run the uniqueness check
     *
     * This should be ABOVE the finding code since the unquieness
     * check is the key to determining if this should accrue more
     * points. If it's not unique, we can bail out instantly.
     *
     */

    if(ut_check(&pstp->unique_tracker, &flowp->key, &unique) != FLOW_SUCCESS)
    {
#ifndef WIN32
        flow_printf("ut check failed in %s\n", __func__);
#else
        flow_printf("ut check failed in %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    
    if(unique == UT_OLD)
    {
        /* bail out if we do not have a reason to further evaluate the
         * score. The score can only be changed if this flow is truely
         * a unique (dport+proto+address)
         */
        *score = 0;
        return FLOW_SUCCESS;
    }
    else /* UT_NEW */
    {
        if(flowps_server_watch(pstp,flowp->key.resp_address) == FLOW_SUCCESS)
        {
            /* perform the hitcount management */            
            if(cur < (packet_first_time() + pstp->config.server_learning_time))
            {
                if(server_stats_add_ipv4(&pstp->server_stats,
                                         flowp->key.protocol,
                                         flowp->key.resp_address,
                                         flowp->key.resp_port,
                                         &hitcount) != FLOW_SUCCESS)
                {
#ifdef DEBUG
                    flow_printf("Unable to add ipv4 to server stats!\n");
#endif /* DEBUG */
                }
                
            }
            else
            {
                hitcount = server_stats_hitcount_ipv4(&pstp->server_stats,
                                                      flowp->key.protocol,
                                                      flowp->key.resp_address,
                                                      flowp->key.resp_port);

                if(pstp->config.server_scanner_limit &&
                   hitcount < pstp->config.server_scanner_limit)
                {
                    *type = TRACKER_SCANNER;
                }
            }

            if(pstp->config.server_ignore_limit > 0 &&
               hitcount > pstp->config.server_ignore_limit)
            {
                /* this must be a semi-active service -- it's not worth
                 * anything */
                
                if(s_debug > 5)
                {
                    flow_printf("Happy Server hitcount: %d proto: %d %s:%d\n",
                                hitcount,
                                flowp->key.protocol,
                                inet_ntoa(*(struct in_addr *) &flowp->key.resp_address),
                                flowp->key.resp_port);
                }
                
                base_score = 0;
            }
            
        } /* this IP is not being watched or something like it */
        else
        {
            hitcount = 1;
        }
    }

    /*
     * possibly assign penalty points for "bad session initiators
     */
    if(pstp->config.tcp_penalties && flowp->key.protocol == 6)
    {        
        flowps_tcp_penalty(flags, base_score, score);
    }
    else
    {
        *score = base_score;
    }

    /* @todo switch tables */
    return FLOW_SUCCESS;
}
Example #20
0
/**
 * The callback for the flow-portscan module
 *
 * This function's purpose is to do about the same thing as a
 * traditional snort preprocessor.  The only difference is that this
 * occurs only on a specific FLOW position.
 *
 * This individual callback position is only valid in the "NEW" flow
 * position.
 *
 * The operations are pretty much the same as laid out by
 *
 * Chris Green, Marc Norton, Dan Roelker
 *
 * Basic code flow:
 *
 * 1) Get the score and flag type
 * 2) return if the score is 0
 * 3) Get the score entry node
 * 4) Perform time window maintence 
 *    - includes flushing the "scan data" out of the subsys
 * 5) Process the score data
 * 6) Generate alerts if necessary
 *
 * @param position where in the flow module this is being called from
 * @param flow the flow that the stats are kept for
 * @param direction the direction of the flow
 * @param cur the current time
 * @param p the current packet (may be NULL)
 *
 * @return TBD
 */
int flowps_newflow_callback(FLOW_POSITION position, FLOW *flowp,
                            int direction, time_t cur, FLOWPACKET *p)
{
    TRACKER_POSITION tr_pos = TRACKER_ACTIVE; /* where new nodes get inserted */
    PS_TRACKER *pstp = &s_tracker;
    SCORE_ENTRY *current_entry = NULL;
    int ret, score;    
    u_int32_t alert_flags;
    u_int8_t cflags;
    u_int32_t *address = &flowp->key.init_address;

    if(!flowps_enabled())
        return 0;

    if(s_debug > 5)
    {
        printf("DEBUG: callback %s:%d -> %s:%d\n",
               inet_ntoax(p->iph->ip_src.s_addr), p->sp,
               inet_ntoax(p->iph->ip_dst.s_addr), p->dp);
    }

    if(position != FLOW_NEW)        
    {
#ifndef WIN32
        flow_printf("Wrong callback position for %s\n", __func__);
#else
        flow_printf("Wrong callback position for %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    if(flowps_is_ignored_ipv4(pstp,
                              &flowp->key.init_address,
                              &flowp->key.resp_address) == FLOW_SUCCESS)
    {
        return 0;
    }

    if(IsTcpPacket(p))
    {
        /* allow radically different flags from SYN help score
         * differently */
        cflags = GetTcpFlags(p);
    }
    else
    {
        cflags = 0;
    }

    /*
     * if we can't find the score for whatever reason, or the
     * resultant score is 0 (indicating that this a "normal" event),
     * just go ahead and return 
     */
    if(flowps_get_score(pstp, flowp, cur,
                        cflags, &score, &tr_pos) != FLOW_SUCCESS)
    {
        return -1;
    }

    if(score == 0)
    {
        return 0;
    }
    else if(s_debug > 5)
    {
        flow_printf("new unique flow!\n");
        flowkey_print(&flowp->key);
        flow_printf("\n");
    }
    
    /* run the "score entry finder" or create a new node */    
    ret = flowps_find_entry(pstp, address, &current_entry);

    if(ret == FLOW_NOTFOUND)
    {
        ret = flowps_add_entry(pstp,  tr_pos, address, &current_entry);

        if(ret != FLOW_SUCCESS)            
        {
            /* tracker failed horribly */
#ifndef WIN32
            flow_printf("flowps_add_entry check failed in %s\n", __func__);
#else
            flow_printf("flowps_add_entry check failed in %s(%d)\n", __FILE__, __LINE__);
#endif
            return 0;
        }
    }
    else if(ret != FLOW_SUCCESS)
    {
#ifndef WIN32
        flow_printf("bad return for finding the entry %s\n", __func__);
#else
        flow_printf("bad return for finding the entry %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    flowps_sliding_winadj(&current_entry->sliding_talker,
                          cur,
                          &pstp->config.limit_talker);

    flowps_fixed_winadj(&current_entry->fixed_talker,
                        cur,
                        &pstp->config.limit_talker);

    flowps_sliding_winadj(&current_entry->sliding_scanner,
                          cur,
                          &pstp->config.limit_scanner);

    flowps_fixed_winadj(&current_entry->fixed_scanner,
                        cur,
                        &pstp->config.limit_scanner);

    /* maintain the list of recent connections */
    flowps_set_last_address(current_entry, flowp, cflags);

    /* windows adjusted, lets get us some alerts */
    if(s_debug > 5 && score > 1)
    {
        flow_printf("XXXX **** got a big old score(%d) because of [%s] -> %s\n",
               score,  mktcpflag_str(cflags),
               inet_ntoa(*(struct in_addr *) (&flowp->key.resp_address)));
        flowps_entry_print(current_entry, address);
        flow_printf("\nXXXX ****\n");
    }

    if(flowps_score_entry(pstp, current_entry, score, tr_pos, 
                          pstp->config.alert_once,
                          &alert_flags) != FLOW_SUCCESS)
    {
#ifndef WIN32
        flow_printf("bad return for finding the entry %s\n", __func__);
#else
        flow_printf("bad return for finding the entry %s(%d)\n", __FILE__, __LINE__);
#endif
        return 0;
    }

    /* If someone generates an event 
     * 
     *
     */
    if(current_entry->position == TRACKER_ACTIVE && tr_pos == TRACKER_SCANNER)
    {
        //flow_printf("moving this one! (cur %d) -> (new %d) %s\n",
        //current_entry->position, tr_pos, inet_ntoa(*(struct in_addr *) address));

        /* move address TO scanner FROM active */
        ret = scoreboard_move(&pstp->table_scanner, &pstp->table_active, address);
        
        if(ret != FLOW_SUCCESS)
        {
            flow_printf("Unable to move %s\n",inet_ntoa(*(struct in_addr *) address));
            return -1;
        }
        else
        {
            /* @todo - move this into the scoreboard mv call */
            current_entry->position = TRACKER_SCANNER;
        }
       
    }

    if(s_debug > 5)
    {
        if(tr_pos == TRACKER_SCANNER)
        {
            flow_printf("Found a tracker scanner!\n");
            flowps_entry_print(current_entry, address);
        }
    }
    
    if(s_debug > 10)
    {
        flowps_entry_print(current_entry, address);
    }
    
    if(alert_flags)        
    {
        /*
        **  We OR the alert_flags here because we only want to add
        **  new alerts and reset alerts that might not be set in
        **  alert_flags.  This is for the case of alert_once being
        **  set.
        */
        current_entry->flags |= alert_flags;
            
        /* push things through the output system */
        
        flowps_generate_flow_event(current_entry, p, address,
                                   pstp->config.output_mode, cur);
    }

    return 0;
}
Example #21
0
int server_stats_save(SERVER_STATS *ssp, char *filename)
{
    SFXHASH_NODE *nodep;
    unsigned char buf[STATSREC_SIZE];
    int fd;
    
    if(!filename || !ssp)
        return FLOW_ENULL;
#ifndef O_SYNC
#define O_SYNC O_FSYNC
#endif

    /* open this description, create it if necessary, always wait on
     * sync to disk w/ every write, only write */
    fd = open(filename, O_CREAT|O_TRUNC|O_SYNC|O_WRONLY);

    if(fd < 0)
    {
        if(s_debug)
        {
            flow_printf("%s was not found\n", filename);
        }
        return FLOW_NOTFOUND;
    }

    /* this is a crappy parser... that's par for the course */
    for( nodep = sfxhash_ghead(ssp->ipv4_table);
         nodep != NULL;
         nodep = sfxhash_gnext(nodep) )
    {
        SERVER_KEY *kp = (SERVER_KEY *) nodep->key;
        u_int32_t count = *(u_int32_t *) nodep->data;
        u_int8_t  family = '4';
        u_int32_t ipv4_address;
        u_int16_t port;
        u_int8_t  protocol;
        ssize_t  wbytes = 0;
        ssize_t wsize;
            
        
        count        = ntohl(count);       
        ipv4_address = htonl(kp->address);
        port         = htons(kp->port);
        protocol     = kp->protocol;

        memcpy(buf + FAMILY_OFFSET,   &family,        FAMILY_SIZE);
        memcpy(buf + IPV4_OFFSET,     &ipv4_address,  IPV4_SIZE);       
        memcpy(buf + PORT_OFFSET,     &port,          PORT_SIZE);
        memcpy(buf + IP_PROTO_OFFSET, &protocol,      IP_PROTO_SIZE);
        memcpy(buf + COUNT_OFFSET,    &count,         COUNT_SIZE);

        /* now make sure we get a full record on disk */
        while(wbytes < STATSREC_SIZE)
        {
            /* write the number of bytes we already have - the #
             * already written */
            wsize = write(fd, buf, (STATSREC_SIZE - wbytes));

            if(wsize < 0)
            {
                /* this record was truncated */
                flow_printf("Truncated Server Record!\n");
                return FLOW_EINVALID;
            }
            else
            {
                wbytes += wsize;
            }
        }
    }
    
    return FLOW_SUCCESS;
}