what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

ICMP Ping Sweep

ICMP Ping Sweep
Posted Jan 17, 2012
Authored by James Stevenson | Site stev.org

This is a simple ICMP ping sweeping tool that takes in a range of IP addresses.

tags | tool, scanner
systems | unix
SHA-256 | f42e0187f536097a0191dec4e7b0d24b97b53a7add5c373fe34cd95f26a39102

ICMP Ping Sweep

Change Mirror Download
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: icmp-psweep.c,v 1.2 2011/12/08 20:13:47 james.stevenson Exp $
*
* Author:
* NAME: James Stevenson
* WWW: http://www.stev.org
*
* Usage:
* Compile : gcc -Wall -O2 icmp-psweep.c -o icmp-psweep
* Run : ./icmp-psweep -h
*
* icmp-psweep:
* this is a small program to ping a range of ip addresses
* your mileage may vary on the responses you get back from
* hosts as most people tend to block icmp echo packets now
*/


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>

#define DEFAULT_RESEND 4
#define DEFAULT_RATE 10
#define DEFAULT_DELAY 10

struct host_t {
struct host_t *next; /* next host entry */
struct host_t *prev; /* prev entry */
unsigned long hip; /* ip in host bytes */
unsigned long nip; /* ip in network order */
unsigned long blocked; /* a host that is blocking it */
unsigned short blk_type; /* the type of block eg UNREACHABLE */
unsigned short blk_code; /* the code of block eg NETWORK */
int errors; /* errors ? */
int sent; /* number of packets sent */
int recv; /* number recived */
time_t last; /* last time a packet was sent */
};


/* Function in the file in order of occurance */
int run_q(); /* run the resend q */
int icmp_read(int seconds); /* reads packets from network */
void icmp_read_other(struct iphdr *ip, struct icmphdr *icmp, int len);
void icmp_read_echoreply(struct iphdr *ip, struct icmphdr *icmp, int len);
int icmp_send_ping(struct host_t *p); /* sends a ping packet */
int host_add(unsigned long ip); /* adds a host */
void host_del(struct host_t *p); /* deletes a host */
struct host_t *host_get(unsigned long ip); /* get a host from ip */
unsigned short in_cksum(unsigned short *addr,int len);
char *icmp_human_readable(int type, int code);
void print_usage(FILE *file); /* prints help for program */

/* Global Vars */

int sockfd; /* raw ICMP socket for network data */
struct host_t *host; /* hosts data */
struct host_t *last_host; /* so we can run backwards though the list */
int max = DEFAULT_RESEND;/* max packets to send to each host */
int rate = DEFAULT_RATE;/* how many packets per second */
int resend = DEFAULT_DELAY;/* how long to wait for resend */
int only_exist = 0;
int only_blocked = 0;

int main(int argc, char **argv) {
unsigned long ip_start, ip_stop, tswap;
int i, c;

while(( c = getopt(argc, argv, "bhr:m:nd:")) != -1) {
switch(c) {
case 'b':
only_blocked++;
break;
case 'h':
print_usage(stdout);
exit(0);
break;
case 'r':
rate = atoi(optarg);
if (rate == 0) {
print_usage(stderr);
fprintf(stderr, "'%d' is an invalid arg to -r\n", rate);
exit(-1);
}
break;
case 'm':
max = atoi(optarg);
if (max == 0) {
print_usage(stderr);
fprintf(stderr, "'%d' is an invalid arg to -m\n", max);
exit(-1);
}
break;
case 'n':
only_exist++;
break;
case 'd':
resend = atoi(optarg);
break;
default:
break;
}
}

if (argc > 2) {
ip_start = ntohl(inet_addr(argv[argc - 2]));
ip_stop = ntohl(inet_addr(argv[argc - 1]));
} else {
fprintf(stderr, "You Must Provide 2 ip addresses\n");
print_usage(stderr);
exit(-1);
}

if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket");
exit(-1);
}

if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
perror("fcntl");
exit(-2);
}

if (ip_start > ip_stop) {
tswap = ip_start;
ip_start = ip_stop;
ip_stop = ip_start;
}

while(ip_start < ip_stop) {
i = run_q(rate);
if (ip_start + rate > ip_stop)
i = ip_stop - ip_start;
while(i) {
tswap = htonl(ip_start);
host_add(tswap);
icmp_send_ping( host_get(tswap));
ip_start++;
i--;
}
icmp_read(1);
}

while(1) {
icmp_read(resend);
run_q(rate);
if (!host && !last_host)
exit(0);

}

return 0;
}

/* this will return the number of packets sent */
int run_q(int can_send) {
int tot_sent = 0, i;
struct host_t *p, *oldp;
time_t ctime = time(NULL);

p = last_host;
recheck:
if (!p)
return can_send;

/* lets see how many hosts we can dump */
/* but we want to dump them in order :) */
if ( (p->recv || p->sent >= max || p->blocked || p->errors) && (p->recv < p->sent || p->last + resend < ctime) ) {
oldp = p;
p = p->prev;
host_del(oldp);
goto recheck;
}

/* process resends until we send rate */
i = can_send;
ctime = time(NULL);
next_resend:
/* return if we hit a host that has good info */
if ( (p->recv || p->errors || p->blocked) ||
(ctime - resend < p->last) ||
(p->sent > max)) {
if (p->prev) {
p = p->prev;
goto next_resend;
} else {
return can_send - tot_sent;
}
}

if (icmp_send_ping(p) >= 0) {
i--;
tot_sent++;
}

/* we cannot send any more */
if (tot_sent >= can_send)
return 0;

if (p->prev) {
p = p->prev;
goto next_resend;
}

return can_send - tot_sent;
}


int icmp_read(int seconds) {
char buf[1024]; /* we should not get a ping reply this size */
int length, ret;
struct iphdr *ip = (void *) &buf[0];
struct icmphdr *icmp;
fd_set fds;
struct timeval tv;


FD_ZERO(&fds);
FD_SET(sockfd, &fds);
tv.tv_sec = seconds;
tv.tv_usec = 0;

re_select:
ret = select(sockfd + 1, &fds, NULL, NULL, &tv);
if (ret > 0) {
re_read:
length = read(sockfd, &buf[0], 1023);
if (length == 0)
return 0;
if (length < 0) {
switch(errno) {
case ERESTART:
case EINTR:
goto re_read;
case EAGAIN:
return 0;
default:
return 0;
}
}
if (ip->protocol == IPPROTO_ICMP) { /* we are only intresting in icmp packets */
icmp = (void *) ip + (ip->ihl * 4);
length -= ip->ihl * 4;
length -= sizeof(struct icmphdr);
/* lets see if we have a ping reply */
if (icmp->type == ICMP_ECHOREPLY) {
icmp_read_echoreply(ip, icmp, length);
} else {
icmp_read_other(ip, icmp, length);
}
}
goto re_select;
} else if (ret < 0) {
perror("select");
}


return 0;
}

void icmp_read_other(struct iphdr *ip, struct icmphdr *icmp, int len) {
struct iphdr *encap_ip;
struct icmphdr *encap_icmp;
struct host_t *p;

if (len < sizeof(struct iphdr))
return; /* no data to work with */

/* we should now have a proper icmp message to deal with */
encap_ip = (struct iphdr *) ( (char *) icmp + sizeof(struct icmphdr));

if (encap_ip->ihl < 5 || encap_ip->version != 4)
return;

len -= encap_ip->ihl * 4;
if (encap_ip->protocol != IPPROTO_ICMP || len < sizeof(struct icmphdr))
return;

encap_icmp = (struct icmphdr *) encap_ip + sizeof(struct icmphdr);

p = host_get(encap_ip->daddr);
if (!p)
return;

p->blocked = ip->saddr;
p->blk_code = icmp->code;
p->blk_type = icmp->type;

return;
}

void icmp_read_echoreply(struct iphdr *ip, struct icmphdr *icmp, int len) {
struct host_t *p;
p = host_get(ip->saddr);
if (!p)
return; /* invalid host */
p->recv++;
}


int icmp_send_ping(struct host_t *p) {
struct sockaddr_in out_addr;
char *buf[30];
int length;
struct icmphdr *icmp = (void *) &buf[0];

/* set up the dest address */
bzero(&out_addr, sizeof(out_addr));
out_addr.sin_addr.s_addr = p->nip;

/* set up the length of the packet */
length = sizeof(struct icmphdr);

/* set up the ping packet */
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->un.echo.id = getpid();
icmp->un.echo.sequence = p->sent;
icmp->checksum = 0;
icmp->checksum = in_cksum((unsigned short *) icmp, length);

if(sendto(sockfd , (void *) &buf[0] , length, 0x0,
(struct sockaddr *) &out_addr, sizeof(out_addr)) < 0) {
p->errors++;
return -1;
}
p->last = time(NULL);
p->sent++;

return 1;
}

int host_add(unsigned long ip) {
struct host_t *p;

p = malloc( sizeof(struct host_t));
if (!p) {
fprintf(stderr, "malloc for host entry failed !!!!\n");
return -1;
}

p->nip = ip;
p->hip = ntohl(ip);
p->blocked = 0;
p->blk_type = 0;
p->blk_code = 0;
p->errors = 0;
p->sent = 0;
p->last = 0;
p->prev = NULL;


if (!last_host)
last_host = p;

if (host)
host->prev = p;

p->next = host;
host = p;

return 1;
}

void host_del(struct host_t *p) {
struct in_addr inaddr, blocked;
char ipbuf[20];
inaddr.s_addr = p->nip;

if (p->blocked && (only_exist == 0 || only_blocked) ) {
blocked.s_addr = p->blocked;
strcpy(&ipbuf[0], inet_ntoa(blocked));
printf("%20s Sent: %d Recv: %d\tBlocked by %s %s\n", inet_ntoa(inaddr),
p->sent, p->recv, &ipbuf[0], icmp_human_readable(p->blk_type, p->blk_code));
} else {
if (p->recv || only_exist == 0)
printf("%20s Sent: %d Recv: %d\t%s\n", inet_ntoa(inaddr), p->sent, p->recv, p->recv ? "Host Up !!!!" : "Host Down");
}

/* drop it out of the linked list */
if (p->next) {
p->next->prev = p->prev;
} else {
last_host = p->prev;
}

if (p->prev) {
p->prev->next = p->next;
} else {
host = p->next;
}

free(p);
return;
}

struct host_t *host_get(unsigned long ip) {
struct host_t *p;

p = host;
while(p) {
if (p->nip == ip)
return p;
p = p->next;
}
return NULL;
}

unsigned short in_cksum(unsigned short *addr,int len) {
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;

/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}

/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}

/* convert icmp messages into human readable form */
char *icmp_human_readable(int type, int code) {
static char tmp[35];
char *half = NULL; /* for setting the first half */

switch (type) {
case ICMP_ECHOREPLY:
return "Echo Reply";
break;
case 1:
case 2:
break;
case ICMP_DEST_UNREACH:
switch (code) {
case ICMP_NET_UNREACH:
return "Network Unreachable";
break;
case ICMP_HOST_UNREACH:
return "Host Unreachable";
break;
case ICMP_PROT_UNREACH:
return "Protocol Unreachable";
break;
case ICMP_PORT_UNREACH:
return "Port Unreachable";
break;
case ICMP_FRAG_NEEDED:
return "Fragment Needed";
break;
case ICMP_SR_FAILED:
return "Source route failed";
break;
case ICMP_NET_UNKNOWN:
return "Network Unknown";
break;
case ICMP_HOST_UNKNOWN:
return "Host Unknown";
break;
case ICMP_NET_ANO:
return "Network ANO";
break;
case ICMP_HOST_ANO:
return "Host ANO";
break;
case ICMP_NET_UNR_TOS:
return "Network TOS Unreachable";
break;
case ICMP_HOST_UNR_TOS:
return "Host TOS Unreachable";
break;
case ICMP_PKT_FILTERED:
return "Packet Filtered";
break;
case ICMP_PREC_VIOLATION:
return "Precedence violation";
break;
case ICMP_PREC_CUTOFF:
return "Precedence Cutoff";
break;
default:
half = "Unreachable";
break;
}
break;
case ICMP_SOURCE_QUENCH:
return "Source QUENCH";
break;
case ICMP_REDIRECT:
switch(code) {
case ICMP_REDIR_NET:
return "Redirect Network";
break;
case ICMP_REDIR_HOST:
return "Redirect Host";
break;
case ICMP_REDIR_NETTOS:
return "Redirect Network TOS";
break;
case ICMP_REDIR_HOSTTOS:
return "Redirect Host TOS";
break;
default:
half = "Redirect";
break;
}
break;
case 6: /* unused */
case 7: /* unused */
break;
case ICMP_ECHO:
return "Echo";
break;
case ICMP_TIME_EXCEEDED:
switch(code) {
case ICMP_EXC_TTL:
return "TTL Exceeded";
break;
case ICMP_EXC_FRAGTIME:
return "Fragment Timeout";
break;
default:
half = "Time Exceeded";
break;
}
return "Time Exceeded";
break;
case ICMP_PARAMETERPROB:
return "Parameter Proglem";
break;
case ICMP_TIMESTAMP:
return "Timestamp";
break;
case ICMP_TIMESTAMPREPLY:
return "Timestamp Reply";
break;
case ICMP_INFO_REQUEST:
return "Info Request";
break;
case ICMP_INFO_REPLY:
return "Info Reply";
break;
case ICMP_ADDRESS:
return "Address";
break;
case ICMP_ADDRESSREPLY:
return "Address Reply";
break;
default:
break;
}

if (half)
snprintf(&tmp[0], sizeof(tmp) - 1, "%s Code: %d\n", half, code);
else snprintf(&tmp[0], sizeof(tmp) - 1, "Type: %d Code: %d\n", type, code);

return &tmp[0];
}

/* dump the help on stderr or stdout */
void print_usage(FILE *file) {
fprintf(file, "Usage:\n");
fprintf(file, "\t./icmp-psweep [<opts>] <start ip> <stop ip>\n");
fprintf(file, "\t-b Show hosts that are blocked only usefull when -n is used\n");
fprintf(file, "\t-d x Time to wait in seconds before attempting to resend default: %d\n", DEFAULT_DELAY);
fprintf(file, "\t-r x Number of packets to send per second default: %d\n", DEFAULT_RATE);
fprintf(file, "\t-m x Maximum resend to make per host default: %d\n", DEFAULT_RESEND);
fprintf(file, "\t-n Only display hosts that exist\n");
fprintf(file, "\t-h Displays this help\n");
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    16 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close