1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#define HEX_PER_COLUMN 16
#define MAX_PACKET_SIZE 100
#define IPHDR_ID 0x1234
#define IPHDR_TTL 100
#define IPHDR_SOURCE "192.168.1.2"
#define IPHDR_DESTINATION "192.168.1.254"
#define ICMPHDR_ID 0x5678
#define ICMPHDR_SEQUENCE 1
#define MAX_BUFFER 1000
char * createPing(int * length);
void computeICMPChecksum(char * packet, int length);
void computeIPChecksum(char * packet, int length);
void computeChecksums(char * packet, int length);
void displayPacket(char *, int length);
short checksum(char * buffer, short length);
int main(void) {
char * packet;
int length;
int s;
int s2;
char buffer[MAX_BUFFER];
int i;
struct sockaddr_in from;
// creates packet
packet = createPing(&length);
displayPacket(packet, length);
computeChecksums(packet, length);
displayPacket(packet, length);
// creates socket
s = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (s<0) {
perror("socket");
}
s2 = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
if (s2<0) {
perror("socket (s2)");
}
// sends packet
struct sockaddr_in destination;
destination.sin_family = AF_INET;
destination.sin_port = htons(0);
destination.sin_addr.s_addr = inet_addr(IPHDR_DESTINATION);
for (i=0; i<8; i++) {
destination.sin_zero[i] = 0;
}
int hincl = 1;
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)) < 0)
{
perror("Setsockopt error");
printf("Errno = %d",errno);
}
if (sendto(s, packet, length, 0, (struct sockaddr *)&destination, sizeof(struct sockaddr_in))<0) {
perror("send");
}
// wait for packet
while (1) {
length = recvfrom(s2, buffer, MAX_BUFFER, 0, (struct sockaddr *)&from, &i);
packet = inet_ntoa(from.sin_addr);
printf("recv from %s, length=%d\n", packet, length);
if (length<0) {
perror("recvfrom");
exit(EXIT_FAILURE);
}
displayPacket(buffer, length);
}
close(s);
close(s2);
free(packet);
}
char * createPing(int * length) {
char * packet;
struct ip * ipHeader;
struct icmp * icmpHeader;
packet = (char *)malloc(MAX_PACKET_SIZE*sizeof(char));
*length = sizeof(struct ip)+sizeof(struct icmp);
// IP header
ipHeader = (struct ip *)packet;
ipHeader->ip_hl = sizeof(struct ip)/4;
ipHeader->ip_v = 4;
ipHeader->ip_tos = 0;
ipHeader->ip_len = htons(sizeof(struct ip)+sizeof(struct icmp));
ipHeader->ip_id = htons(IPHDR_ID);
ipHeader->ip_off = htons(0);
ipHeader->ip_ttl = IPHDR_TTL;
ipHeader->ip_p = IPPROTO_ICMP;
ipHeader->ip_sum = htons(0);
inet_aton(IPHDR_SOURCE,&ipHeader->ip_src);
inet_aton(IPHDR_DESTINATION,&ipHeader->ip_dst);
// ICMP header
icmpHeader = (struct icmp *)(packet+sizeof(struct ip));
icmpHeader->icmp_type = ICMP_ECHO;
icmpHeader->icmp_code = 0;
icmpHeader->icmp_cksum = htons(0);
icmpHeader->icmp_hun.ih_idseq.icd_id = htons(ICMPHDR_ID);
icmpHeader->icmp_hun.ih_idseq.icd_seq = htons(ICMPHDR_SEQUENCE);
return packet;
}
void displayPacket(char * packet, int length) {
int i, j;
for (i=0; i<(length+HEX_PER_COLUMN-1)/HEX_PER_COLUMN; i++) {
j = 0;
while ((j<HEX_PER_COLUMN) && (HEX_PER_COLUMN*i+j<length)) {
printf("%02x ", (unsigned char)packet[HEX_PER_COLUMN*i+j]);
j = j+1;
}
printf("\n");
}
}
void computeChecksums(char * packet, int length) {
computeICMPChecksum(packet, length);
computeIPChecksum(packet, length);
}
void computeIPChecksum(char * packet, int length) {
struct ip * ipHeader;
ipHeader = (struct ip *)packet;
ipHeader->ip_sum = htons(checksum((char *)ipHeader, length));
}
void computeICMPChecksum(char * packet, int length) {
struct icmp * icmpHeader;
icmpHeader = (struct icmp *)(packet+sizeof(struct ip));
icmpHeader->icmp_cksum = htons(checksum((char *)icmpHeader, length-sizeof(struct ip)));
}
short checksum(char * buffer, short length) {
short word;
int sum = 0;
int i = 0;
while (i<length) {
if (i+1<length) {
word = 256*buffer[i]+buffer[i+1];
}
else {
word = 256*buffer[i];
}
sum = sum+word;
i = i+2;
}
while ((sum>>16)!=0) {
sum = (sum&0xFFFF)+(sum>>16);
}
sum = ~sum;
word = (short)sum;
return word;
} |
Partager