I am trying to send packets via UDP, and I am not allowed to use SOCK_RAW (school project).
The packet I am sending has a header struct ip and a string data part. I put them into one char array (the packet itself is configured correctly).
Here is how I send:
sendPacket(packet);
where packet is a char[] and
where sendPacket is defined as:
void IPNode::sendPacket(char* packet){
//define socket, destSockAddr
int success = sendto(socket, packet, sizeof(packet), 0,
(struct sockaddr *) &destSockAddr, sizeof(destSockAddr));
}
}
The packet seems to be correct.
However, this is how I read it in.
while (true) {
struct sockaddr_in remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
char buffer[BUF_SIZE];
int recvlen = recvfrom(myListenSocket, buffer, BUF_SIZE, 0, 0, 0);
onReceive(buffer);
// other stuff
}
where onReceive is:
void onReceive(char* packet) {
ip* ptr = (ip*)packet; //the struct ip is the beginning of the packet
struct ip ipCpy = *ptr;
struct in_addr inAddrCpy = ipCpy.ip_src;
char* ipString = inet_ntoa(inAddrCpy);
cout << ipString << endl;
return;
}
However, the ipString that is printed is different from the ipString that was in the packet before being sent. Am I accessing the received packets wrongly?
You are sending sizeof(packet) bytes. But sizeof(packet) is 4, because packet is a pointer. You need a better way to keep track of the actual size you want to send.
Related
I want to send() body and header which has body size from the Side A.
On the Side B, in the first recv() header to determine the size of payload. The second, recv() body.
I tried to use recv() twice but could not through the second recv() function.
Side A
struct CommandHeader_t {
int BodySizeByte;
};
void Send()
{
const int BODY_SIZE_BYTE = 10;
CommandHeader_t* header_ptr = (CommandHeader_t*) malloc(sizeof(CommandHeader_t) + BODY_SIZE_BYTE);
header_ptr->BodySizeByte = BODY_SIZE_BYTE;
char* body_ptr = (char*) (header_ptr + sizeof(CommandHeader_t));
snprintf(body_ptr, BODY_SIZE_BYTE, "Hello World");
int sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
struct sockaddr_un addr = {0};
addr.sun_family = AF_LOCAL;
strcpy(addr.sun_path, SENDING_SOCKET);
sendto(sock, header_ptr, sizeof(CommandHeader_t) + BODY_SIZE_BYTE, 0, (const struct sockaddr*)&addr, sizeof(addr));
close(sock);
}
Side B
void Reveice()
{
// something
CommandHeader_t header;
char* body_ptr;
recv(sockfd, &header, sizeof(CommandHeader_t), 0);
body_ptr = (char*) malloc(header.BodySizeByte);
recv(sockfd, body_ptr, header.BodySizeByte, 0); // CANNOT recv anything
}
There are some mistakes in your code:
On the sending side, you are not doing pointer arithmetic correctly when assigning the body_ptr pointer. As header_ptr is declared as CommandHeader_t*, doing (header_ptr + sizeof(CommandHeader_t)) will calculate a memory address that is sizeof(CommandHeader_t) number of CommandHeader_t elements past the address that header_ptr is pointing at. That is not what you want. You need to instead calculate an address that is sizeof(CommandHeader_t) number of chars past the header_ptr address.
So, you need to change this:
char* body_ptr = (char*) (header_ptr + sizeof(CommandHeader_t));
To this instead:
char* body_ptr = ((char*) header_ptr) + sizeof(CommandHeader_t);
A simpler way to handle this is to add a char[1] member to CommandHeader_t, and then subtract 1 when malloc()'ing it, eg:
#pragma pack(push, 1) // or equivalent
struct CommandHeader_t {
int BodySizeByte;
char data[1];
};
#pragma pack(pop) // or equivalent
CommandHeader_t* header_ptr = (CommandHeader_t*) malloc(offsetof(CommandHeader_t, data) + BODY_SIZE_BYTE);
header_ptr->BodySizeByte = BODY_SIZE_BYTE;
char* body_ptr = header_ptr->data;
snprintf(body_ptr, BODY_SIZE_BYTE, "Hello World");
Also, since you are using SOCK_DGRAM on the sending side, the sendto() is message-oriented, sending the entire data in 1 message. But your receiving code is written as if it were using a stream-oriented socket instead. Don't mismatch socket types like that. If you want to call recv() multiple times, use a stream-oriented socket on both sides. Otherwise, use a message-oriented socket on both sides, and then have the receiver allocate a buffer large enough to receive an entire message in 1 recvfrom() (you can use ioctl(FIONREAD) to determine the size of the next pending message), and then parse the contents of that message as needed.
Also, your receiver is leaking the body_ptr buffer it allocated with malloc().
I capture all the packets in one side with help of nfqueue, "record" them (all the data: ip info, next protocol info etc) with nfq_get_payload and deliver them into another side with help of udp. How can I restore this packet on another side and then send to myself(2 side) like there is no udp-encapsulation between? Should I use some nfqueue API or I have to implement all the protocols packet creation (UDP, ICMP, TCP, etc)? And how should I send this restored packet?
Ok, I successfully recreated and sent forward my packet encapsulated in UDP. After recreation I needed to send this packet to another IP, but you can use original destination address. So the code snippet:
char *full_packet;
int size;
// some actions to get full_packet and size from UDP packet
// assume you recreated this: int size = nfq_get_payload(nfa, &full_packet);
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
// also optional string needed in my case:
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, "wlan0", strlen("wlan0"));
if (sock == -1) {
perror("socket() failed");
return 1;
}
struct sockaddr_in to;
struct ip *iph = (struct ip *)full_packet;
to.sin_addr.s_addr = inet_addr("192.168.0.107"); // here you can set IP address where you need send this packet
to.sin_family = AF_INET;
int bytes = sendto(sock, full_packet, size, 0, (struct sockaddr*) &to, sizeof(to));
if (bytes == -1) {
perror("send() failed");
return 1;
}
I hope this will help somebody
I have been trying to send packets using raw socket in following code.This code I found somewhere in the internet. I created my own ipheader and udp header. The whole data packet is sent using sendto() function on raw socket. sendto() returns 0. Which means a packet of 0 length is sent out of it and hence even wireshark doesnt detect any packet. Where is my mistake?
// Must be run by root lol! Just datagram, no payload/data
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
// The packet length
#define PCKT_LEN 35
// Can create separate header file (.h) for all headers' structure
// The IP header's structure
struct ipheader {
unsigned char iph_ihl:4, iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flag;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
// UDP header's structure
struct udpheader {
unsigned short int udph_srcport;
unsigned short int udph_destport;
unsigned short int udph_len;
unsigned short int udph_chksum;
};
// total udp header length: 8 bytes (=64 bits)
// Function for checksum calculation. From the RFC,
// the checksum algorithm is:
// "The checksum field is the 16 bit one's complement of the one's
// complement sum of all 16 bit words in the header. For purposes of
// computing the checksum, the value of the checksum field is zero."
unsigned short csum(unsigned short *buf, int nwords)
{ //
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
int sd;
// No data/payload just datagram
char buffer[PCKT_LEN];
// Our own headers' structures
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
// Source and destination addresses: IP and port
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}
// Create a raw socket with UDP protocol
sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if(sd < 0)
{
perror("socket() error");
// If something wrong just exit
exit(-1);
}
else
printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");
// The source is redundant, may be used later if needed
// The address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Port numbers
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// IP addresses
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
// Fabricate the IP header or we can use the
// standard header structures but assign our own values.
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16; // Low delay
ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader);
ip->iph_ident = htons(54321);
ip->iph_ttl = 64; // hops
ip->iph_protocol = 17; // UDP
// Source IP address, can use spoofed address here!!!
ip->iph_sourceip = inet_addr(argv[1]);
// The destination IP address
ip->iph_destip = inet_addr(argv[3]);
// Fabricate the UDP header. Source port number, redundant
udp->udph_srcport = htons(atoi(argv[2]));
// Destination port number
udp->udph_destport = htons(atoi(argv[4]));
udp->udph_len = htons(sizeof(struct udpheader));
// Calculate the checksum for integrity
ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader));
// Inform the kernel do not fill up the packet structure. we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK.\n");
// Send loop, send for every 2 second for 100 count
printf("Trying...\n");
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
int count;
int i;
for(count = 1; count <=20; count++)
{
if(i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
{
printf("Count #%u - sendto() is OK. Data Length#%d\n", count,i);
sleep(2);
}
}
close(sd);
return 0;
}
Aha! I've got at least part of it.
i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0
is the same as
i = (sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
you probably want:
(i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin))) < 0
You may want to:
Turn on warnings in your compiler - at least if you use gcc, that should give you a warning for comparing and assigning in the same if-statement.
Retry with the fixed code.
I'm sure there may be other problems in your code too - I'm no network expert.
It is really hard to read this piece of code and to understand what and why you're doing. So I can recoomend you look at my piece of code: dhcp client implementation
Look at function getSock() to see how socket is created, and on function talker() on how to form and send completed packet.
Local IP header structure is wrong... my suggestion is to include the IP header provided with your distro (are you using linux? don't you?).
What i did is just include linux/ip.h, rename ipheader structure reference to iphdr, and rename the ip header fields according to the structure described in the latter file.
I tried to sniff packets with tcpdump and it works now (i didn't try with wireshark but it must work too)
Try this fixed code:
// Must be run by root lol! Just datagram, no payload/data
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/udp.h>
#include <linux/ip.h>
// The packet length
#define PCKT_LEN 35
// UDP header's structure
struct udpheader {
unsigned short int udph_srcport;
unsigned short int udph_destport;
unsigned short int udph_len;
unsigned short int udph_chksum;
};
// total udp header length: 8 bytes (=64 bits)
// Function for checksum calculation. From the RFC,
// the checksum algorithm is:
// "The checksum field is the 16 bit one's complement of the one's
// complement sum of all 16 bit words in the header. For purposes of
// computing the checksum, the value of the checksum field is zero."
unsigned short csum(unsigned short *buf, int nwords)
{ //
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
int sd;
// No data/payload just datagram
char buffer[PCKT_LEN];
// Our own headers' structures
struct iphdr *ip = (struct iphdr *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct iphdr));
// Source and destination addresses: IP and port
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}
// Create a raw socket with UDP protocol
sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if(sd < 0)
{
perror("socket() error");
// If something wrong just exit
exit(-1);
}
else
printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");
// The source is redundant, may be used later if needed
// The address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Port numbers
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// IP addresses
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
// Fabricate the IP header or we can use the
// standard header structures but assign our own values.
ip->ihl = 5;
ip->version = 4;
ip->tos = 16; // Low delay
ip->tot_len = sizeof(struct iphdr) + sizeof(struct udpheader);
ip->id = htons(54321);
ip->ttl = 64; // hops
ip->protocol = 17; // UDP
// Source IP address, can use spoofed address here!!!
ip->saddr = inet_addr(argv[1]);
// The destination IP address
ip->daddr = inet_addr(argv[3]);
// Fabricate the UDP header. Source port number, redundant
udp->udph_srcport = htons(atoi(argv[2]));
// Destination port number
udp->udph_destport = htons(atoi(argv[4]));
udp->udph_len = htons(sizeof(struct udpheader));
// Calculate the checksum for integrity
ip->check = csum((unsigned short *)buffer, sizeof(struct iphdr) + sizeof(struct udpheader));
// Inform the kernel do not fill up the packet structure. we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK.\n");
// Send loop, send for every 2 second for 100 count
printf("Trying...\n");
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
int count;
int i;
for(count = 1; count <=20; count++)
{
if((i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin))) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
{
printf("Count #%u - sendto() is OK. Data Length# %d\n", count,i);
sleep(2);
}
}
close(sd);
return 0;
}
I'm guessing you based that on this example code, which has multiple fatal bugs. It has wasted many hours of my life.
But to answer this specific question (and to help anyone else who is unfortunate enough to try to use that code), the bug that prevents you from seeing the packets in wireshark is here:
sin.sin_addr.s_addr = inet_addr(argv[1]);
This sets the address used for sending the packet in sentdo() to the source address. Therefore, the packet is sent over the loopback interface, and it goes nowhere. (Wireshark or other capture tools will be able to see the packet if you capture the lo/loopback interface, fwiw.)
So the corrected line for this particular program is:
sin.sin_addr.s_addr = inet_addr(argv[3]);
I am trying to build a packet that will be sent via UDP. However I am not getting the correct data on the receiving side.
In the packet I want to include an IP Header, UDP Header, and the data that needs to be sent. In this case I just want to send the word "Hello" along with random header information.
char *data = "Hello";
char *packet = (char *)malloc(sizeof(struct iphdr) + sizeof(struct udphdr) + strlen(data));
struct iphdr *ip = (struct iphdr*) packet;
struct udphdr *udp = (struct udphdr*) (packet + sizeof(struct iphdr));
char *send_buff = (char *) (packet + sizeof(struct iphdr) + sizeof(struct udphdr));
ip->saddr = inet_addr("1.2.3.4");
ip->daddr = inet_addr("5.6.7.8");
ip->ttl = 5;
udp->source = 5950;
udp->dest = 5950;
udp->len = sizeof(struct udphdr);
udp->check = 0;
strcpy(send_buff, data);
sendto(sock, packet, (sizeof(struct iphdr) + sizeof(struct udphdr) + strlen(data)), ROUTER_IP);
The problem I'm having is that the receiving end just gets random data so I'm assuming the number of bytes is incorrect somewhere.
On the receiving side I have it print out one of the fields of the IP header as a test, but it's not correct.
char recv_buff[1000];
int recv_bytes = recvfrom(sock, recv_buff, sizeof(recv_buff));
struct iphdr *ip = (struct iphdr*) recv_buff;
cout << static_cast<int16_t>(ip->ttl) << endl;
Am I putting the packet together wrong or is there a problem on the receiving end?
I used this example http://www.winlab.rutgers.edu/~zhibinwu/html/c_prog.htm as a reference for putting together the packet.
You are creating the socket as socket(AF_INET, SOCK_DGRAM, 0); meaning that it's a datagram (=UDP, typically) socket, so the network stack will automatically include IP header & UDP headers, etc.
But since you are trying to create your own IP and UDP headers you must create a raw socket, then send the packet (and also calculate the checksum as your reference code is doing).
To create a raw socket, use socket(AF_INET, SOCK_RAW, 0).
Besides the problem with not using raw sockets, you also don't set e.g. port numbers correctly. The have to be in network byte-order, so you should use e.g. htons for that. There are also other fields that should be in network byte orders.
if you are using your own ip and udp headers ON TOP of the stack's I hope you are parsing the data after removing both headers of yours and stack's. If the receiving socket is RAW, you will get the ip and udp headers of the stack as well.
I already asked this question on raw IP packet implementation. But I didn't get any solutions.
My code:
if((s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_TCP, 0, 0, 0))==SOCKET_ERROR) // Socket
{
printf("Creation of raw socket failed.");
return 0;
}
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))==SOCKET_ERROR)
{
printf("failed to set socket in raw mode.");
return 0;
}
if((sendto(s ,(char *) buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR) + payload, 0,(SOCKADDR *)&dest, sizeof(dest)))==SOCKET_ERROR)
{
printf("Error sending Packet : %d",WSAGetLastError());
break;
}
Error:
WSAGetLastError() returns 10022:
Description:
An invalid argument (for example, an argument that specified an invalid level) was supplied to the setsockopt (Wsapiref_94aa.asp) function. Sometimes, it also refers to the current state of the sockets, for example, calling accept (Wsapiref_13aq.asp) on a socket that is not listening.
Commentary:
But I have set the correct option value and size.
What am I doing wrong? I am using Windows XP (SP3). In setsocketopt I tried IP_OPTIONS for that program it works fine and it sends IP Packets too. But in ethereal for every IP packet it generates ICMP packets from the destination.
How can I fix this?
Source code:
//raw tcp packet crafter
#include "stdio.h"
#include "winsock2.h"
#include "ws2tcpip.h" //IP_HDRINCL is here
#include "conio.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, *PIPV4_HDR, FAR * LPIPV4_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 ns :1; //Nonce Sum Flag Added in RFC 3540.
unsigned char reserved_part1:3; //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 ecn :1; //ECN-Echo Flag
unsigned char cwr :1; //Congestion Window Reduced Flag
////////////////////////////////
unsigned short window; // window
unsigned short checksum; // checksum
unsigned short urgent_pointer; // urgent pointer
} TCP_HDR , *PTCP_HDR , FAR * LPTCP_HDR , TCPHeader , TCP_HEADER;
int main()
{
char host[100],buf[1000],*data=NULL,source_ip[20]; //buf is the complete packet
SOCKET s;
int k=1;
IPV4_HDR *v4hdr=NULL;
TCP_HDR *tcphdr=NULL;
int payload=512 ;
int optval= 1;
SOCKADDR_IN dest;
hostent *server;
//Initialise Winsock
WSADATA wsock;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsock) != 0)
{
fprintf(stderr,"WSAStartup() failed");
exit(EXIT_FAILURE);
}
printf("Initialised successfully.");
////////////////////////////////////////////////
//Create Raw TCP Packet
printf("\nCreating Raw TCP Socket...");
if((s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_TCP, 0, 0, 0))==SOCKET_ERROR)
{
printf("Creation of raw socket failed.");
return 0;
}
printf("Raw TCP Socket Created successfully.");
////////////////////////////////////////////////
//Put Socket in RAW Mode.
printf("\nSetting the socket in RAW mode...");
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))==SOCKET_ERROR)
{
printf("failed to set socket in raw mode.");
return 0;
}
printf("Successful.");
////////////////////////////////////////////////
//Target Hostname
printf("\nEnter hostname : ");
gets(host);
printf("\nResolving Hostname...");
if((server=gethostbyname(host))==0)
{
printf("Unable to resolve.");
return 0;
}
dest.sin_family = AF_INET;
dest.sin_port = htons(8888); //your destination port
memcpy(&dest.sin_addr.s_addr,server->h_addr,server->h_length);
printf("Resolved.");
/////////////////////////////////////////////////
printf("\nEnter Source IP : ");
gets(source_ip);
v4hdr = (IPV4_HDR *)buf; //lets point to the ip header portion
v4hdr->ip_version=4;
v4hdr->ip_header_len=5;
v4hdr->ip_tos = 0;
v4hdr->ip_total_length = htons ( sizeof(IPV4_HDR) + sizeof(TCP_HDR) + payload );
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 = 8;
v4hdr->ip_protocol = IPPROTO_TCP;
v4hdr->ip_srcaddr = inet_addr(source_ip);
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(1234);
tcphdr->dest_port = htons(8888);
tcphdr->cwr=0;
tcphdr->ecn=1;
tcphdr->urg=0;
tcphdr->ack=0;
tcphdr->psh=0;
tcphdr->rst=1;
tcphdr->syn=0;
tcphdr->fin=0;
tcphdr->ns=1;
tcphdr->checksum = 0;
// Initialize the TCP payload to some rubbish
data = &buf[sizeof(IPV4_HDR) + sizeof(TCP_HDR)];
memset(data, '^', payload);
printf("\nSending packet...\n");
while(!_kbhit())
{
printf(" %d packets send\r",k++);
if((sendto(s ,(char *) buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR) + payload, 0,(SOCKADDR *)&dest, sizeof(dest)))==SOCKET_ERROR)
{
printf("Error sending Packet : %d",WSAGetLastError());
break;
}
}
return 0;
}
You can't send data on a raw tcp socket in windows.
From here:
"Limitations on Raw Sockets
On Windows 7, Windows Vista, Windows XP with Service Pack 2 (SP2), and Windows XP with Service Pack 3 (SP3), the ability to send traffic over raw sockets has been restricted in several ways:
TCP data cannot be sent over raw sockets.
UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address).
A call to the bind function with a raw socket for the IPPROTO_TCP protocol is not allowed.
"
Well, seems you don't have a counterparty to send to.
You have created the socket and set its option, but then you need either listen for incoming connection (bind() + accept()) or connect() to other party.
Error description: Sometimes, it also refers to the current state of the sockets - I guess it's your case. Your socket is not in connected state so sendto() is invalid.
Btw, for reference, there is a discussion regarding 'optval', whether it is bool or int. Apparently 'int' is the better choice, but I've seen lots of examples with bool.
Set IP_HDRINCL to setsockopt function in win32
I had used 'bool' and my program worked fine on Windows XP. Now it doesn't work on Win 7, with the 10022 error code.