Here is a small demo of raw sockets under Linux.
This will send an ICMP ping over network and wait for response.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>

#include <sys/socket.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <arpa/inet.h>

#define PROTOCOL (IPPROTO_ICMP)
#define ADDRESS "172.17.57.112"


uint16_t chksum16(void* addr, int len) {
register int sum = 0;
uint16_t answer = 0;
register uint16_t* w = (uint16_t*)addr;
register int nleft = len;

while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

if (nleft == 1) {
*(uint8_t *) (&answer) = *(uint8_t *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}

struct Packet {
iphdr ip;
icmphdr icmp;
};

int main() {
Packet outBuff;
memset(&outBuff, 0, sizeof(Packet));

outBuff.ip.ihl = 5;
outBuff.ip.version = 4;
outBuff.ip.tot_len = sizeof(Packet);
outBuff.ip.id = htons(getuid());
outBuff.ip.ttl = 255;
outBuff.ip.protocol = PROTOCOL;
outBuff.ip.saddr = inet_addr("172.17.57.112");
outBuff.ip.daddr = inet_addr(ADDRESS);
outBuff.ip.check = chksum16(&outBuff.ip, sizeof(iphdr));

outBuff.icmp.type = ICMP_ECHO;
outBuff.icmp.checksum = chksum16(&outBuff.icmp, sizeof(icmphdr));

struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_addr.s_addr = inet_addr(ADDRESS);

int sock = socket(AF_INET, SOCK_RAW, PROTOCOL);
int optval;
if (sock != -1 && setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int)) != -1) {
if (sendto(sock, &outBuff, sizeof(Packet), 0, (sockaddr *)&peer, sizeof(sockaddr)) != -1) {
printf("Echo sent\n");

Packet inBuff;
memset(&inBuff, 0, sizeof(Packet));
while (recv(sock, &inBuff, sizeof(Packet), 0) != -1) {
if (chksum16((unsigned short *)&inBuff.ip, sizeof(iphdr)) == 0) {
} else {
printf("IP CRC error\n");
}

if (chksum16((unsigned short *)&inBuff.icmp, sizeof(icmphdr)) == 0) {
switch (inBuff.icmp.type) {
case ICMP_ECHO: {
printf("Echo received\n");
continue;
} break;
case ICMP_ECHOREPLY: {
printf("Got reply\n");
} break;
case ICMP_DEST_UNREACH: {
printf("Destination unreachable\n");
} break;
case ICMP_HOST_UNKNOWN: {
printf("Host unknown\n");
} break;
default: {
printf("Type: %d\n", inBuff.icmp.type);
} break;
}
} else {
printf("ICMP CRC error\n");
}

break;
}
}

close(sock);
} else {
printf("Cannot open socket\n");
}

return 0;
}

Advertisements