diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | libping.c | 311 | ||||
-rw-r--r-- | libping.h | 76 |
3 files changed, 390 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2fbe6f8 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +make: + gcc -c libping.c + gcc libping.o ping.c -o ping
\ No newline at end of file diff --git a/libping.c b/libping.c new file mode 100644 index 0000000..b65b802 --- /dev/null +++ b/libping.c @@ -0,0 +1,311 @@ +#include "libping.h" + +/* From Stevens, UNP2ev1 */ +unsigned short +in_cksum(unsigned short *addr, int len) +{ + int nleft = len; + int sum = 0; + unsigned short *w = addr; + unsigned short answer = 0; + + while (nleft > 1) + { + sum += *w++; + nleft -= 2; + } + + if (nleft == 1) + { + *(unsigned char *)(&answer) = *(unsigned char *)w; + sum += answer; + } + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + answer = ~sum; + return (answer); +} + +// Computing the internet checksum (RFC 1071). +// Note that the internet checksum does not preclude collisions. +uint16_t +ip_checksum (uint16_t *addr, int len) +{ + int count = len; + register uint32_t sum = 0; + uint16_t answer = 0; + + // Sum up 2-byte values until none or only one byte left. + while (count > 1) { + sum += *(addr++); + count -= 2; + } + + // Add left-over byte, if any. + if (count > 0) { + sum += *(uint8_t *) addr; + } + + // Fold 32-bit sum into 16 bits; we lose information by doing this, + // increasing the chances of a collision. + // sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits) + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); + } + + // Checksum is one's compliment of sum. + answer = ~sum; + + return (answer); +} + + +int icmp_eth_init( icmp_pckt_t *icmp ) +{ + uint8_t dest[] = {0x00,0x22,0x43,0x68,0xe5,0xab}; + uint8_t src[] = {0x6c,0x88,0x14,0x0a,0x89,0x58}; + + memcpy( icmp->eth_dest, dest, 6 ); + memcpy( icmp->eth_src, src, 6 ); + icmp->eth_type = 0x0008; + return 0; +} + + +int icmp_eth_dest( icmp_pckt_t *icmp, uint8_t *mac ) +{ + memcpy( icmp->eth_dest, mac, 6 ); + return 0; +} + + +int icmp_eth_src( icmp_pckt_t *icmp, uint8_t *mac ) +{ + memcpy( icmp->eth_src, mac, 6 ); + return 0; +} + +int icmp_eth_len( icmp_pckt_t *icmp ) +{ + return 14; +} + + +int icmp_ip_init( icmp_pckt_t *icmp ) +{ + icmp->head_hlength = 0x45; //ip4,header size 20 byte + icmp->tos = 0x00; + icmp->ip_length = htons(20+8+ICMP_MAX_DATA); //ip4 header + icmp message + icmp->ip_ident = htons(0xfbea); + icmp->flags_fragment_off = 0x0040; + icmp->ttl = 64; + icmp->protocol = 1; //ICMP + icmp->source_addr = inet_addr("127.0.0.1"); + icmp->dest_addr = inet_addr("127.0.0.1"); + return 0; +} + + +int icmp_ip_chksum( icmp_pckt_t *icmp ) +{ + uint16_t chk; + + icmp->ip_chksum = 0; + chk = ip_checksum( (uint16_t *)icmp+7, 20 ); + + icmp->ip_chksum = chk; + return 0; +} + + +int icmp_ip_dest( icmp_pckt_t *icmp, uint32_t dest ) +{ + uint32_t s = dest; + uint8_t a,b,c,d; + + a = s; + b = s>>8; + c = s>>16; + d = s>>24; + + uint32_t aa = a; + uint32_t bb = b; + uint32_t cc = c; + uint32_t dd = d; + + printf("%d.%d.%d.%d\n",a,b,c,d); + + s = 0x0; + s = aa + (bb<<8) + (cc<<16) + (dd<<24); + icmp->dest_addr = s; + return 0; +} + + +int icmp_ip_src( icmp_pckt_t *icmp, uint32_t src ) +{ + uint32_t s = src; + uint8_t a,b,c,d; + + a = s; + b = s>>8; + c = s>>16; + d = s>>24; + + uint32_t aa = a; + uint32_t bb = b; + uint32_t cc = c; + uint32_t dd = d; + + printf("%d.%d.%d.%d\n",a,b,c,d); + + s = 0x0; + s = aa + (bb<<8) + (cc<<16) + (dd<<24); + + icmp->source_addr = s; + return 0; +} + +int icmp_ip_ident( icmp_pckt_t *icmp, uint16_t ident ) +{ + icmp->ip_ident = htons(ident); + //icmp->ip_ident = ident; + return 0; +} + + +int icmp_ip_ttl( icmp_pckt_t *icmp, uint8_t ttl ) +{ + icmp->ttl = ttl; + return 0; +} + + +int icmp_ip_len( icmp_pckt_t *icmp ) +{ + return 20; +} + + +int icmp_icmp_init( icmp_pckt_t *icmp ) +{ + int i = 0; + + icmp->type = ICMP_TREQUEST; + icmp->code = 0; + icmp->icmp_ident = 0x4062; + icmp->seq_num = 0x0001; + //icmp->timestamp = 0x5749aae7;//0xe7aa4957; + + for (i=0;i<ICMP_MAX_DATA;i++) + { + icmp->data[i] = 0; + } + + return 0; +} + + +int icmp_icmp_set_chks( icmp_pckt_t *icmp ) +{ + uint16_t chk=0x0; + uint16_t offset=0x0; + + icmp->icmp_check_sum = 0x0000; + + //fot ICMP header + offset = icmp_eth_len(icmp) + icmp_ip_len(icmp); + printf("offset %d len %d\n", offset, icmp_icmp_len(icmp)); + chk = ip_checksum( ((uint16_t *)icmp)+offset/2, + icmp_icmp_len(icmp) ); + + icmp->icmp_check_sum = chk; + return 0; +} + + +int icmp_icmp_set_code( icmp_pckt_t *icmp, uint8_t code ) +{ + return 0; +} + + +int icmp_icmp_set_type( icmp_pckt_t *icmp, uint8_t type ) +{ + icmp->type = type; + return 0; +} + + +int icmp_icmp_len( icmp_pckt_t *icmp ) +{ + return 8+ICMP_MAX_DATA; +} + +int icmp_icmp_ident( icmp_pckt_t *icmp, uint16_t ident ) +{ + icmp->icmp_ident = htons(ident); + return 0; +} + +int icmp_icmp_seq( icmp_pckt_t *icmp, uint16_t seq) +{ + icmp->seq_num = htons(seq); + return 0; +} + +int icmp_total_len( icmp_pckt_t *icmp ) +{ + int ret=0; + + ret = icmp_eth_len(icmp) + +icmp_ip_len(icmp) + +icmp_icmp_len(icmp); + + return ret; +} + +int icmp_icmp_ts( icmp_pckt_t *icmp, uint64_t timestamp ) +{ + //icmp->timestamp = timestamp; + return 0; +} + +int icmp_dump( icmp_pckt_t *icmp ) +{ + int i=0,j=0,m=0; + + printf("Etherenet header\n"); + for (i=0;i<j+14;i++) + { + printf("%02X ", ((unsigned char *)icmp)[i]); + if (i%16==15) printf("\n"); + } + printf("\n"); + + j = i; + printf("IP header\n"); + for (i=j,m=0;i<j+20;i++,m++) + { + printf("%02X ", ((unsigned char *)icmp)[i]); + if (m%16==15) printf("\n"); + } + printf("\n"); + + j = i; + printf("ICMP header\n"); + for (i=j,m=0;i<sizeof(icmp_pckt_t);i++,m++) + { + printf("%02X ", ((unsigned char *)icmp)[i]); + if (m%16==15) printf("\n"); + } + printf("\n"); + return 0; +} + +int icmp_data( icmp_pckt_t *icmp, uint8_t *data, size_t size ) +{ + memcpy( icmp->data, data, size ); + return 0; +}
\ No newline at end of file diff --git a/libping.h b/libping.h new file mode 100644 index 0000000..071915a --- /dev/null +++ b/libping.h @@ -0,0 +1,76 @@ +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <linux/if_packet.h> +#include <linux/if_ether.h> +#include <sys/ioctl.h> +#include <net/if.h> + +#define ICMP_TREQUEST 8 +#define ICMP_TECHO 0 + +#define ICMP_DEFAULT_SIZE 0 +//#define ICMP_MAX + +typedef struct icmp_pckt_t +{ + //etherenet header - 14 bytes + uint8_t eth_dest[6]; + uint8_t eth_src[6]; + uint16_t eth_type; + + //IP4 header - 20 bytes + uint8_t head_hlength; //4bits version, 4bit header length + uint8_t tos; + uint16_t ip_length; + + uint16_t ip_ident; + uint16_t flags_fragment_off; + + uint8_t ttl; //time to live + uint8_t protocol; + uint16_t ip_chksum; + + uint32_t source_addr; + uint32_t dest_addr; + + //ICMP header 12 bytes + uint8_t type; + uint8_t code; + uint16_t icmp_check_sum; + uint16_t icmp_ident; + uint16_t seq_num; + uint8_t data[ICMP_MAX_DATA]; +} __attribute__((packed, aligned(1))) icmp_pckt_t; + +int icmp_eth_init( icmp_pckt_t *icmp ); +int icmp_eth_dest( icmp_pckt_t *icmp, uint8_t *mac ); +int icmp_eth_src( icmp_pckt_t *icmp, uint8_t *mac ); +int icmp_eth_len( icmp_pckt_t *icmp ); +int icmp_ip_init( icmp_pckt_t *icmp ); +int icmp_ip_chksum( icmp_pckt_t *icmp ); +int icmp_ip_dest( icmp_pckt_t *icmp, uint32_t dest ); +int icmp_ip_src( icmp_pckt_t *icmp, uint32_t src ); +int icmp_ip_ident( icmp_pckt_t *icmp, uint16_t ident ); +int icmp_ip_ttl( icmp_pckt_t *icmp, uint8_t ttl ); +int icmp_ip_len( icmp_pckt_t *icmp ); +int icmp_icmp_init( icmp_pckt_t *icmp ); +int icmp_icmp_set_chks( icmp_pckt_t *icmp ); +int icmp_icmp_set_code( icmp_pckt_t *icmp, uint8_t code ); +int icmp_icmp_set_type( icmp_pckt_t *icmp, uint8_t type ); +int icmp_icmp_len( icmp_pckt_t *icmp ); +int icmp_icmp_ident( icmp_pckt_t *icmp, uint16_t ident ); +int icmp_icmp_seq( icmp_pckt_t *icmp, uint16_t seq); +int icmp_total_len( icmp_pckt_t *icmp ); +int icmp_icmp_ts( icmp_pckt_t *icmp, uint64_t timestamp ); +int icmp_dump( icmp_pckt_t *icmp ); +int icmp_data( icmp_pckt_t *icmp, uint8_t *data, size_t size ); + +uint16_t +ip_checksum (uint16_t *addr, int len); |