Im mimicking the 3-way handshake tcp protocol in C ++, along with wirehark as my code runs. My code processes the headers at the ip and tcp levels, packs them, and then sends them to the http server with the tcp SYN header flag set to 1.
I can see on wirehark a complete datagram with ip and tcp headers in order. There seems to be no errors. My process associates a socket with the same address and port as in the packet header already sent.
Wireshark shows that the packet was sent successfully, but there is no revenue packet on the server confirming my SYN. What am I doing wrong?
I'm on Ubuntu 10.10, 2.6.35-23.
The code is dirty, 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 unsigned 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;