UDP Raw Socket set message - c

So, I have the raw sockets set up with some copypasta, it sends data, that part is working fine. But how would I set the data send over the socket? I'm looking to make a DNS request, if that helps. Code below.
int main(int argc, char *argv[])
{
if (!argv[1])
{
printf("Target not specified!\nUsage: ");
printf(argv[0]);
printf(" <target>\n");
exit(1);
}
struct ip ip;
struct udphdr udp;
int sd;
const int on = 1;
struct sockaddr_in sin;
//char msg[] = "\x03\xF0\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01";
u_char *packet;
packet = (u_char *)malloc(120);
ip.ip_hl = 0x5;
ip.ip_v = 0x4;
ip.ip_tos = 0x0;
ip.ip_len = 60;
ip.ip_id = htons(12830);
ip.ip_off = 0x0;
ip.ip_ttl = 64;
ip.ip_p = IPPROTO_UDP;
ip.ip_sum = 0x0;
ip.ip_src.s_addr = inet_addr(argv[1]);
ip.ip_dst.s_addr = inet_addr("67.228.44.4");
ip.ip_sum = in_cksum((unsigned short *)&ip, sizeof(ip));
memcpy(packet, &ip, sizeof(ip));
udp.source = htons(80);
udp.dest = htons(53);
udp.len = htons(22);
udp.check = 0;
udp.check = in_cksum_udp(ip.ip_src.s_addr, ip.ip_dst.s_addr, (unsigned short *)&udp, sizeof(udp));
memcpy(packet + 20, &udp, sizeof(udp));
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("raw socket");
exit(1);
}
if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
perror("setsockopt");
exit(1);
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip.ip_dst.s_addr;
if (sendto(sd, packet, 120, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0)
{
perror("sendto");
exit(1);
}
}

Hmmm...I think you're wondering how to set the payload in your message? Basically, you want to offset from the IP and UDP headers and start writing your payload data at that point.
A hastily thrown together example of this:
int offset = packet + sizeof(struct ip) + sizeof(struct udphdr);
Then you can write your payload as follows:
strcpy(offset, "1234");
Here's some working ICMP code that is effectively writing out the data over a RAW IP socket:
struct icmphdr *icmp_hdr;
char *datapart;
icmp_hdr = (struct icmphdr *) icmp_data;
icmp_hdr->i_type = ICMP_ECHO;
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (unsigned short) getpid();
icmp_hdr->i_cksum = 0;
icmp_hdr->i_seq = 0;
datapart = icmp_data + sizeof(struct icmphdr);
memset(datapart, 'E', datasize - sizeof(struct icmphdr));

Related

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

Did my code cause too many socket didn't get release

I wrote a network ICMP ping code in C, the following is my code, it tried to ping thousands of IP, but after a few days run, the total number of open socket increased to 35K. Where should I release my socket please.
struct packet {
struct icmphdr hdr;
char msg[64 - sizeof(struct icmphdr)];
};
struct protoent *proto = NULL;
void ping(char *bindIp, char **ipArr, size_t ipCount) {
//bindIp is the Ip in my machine for sending ip
//ipArr is the destination Ips need to ping
//ipCount is the total destination ip number
const int val = 255;
int i, sd, cnt = 1;
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_addr.s_addr = inet_addr(bindIp);
r_addr.sin_port = 0;
sd = socket(PF_INET, SOCK_RAW, proto->p_proto);
bind(sd, (struct sockaddr *) &r_addr, sizeof(r_addr));
if (sd < 0) {
perror("socket,you might need root/admin to operate\n");
return;
}
if (setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
perror("Set TTL option");
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
perror("Request nonblocking I/O");
for (i = 0; i < ipCount; i++) {
struct packet pckt;
struct hostent *hname;
hname = gethostbyname(ipArr[i]);
struct sockaddr_in addr;
proto = getprotobyname("ICMP");
bzero(&addr, sizeof(addr));
addr.sin_port = 0;
addr.sin_family = hname->h_addrtype;
addr.sin_addr.s_addr = *(long*) hname->h_addr;
if(i%5==0){
usleep(1001);
if(i%50000==0){
printf("ping oversea--i=%d,ip=%s\n",i,ipArr[i]);
}
}
bzero(&pckt, sizeof(pckt));
pckt.hdr.type = ICMP_ECHO;
long currTs = current_timestamp();
char buffer[20];
sprintf(buffer,"_%lu", currTs);
char *payload=concat(sendIp,buffer);
strcpy(pckt.msg,payload);
pckt.hdr.un.echo.id = 8899;
pckt.hdr.un.echo.sequence = cnt++;
pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
free(payload);
sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*) &addr,
sizeof(addr));
}
}
You should close the socket at the end of the function. After the for loop.

get ECHO REPLY with data from server to client behind nat

I have to write c program that send ICMP ECHO REQUEST from phone(it is connected by Mobile isp and it is behind NAT)to server with IP PUBLIC. i wrote a simple program that sends echo request and receives echo reply but now i want to send ECHO REQUEST from client to server and receive ECHO REPLY with some data(an IP PUBLIC and ICMP ID) from server to client. How can i make that?
Herre's my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
typedef unsigned char u8;
typedef unsigned short int u16;
struct icmp_header{
unsigned char type;
unsigned char code;
unsigned short checksum;
unsigned short id;
unsigned short seq;
};
unsigned short in_cksum(unsigned short *ptr, int nbytes);
int main(int argc, char **argv){
int c=100;
int ls;//lunghezza struct sockaddr_in serveraddr
int rf;//receive from
unsigned long daddr;
unsigned long saddr;
int payload_size = 0, sent = 0, sent_size;
saddr = inet_addr("IP PRIVATE");
daddr = inet_addr("IP PUBLIC");
//Raw socket - if you use IPPROTO_ICMP, then kernel will fill in the correct ICMP header checksum, if IPPROTO_RAW, then it wont
int sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0){
perror("could not create socket");
return (0);
}
int on = 1;
// We shall provide IP headers
if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, (const char*)&on, sizeof (on)) == -1){
perror("setsockopt");
return (0);
}
//allow socket to send datagrams to broadcast addresses
if (setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof (on)) == -1){
perror("setsockopt");
return (0);
}
//Calculate total packet size
int packet_size = sizeof (struct iphdr) + sizeof (struct icmp_header) + payload_size;
char *buffer = (char *) malloc (packet_size);
char *packet = (char *) malloc (packet_size);
if (!packet){
perror("out of memory");
close(sockfd);
return (0);
}
//ip header
struct iphdr *ip = (struct iphdr *) packet;
//struct icmphdr *icmp = (struct icmphdr *) (packet + sizeof (struct iphdr));
struct icmp_header *icmphdr = (struct icmp_header *) (packet + sizeof(struct iphdr));
//zero out the packet buffer
memset (packet, 0, packet_size);
memset (buffer, 0, packet_size);
ip->version = 4;
ip->ihl = 5;
ip->tos = 0;
ip->tot_len = htons (packet_size);
ip->id = rand ();
ip->frag_off = 0;
ip->ttl = 255;
ip->protocol = IPPROTO_ICMP;
ip->saddr = saddr;
ip->daddr = daddr;
//ip->check = in_cksum ((u16 *) ip, sizeof (struct iphdr));
//icmp->type = ICMP_ECHO significa ECHO REQUEST
//icmp->code = 0 è il codice dei ECHO REQUEST
icmphdr->type = ICMP_ECHO;
icmphdr->code = 0;
icmphdr->id = 5;
icmphdr->seq = 66;
//checksum
icmphdr->checksum = 0;
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = daddr;
memset(&servaddr.sin_zero, 0, sizeof (servaddr.sin_zero));
puts("flooding...");
//while (1)
while(c>0){
memset(packet + sizeof(struct iphdr) + sizeof(struct icmp_header), rand() % 255, payload_size);
//memset(buffer + sizeof(struct iphdr) + sizeof(struct icmphdr), rand() % 255, payload_size);
//recalculate the icmp header checksum since we are filling the payload with random characters everytime
icmphdr->checksum = 0;
icmphdr->checksum = in_cksum((unsigned short *)icmphdr, sizeof(struct icmp_header) + payload_size);
if ( (sent_size = sendto(sockfd, packet, packet_size, 0, (struct sockaddr*) &servaddr, sizeof (servaddr))) < 1){
perror("send failed\n");
break;
}
++sent;
printf("%d packets sent\r", sent);
fflush(stdout);
ls = sizeof(servaddr);
//rf = recvfrom(sockfd, buffer, 42, 0, (struct sockaddr *)&servaddr, &ls);
rf = recvfrom(sockfd, buffer, packet_size, 0, (struct sockaddr *)&servaddr, &ls);
if(rf < 0){
perror("Errore recvfrom\n");
break;
}
else{
char *cp;
struct iphdr *ip_reply = (struct iphdr *)buffer;
cp = (char *)&ip_reply->saddr;
printf("Received %d byte reply from %u.%u.%u.%u:\n", ntohs(ip_reply->tot_len), cp[0]&0xff,cp[1]&0xff,cp[2]&0xff,cp[3]&0xff);
printf("ID: %d\n", ntohs(ip_reply->id));
printf("TTL: %d\n", ip_reply->ttl);
}
usleep(10000); //microseconds
c--;
}
free (buffer);
free(packet);
close(sockfd);
return (0);
}
/*
Function calculate checksum
*/
unsigned short in_cksum(unsigned short *ptr, int nbytes){
register long sum;
u_short oddbyte;
register u_short answer;
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((u_char *) & oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
ANSWER.
Ok, i solve problem. I create custom icmp header with unsigned char array as payload (pay in this example). i use this array, in server side, to store data in this way
memcpy(pay, (unsigned char *)&icmp->id, 2); //here i store incoming icmp echo request id.
Then i prepare sending buffer
struct eth_frame *eths = (struct eth_frame *) buffer;
crea_eth(eths,0x0800,mactarget);//create eth frame
struct ip_datagram *ips = (struct ip_datagram*) eths->payload;
struct icmp_packet *icmps = (struct icmp_packet*) ips->payload;
Then i build custom icmp echo reply and custom ip packet that i have to send from server to client
memcpy(icmps->payload, &pay, 10);
icmps->type = 0;
icmps->code = 0;
icmps->checksum = 0;
icmps->id = (icmp->id);//i use same receiving icmp id
icmps->seq = htons(1);
icmps->checksum = //calculate checksum
ips->ver_ihl = 0x45;
ips->tos = 0x00;
ips->totlen = htons(20 + 8 + 8);
ips->id = 0xABCD;
ips->flags_offs = 0;
ips->ttl = 255;
ips->proto = IPPROTO_ICMP;
ips->checksum = 0;
ips->src = *(unsigned int *)serverip;
ips->dst = *(unsigned int *)clientip;//fill with IP PUBLIC ADDRESS OF CLIENT!!
ips->checksum = htons(calcola_checksum((unsigned char*)ips,20));
Then send icmp packet from server to client
unsigned char *p = (unsigned char *)&addr;
for(i = 0;i < sizeof(struct sockaddr_ll);i++)
p[i] = 0;
addr.sll_family = AF_PACKET;
addr.sll_ifindex = 3;
/*send to*/
n=sendto(s, buffer, 14 + 20 + 8 + 8 , 0 , (struct sockaddr*) &addr , sizeof(addr));

Despite RAW socket and HDRINCL, IP source address is still filled by system

I'm writing simple DHCP client so, according to the RFC 951, I need to send packets with IP source address = "0.0.0.0". As I know it is possible using RAW sockets, but apparently something in my code is wrong - source address is always filled by kernel (to the defined address of other interface).
if (sockfd==0)
{
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (sockfd<0)
{
return result.setError(-1, "Can't create socket.");
}
status = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, m_ifName, strlen(m_ifName));
if (status<0)
{
return result.setError(status, "Can't bind socket to the interface.");
}
int optVal = 1;
status = setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optVal, sizeof(optVal));
if (status != 0)
{
return result.setError(status, "Can't set IP_HDRINCL option on a socket");
}
int broadcastVal = 1;
status = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
reinterpret_cast<const void*>(&broadcastVal), sizeof(broadcastVal));
if (status!=0)
{
return result.setError(status, "Can't set a broadcast option on a socket.");
}
int reuseAddrVal = 1;
status = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseAddrVal, sizeof(reuseAddrVal));
if(status != 0)
return result.setError(status, "Can't set a SO_REUSEADDR opt on socket.");
struct sockaddr_in src_addr;
src_addr.sin_family = AF_INET;
src_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
src_addr.sin_port = htons(sourcePort);
status = bind(sockfd, reinterpret_cast<sockaddr *>(&src_addr), sizeof(sockaddr_in));
if (status != 0)
{
return result.setError(status, "Can't bind to the socket.");
}
}
unsigned char buffer[8192];
struct sockaddr_in dest_addr;
char* packetData = (char*)(buffer + sizeof(struct ip) + sizeof(struct udphdr));
struct ip* ip_header = (struct ip*) buffer;
struct udphdr* udp_header = (struct udphdr*) (buffer + sizeof(struct ip));
memset(buffer, 0, sizeof(buffer));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = INADDR_BROADCAST;
dest_addr.sin_port = htons(67);
ip_header->ip_v = 4;
ip_header->ip_hl = 5;
ip_header->ip_tos = 0;
ip_header->ip_id = 0;
ip_header->ip_ttl = 63;
ip_header->ip_p = IPPROTO_UDP;
ip_header->ip_off = 0;
ip_header->ip_sum = 0;
ip_header->ip_src.s_addr = inet_addr("0.0.0.0");
ip_header->ip_dst.s_addr = htonl(INADDR_BROADCAST);
udp_header->source = htons(68);
udp_header->dest = htons(67);
udp_header->check = htons(0);
DhcpData data(sizeof(DhcpHdr), 0);
prepareDhcpPacket(type, data, result);
if (result.errCode != 0)
{
return result;
}
strcpy(packetData, (const char*) data.constData());
ip_header->ip_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + data.size());
udp_header->len = htons(sizeof(struct udphdr) + data.size());
ip_header->ip_sum = ComputeChecksum((unsigned char *)ip_header, ip_header->ip_hl*4);
int segment_len = (sizeof(struct iphdr) + sizeof(struct udphdr) + data.size()) - ip_header->ip_hl*4;
int header_len = sizeof(PseudoHeader) + segment_len;
unsigned char* hdr = (unsigned char *)malloc(header_len);
PseudoHeader* pseudo_header;
pseudo_header = (PseudoHeader *)hdr;
pseudo_header->source_ip = ip_header->ip_src.s_addr;
pseudo_header->dest_ip = ip_header->ip_dst.s_addr;
pseudo_header->reserved = 0;
pseudo_header->protocol = ip_header->ip_p;
pseudo_header->udp_length = htons(segment_len);
memcpy((hdr + sizeof(PseudoHeader)), (void *)udp_header, 8);
memcpy((hdr + sizeof(PseudoHeader) + 8), packetData, data.size());
udp_header->check = ComputeChecksum(hdr, header_len);
free(hdr);
int res = sendto(sockfd, buffer, (sizeof(struct ip) + sizeof(struct udphdr) + data.size()), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if(res < 0)
{
printf("Errno=%s", strerror(errno));
}
/* taken from TCP/IP Illustrated Vol. 2(1995) by Gary R. Wright and W. Richard Stevens. Page 236 */
unsigned short ComputeChecksum(unsigned char *data, int len)
{
long sum = 0; /* assume 32 bit long, 16 bit short */
unsigned short *temp = (unsigned short *)data;
while(len > 1){
sum += *temp++;
if(sum & 0x80000000) /* if high order bit set, fold */
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}
if(len) /* take care of left over byte */
sum += (unsigned short) *((unsigned char *)temp);
while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);
return ~sum;
}
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
Do not allow to change the IP on 0.0.0.0 see man: raw(7)
Source Address │ Filled in when zero
(0.0.0.0) is zerro
You must use:
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
Yes you will have to generate an additional 14 bytes are now Ethernet header
simple example see: simple DHCP client

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