在tcp标头中设置最大段大小

时间:2009-08-18 19:20:38

标签: c linux sockets tcp struct

我正在整理端口扫描仪作为学习练习。我的问题是我正在尝试在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那么有更好的方法吗?

1 个答案:

答案 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);
}