/** * 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"); } }
/** * 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, ¤t_entry); if(ret == FLOW_NOTFOUND) { ret = flowps_add_entry(pstp, tr_pos, address, ¤t_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(¤t_entry->sliding_talker, cur, &pstp->config.limit_talker); flowps_fixed_winadj(¤t_entry->fixed_talker, cur, &pstp->config.limit_talker); flowps_sliding_winadj(¤t_entry->sliding_scanner, cur, &pstp->config.limit_scanner); flowps_fixed_winadj(¤t_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; }