📄 spp_stream4.c
字号:
void Stream4ShutdownFunction(int, void *);void Stream4CleanExitFunction(int, void *);void Stream4RestartFunction(int, void *);void PrintSessionCache();int CheckRst(Session *, int, u_int32_t, Packet *);int PruneSessionCache(u_int8_t, u_int32_t, int, Session *);void StoreStreamPkt2(Session *, Packet *, u_int32_t);void FlushStream(Stream *, Packet *, int);void InitStream4Pkt();void Stream4VerifyConfig(void);int BuildPacket(Stream *, u_int32_t, Packet *, int);int CheckPorts(u_int16_t, u_int16_t);void PortscanWatch(Session *, u_int32_t);void PortscanDeclare(Packet *);int LogStream(Stream *);void WriteSsnStats(BinStats *);void OpenStatsFile();void Stream4Init(char *);void PreprocFunction(Packet *);void PreprocRestartFunction(int);void PreprocCleanExitFunction(int);static void Stream4PrintStats(int);static INLINE int isBetween(u_int32_t low, u_int32_t high, u_int32_t cur);static INLINE int NotForStream4(Packet *p);static INLINE int SetFinSent(Session *ssn, int direction, u_int32_t pkt_seq, Packet *p);static INLINE int WithinSessionLimits(Packet *p, Stream *stream); /* helpers for dealing with session byte_counters */static INLINE void StreamSegmentSub(Stream *stream, u_int16_t sub);static INLINE void StreamSegmentAdd(Stream *stream, u_int16_t add);static StreamPacketData *RemoveSpd(Stream *s, StreamPacketData *spd);static void AddSpd(Stream *s, StreamPacketData *prev, StreamPacketData *new);static int DupSpd(Packet *p, Stream *s, StreamPacketData *left, StreamPacketData **retSpd);static StreamPacketData *SpdSeqExists(Stream *s, u_int32_t pkt_seq);/* Here is where we separate which functions will be called in the normal case versus in the asynchronus state*/ //int UpdateState(Session *, Packet *, u_int32_t); int UpdateState2(Session *, Packet *, u_int32_t); int UpdateStateAsync(Session *, Packet *, u_int32_t);static void TcpAction(Session *ssn, Packet *p, int action, int direction, u_int32_t pkt_seq, u_int32_t pkt_ack);static void TcpActionAsync(Session *ssn, Packet *p, int action, int direction, u_int32_t pkt_seq, u_int32_t pkt_ack);/* * Define the functions for the Stream API */static int Stream4MidStreamDropAlert() { return s4data.ms_inline_alerts; }static void Stream4UpdateDirection( void * ssnptr, char dir, ip_p ip, u_int16_t port) { }static u_int32_t Stream4GetPacketDirection( Packet *p) { return 0;} static void SetIgnoreChannel( void * ssnptr, Packet *p, char dir, int32_t bytes, int response);static int Stream4IgnoreChannel( ip_p srcIP, u_int16_t srcPort, ip_p dstIP, u_int16_t dstPort, char protocol, char direction, char flags);static void Stream4ResumeInspection( void *ssnptr, char dir) { }static void Stream4DropTraffic( void *ssnptr, char dir);static void Stream4DropPacket( Packet *p);static void Stream4SetApplicationData( void *ssnptr, u_int32_t protocol, void *data, StreamAppDataFree free_func);static void *Stream4GetApplicationData(void *, u_int32_t);static u_int32_t Stream4SetSessionFlags(void *, u_int32_t);static u_int32_t Stream4GetSessionFlags(void *);static int AlertFlushStream(Packet *);static int ForceFlushStream(Packet *);static int Stream4AddSessionAlert(void *ssnptr, Packet *p, u_int32_t gid, u_int32_t sid);static int Stream4CheckSessionAlert(void *ssnptr, Packet *p, u_int32_t gid, u_int32_t sid);static char Stream4SetReassembly(void *ssnptr, u_int8_t flush_policy, char dir, char flags);static char Stream4GetReassemblyDirection(void *ssnptr);static char Stream4GetReassemblyFlushPolicy(void *ssnptr, char dir);static char Stream4IsStreamSequenced(void *ssnptr, char dir);/* Not an API function but part of the Session alert tracking */void CleanSessionAlerts(Session *ssn, Packet *flushed_pkt);static int Stream4TraverseReassembly( Packet *p, PacketIterator callback, void *userdata);static StreamFlowData *Stream4GetFlowData( Packet *p);#ifdef TARGET_BASEDstatic int16_t Stream4GetApplicationProtocolId(void *ssnptr) { return 0; }static int16_t Stream4SetApplicationProtocolId(void *ssnptr, int16_t id) { return 0; }#endifStreamAPI s4api = { STREAM_API_VERSION4, Stream4MidStreamDropAlert, Stream4UpdateDirection, /* Not supporrted in Stream4 */ Stream4GetPacketDirection, /* Not supporrted in Stream4 */ SetIgnoreChannel, Stream4IgnoreChannel, Stream4ResumeInspection, /* Not supported in Stream4 */ Stream4DropTraffic, Stream4DropPacket, Stream4SetApplicationData, Stream4GetApplicationData, Stream4SetSessionFlags, Stream4GetSessionFlags, AlertFlushStream, ForceFlushStream, Stream4TraverseReassembly, Stream4AddSessionAlert, Stream4CheckSessionAlert, Stream4GetFlowData, Stream4SetReassembly, Stream4GetReassemblyDirection, Stream4GetReassemblyFlushPolicy, Stream4IsStreamSequenced#ifdef TARGET_BASED , Stream4GetApplicationProtocolId, /* Not supported in Stream4 */ Stream4SetApplicationProtocolId /* Not supported in Stream4 */#endif /* More to follow */};/** * See if a sequence number is in range. * * @param low base sequence number * @param high acknowledged sequence number * @param cur sequence number to check * * @return 1 if we are between these sequence numbers, 0 otherwise */static INLINE int isBetween(u_int32_t low, u_int32_t high, u_int32_t cur){ DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"(%u,%u,%u) = (low, high, cur)\n", low,high,cur);); return (cur - low) <= (high - low);}static void TraverseFunc(StreamPacketData *NodePtr, void *build_data){ Stream *s; StreamPacketData *spd; BuildData *bd; u_int8_t *buf; int trunc_size; int offset = 0; if(s4data.stop_traverse) return; spd = (StreamPacketData *) NodePtr; bd = (BuildData *) build_data; s = bd->stream; buf = (u_int8_t *)bd->buf; /* Don't reassemble if there's nothing to reassemble. * The first two cases can probably never happen. I personally * prefer strong error checking (read: paranoia). */ if(spd->payload_size == 0) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "not reassembling because " "the payload size is zero.\n");); spd->chuck = SEG_FULL; return; } else if(SEQ_EQ(s->base_seq, s->last_ack)) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "not reassembling because " "base_seq = last_ack (%u).\n", s->base_seq);); return; } /* Packet is completely before the current window. */ else if(SEQ_LEQ(spd->seq_num, s->base_seq) && SEQ_LEQ(spd->seq_num + spd->payload_size, s->base_seq)) { /* ignore this segment, we've already looked at it */ spd->chuck = SEG_FULL; return; } /* Packet starts outside the window and ends inside it. */ else if(SEQ_LT(spd->seq_num, s->base_seq) && isBetween(s->base_seq+1, s->last_ack, (spd->seq_num + spd->payload_size))) { /* case where we've got a segment that wasn't completely ack'd * last time it was processed, do a partial copy into the buffer */ DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Incompleted segment, copying up " "to last-ack\n");); /* calculate how much un-ack'd data to copy */ trunc_size = (spd->seq_num+spd->payload_size) - s->base_seq; /* figure out where in the original data payload to start copying */ offset = s->base_seq - spd->seq_num; if (offset < 0) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Negative offset, not using " "old packet: Base: 0x%x Packet: 0x%x Offset: %d\n", s->base_seq, spd->seq_num, offset);); spd->chuck = SEG_FULL; return; } if(trunc_size < 65500 && trunc_size > 0) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Copying %d bytes into buffer, " "offset %d, buf %p\n", trunc_size, offset, buf);); SafeMemcpy(buf, spd->payload+offset, trunc_size, stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE); pc.rebuilt_segs++; bd->total_size += trunc_size; } else { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Woah, got bad TCP segment " "trunctation value (%d)\n", trunc_size);); } spd->chuck = SEG_FULL; } /* if it's in bounds... */ else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) && isBetween(s->base_seq, s->last_ack, (spd->seq_num + spd->payload_size))) { offset = spd->seq_num - s->base_seq; if (offset < 0) { /* This shouldn't happen because of the bounds check above */ DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Negative offset, not using " "old packet: Base: 0x%x Packet: 0x%x Offset: %d\n", s->base_seq, spd->seq_num, offset);); spd->chuck = SEG_FULL; return; } s->next_seq = spd->seq_num + spd->payload_size; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Copying %d bytes into buffer, " "offset %d, buf %p\n", spd->payload_size, offset, buf);); DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "spd->seq_num (%u) s->last_ack (%u) " "s->base_seq(%u) size: (%u) s->next_seq(%u), " "offset(%u), MAX(%u)\n", spd->seq_num, s->last_ack, s->base_seq, spd->payload_size, s->next_seq, offset, MAX_STREAM_SIZE)); SafeMemcpy(buf+offset, spd->payload, spd->payload_size, stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE); pc.rebuilt_segs++; spd->chuck = SEG_FULL; bd->total_size += spd->payload_size; } else if(isBetween(s->base_seq, s->last_ack-1, spd->seq_num) && SEQ_GT((spd->seq_num + spd->payload_size), s->last_ack)) { /* * if it starts in bounds and hasn't been completely ack'd, * truncate the last piece and copy it in */ trunc_size = s->last_ack - spd->seq_num; DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Truncating overlap of %d bytes\n", spd->seq_num + spd->payload_size - s->last_ack); DebugMessage(DEBUG_STREAM, " => trunc info seq: 0x%X " "size: %d last_ack: 0x%X\n", spd->seq_num, spd->payload_size, s->last_ack); ); offset = spd->seq_num - s->base_seq; if (offset < 0) { /* This shouldn't happen because of the bounds check above */ DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Negative offset, not using " "old packet: Base: 0x%x Packet: 0x%x Offset: %d\n", s->base_seq, spd->seq_num, offset);); spd->chuck = SEG_FULL; return; } if(trunc_size < (65500-offset) && trunc_size > 0) { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Copying %d bytes into buffer, " "offset %d, buf %p\n", trunc_size, offset, buf);); SafeMemcpy(buf+offset, spd->payload, trunc_size, stream_pkt->data, stream_pkt->data + MAX_STREAM_SIZE); pc.rebuilt_segs++; bd->total_size += trunc_size; spd->chuck = SEG_PARTIAL; } else { DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Woah, got bad TCP segment " "trunctation value (%d)\n", trunc_size);); } } else if(SEQ_GEQ(spd->seq_num,s->last_ack)) { /* we're all done, we've walked past the end of the ACK'd data */ DEBUG_WRAP(DebugMessage(DEBUG_STREAM, " => Segment is past last ack'd data, " "ignoring for now...\n"); DebugMessage(DEBUG_STREAM, " => (%d bytes @ seq 0x%X, " "ack: 0x%X)\n", spd->payload_size, spd->seq_num, s->last_ack); ); /* since we're reassembling in order, once we hit an overflow condition * let's stop trying for now */ s4data.stop_traverse = 1; //s4data.stop_seq = spd->seq_num; s4data.stop_seq = s->last_ack; } else { /* The only case that should reach this point is if * spd->seq_num < s->base_seq && * spd->seq_num + spd->payload_size >= s->last_ack * Can that ever happen? */ DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Ended up in the default case somehow.. !\n" "spd->seq_num(%u) spd->payload_size(%u)\n", spd->seq_num, spd->payload_size);); }} void SegmentCleanTraverse(Stream *s){ StreamPacketData *spd; StreamPacketData *foo; spd = s->seglist; while(spd != NULL) { if(spd->chuck == SEG_FULL || SEQ_GEQ(s->last_ack,(spd->seq_num+spd->payload_size))) { StreamPacketData *savspd = spd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -