📄 spp_stream4.c
字号:
else { FatalError("%s(%d) => Bad flush_data_diff_size in config file\n", file_name, file_line); } } else { FatalError("%s(%d) => Bad stream4_reassemble option " "specified: \"%s\"\n", file_name, file_line, toks[i]); } i++; } if (num_toks) mSplitFree(&toks, num_toks); /* Setup flushpoints, per config */ if ( s4data.flush_behavior == FLUSH_BEHAVIOR_LARGE ) { /* Default, larger static flushpoints */ int elm; for( elm = 0; elm < FCOUNT; elm += 1 ) { flush_points[elm] = new_flush_points[elm]; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Setting new static " "flush value of (%d bytes) at index %d\n", flush_points[elm],elm);); } LogMessage("WARNING %s(%d) => flush_behavior set in " "config file, using new static flushpoints (%d)\n", file_name, file_line, s4data.flush_behavior); } else if ( s4data.flush_behavior == FLUSH_BEHAVIOR_RANDOM ) { /* set up random flush points */ int elm; int rfp; srand(s4data.flush_seed); for( elm = 0; elm < FCOUNT; elm += 1 ) { rfp = rand() % s4data.flush_range; flush_points[elm] = rfp + s4data.flush_base; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Setting random " "flush value of (%d bytes) at index %d\n", flush_points[elm],elm);); } } else { /* Use the old flushpoints -- default behavior */ int elm; for( elm = 0; elm < FCOUNT; elm += 1 ) { flush_points[elm] = old_flush_points[elm]; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Setting old static " "flush value of %d bytes) at index %d\n", flush_points[elm],elm);); } LogMessage("WARNING %s(%d) => flush_behavior set in " "config file, using old static flushpoints (%d)\n", file_name, file_line, s4data.flush_behavior); } LogMessage("Stream4_reassemble config:\n"); LogMessage(" Server reassembly: %s\n", s4data.reassemble_server ? "ACTIVE": "INACTIVE"); LogMessage(" Client reassembly: %s\n", s4data.reassemble_client ? "ACTIVE": "INACTIVE"); LogMessage(" Reassembler alerts: %s\n", s4data.reassembly_alerts ? "ACTIVE": "INACTIVE"); LogMessage(" Zero out flushed packets: %s\n", s4data.zero_flushed_packets ? "ACTIVE": "INACTIVE"); LogMessage(" Flush stream on alert: %s\n", s4data.flush_on_alert ? "ACTIVE": "INACTIVE"); LogMessage(" flush_data_diff_size: %d\n", s4data.flush_data_diff_size); LogMessage(" Reassembler Packet Preferance : %s\n", s4data.reassy_method == METHOD_FAVOR_NEW ? "Favor New" : "Favor Old"); LogMessage(" Packet Sequence Overlap Limit: %d\n", s4data.overlap_limit); LogMessage(" Flush behavior: %s\n", s4data.flush_behavior == FLUSH_BEHAVIOR_DEFAULT ? "Small (<255 bytes)": (s4data.flush_behavior == FLUSH_BEHAVIOR_LARGE ? "Large (<2550 bytes)" : "random")); if (s4data.flush_behavior == FLUSH_BEHAVIOR_RANDOM) { LogMessage(" Flush base: %d\n", s4data.flush_base); LogMessage(" Flush seed: %d\n", s4data.flush_seed); LogMessage(" Flush range: %d\n", s4data.flush_range); } memset(buf, 0, STD_BUF+1); snprintf(buf, STD_BUF, " Ports: "); for(i=0;i<65536;i++) { if(s4data.assemble_ports[i]) { sfsnprintfappend(buf, STD_BUF, "%d ", i); j++; } if(j > 20) { LogMessage("%s...\n", buf); return; } } LogMessage("%s\n", buf); memset(buf, 0, STD_BUF+1); snprintf(buf, STD_BUF, " Emergency Ports: "); j=0; for(i=0;i<65536;i++) { if(s4data.emergency_ports[i]) { sfsnprintfappend(buf, STD_BUF, "%d ", i); j++; } if(j > 20) { LogMessage("%s...\n", buf); return; } } LogMessage("%s\n", buf); return;}/** * Set that this side of the session has sent a fin. * * This overloads the next_seq variable to also be used to tell how * far forward we can acknowledge data. * * @param p packet to grab the session from * @param s stream to set the next_seq on * * @return 0 if everything went ok */static INLINE int SetFinSent(Packet *p, Session *ssn, int direction){ Stream *stream; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "SetFinSet() called for %s\n", direction ? "FROM_CLIENT":"FROM_SERVER");); if(direction == FROM_SERVER) { stream = &ssn->server; ssn->session_flags |= SSNFLAG_SERVER_FIN; } else { stream = &ssn->client; ssn->session_flags |= SSNFLAG_CLIENT_FIN; } stream->next_seq = ntohl(p->tcph->th_seq); return 0;}/** * See if we can get ignore this packet * * The Emergency Status stuff is taken care of here. * * @param p Packet * * @return 1 if this packet isn't destined to be processeed, 0 otherwise */static INLINE int NotForStream4(Packet *p){ if(!(p->preprocessors & PP_STREAM4)) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "p->preprocessors does not have STREAM4\n");); return 1; } if(p->tcph == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "p->tcph is null, returning\n");); return 1; } if(p->packet_flags & PKT_REBUILT_STREAM) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "REBUILT_STREAM returning\n");); return 1; } if(s4_emergency.status != OPS_NORMAL) { /* Check to see if we should return to our non-emergency mode. * If we happen to stay in SUSPSEND mode, exit out */ if(p->pkth->ts.tv_sec >= s4_emergency.end_time) { s4_emergency.status = OPS_NORMAL; s4_emergency.end_time = 0; s4_emergency.new_session_count = 0; s4data.reassembly_alerts = s4_emergency.old_reassembly_alerts; s4data.reassemble_client = s4_emergency.old_reassemble_client; s4data.reassemble_server = s4_emergency.old_reassemble_server; pv.assurance_mode = s4_emergency.old_assurance_mode; pv.stateful = s4_emergency.old_stateful_mode; } if(s4_emergency.status == OPS_SUSPEND) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "OPS_SUSPEND returning\n");); return 1; } } /* don't accept packets w/ bad checksums */ if(p->csum_flags & CSE_IP || p->csum_flags & CSE_TCP) { DEBUG_WRAP( u_int8_t c1 = (p->csum_flags & CSE_IP); u_int8_t c2 = (p->csum_flags & CSE_TCP); DebugMessage(DEBUG_STREAM, "IP CHKSUM: %d, CSE_TCP: %d", c1,c2); DebugMessage(DEBUG_STREAM, "Bad checksum returning\n"); ); p->packet_flags |= PKT_STREAM_UNEST_UNI; return 1; } DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Packet is for stream4...\n");); return 0;}/** * Subtract from the byte counters for the stream session * * @param stream Stream to adjust the byte counters on * @param sub amount to subtract from the byte_counters */static INLINE void StreamSegmentSub(Stream *stream, u_int16_t sub){ /* don't allow us to overflow */#ifdef _DEBUG_SEGMENTS DebugMessage(DEBUG_STREAM, "[sss] %u -> %u (mem: %u)\n,", stream->bytes_tracked, stream->bytes_tracked - sub, stream4_memory_usage);#endif /* DEBUG_SEGMENTS */ if((stream->bytes_tracked - sub) > stream->bytes_tracked) { stream->bytes_tracked = 0; } else { stream->bytes_tracked -= sub; }}/** * Add to the byte counters for the stream session * * @param stream Stream to adjust the byte counters on * @param add amount to add to the byte_counters */static INLINE void StreamSegmentAdd(Stream *stream, u_int16_t add){ /* don't allow us to overflow */#ifdef _DEBUG_SEGMENTS DebugMessage(DEBUG_STREAM, "[ssa] %u -> %u (mem: %u)\n,", stream->bytes_tracked, stream->bytes_tracked + add, stream4_memory_usage);#endif /* _DEBUG_SEGMENTS */ /* don't allow us to overflow */ if((stream->bytes_tracked + add) < stream->bytes_tracked) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"[E] How'd we get this high?\n");); return; } else { stream->bytes_tracked += add; stream->bytes_sent += add; stream->pkts_sent++; }}/** * Make sure that we do not log * * @param p Packet to evaluate * @param stream Stream to compare against * * @return 1 if we are within established limits, 0 otherwise. */static INLINE int WithinSessionLimits(Packet *p, Stream *stream){ u_int32_t limit; return 1; /* use a different limit if the session was picked up midstream * rather than having a full 3whs */ if(((Session *)(p->ssnptr))->session_flags & SSNFLAG_MIDSTREAM) { limit = 5000; } else { limit = (MAX_STREAM_SIZE + 5000); } if((stream->bytes_tracked + p->dsize) >= limit) { /* Go ahead and remove these statistics since we're not going to * store the packet */ StreamSegmentSub(stream, p->dsize); return 0; } return 1;}/** * Prune The state machine if we need to * * Also updates all variables related to pruning that only have to * happen at initialization * * For want of packet time at plugin initialization. (It only happens once.) * It wood be nice to get the first packet and do a little extra before * getting into the main snort processing loop. * -- cpw * * @param p Packet ptr */static INLINE void PruneCheck(Packet *p){ if (!s4data.last_prune_time) { s4data.last_prune_time = p->pkth->ts.tv_sec; return; } if( (u_int)(p->pkth->ts.tv_sec) > s4data.last_prune_time + s4data.timeout) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Prune time quanta exceeded, pruning " "stream cache\n");); sfPerf.sfBase.iStreamTimeouts++; PruneSessionCache(p->pkth->ts.tv_sec, 0, NULL); s4data.last_prune_time = p->pkth->ts.tv_sec; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Pruned for timeouts, %lu sessions " "active, %lu bytes " "in use\n", (unsigned long int) GetSessionCount(), stream4_memory_usage); DebugMessage(DEBUG_STREAM, "Stream4 memory cap hit %lu times\n", safe_alloc_faults);); }}/* * Function: PreprocFunction(Packet *) * * Purpose: Perform the preprocessor's intended function. This can be * simple (statistics collection) or complex (IP defragmentation) * as you like. Try not to destroy the performance of the whole * system by trying to do too much.... * * Arguments: p => pointer to the current packet data struct * * Returns: void function */void ReassembleStream4(Packet *p, void *context){ Session *ssn = NULL; int action; int reassemble = 0; u_int32_t pkt_seq; u_int32_t pkt_ack; int direction; static int aler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -