( (flow.sport & 0xff) | ((flow.dport & 0xff) << 8) | \
((flow.src & 0xff) << 16) | ((flow.dst & 0xff) << 24) \
) % HASH_SIZE)
{
/* create space for the new state */
flow_state_t *new_flow = MALLOC(flow_state_t, 1);
int index = HASH_FLOW(flow); //计算flow的hash key
new_flow->next = flow_hash[index]; //将新创建的flow插入到链表的头部
flow_hash[index] = new_flow;
new_flow->flow = flow;
new_flow->isn = isn; //tcp流起始序号
new_flow->fp = NULL; //存储文件的句柄
new_flow->pos = 0; //存储文件中的位置记录
new_flow->flags = 0; //流状态标识,如文件存在、流记录完成等
new_flow->last_access = current_time++; //current_time是个静态变量,用于表示每个流的生成时间
}
- 利用循环队列来存储打开的fd
max_fds = get_max_fds() - NUM_RESERVED_FDS;
fd_ring = MALLOC(flow_state_t *, max_fds);
for (i = 0; i < max_fds; i++)
fd_ring[i] = NULL;
- 队列满时的处理策略
if (fd_ring[next_slot] != NULL) //如果队列满了,关闭下一个fd
close_file(fd_ring[next_slot]);
/* put ourslves in its place */
fd_ring[next_slot] = flow_state;
/* set flags and remember where in the file we are */
SET_BIT(flow_state->flags, FLOW_FILE_EXISTS);
FGETPOS(flow_state->fp, &(flow_state->pos));
return flow_state->fp;
- 系统fd耗尽时的处理策略
do {
if (attempt_fopen(flow_state, filename) != NULL) {
/* open succeeded... great */
done = 1;
} else {
if (errno == ENFILE || errno == EMFILE) {
/* open failed because too many files are open... close one
and try again */
contract_fd_ring();
DEBUG(5) ("too many open files -- contracting FD ring to %d", max_fds);
done = 0;
} else {
/* open failed for some other reason... give up */
done = 1;
}
}
} while (!done);
- 创建
char *filename = flow_filename(flow_state->flow);
根据flow的src,dst和src port和dst port来创建对应的文件名
- 查找
flow流对象中记录了对应文件的fd
if (state->fp == NULL) {
if (open_file(state) == NULL) {
return;
}
}
4、数据结构
typedef struct {
u_int32_t src; /* Source IP address */
u_int32_t dst; /* Destination IP address */
u_int16_t sport; /* Source port number */
u_int16_t dport; /* Destination port number */
} flow_t; //TCP流四元组
typedef struct flow_state_struct {
struct flow_state_struct *next; /* Link to next one */ //单向链表next指针
flow_t flow; /* Description of this flow */ //流ID:四元组
tcp_seq isn; /* Initial sequence number we've seen */ //tcp 起始ID
FILE *fp; /* Pointer to file storing this flow's data */ //存储文件的fd
long pos; /* Current write position in fp */ //上次存储的位置
int flags; /* Don't save any more data from this flow */ //流状态
int last_access; /* "Time" of last access */ //记录访问时间先后
} flow_state_struct;