Setting max segment size in tcp header
I am building a port scanner as a training exercise. My problem is I am trying to set the maximum segment size (MSS) option in the TCP header. I looked at tcp.h but I am having a hard time figuring out how to install it. I was hoping there would be an option like this:
tcp_header->mss(32000);
Something similar above was in tcp.h, but not in the correct structure. Admittedly, I'm still pretty new to reading structure descriptions and I couldn't understand much from tcp.h, so at the end I tried to just bind the required bytes to the end of the TCP header:
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);
}
But after I wrote this, it was clear that this is not a real solution, plus it still doesn't work: P So, the best way?
source to share
struct tcphdr
in tcp.h defines the required part of the TCP header. (Look at the TCP header , and you can match the definitions in struct tcphdr
with your actual bits, which will appear in the header.) Structures in C are constant in size, but TCP allows for more data. The header length field ( doff
in structure) is the total length of the header including parameters, so you need to add one account word for the MSS option:
tcp_header->doff = (sizeof(struct tcphdr))/4 + 1;
Define a structure for the MSS option:
struct tcp_option_mss {
uint8_t kind; /* 2 */
uint8_t len; /* 4 */
uint16_t mss;
} __attribute__((packed));
Now you can fill in the structure in the correct order:
/*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);
Take one more step and define a single structure for your package so the compiler can help us:
struct tcphdr_mss {
struct tcphdr tcp_header;
struct tcp_option_mss mss;
};
(You may need to add an end of option list option at the end and nop options to insert an 8 byte option list.)
Now we can collect all the parts:
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);
}
source to share