我正在整理端口扫描仪作为学习练习。我的问题是我正在尝试在TCP标头中设置最大段大小选项(MSS)。我看了一下tcp.h,但是我无法弄清楚如何设置它。我希望会有这样的选项:
tcp_header->mss(32000);
类似于上面的内容在tcp.h中,但在右侧结构中没有。不可否认,我仍然是读取结构定义的新手,而且我对tcp.h没有多大意义,所以最后我尝试在TCP头的末尾添加必要的字节:
struct tcphdr *CreateTcpHeader()
{
struct tcphdr *tcp_header;
tcp_header = (struct tcphdr *)malloc(sizeof(struct tcphdr)+4*sizeof(int));
tcp_header->source = htons(SRC_PORT);
tcp_header->dest = htons(DST_PORT);
tcp_header->seq = htonl(0);
tcp_header->ack_seq = htonl(0);
tcp_header->res1 = 0;
tcp_header->doff = (sizeof(struct tcphdr))/4;
tcp_header->syn = 1;
tcp_header->window = htons(4096);
tcp_header->check = 0; /* Will calculate the checksum with pseudo-header later */
tcp_header->urg_ptr = 0;
/*memcpy the mss data onto the end of the tcp header. */
int mssCode = 2;
int mssLength = 4;
uint16_t mss = htonl(32000);
int offset = sizeof(struct tcphdr);
memcpy( (tcp_header+offset), &mssCode, 1 );
memcpy( (tcp_header+offset+1), &mssLength, 1 );
memcpy( (tcp_header+offset+2), &mss, 2);
return (tcp_header);
}
但是在我写完之后很明显这不是一个真正的解决方案,而且它仍然不起作用:P那么有更好的方法吗?
答案 0 :(得分:5)
tcp.h中的struct tcphdr
定义了TCP标头的必需部分。 (查看TCP header,您可以将struct tcphdr
中的定义与标题中显示的实际位相匹配。)C中的结构具有常量大小,但TCP允许可选数据。标题长度字段(结构中的doff
)是标题的总长度,包括选项,因此您需要添加一个单词来考虑MSS选项:
tcp_header->doff = (sizeof(struct tcphdr))/4 + 1;
让我们为MSS选项定义一个结构:
struct tcp_option_mss {
uint8_t kind; /* 2 */
uint8_t len; /* 4 */
uint16_t mss;
} __attribute__((packed));
现在您可以按正确的顺序填充结构:
/*memcpy the mss data onto the end of the tcp header. */
struct tcp_option_mss mss;
mss.kind = 2;
mss.len = 4;
mss.mss = htons(32000);
让我们更进一步,为您的数据包定义一个结构,让编译器 帮助我们:
struct tcphdr_mss {
struct tcphdr tcp_header;
struct tcp_option_mss mss;
};
(您可能需要在末尾添加end-of-option-list选项,并使用nop选项将选项列表填充为8个字节。)
现在我们可以将所有部分组合在一起:
struct tcphdr *CreateTcpHeader()
{
struct tcphdr_mss *tcp_header;
tcp_header = malloc(sizeof(struct tcphdr_mss));
tcp_header->tcp_header.source = htons(SRC_PORT);
tcp_header->tcp_header.dest = htons(DST_PORT);
tcp_header->tcp_header.seq = htonl(0);
tcp_header->tcp_header.ack_seq = htonl(0);
tcp_header->tcp_header.res1 = 0;
tcp_header->tcp_header.doff = (sizeof(struct tcphdr_mss))/4;
tcp_header->tcp_header.syn = 1;
tcp_header->tcp_header.window = htons(4096);
tcp_header->tcp_header.check = 0; /* Will calculate the checksum with pseudo-header later */
tcp_header->tcp_header.urg_ptr = 0;
tcp_header->mss.kind = 2;
tcp_header->mss.len = 2;
tcp_header->mss.mss = htons(32000);
return (tcp_header);
}