我没有时间为您编写代码,但以下是从我对您的其他问题的答案所做的编辑中复制的一些信息:
为每个数据包传递给 TCP 分路器的 C 结构是:
/* the tcp header structure, passed to tap listeners */
typedef struct tcpheader {
guint32 th_seq;
guint32 th_ack;
gboolean th_have_seglen; /* TRUE if th_seglen is valid */
guint32 th_seglen;
guint32 th_win; /* make it 32 bits so we can handle some scaling */
guint16 th_sport;
guint16 th_dport;
guint8 th_hlen;
guint16 th_flags;
guint32 th_stream; /* this stream index field is included to help differentiate when address/port pairs are reused */
address ip_src;
address ip_dst;
/* This is the absolute maximum we could find in TCP options (RFC2018, section 3) */
#define MAX_TCP_SACK_RANGES 4
guint8 num_sack_ranges;
guint32 sack_left_edge[MAX_TCP_SACK_RANGES];
guint32 sack_right_edge[MAX_TCP_SACK_RANGES];
} tcp_info_t;
因此,对于 C 语言点击,点击侦听器的“数据包”例程的“数据”参数指向该类型的结构。
对于 Lua taps,作为第三个参数传递给 tap listener 的“packet”例程的“tapinfo”表被描述为“一个基于 Listener 类型或 nil 的信息表”。对于 TCP 分路,表中的条目包括该结构中的所有字段,除了sack_left_edge
和sack_right_edge
; 表中的键是结构成员名称。
该th_stream
字段标识连接;每次 TCP 解析器找到一个新连接时,它都会分配一个新值。如注释所示,“包含此流索引字段以帮助区分何时重用地址/端口对”,因此,如果给定连接已关闭,并且稍后的连接使用相同的端点,th_stream
即使这两个连接具有不同的值它们具有相同的端点。
因此,您将拥有一个使用该th_stream
值作为键的表。该表将存储端点(地址和端口)以及每个方向的数据包和字节数。对于传递给侦听器的“数据包”例程的每个数据包,您将th_stream
在表中查找值,如果找不到,您将创建一个新条目,从零开始计数,并使用它新条目; 否则,您将使用您找到的条目。然后,您将确定数据包是从 A 到 B 还是从 B 到 A,并增加适当的数据包计数和字节计数。
您还需要跟踪时间戳。对于第一个数据包,您将存储该数据包的时间戳。对于每个数据包,您将查看时间戳,如果它比存储的时间戳晚一分钟或更长时间,您将:
- 从连接表中转储统计信息;
- 清空连接表;
- 存储新数据包的时间戳,替换之前存储的时间戳。