I know there are many similar questions. But none of the solutions seemed to work for me.
So basically, I just want to create a raw socket and write the IP header of the IP packet. Then I want to read it on the receiving end and print it.
But, I don't want to give the third parameter(protocol
) in socket
system call as IPPROTO_UDP
or IPPROTO_TCP
as many examples on the internet seem to suggest. I am giving it as IPPROTO_RAW
.
Then I am using setsockopt
to set the IP_HDRINCL
option and am passing the IP header as the buffer in the sendto()
system call.
While everything seems to work fine, the recv()
system call is blocking and is not continuing even after the sender is run and terminated. This indicates, I think, that the Network layer is not giving my packet to the receiver process.
Then I ran another sender code which has protocol
= 200, directly in socket()
system call and no IP_HDRINCL
. It is receiving packets sent by that socket.
The following are the c++ codes of sender and receiver respectively.
sender.cpp
//SENDER
#include <bits/stdc++.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <fcntl.h>
using namespace std;
struct ip_header
{
unsigned int version, header_len, TOS, packk_len;
unsigned int ID, FRAG;
unsigned int TTL, HLP, CheckBit;
unsigned int sender;
unsigned int reciever;
void *opt;
};
ip_header resolveHeader(void *buffer)
{
unsigned char *pc = (unsigned char *)buffer;
unsigned int *pi = (unsigned int *)buffer;
ip_header head;
head.version = (pc[0] & 0xF0) >> 4;
head.header_len = pc[0] & 0x0F;
head.TOS = pc[1];
head.packk_len = pi[0] & 0x0000FFFF;
head.ID = (pi[1] & 0xFFFF0000) >> 16;
head.FRAG = pi[1] & 0x0000FFFF;
head.TTL = pc[8];
head.HLP = pc[9];
head.CheckBit = pi[2] & 0x0000FFFF;
head.sender = pi[3];
head.reciever = pi[4];
head.opt = pi + 5;
return head;
}
string getIP(unsigned int IP)
{
unsigned char *p = (unsigned char *)&IP;
return to_string(p[0]) + "." + to_string(p[1]) + "." + to_string(p[2]) + "." + to_string(p[3]);
}
void print(ip_header head)
{
cout << "Version: " << head.version << endl;
cout << "Header Length: " << head.header_len << endl;
cout << "Type of Service: " << head.TOS << endl;
cout << "Packet Length: " << head.packk_len << endl;
cout << "ID: " << head.ID << endl;
cout << "Fragment: " << head.FRAG << endl;
cout << "Time to Live: " << head.TTL << endl;
cout << "Higher Level Protocol: " << head.HLP << endl;
cout << "CheckBits: " << head.CheckBit << endl;
cout << "Sender: " << getIP(head.sender) << endl;
cout << "Reciever: " << getIP(head.reciever) << endl;
}
int main()
{
int rsfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
cout << "Higher level Protocol Used:" << 200 << endl;
int res = 1;
res = setsockopt(rsfd, IPPROTO_IP, IP_HDRINCL, &res, sizeof(res));
cout << res << endl;
if (res == -1)
perror("setsockopt");
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
int len = sizeof(sockaddr_in);
char buffer[1024] = "";
ip *I = (ip *)buffer;
I->ip_hl = 6;
I->ip_v = 4;
I->ip_tos = 0;
I->ip_len = 69;
I->ip_id = 65;
I->ip_off = 47877;
I->ip_ttl = 64;
I->ip_p = 200;
I->ip_sum = 51264;
I->ip_src.s_addr = inet_addr("127.0.0.1");
I->ip_dst.s_addr = inet_addr("127.0.0.1");
// Send packet.
if (sendto(rsfd, buffer, 1024, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("sendto() failed ");
exit(EXIT_FAILURE);
}
ip_header head = resolveHeader(buffer);
print(head);
}
receiver.cpp
//RECEIVER
#include <bits/stdc++.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <fcntl.h>
using namespace std;
struct ip_header
{
unsigned int version, header_len, TOS, packk_len;
unsigned int ID, FRAG;
unsigned int TTL, HLP, CheckBit;
unsigned int sender;
unsigned int reciever;
void *opt;
};
ip_header resolveHeader(void *buffer)
{
unsigned char *pc = (unsigned char *)buffer;
unsigned int *pi = (unsigned int *)buffer;
ip_header head;
head.version = (pc[0] & 0xF0) >> 4;
head.header_len = pc[0] & 0x0F;
head.TOS = pc[1];
head.packk_len = pi[0] & 0x0000FFFF;
head.ID = (pi[1] & 0xFFFF0000) >> 16;
head.FRAG = pi[1] & 0x0000FFFF;
head.TTL = pc[8];
head.HLP = pc[9];
head.CheckBit = pi[2] & 0x0000FFFF;
head.sender = pi[3];
head.reciever = pi[4];
head.opt = pi + 5;
return head;
}
string getIP(unsigned int IP)
{
unsigned char *p = (unsigned char *)&IP;
return to_string(p[0]) + "." + to_string(p[1]) + "." + to_string(p[2]) + "." + to_string(p[3]);
}
void print(ip_header head)
{
cout << "Version: " << head.version << endl;
cout << "Header Length: " << head.header_len << endl;
cout << "Type of Service: " << head.TOS << endl;
cout << "Packet Length: " << head.packk_len << endl;
cout << "ID: " << head.ID << endl;
cout << "Fragment: " << head.FRAG << endl;
cout << "Time to Live: " << head.TTL << endl;
cout << "Higher Level Protocol: " << head.HLP << endl;
cout << "CheckBits: " << head.CheckBit << endl;
cout << "Sender: " << getIP(head.sender) << endl;
cout << "Reciever: " << getIP(head.reciever) << endl;
}
int main()
{
int rsfd = socket(AF_INET, SOCK_RAW, 200);
if (rsfd == -1)
perror("socket");
int res = 1;
res = setsockopt(rsfd, IPPROTO_IP, SO_BROADCAST, &res, sizeof(res));
cout << res << endl;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
bind(rsfd, (sockaddr *)&addr, sizeof(addr));
int len = sizeof(sockaddr_in);
char buffer[1024];
memset(buffer, 0, 1024);
int bytes = recv(rsfd, buffer, 1024, 0);
buffer[bytes] = 0;
cout << bytes << " bytes received\n";
ip_header head = resolveHeader(buffer);
print(head);
}
Any idea why it's not working? Please ask for any more details in the comments, if required.
User contributions licensed under CC BY-SA 3.0