Created
December 16, 2014 04:27
-
-
Save codemonkey2841/84b6fb4049efb2893cbc to your computer and use it in GitHub Desktop.
A parallelized ping scanner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********************************************************************/ | |
/* pscan.c -- Parallelized ping scanner */ | |
/* */ | |
/* (c) 1997 David Simmons, simmons@simmons.starkville.ms.us */ | |
/* */ | |
/* compile with: cc -o pscan pscan.c */ | |
/* */ | |
/* This program has only been tested under Linux. */ | |
/* */ | |
/********************************************************************/ | |
/* 2000.01.31 D. Duccini, duck@backpack.net */ | |
/* */ | |
/* hack to compile under solaris */ | |
/* */ | |
/* compile with: gcc -o pscan pscan.c -lsocket -lnsl */ | |
/* */ | |
/********************************************************************/ | |
/* include files */ | |
#include <errno.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <signal.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <netdb.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
//#include <netinet/in_systm.h> | |
// #include <netinet/ip_icmp.h> | |
#include <arpa/inet.h> | |
#include <sys/uio.h> | |
#include <time.h> | |
#define ICMP_ECHO 8 /* Echo Request */ | |
struct icmphdr | |
{ | |
u_char type; /* message type */ | |
u_char code; /* type sub-code */ | |
u_short checksum; | |
union | |
{ | |
struct | |
{ | |
u_short id; | |
u_short sequence; | |
} echo; /* echo datagram */ | |
u_long gateway; /* gateway address */ | |
struct | |
{ | |
u_short __unused; | |
u_short mtu; | |
} frag; /* path mtu discovery */ | |
} un; | |
}; | |
/* useful defines */ | |
#define DEFDATALEN (64 - 8) | |
#define MAXIPLEN 60 | |
#define MAXICMPLEN 76 | |
#define MAXPACKET (65536 - 60 - 8) | |
/* prototypes */ | |
int in_cksum(u_short *addr, int len); | |
void send_ping(); | |
void ping16(); | |
void finish(); | |
char *niceip(); | |
void usage(); | |
/* global variables */ | |
int s; /* icmp socket file descriptor */ | |
int datalen = DEFDATALEN; /* data length */ | |
struct sockaddr_in *in; /* current address to ping */ | |
long ipstart; /* initial ip address */ | |
struct timeval sent[256]; /* array representing hosts in network */ | |
struct timeval recvd[256]; /* array representing hosts in network */ | |
u_char outpack[MAXPACKET]; /* prepare for sending packet */ | |
/* functions */ | |
/* ip_checksum() -- calculate IP checksum for headers */ | |
int ip_checksum(u_short *addr, int len) { | |
register int nleft = len; | |
register u_short *w = addr; | |
register int sum = 0; | |
u_short answer = 0; | |
while (nleft > 1) { | |
sum += *w++; | |
nleft -= 2; | |
} | |
if (nleft == 1) { | |
*(u_char *)(&answer) = *(u_char *)w ; | |
sum += answer; | |
} | |
sum = (sum >> 16) + (sum & 0xffff); | |
sum += (sum >> 16); | |
answer = ~sum; | |
return(answer); | |
} | |
/* compatibility defines */ | |
#define icmp_type type | |
#define icmp_code code | |
#define icmp_cksum checksum | |
#define icmp_id un.echo.id | |
#define icmp_seq un.echo.sequence | |
#define icmp_gwaddr un.gateway | |
#define ip_hl ihl | |
#define ip_v version | |
#define ip_tos tos | |
#define ip_len tot_len | |
#define ip_id id | |
#define ip_off frag_off | |
#define ip_ttl ttl | |
#define ip_p protocol | |
#define ip_sum check | |
#define ip_src saddr | |
#define ip_dst daddr | |
/* send_ping() -- transmit an icmp echo request to a host */ | |
void send_ping() { | |
struct sockaddr *targetaddr = (struct sockaddr *)in; | |
register struct icmphdr *icp; | |
register int cc; | |
int i; | |
/* prepare packet */ | |
icp = (struct icmphdr *)outpack; | |
icp->icmp_type = ICMP_ECHO; | |
icp->icmp_code = 0; | |
icp->icmp_cksum = 0; | |
icp->icmp_seq = 1; | |
icp->icmp_id = 42; | |
cc = datalen + 8; | |
icp->icmp_cksum = ip_checksum((u_short *)icp, cc); | |
/* send packet */ | |
i = sendto(s, (char *)outpack, cc, 0, targetaddr, | |
sizeof(struct sockaddr)); | |
/* did everything go okay? */ | |
if ((i<0) || (i!=cc)) { | |
if (i < 0) { | |
perror("pscan: sendto"); | |
} | |
} | |
} | |
/* ping16() -- ping 16 hosts at once */ | |
void ping16() { | |
static unsigned char octet = 0x00; /* current octet */ | |
int i; | |
/* convenient union to manipulate octets */ | |
union { | |
unsigned long l; | |
unsigned char a[4]; | |
} ipset; | |
/* load ipset with address */ | |
ipset.l = in->sin_addr.s_addr; | |
/* informative message to stderr */ | |
fprintf(stderr,"sending pings %02X - %02X\n",octet,octet+0xFF); | |
/* iterate over the next 16 ip addresses, pinging each. */ | |
for (i=0; i<256; i++) { | |
// if (((octet+i)!=0x00) && ((octet+i)!=0xFF)) { | |
ipset.a[3] = octet+i; | |
in->sin_addr.s_addr = ipset.l; | |
send_ping(); | |
gettimeofday(&(sent[i]), (struct timeval *)NULL); | |
// } | |
} | |
/* bump octet count and set the alarm for 2 seconds in the future, | |
when we will wake up to ping the next 16 ip addresses. */ | |
octet+=0x10; | |
octet = 0; | |
if (octet == 0x00) { | |
/* if finished, set the alarm to call finish() in 6 seconds, | |
allowing time for any remaining echo replies to be received. */ | |
signal(SIGALRM, finish); | |
alarm(5); | |
} else { | |
signal(SIGALRM, ping16); | |
alarm(2); | |
} | |
} | |
/* finish() -- wrap it up and display chart. */ | |
void finish() { | |
int i; | |
unsigned long fip; | |
char *ipstring; | |
struct sockaddr_in sin; | |
struct hostent *hp; | |
//struct timeval s,r,d; | |
int alive; | |
/* print heading */ | |
printf("#\n# ping scan of network: %s\n#\n",niceip(ipstart)); | |
/* iterate over chart elements, printing each host that we | |
received an echo reply from. */ | |
for (i=0; i<256; i++) { | |
fip = htonl((ntohl(ipstart) + i)); | |
ipstring = niceip(fip); | |
bzero(&sin, sizeof(sin)); | |
//bzero(&r, sizeof(struct timeval)); | |
//bzero(&s, sizeof(struct timeval)); | |
//bzero(&d, sizeof(struct timeval)); | |
sin.sin_family = AF_INET; | |
sin.sin_addr.s_addr = fip; | |
hp = gethostbyaddr((char*)&(sin.sin_addr),sizeof(sin.sin_addr),AF_INET); | |
//s.tv_sec = sent[i].tv_sec - sent[0].tv_sec; | |
//s.tv_usec = sent[i].tv_usec - sent[0].tv_usec; | |
alive = 0; | |
if (recvd[i].tv_sec != 0 && recvd[i].tv_usec != 0){ | |
//r.tv_sec = recvd[i].tv_sec - sent[0].tv_sec; | |
//d.tv_sec = r.tv_sec - s.tv_sec; | |
alive = 1; | |
} | |
//if (recvd[i].tv_sec != 0){ | |
//r.tv_usec = recvd[i].tv_usec - sent[0].tv_usec; | |
//d.tv_usec = r.tv_usec - s.tv_usec; | |
//} | |
//printf("%s %lu.%.6lu %lu.%.6lu %lu.%.6lu", ipstring, s.tv_sec, s.tv_usec, r.tv_sec, r.tv_usec, d.tv_sec,d.tv_usec); | |
printf("%s %d", ipstring, alive); | |
if ((hp != NULL) && (hp->h_name != NULL)) { | |
printf(" (%s)\n",hp->h_name); | |
} else { | |
printf("\n"); | |
} | |
} | |
exit(1); | |
} | |
/* niceip() -- print a network-order ipaddress in the standard | |
human readable dotted-quad format. */ | |
char *niceip(unsigned long ip) { | |
static char ipstring[32]; | |
union { | |
unsigned long ip; | |
unsigned char a[4]; | |
} ipset; | |
ipset.ip = ip; | |
sprintf(ipstring,"%d.%d.%d.%d", | |
ipset.a[0],ipset.a[1],ipset.a[2],ipset.a[3]); | |
return ipstring; | |
} | |
/* offer some advice. */ | |
void usage() { | |
fprintf(stderr,"usage: pscan <class-c net address>\n" | |
" example: pscan 192.168.42.0\n"); | |
exit(1); | |
} | |
main(int argc, char **argv) { | |
struct sockaddr targetaddr; | |
struct protoent *proto; | |
u_char *packet; | |
int packlen; | |
int hold, offset; | |
/* clear hosts array */ | |
bzero(sent, 256*sizeof(struct timeval)); | |
bzero(recvd,256*sizeof(struct timeval)); | |
/* parse IP address */ | |
if (argc != 2) usage(); | |
ipstart = htonl(ntohl(inet_addr(argv[1])) & 0xFFFFFF00); | |
/* set up initial address structure */ | |
bzero((char *)&targetaddr, sizeof(struct sockaddr)); | |
in = (struct sockaddr_in *)&targetaddr; | |
in->sin_family = AF_INET; | |
in->sin_addr.s_addr = ipstart; | |
/* open and configure socket for icmp */ | |
if (!(proto = getprotobyname("icmp"))) { | |
fprintf(stderr, "pscan: unknown protocol icmp.\n"); | |
exit(1); | |
} | |
if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { | |
perror("pscan: socket"); | |
exit(1); | |
} | |
hold=1; | |
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&hold, sizeof(hold)); | |
hold=48*1024; | |
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); | |
packlen = datalen+MAXIPLEN+MAXICMPLEN; | |
if (!(packet = (u_char *)malloc((u_int)packlen))) { | |
fprintf(stderr, "pscan: out of memory.\n"); | |
exit(1); | |
} | |
/* prepare ping16() to fire up... T minus one second! */ | |
signal(SIGALRM, ping16); | |
alarm(1); | |
/* pseudo-infinite loop to watch for icmp echo replies */ | |
for (;;) { | |
struct sockaddr_in from; | |
int cc, fromlen; | |
fromlen = sizeof(from); | |
if ((cc = recvfrom(s, (char *)packet, packlen, 0, | |
(struct sockaddr *)&from, &fromlen)) < 0) { | |
if (errno == EINTR) continue; | |
perror("pscan: recvfrom"); | |
continue; | |
} else { | |
offset = ntohl(from.sin_addr.s_addr) - ntohl(ipstart); | |
if ((offset > 0) && (offset < 255)) { | |
gettimeofday(&(recvd[offset]), (struct timeval *)NULL); | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment