Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <time.h>
- #include <linux/if_ether.h>
- #include <sys/ioctl.h>
- #include <netpacket/packet.h>
- #include <net/if_arp.h>
- #include <net/if.h>
- #include <netinet/ip.h>
- #include <netinet/ip_icmp.h>
- #include "headers.h"
- /* Global variables */
- #define MACSIZ 6
- int p_socket;
- struct sockaddr_ll sa_ll; /* L2 address of gateway */
- u_int32_t src_ip, dst_ip; /* src & dst ip addresses */
- u_int16_t icmp_id_num; /* id number of last ICMP sent */
- size_t packet_size; /* how many bytes to send or were received */
- char packet_buf[1600]; /* raw packet buffer */
- /* Declarations */
- void init_session(char *ifname, char *gw_ip, char *dst);
- void close_session();
- size_t create_icmp_hdr(void *buf, size_t buf_size);
- size_t add_ip_opt_rroute(void *buf, size_t buf_size, int count);
- size_t create_ip_hdr(void *buf, size_t buf_size, int ttl, size_t data_len);
- void send_icmp(int ttl);
- void send_packet();
- void receive_packet();
- void receive_icmp_reply();
- void print_record_route();
- u_int16_t calc_checksum(void *buff, int len);
- /*
- Main function
- */
- int main(int argc, char **argv) {
- if (argc < 4) {
- fprintf(stderr, "Usage: %s <output-dev> <gateway-ip> <dst-ip>\n", *argv);
- exit(1);
- }
- init_session(argv[1], argv[2], argv[3]);
- printf("Jesli po paru chwilach nic sie nie pojawi to pakiet IP zostal pewnie odrzucony przez host docelowy (ze wzgledu na opcje Record Route) - najlepiej sprawdzic tcpdumpem/wiresharkiem lub sprobowac dla innego docelowego IP.\n\n");
- send_icmp(56);
- receive_icmp_reply();
- print_record_route();
- close_session();
- }
- /*
- Initializes global variables and opens packet socket.
- @param dev Output device name, e.g. eth0, wlan0
- @param gw IP address of default gateway
- @param dst Destination IP address
- */
- void init_session(char *ifname, char *gw_ip, char *dst) {
- int fd;
- struct ifreq ifr;
- struct arpreq arpreq;
- struct sockaddr_in *in;
- char gw_mac[MACSIZ]; /* gateway MAC address */
- int ifindex; /* index number of output interface */
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- /* copying ifname */
- /*strncpy(ifname, dev, sizeof(ifname)-1);*/
- /* getting gateway mac */
- bzero(&arpreq, sizeof(arpreq));
- in = (struct sockaddr_in *)&arpreq.arp_pa;
- in->sin_family = AF_INET;
- inet_pton(AF_INET, gw_ip, &(in->sin_addr.s_addr));
- strncpy(arpreq.arp_dev, ifname, 15);
- if (ioctl(fd, SIOCGARP, &arpreq) < 0) {
- fprintf(stderr, "Error /ioctl(fd, SIOCGARP, &arpreq)/: %s\n", strerror(errno));
- exit(1);
- }
- memcpy(gw_mac, arpreq.arp_ha.sa_data, MACSIZ);
- /* getting index number of output interface */
- bzero(&ifr, sizeof(ifr));
- strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
- if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
- fprintf(stderr, "Error /ioctl(fd, SIOCGIFINDEX, &ifr)/: %s\n", strerror(errno));
- exit(1);
- }
- ifindex = ifr.ifr_ifindex;
- /* getting ip number of output interface (our src ip address) */
- bzero(&ifr, sizeof(ifr));
- strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
- if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
- fprintf(stderr, "Error /ioctl(fd, SIOCGIFADDR, &ifr)/: %s\n", strerror(errno));
- exit(1);
- }
- src_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
- /* destination ip */
- if (inet_pton(AF_INET, dst, &dst_ip) < 1) {
- fprintf(stderr, "Error %s:%d: %s\n", __FILE__, __LINE__, "Invalid dst ip");
- exit(1);
- }
- close(fd);
- /* creating packet socket */
- if ((p_socket = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
- fprintf(stderr, "ERROR: %s\n", strerror(errno));
- exit(1);
- }
- /* setting values in sockaddr_ll */
- bzero(&sa_ll, sizeof(sa_ll));
- sa_ll.sll_family = AF_PACKET;
- memcpy(&sa_ll.sll_addr, gw_mac, sizeof(gw_mac));
- sa_ll.sll_halen = sizeof(gw_mac);
- sa_ll.sll_ifindex = ifindex;
- sa_ll.sll_protocol = htons(ETH_P_IP);
- /* binding */
- if (bind(p_socket, (const struct sockaddr *)&sa_ll, sizeof(sa_ll)) < 0) {
- fprintf(stderr, "ERROR (bind): %s\n", strerror(errno));
- exit(1);
- }
- }
- /*
- Closes sessions.
- */
- void close_session() {
- close(p_socket);
- }
- /*
- Creates icmp header (ICMP_ECHO).
- @param buf Pointer to buffer where to put header
- @param buf_size Buffer size
- @return Number of bytes added
- */
- size_t create_icmp_hdr(void *buf, size_t buf_size) {
- struct icmphdr *icmp;
- srand(time(0));
- icmp_id_num = random() % 0xFFFF;
- bzero(buf, buf_size);
- icmp = (struct icmphdr *)buf;
- icmp->type = ICMP_ECHO;
- icmp->un.echo.id = icmp_id_num;
- icmp->checksum = calc_checksum(buf, sizeof(struct icmphdr));
- return sizeof(struct icmphdr);
- }
- /*
- Adds IP option Record Route with ability to record 'count'
- hops (count in 0 .. 10). Adds padding if necessary.
- @param buf Pointer to buffer where to add RR option
- @param buf_size Bufer size
- @return Number of bytes added
- */
- size_t add_ip_opt_rroute(void *buf, size_t buf_size, int count) {
- struct opt_ip_route *opt;
- size_t opt_len;
- /* padding is always 1 byte for this option */
- opt_len = sizeof(struct opt_ip_route) + 4*count + 1;
- if (opt_len > buf_size || count > 9) {
- perror("Record Route option is too long (count>9 or no space left in buffer)");
- return 0;
- }
- *(char *)(buf++) = OPT_IP_NOP; /* padding */
- opt = (struct opt_ip_route *)buf;
- opt->cpy_flag = 0;
- opt->class_opt = 0;
- opt->option = OPT_IP_RR;
- opt->length = opt_len-1; /* minus padding */
- opt->ptr = 4;
- return opt_len;
- }
- /*
- Creates IPv4 header with given TTL
- @param buf Pointer to buffer where to put header
- @param buf_size Buffer size
- @return Number of bytes added
- */
- size_t create_ip_hdr(void *buf, size_t buf_size, int ttl, size_t data_len) {
- static short ip_id = 0;
- struct iphdr *iphdr;
- size_t hdr_len;
- /* assuming buf was already zeroed */
- iphdr = (struct iphdr *)buf;
- iphdr->version = 4; /* IPv4 */
- iphdr->id = htons(ip_id++); /* Ip id */
- iphdr->ttl = ttl; /* TTL */
- iphdr->protocol = IPPROTO_ICMP; /* L4 protocol */
- iphdr->saddr = src_ip; /* Src IP address */
- iphdr->daddr = dst_ip; /* Dst IP address */
- hdr_len = sizeof(struct iphdr);
- /* adding IP options */
- hdr_len += add_ip_opt_rroute(buf+hdr_len, buf_size-hdr_len, 9);
- /*hdr_len += add_ip_opt_lsr(buf+hdr_len, buf_size-hdr_len);*/
- /* correcting 'length' fields in header */
- if (hdr_len > 60) {
- fprintf(stderr, "IP header is too long (%d/60 bytes): change IP options", hdr_len);
- exit(1);
- }
- iphdr->ihl = hdr_len/4;
- iphdr->tot_len = htons(hdr_len + data_len);
- /* calculating checksum */
- iphdr->check = calc_checksum(buf, hdr_len);
- return hdr_len;
- }
- /*
- Sends icmp packet with given ttl value.
- */
- void send_icmp(int ttl) {
- char icmp_header[128];
- char ip_header[128];
- size_t icmp_size, ip_size, eth_size;
- /* cleaning buffers */
- bzero(packet_buf, sizeof(packet_buf));
- bzero(icmp_header, sizeof(icmp_header));
- bzero(ip_header, sizeof(ip_header));
- /* preparing headers */
- icmp_size = create_icmp_hdr(icmp_header, sizeof(icmp_header));
- ip_size = create_ip_hdr(ip_header, sizeof(ip_header), ttl, icmp_size);
- /* preparing final packet and sending */
- memcpy(packet_buf, ip_header, ip_size);
- memcpy(packet_buf+ip_size, icmp_header, icmp_size);
- packet_size = ip_size + icmp_size;
- send_packet();
- }
- /*
- Prints IP Record Route values from packet
- stored in packet_buf.
- */
- void print_record_route() {
- struct iphdr *iphdr;
- struct opt_ip_route *opt;
- int hdr_len;
- void *opt_start;
- int rr_end;
- char ip_addr[24];
- iphdr = (struct iphdr*)packet_buf;
- hdr_len = iphdr->ihl*4;
- hdr_len -= sizeof(struct iphdr);
- opt_start = packet_buf+sizeof(struct iphdr);
- while (hdr_len > 0) {
- opt = (struct opt_ip_route *)opt_start;
- if (opt->option == OPT_IP_NOP || opt->option == OPT_IP_EOP) {
- ++opt_start;
- --hdr_len;
- continue;
- } else if (opt->option == OPT_IP_RR) {
- /* printing... */
- rr_end = opt->ptr;
- opt->ptr -= 4;
- while (opt->ptr > 0) {
- /* a little black magic with pointers & indexes ];-> */
- inet_ntop(AF_INET, opt_start+rr_end-opt->ptr-1, ip_addr, sizeof(ip_addr));
- printf("%s\n", ip_addr);
- opt->ptr -= 4;
- }
- hdr_len -= opt->length;
- opt_start += opt->length;
- } else {
- fprintf(stderr, "Unknown ip option : %d\n", opt->option);
- exit(1);
- }
- }
- }
- /*
- Receives icmp reply
- */
- void receive_icmp_reply() {
- struct iphdr *iphdr;
- struct icmphdr *icmphdr;
- while(1) {
- receive_packet();
- iphdr = (struct iphdr *)packet_buf;
- if (iphdr->protocol == IPPROTO_ICMP) {
- icmphdr = (struct icmphdr *)(packet_buf + iphdr->ihl*4);
- /* checking if received ICMP is our reply */
- if (icmphdr->un.echo.id != icmp_id_num)
- continue;
- break;
- }
- }
- }
- /*
- Sends raw packet
- */
- void send_packet() {
- int rtn;
- rtn = sendto(p_socket, (void *)packet_buf, packet_size, 0, (const struct sockaddr *)&sa_ll, sizeof(sa_ll));
- if (rtn < 0) {
- fprintf(stderr, "ERROR(send): %s\n", strerror(errno));
- exit(1);
- }
- }
- /*
- Receives next packet to packet_buf
- */
- void receive_packet() {
- int rtn;
- struct sockaddr_ll sa;
- int size = sizeof(sa);
- bzero(packet_buf, sizeof(packet_buf));
- rtn = recvfrom(p_socket, (void*)packet_buf, sizeof(packet_buf), 0, (struct sockaddr*)&sa, &size);
- if (rtn < 0) {
- fprintf(stderr, "ERROR(receive): %s\n", strerror(errno));
- }
- packet_size = rtn;
- }
- /*
- Calculates checksum using 1's complement.
- Based on example in RFC-1071 (4.1)
- @param buff Pointer to buffer with data
- @param len Data length in buffer
- @return 16bit checksum
- */
- u_int16_t calc_checksum(void *buff, int len) {
- register long sum = 0;
- while (len > 1) {
- sum += *((unsigned short *)buff);
- buff += 2;
- len -= 2;
- }
- if (len > 0)
- sum += *((unsigned char *)buff);
- while (sum>>16)
- sum = (sum & 0xffff) + (sum >> 16);
- return ~sum;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement