流更新
通过FlowWorker线程函数中调用FlowUpdate,FlowUpdate中又调用了FlowHandlePacketUpdate来更新流。
在获取到包所属的流后,接下来将根据这个包对流进行更新。
/** \brief Update Packet and Flow
*
* Updates packet and flow based on the new packet.
*
* \param f locked flow
* \param p packet
*
* \note overwrites p::flowflags
*/
void FlowHandlePacketUpdate(Flow *f, Packet *p)
{
SCLogDebug("packet %"PRIu64" -- flow %p", p->pcap_cnt, f);
/* update flags and counters */
if (FlowGetPacketDirection(f, p) == TOSERVER) {
//调用FlowGetPacketDirection获取数据包的方向。注意,这里的方向是相对于流来说的,而流的初始方向由该流的第一个包决定,若当前包与流的第一个包的方向一致(源端口相同或源地址相同),则方向为TOSERVER(可以认为是正向),否则为TOCLIENT(反向)。
f->todstpktcnt++;
f->todstbytecnt += GET_PKT_LEN(p);
p->flowflags = FLOW_PKT_TOSERVER;
if (!(f->flags & FLOW_TO_DST_SEEN)) {
if (FlowUpdateSeenFlag(p)) {
f->flags |= FLOW_TO_DST_SEEN;
p->flowflags |= FLOW_PKT_TOSERVER_FIRST;
}
}
//若数据包方向为TOSERVER,则增加对应的引用计数,添加流状态标志FLOW_TO_DST_SEEN,并且为数据包的flowflags添加FLOW_PKT_TOSERVER。
} else {
f->tosrcpktcnt++;
f->tosrcbytecnt += GET_PKT_LEN(p);
p->flowflags = FLOW_PKT_TOCLIENT;
if (!(f->flags & FLOW_TO_SRC_SEEN)) {
if (FlowUpdateSeenFlag(p)) {
f->flags |= FLOW_TO_SRC_SEEN;
p->flowflags |= FLOW_PKT_TOCLIENT_FIRST;
}
}
}
//若数据包方向为TOCLIENT,则增加对应的引用计数,添加流状态标志FLOW_TO_SRC_SEEN,并且为数据包的flowflags添加FLOW_PKT_TOSERVER。
if ((f->flags & (FLOW_TO_DST_SEEN|FLOW_TO_SRC_SEEN)) == (FLOW_TO_DST_SEEN|FLOW_TO_SRC_SEEN)) {
SCLogDebug("pkt %p FLOW_PKT_ESTABLISHED", p);
p->flowflags |= FLOW_PKT_ESTABLISHED;
if (f->proto != IPPROTO_TCP) {
SC_ATOMIC_SET(f->flow_state, FLOW_STATE_ESTABLISHED);
}
}
//若流的FLOW_TO_DST_SEEN和FLOW_TO_SRC_SEEN都设置了,说明流已经建立,给包添加FLOW_PKT_ESTABLISHED标志。后面检测时会用到这个标志。
/*set the detection bypass flags*/
if (f->flags & FLOW_NOPACKET_INSPECTION) {
SCLogDebug("setting FLOW_NOPACKET_INSPECTION flag on flow %p", f);
DecodeSetNoPacketInspectionFlag(p);
}
if (f->flags & FLOW_NOPAYLOAD_INSPECTION) {
SCLogDebug("setting FLOW_NOPAYLOAD_INSPECTION flag on flow %p", f);
DecodeSetNoPayloadInspectionFlag(p);
}
}
//若流的FLOW_NOPACKET_INSPECTION(绕过包检测)或FLOW_NOPAYLOAD_INSPECTION(绕过负载检测)设置了,则给包也添加相应标志。