Im simulating tcp protocol's 3-way handshake in c++, along with wireshark as my code runs. My code crafts the headers at ip and tcp layers, packs them, then send it to an http server with tcp header's SYN flag set to 1.
I can see on wireshark the full datagram with both ip and tcp headers ok. Seems to be no errors. My process bind a socket with the same address and port as contained in the already sent packet's header.
Wireshark shows packet successfully sent but there isn't any income packet from the server acknowledging my SYN. What am i doing wrong?
I am on Ubuntu 10.10, 2.6.35-23.
The code is messy, sorry for that. Its just for testing.
main.cpp:
char host[100],buf[1000],*data=NULL,source_ip[20]; //buf is the complete packet
sockaddr_in dest;
hostent *server;
IPV4_HDR *v4hdr=NULL;
TCP_HDR *tcphdr=NULL;
memset(&buf, 0, sizeof(buf));
cout << "Creating RAW socket..." << endl;
int s;
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
cout << "Error creating socket: " << errno << endl;
return 1;
}
cout << "Setting the socket in RAW mode..." << endl;
int optval = 1;
if ((setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval))) == -1) {
cout << "Failed to set socket in RAW mode..." << endl;
return 1;
}
cout << "Successful.\n";
cout << "nResolving Hostname..." << endl;
if((server=gethostbyname("www.site.com"))==0)
{
cout << "Unable to resolve." << endl;
return 1;
}
dest.sin_family = AF_INET;
dest.sin_port = htons(50000);
memcpy(&dest.sin_addr.s_addr,server->h_addr,server->h_length);
cout << "Resolved." << endl;
v4hdr = (IPV4_HDR *)buf; //lets point to the ip header portion
v4hdr->ip_version=4;
v4hdr->ip_header_len=5;
v4hdr->ip_tos = 16;
v4hdr->ip_total_length = htons ( sizeof(IPV4_HDR) + sizeof(TCP_HDR) );
v4hdr->ip_id = htons(2);
v4hdr->ip_frag_offset = 0;
v4hdr->ip_frag_offset1 = 0;
v4hdr->ip_reserved_zero = 0;
v4hdr->ip_dont_fragment = 1;
v4hdr->ip_more_fragment = 0;
v4hdr->ip_ttl = 64;
v4hdr->ip_protocol = IPPROTO_TCP;
v4hdr->ip_srcaddr = inet_addr("192.168.0.103");
v4hdr->ip_destaddr = inet_addr(inet_ntoa(dest.sin_addr));
v4hdr->ip_checksum = 0;
tcphdr = (TCP_HDR *)&buf[sizeof(IPV4_HDR)]; //get the pointer to the tcp header in the packet
tcphdr->source_port = htons(52000);
tcphdr->dest_port = htons(80);
tcphdr->window = htons(5840);
tcphdr->acknowledge = 0;
tcphdr->data_offset = 8;
tcphdr->urg=0;
tcphdr->ack=0;
tcphdr->psh=0;
tcphdr->rst=0;
tcphdr->syn=1;
tcphdr->fin=0;
tcphdr->options1=htonl(0x020405b4);
tcphdr->options2=htonl(0x04020103);
tcphdr->options3=htonl(0x03060000);
cout << sizeof(*tcphdr) << endl;
//tcphdr->ns=0;
tcphdr->checksum = csum((unsigned short *) buf, (sizeof(ip_hdr) + sizeof(tcp_header)));;
int bytes = 0;
if((bytes = sendto(s , buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR), 0,
(sockaddr *)&dest, sizeof(dest)))==-1)
{
cout << "Error sending packet: " << errno << endl;
return 1;
}
cout << bytes << " bytes sent!" << endl;
close(s);
// This is on tcp.h...
typedef struct ip_hdr
{
unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words)
// normally=5 (Means 20 Bytes may be 24 also)
unsigned char ip_version :4; // 4-bit IPv4 version
unsigned char ip_tos; // IP type of service
unsigned short ip_total_length; // Total length
unsigned short ip_id; // Unique identifier
unsigned char ip_frag_offset :5; // Fragment offset field
unsigned char ip_more_fragment :1;
unsigned char ip_dont_fragment :1;
unsigned char ip_reserved_zero :1;
unsigned char ip_frag_offset1; //fragment offset
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
// TCP header
typedef struct tcp_header
{
unsigned short source_port; // source port
unsigned short dest_port; // destination port
unsigned int sequence; // sequence number - 32 bits
unsigned int acknowledge; // acknowledgement number - 32 bits
unsigned char reserved_part1:4; //according to rfc
unsigned char data_offset:4; /*The number of 32-bit words
in the TCP header.
This indicates where the data begins.
The length of the TCP header
is always a multiple
of 32 bits.*/
unsigned char fin :1; //Finish Flag
unsigned char syn :1; //Synchronise Flag
unsigned char rst :1; //Reset Flag
unsign开发者_JAVA百科ed char psh :1; //Push Flag
unsigned char ack :1; //Acknowledgement Flag
unsigned char urg :1; //Urgent Flag
unsigned char reserved_part2:2;
unsigned short window :16; // window
//unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540.
//unsigned char ecn :1; //ECN-Echo Flag
//unsigned char cwr :1; //Congestion Window Reduced Flag
////////////////////////////////
unsigned short checksum; // checksum
unsigned short urgent_pointer; // urgent pointer
unsigned int options1;
unsigned int options2;
unsigned int options3;
} TCP_HDR;
You haven't gotten this far yet, but you will need to firewall the local port you are using so that the kernel doesn't reply to SYN/ACK with a RST.
精彩评论