Skip to content

Instantly share code, notes, and snippets.

@codemonkey2841
Created December 16, 2014 04:27
Show Gist options
  • Save codemonkey2841/84b6fb4049efb2893cbc to your computer and use it in GitHub Desktop.
Save codemonkey2841/84b6fb4049efb2893cbc to your computer and use it in GitHub Desktop.
A parallelized ping scanner
/********************************************************************/
/* 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