Packet router for C Linux. Setting up sendto() - c

I am trying to make a packet router that receives a packet, reads its destination, and sends it on its way. It receives packets just fine, the problem is that when I attempt to do a sendto() I always get the error
sendto() failed: No such device or address
I am grabbing the destination MAC address from the ethernet header of the received packet, loading it into a struct sockaddr_ll and passing that to sendto() but it isn't working.
Also when I ping one host to another the output of my print statements has the source ip as 40.41.42.43 and the destination ip as 44.45.46.47, and neither of those devices exist. Am I reading the ethernet and IP headers correctly? Or maybe the socket is getting messed up somehow?
Anyway here is the code.
int main(int argc, char *argv[])
{
int sock1, sock2, sock3;
int status = 0;
fd_set readfds;
int buffer[256];
int socknum = 0;
// Create 3 sockets
if ((sock1 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){
perror("socket() failed");
exit(1);
}
if ((sock2 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){
perror("socket() failed");
exit(1);
}
if ((sock3 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){
perror("socket() failed");
exit(1);
}
// Bind sockets to interfaces
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth1");
if (setsockopt(sock1, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt() inf config failed");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth2");
if (setsockopt(sock2, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt() inf config failed");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth3");
if (setsockopt(sock3, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt() inf config failed");
exit(1);
}
printf("All sockets bound to interfaces.\n");
while(1)
{
//Setup select
FD_ZERO(&readfds);
FD_SET(sock1, &readfds);
FD_SET(sock2, &readfds);
FD_SET(sock3, &readfds);
printf("Sockets set to read.\n");
struct timeval tv = {2, 0};
printf("Starting select.\n");
status = select( sock3 + 1, &readfds , NULL , NULL , &tv );
printf("status = %d\n", status);
struct sockaddr_in sockAddr;
socklen_t sockLen = sizeof(sockAddr);
memset(&sockAddr, 0, sockLen);
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int bufLen = 0;
// Check select
if (status > 0) {
printf("status = %d, preparing to read.\n", status);
// Read IP datagram (d)
if (FD_ISSET(sock1, &readfds)) {
printf("Socket 1 ready to receive.\n");
printf("Attempting to receive packet.\n");
bufLen = recvfrom(sock1, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen);
printf("Received packet.\n");
socknum = 1;
}
else if (FD_ISSET(sock2, &readfds)) {
printf("Socket 2 ready to receive.\n");
printf("Attempting to receive packet.\n");
bufLen = recvfrom(sock2, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen);
printf("Received packet.\n");
socknum = 2;
}
else if (FD_ISSET(sock3, &readfds)) {
printf("Socket 3 ready to receive.\n");
printf("Attempting to receive packet.\n");
bufLen = recvfrom(sock3, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen);
printf("Received packet.\n");
socknum = 3;
}
printf("Testing Packet.\n");
struct ethhdr *eth = (struct ethhdr *)(buffer);
printf("\nEthernet Header\n");
printf("\t|-Source Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
printf("\t|-Destination Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
printf("\t|-Protocol : %d\n",eth->h_proto);
// Inspect IP (e)
unsigned short iphdrlen;
struct sockaddr_in source;
struct sockaddr_in dest;
struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr));
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = ip->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = ip->daddr;
printf("\t|-Version : %d\n",(unsigned int)ip->version);
printf("\t|-Internet Header Length : %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4);
printf("\t|-Type Of Service : %d\n",(unsigned int)ip->tos);
printf("\t|-Total Length : %d Bytes\n",ntohs(ip->tot_len));
printf("\t|-Identification : %d\n",ntohs(ip->id));
printf("\t|-Time To Live : %d\n",(unsigned int)ip->ttl);
printf("\t|-Protocol : %d\n",(unsigned int)ip->protocol);
printf("\t|-Header Checksum : %d\n",ntohs(ip->check));
printf("\t|-Source IP : %s\n", inet_ntoa(source.sin_addr));
printf("\t|-Destination IP : %s\n",inet_ntoa(dest.sin_addr));
printf("index=%d\n",ifreq_i.ifr_ifindex);
// Pull the address from the ethernet header.
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
addr.sll_family = AF_PACKET;
addr.sll_ifindex = ifr.ifr_ifindex;
addr.sll_halen = ETHER_ADDR_LEN;
addr.sll_protocol = htons(0x0800);
addr.sll_addr[0] = eth->h_dest[0];
addr.sll_addr[1] = eth->h_dest[1];
addr.sll_addr[2] = eth->h_dest[2];
addr.sll_addr[3] = eth->h_dest[3];
addr.sll_addr[4] = eth->h_dest[4];
addr.sll_addr[5] = eth->h_dest[5];
if(sendto(sock1, buffer, bufLen, 0, (struct sockaddr *) &addr, sizeof(addr)) < bufLen){
perror("sendto() failed");
exit(1);
}
}
Any help is appreciated.

I immediately found the answer, but I'm gonna leave this up just in case somebody else has a similar problem. At the bottom part when I am setting up the struct sockaddr_ll addr;. This line:
addr.sll_ifindex = ifr.ifr_ifindex;
should be this instead:
addr.sll_ifindex = ifreq_i.ifr_ifindex;
The socket and the index of the socket were different so sendto() couldn't find a device that fit those parameters.

Related

Sending a broadcast message, then receiving responses from any client

I'm trying to send a multicast message via a socket, then receive responses from devices on the network that respond.
The message sends successfully, and I can see the responses targeting the source IP address on wireshark, but attempting to call recvfrom just results in timeouts.
I have tried many combinations of socket options, bindings, but I've been unable to get past a timeout on recvfrom.
My current code (sending and receiving):
// Ethernet/IP Encapsulation Header
struct __attribute__((__packed__)) EnipEncapHeader
{
uint16_t command;
uint16_t length;
uint32_t session_handle;
uint32_t status;
uint64_t ctx_64;
uint32_t options;
};
int main() {
// initialize winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
// create a udp socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
printf("ERROR opening socket");
return 1;
}
// set the broadcast flag
int broadcastEnable = 1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcastEnable, sizeof(broadcastEnable));
// Construct the message
struct EnipEncapHeader header;
header.command = 0x63;
header.length = 0x0000;
header.session_handle = 0x00000000;
header.status = 0x0000;
header.ctx_64 = (uint64_t)0;
header.options = 0x0000;
// send to 255.255.255.255 on port 44818
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("255.255.255.255");
servaddr.sin_port = htons(44818);
// send the packet
int rc = sendto(sockfd, (const char*)&header, sizeof(header), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (rc < 0) {
printf("ERROR sending packet, %d, %d", rc, WSAGetLastError());
return 1;
}
// clear the broadcast flag
broadcastEnable = 0;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcastEnable, sizeof(broadcastEnable));
// set the timeout to 5 seconds
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
// bind the socket to any address
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));
// recieve from any address on the socket
struct sockaddr_in from;
int fromlen = sizeof(from);
char buf[1024];
rc = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
if (rc < 0) {
printf("ERROR recieving packet, %d, %d", rc, WSAGetLastError());
return 1;
}
else {
printf("Received %d bytes from %s:%d", rc, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
}
return 0;
}
This code results in the following:
ERROR recieving packet, -1, 10060
Winsock Error 10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

Sendto fails with an error "no such device or address" after sometime

int main(int argc, char *argv[]) {
struct sockaddr_in src_socket_address, dest_socket_address;
struct ifreq ifreq_i;
struct ifreq if_mac;
struct ifreq ifreq_ip;
int packet_size;
char ifName[IFNAMSIZ];
char sendbuf[BUF_SIZE];
int tx_len = 0;
unsigned char *buffer = (unsigned char*)malloc(65536);
int sock = socket (AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
int send_soc = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
struct ethhdr *eth = (struct ethhdr*)sendbuf;
struct sockaddr saddr;
struct sockaddr_ll sadr_ll;
int saddr_len = sizeof(saddr);
/*Get interface name*/
if(argc < 1) {
strcpy(ifName, argv[1]);
} else {
strcpy(ifName, DEFAULT_IF);
}
if(sock < 0) {
printf("Failed to create socket");
exit(1);
}
if(send_soc < -1) {
printf("Failed to create socket send");
exit(1);
}
/* Get the index of the interface to send on */
memset(&ifreq_i, 0, sizeof(struct ifreq));
strncpy(ifreq_i.ifr_name, ifName, IFNAMSIZ-1);
if((ioctl(send_soc, SIOCGIFINDEX, (void*)&ifreq_i)) < 0){
printf("Error in index ioctl reading %s\n", strerror(errno));
close(send_soc);
exit(EXIT_FAILURE);
}
/*Get the mac address of the interface*/
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1);
if((ioctl(send_soc, SIOCGIFHWADDR, &if_mac)) <0){
printf("Error in SIOCGIFHWADDR ioctl reading %s\n", strerror(errno));
close(send_soc);
exit(EXIT_FAILURE);
}
/*Get the ip address of the interface"
memset(&ifreq_ip, 0, sizeof(struct ifreq));
strncpy(ifreq_ip.ifr_name, ifName, IFNAMSIZ-1);
if((ioctl(send_soc, SIOCGIFADDR, &ifreq_ip)) <0)
printf("error in SIOCGIFADDR ip address reading\n");*/
while (1) {
packet_size = recvfrom(sock, buffer, 65536, 0, &saddr, (socklen_t*)&saddr_len);
if(packet_size == -1) {
printf("Failed to get packets\n");
return 1;
} else {
printf("Received packets");
}
// struct iphdr *ip_packet = (struct iphdr*)buffer;
// memset(&src_socket_address, 0, sizeof(src_socket_address));
// src_socket_address.sin_addr.s_addr = ip_packet->saddr;
// memset(&dest_socket_address, 0, sizeof(dest_socket_address));
// dest_socket_address.sin_addr.s_addr = ip_packet->daddr;
memset(sendbuf, 0, BUF_SIZE);
/*Construct ethernet header*/
eth->h_source[0] = (unsigned char)(if_mac.ifr_hwaddr.sa_data[0]);
eth->h_source[1] = (unsigned char)(if_mac.ifr_hwaddr.sa_data[1]);
eth->h_source[2] = (unsigned char)(if_mac.ifr_hwaddr.sa_data[2]);
eth->h_source[3] = (unsigned char)(if_mac.ifr_hwaddr.sa_data[3]);
eth->h_source[4] = (unsigned char)(if_mac.ifr_hwaddr.sa_data[4]);
eth->h_source[5] = (unsigned char)(if_mac.ifr_hwaddr.sa_data[5]);
/*filling destination mac address*/
eth->h_dest[0] = DESTMAC0;
eth->h_dest[1] = DESTMAC1;
eth->h_dest[2] = DESTMAC2;
eth->h_dest[3] = DESTMAC3;
eth->h_dest[4] = DESTMAC4;
eth->h_dest[5] = DESTMAC5;
eth->h_proto = htons(ETH_P_IP);
/* end of ethernet header*/
tx_len += sizeof(struct ethhdr);
/*Packet data for dummy data*/
sendbuf[tx_len++] = 0xAA;
sendbuf[tx_len++] = 0xBB;
sendbuf[tx_len++] = 0xCC;
sendbuf[tx_len++] = 0xDD;
sendbuf[tx_len++] = 0xEE;
sadr_ll.sll_ifindex = ifreq_i.ifr_ifindex;
sadr_ll.sll_halen = ETH_ALEN;
sadr_ll.sll_addr[0] = DESTMAC0;
sadr_ll.sll_addr[1] = DESTMAC1;
sadr_ll.sll_addr[2] = DESTMAC2;
sadr_ll.sll_addr[3] = DESTMAC3;
sadr_ll.sll_addr[4] = DESTMAC4;
sadr_ll.sll_addr[5] = DESTMAC5;
/* Send Packet */
if (sendto(send_soc, buffer, packet_size, 0, (const struct sockaddr*)&sadr_ll, sizeof(struct sockaddr_ll)) < 0) {
printf("Sending packet failed\n");
close(send_soc);
} else {
printf("Sending packet successful");
}
printf("================================================\n");
}
close(send_soc);
return 0;
}
I want to receive ethernet packets using raw sockets and duplicate the packets to send to another port in the same machine to analyse the traffic. I can receive the packets however after a while I get an error while sending the packets as "No such device or address".
Can you please explain whats the problem here?
Thanks!
Nivetha

Error: Bad address when using sendto() in raw sockets

I'm writing a simple network application and I need to craft a UDP packet and send it to a specific host.
int main(void){
// Message to be sent.
char message[] = "This is something";
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if(sockfd < 0){
perror("Error creating socket");
exit(1);
}
struct sockaddr_in this, other;
this.sin_family = AF_INET;
other.sin_family = AF_INET;
this.sin_port = htons(8080);
other.sin_port = htons(8000);
this.sin_addr.s_addr = INADDR_ANY;
other.sin_addr.s_addr = inet_addr("10.11.4.99");
if(bind(sockfd, (struct sockaddr *)&this, sizeof(this)) < 0){
printf("Bind failed\n");
exit(1);
}
char packet[64] = {0};
struct udphdr *udph = (struct udphdr *) packet;
strcpy(packet + sizeof(struct udphdr), message);
udph->uh_sport = htons(8080);
udph->uh_dport = htons(8000);
udph->uh_ulen = htons(sizeof(struct udphdr) + sizeof(message));
udph->uh_sum = 0;
if(sendto(sockfd, packet, udph->uh_ulen, 0, (struct sockaddr *) &other, sizeof(other)) < 0)
perror("Error");
else
printf("Packet sent successfully\n");
close(sockfd);
return 0;
}
Everything is working fine till the call to sendto(). The sendto() is giving "Bad address". can anyone point me where I'm going wrong? Is there any problem with binding a port to a raw socket?
The code transform the length of the messag (udph->uh_len) to network byte order (htons). This is not needed, as the parameter type of size_t. Only port number (in sockaddr structures) need the htons conversion.
udph->uh_ulen = sizeof(struct udphdr) + sizeof(message);
Current code produce large number (>8000) in uh_ulen, causing the send to fail.

Trying to make a simple packet router in C on Linux. select() idles indefinitely and I don't know why

Like the title says I'm trying to make a packet router, but it gets stuck on select(). I am using a Mininet environment with 4 hosts (h1, h2, h3, r0), 3 switches (s1, s2, s3) and 3 interfaces (r0-eth1, r0-eth2, r0-eth3). I am compiling the c code and running the executable on r0. Here is the code:
int main(int argc, char *argv[])
{
int sock1, sock2, sock3;
int status = 0;
fd_set readfds;
int buffer[256];
// Create 3 sockets
if ((sock1 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){
perror("socket() failed");
exit(1);
}
if ((sock2 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){
perror("socket() failed");
exit(1);
}
if ((sock3 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){
perror("socket() failed");
exit(1);
}
// Bind sockets to interfaces
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth1");
if (setsockopt(sock1, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt() inf config failed");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth2");
if (setsockopt(sock2, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt() inf config failed");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth3");
if (setsockopt(sock3, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt() inf config failed");
exit(1);
}
//Setup select
FD_ZERO(&readfds);
FD_SET(sock1, &readfds);
FD_SET(sock2, &readfds);
FD_SET(sock3, &readfds);
status = select( sock3 + 1 , &readfds , NULL , NULL , NULL);
while(1)
{
// Check select
if (status > 0) {
// Read IP datagram
if (FD_ISSET(sock1, &readfds)) {
struct sockaddr_in sockAddr;
socklen_t sockLen = sizeof(sockAddr);
memset(&sockAddr, 0, sockLen);
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int bufLen = recvfrom(sock1, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen);
}
}
}
I run it with this command:
r0 ./router &
Then I do a
pingall
To see if the hosts can reach each other. My executable gets stuck on select() and never moves on. During the pingall h1, h2, and h3 can all reach r0, but all other packets are dropped. I know I haven't completed the routing part yet, but I can't really move on to it until this gets solved.
Appreciate the help.
It seems to me that your problem is pretty simple. Note this code segment:
status = select( sock3 + 1 , &readfds , NULL , NULL , NULL);
while(1)
{
// Check select
if (status > 0) {
// Read IP datagram
if (FD_ISSET(sock1, &readfds)) {
struct sockaddr_in sockAddr;
socklen_t sockLen = sizeof(sockAddr);
memset(&sockAddr, 0, sockLen);
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int bufLen = recvfrom(sock1, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen);
}
}
}
You set up to use select(). You then enter a while(1) loop and check to see what's going on with status... but you never call select again, never update the value of status, and never allow the while loop to end.
Additionally, when using select() and FD_SET, you will need to reset FD_SET after each signal.
I guess you need to check if the packets are being sent to the hosts or not.

Why raw socket sends all packets to loopback?

I have a very simple code below. When i run it on Debian 7, this code always sends all packets via 127.0.0.1 interface. But i want it sends it via 192.168.0.103. Where am i wrong?
I searched the solution in Google until past 16 hours but didn't find the answer :(.
Sure, i can fix it via routing table. But ping and traceroute works perfect. Why my code doesn't work?
int rawSocket;
char buffer[PACKET_LENGTH];
struct IPHeader *ipHeader = (struct IPHeader *) buffer;
struct UDPHeader *udpHeader = (struct UDPHeader *) (buffer + sizeof(struct IPHeader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PACKET_LENGTH);
rawSocket = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if (rawSocket < 0) {
printf("socket() error");
exit(-1);
}
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
sin.sin_port = htons(atoi(srcPort));
din.sin_port = htons(atoi(dstPort));
sin.sin_addr.s_addr = inet_addr(realSrcIP);
din.sin_addr.s_addr = inet_addr(dstIP);
ipHeader->iph_ihl = 5;
ipHeader->iph_ver = 4;
ipHeader->iph_tos = 16; // Low delay
ipHeader->iph_len = sizeof(struct IPHeader) + sizeof(struct UDPHeader);
ipHeader->iph_ident = htons(54321);
ipHeader->iph_ttl = 64; // hops
ipHeader->iph_protocol = 17; // UDP
// spoof please lol =P
ipHeader->iph_sourceip = inet_addr(srcIP);
ipHeader->iph_destip = inet_addr(dstIP);
udpHeader->udph_srcport = htons(atoi(srcPort));
udpHeader->udph_destport = htons(atoi(dstPort));
udpHeader->udph_len = htons(sizeof(struct UDPHeader));
ipHeader->iph_chksum = csum((unsigned short *)buffer, sizeof(struct IPHeader) + sizeof(struct UDPHeader));
if(setsockopt(rawSocket, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth0");
if (setsockopt(rawSocket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
printf("HUJ\n");
}
int errorCode = sendto(rawSocket, buffer, ipHeader->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin));
if(errorCode < 0)
{
perror("sendto() error");
exit(-1);
}
close(rawSocket);
I don't think you're setting ifr correctly.
You need to call ioctl(rawsocket, SIOCGIFINDEX, &ifr) to set the index of the device. The name is not enough.
Your index is left as zero which is the first device which happens to be loopback.
Here's a snippet of code from C Language Examples of IPv4 and IPv6 Raw Sockets for Linux:
// Use ioctl() to look up interface index which we will use to
// bind socket descriptor sd to specified interface with setsockopt() since
// none of the other arguments of sendto() specify which interface to use.
memset (&ifr, 0, sizeof (ifr));
snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) {
perror ("ioctl() failed to find interface ");
return (EXIT_FAILURE);
}
There may be other problems (your code is too big) try running/modifying the examples in the link above. Hopefully they are not outdated.

Resources