I am putting together a port scanner as a learning exercise. My problem is I’m trying to set the maximum segment size option(MSS) in the TCP header. I had a look at tcp.h, but I’m having trouble figuring out how to set it. I was hoping there would be an option like this:
tcp_header->mss(32000);
Something similar to the above was in tcp.h but not in the right struct. Admittedly, I’m still fairly new to reading struct definitions and I couldn’t make much sense out of tcp.h so in the end I tried just tacking on the necessary 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 it it was clear that is wasn’t a real solution, plus it still doesn’t work 😛 So is there a better way?
The
struct tcphdrin tcp.h defines the mandatory part of the TCP header. (Look at the TCP header and you can match the definitions instruct tcphdrto your the actual bits to appear in the header.) Structs in C have a constant size, but TCP allows optional data. The header length field (doffin the structure) is the total length of the header, including options, so you’ll need to add one word to account for the MSS option:Let’s define a structure for the MSS option:
Now you can populate the structure, in the right order:
Let’s go one step further and define a single structure for your packet, to let the compiler
help us out:
(You may need to add an end-of-option-list option at the end, and nop options to pad the option list to 8 bytes.)
Now we can put all the pieces together: