Skip to content

Instantly share code, notes, and snippets.

@tiqwab
Created June 18, 2019 23:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiqwab/e20519e2de549402f8df065595d3ac3a to your computer and use it in GitHub Desktop.
Save tiqwab/e20519e2de549402f8df065595d3ac3a to your computer and use it in GitHub Desktop.
IP_HDRINCL socketopt
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#define SEND_BUF_LEN 64
#define RECV_BUF_LEN 128
#define SRC_IP "192.168.33.1"
#define DST_IP "192.168.33.10"
u_int16_t checksum(u_int16_t *data, int len);
int main(int argc, char *argv[]) {
int s;
char send_buf[SEND_BUF_LEN];
struct sockaddr_in send_sa;
int on = 1;
struct ip *send_ip;
struct icmp *send_icmp;
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket");
exit(1);
}
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof on) < 0) {
perror("setsockopt(IP_HDRINCL)");
exit(1);
}
// create icmp echo request
memset(send_buf, 0, SEND_BUF_LEN);
send_ip = (struct ip *) send_buf;
send_ip->ip_v = IPVERSION;
send_ip->ip_hl = sizeof (struct ip) >> 2;
send_ip->ip_id = 0;
send_ip->ip_len = htons(SEND_BUF_LEN);
send_ip->ip_off = htons(0);
send_ip->ip_ttl = 2;
send_ip->ip_p = IPPROTO_ICMP;
send_ip->ip_src.s_addr = inet_addr(SRC_IP);
send_ip->ip_dst.s_addr = inet_addr(DST_IP);
send_ip->ip_sum = 0;
send_ip->ip_sum = checksum((u_int16_t *) send_ip, sizeof send_ip);
send_icmp = (struct icmp *) (send_buf + (send_ip->ip_hl << 2));
send_icmp->icmp_type = ICMP_ECHO;
send_icmp->icmp_code = 0;
send_icmp->icmp_cksum = 0;
send_icmp->icmp_id = htons(1);
send_icmp->icmp_seq = htons(1);
send_icmp->icmp_cksum = checksum((u_int16_t *) send_icmp, SEND_BUF_LEN - sizeof send_ip);
// set send_sa
memset(&send_sa, 0, sizeof send_sa);
send_sa.sin_family = AF_INET;
send_sa.sin_addr.s_addr = inet_addr(DST_IP);
if (sendto(s, send_buf, SEND_BUF_LEN, 0, (struct sockaddr *) &send_sa, sizeof send_sa) < 0) {
perror("sendto");
exit(1);
}
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 200 * 1000;
char recv_buf[RECV_BUF_LEN];
while (1) {
fd_set readfd;
struct ip *recv_ip;
struct icmp *recv_icmp;
int ihlen;
FD_ZERO(&readfd);
FD_SET(s, &readfd);
if (select(s + 1, &readfd, NULL, NULL, &tv) <= 0) {
break;
}
if (recvfrom(s, recv_buf, RECV_BUF_LEN, 0, NULL, NULL) < 0) {
perror("recvfrom");
exit(1);
}
recv_ip = (struct ip *) recv_buf;
ihlen = recv_ip->ip_hl << 2;
recv_icmp = (struct icmp *) (recv_buf + ihlen);
if (recv_icmp->icmp_code == 0 && recv_icmp->icmp_type == ICMP_ECHOREPLY) {
printf("echo reply from %s\n", inet_ntoa(recv_ip->ip_dst));
} else {
printf("unexpected reply from %s, icmp_code = %d, icmp_type = %d\n",
inet_ntoa(recv_ip->ip_dst), recv_icmp->icmp_code, recv_icmp->icmp_type);
}
}
close(s);
return 0;
}
u_int16_t checksum(u_int16_t *data, int len) {
u_int32_t sum = 0;
for (; len > 1; len -= 2) {
sum += *data++;
if (sum & 0x80000000) {
sum = (sum & 0xffff) + (sum >> 16);
}
}
if (len == 1) {
u_int16_t i = 0;
*((u_int8_t *) &i) = *((u_int8_t *) data);
sum += i;
}
while (sum >> 16) {
sum = (sum & 0xff) + (sum >> 16);
}
return ~sum;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#define SEND_BUF_LEN 64
#define RECV_BUF_LEN 128
#define DST_IP "192.168.33.10"
u_int16_t checksum(u_int16_t *data, int len);
int main(int argc, char *argv[]) {
int s;
char send_buf[SEND_BUF_LEN];
struct sockaddr_in send_sa;
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket");
exit(1);
}
// create icmp echo request
memset(send_buf, 0, SEND_BUF_LEN);
((struct icmp *) send_buf)->icmp_type = ICMP_ECHO;
((struct icmp *) send_buf)->icmp_code = 0;
((struct icmp *) send_buf)->icmp_cksum = 0;
((struct icmp *) send_buf)->icmp_id = htons(1);
((struct icmp *) send_buf)->icmp_seq = htons(1);
((struct icmp *) send_buf)->icmp_cksum = checksum((u_int16_t *) send_buf, SEND_BUF_LEN);
// set send_sa
memset(&send_sa, 0, sizeof send_sa);
send_sa.sin_family = AF_INET;
send_sa.sin_addr.s_addr = inet_addr(DST_IP);
if (sendto(s, send_buf, SEND_BUF_LEN, 0, (struct sockaddr *) &send_sa, sizeof send_sa) < 0) {
perror("sendto");
exit(1);
}
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 200 * 1000;
char recv_buf[RECV_BUF_LEN];
while (1) {
fd_set readfd;
struct ip *ip;
struct icmp *icmp;
int ihlen;
FD_ZERO(&readfd);
FD_SET(s, &readfd);
if (select(s + 1, &readfd, NULL, NULL, &tv) <= 0) {
break;
}
if (recvfrom(s, recv_buf, RECV_BUF_LEN, 0, NULL, NULL) < 0) {
perror("recvfrom");
exit(1);
}
ip = (struct ip *) recv_buf;
ihlen = ip->ip_hl << 2;
icmp = (struct icmp *) (recv_buf + ihlen);
if (icmp->icmp_code == 0 && icmp->icmp_type == ICMP_ECHOREPLY) {
printf("echo reply from %s\n", inet_ntoa(ip->ip_dst));
} else {
printf("unexpected reply from %s, icmp_code = %d, icmp_type = %d\n",
inet_ntoa(ip->ip_dst), icmp->icmp_code, icmp->icmp_type);
}
}
close(s);
return 0;
}
u_int16_t checksum(u_int16_t *data, int len) {
u_int32_t sum = 0;
for (; len > 1; len -= 2) {
sum += *data++;
if (sum & 0x80000000) {
sum = (sum & 0xffff) + (sum >> 16);
}
}
if (len == 1) {
u_int16_t i = 0;
*((u_int8_t *) &i) = *((u_int8_t *) data);
sum += i;
}
while (sum >> 16) {
sum = (sum & 0xff) + (sum >> 16);
}
return ~sum;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment