#include #include #include #include #include #include #include "config.h" /* Network includes */ #include "netconfig.h" #include "functions.h" #include #define PACKSIZE IP_MAXPACKET extern struct host *ToPing; extern struct host *Head; extern u_short NumPings; extern u_long NumAlive; extern int FlgDebug; extern int FlgExtraDebug; extern int RawSock; extern fd_set RawFD; extern u_long NumToPing; extern u_long TO; extern pid_t PidSender; extern int errno; /* * This function sweeps numhosts out of the ToPing list * with NumPings ICMP packets. When a packet is received, ToPing.alive * is incremented. */ void pingsweep(int numhosts) { char recvpack[IP_MAXPACKET]; char outpack[sizeof(struct icmp)]; int n, i, cc, ss; struct timeval now; struct timeval start; struct timeval to; register struct icmp *icp = (struct icmp *)outpack; register struct ip *sip; register struct icmp *sicp; u_short seq; cc = sizeof(struct icmp); for(n=0; n < NumPings; n++){ for(i=0; i< numhosts; i++){ bzero(outpack, PACKSIZE); if(n == 0) ToPing[i].alive=0; /* If we've ping'ed and they've responded, skip doing it again */ if(n != 0 && ToPing[i].alive != 0) continue; icp->icmp_type = ICMP_ECHO; icp->icmp_id = PidSender; icp->icmp_seq = i; icp->icmp_cksum = 0; icp->icmp_cksum = ip_cksum((u_short *) icp, cc); ss=sendto(RawSock, outpack, cc, 0, (struct sockaddr *) &ToPing[i].sad, sizeof(ToPing[i].sad)); if(ss != cc) fprintf(stderr, "Problem sending full packet\n"); } /* End sending packets */ FD_ZERO(&RawFD); gettimeofday(&start, NULL); now.tv_sec = start.tv_sec; now.tv_usec = start.tv_usec; do { FD_SET(RawSock, &RawFD); to.tv_sec = (TO % 1000000); to.tv_usec = (TO % 1000000); ss = select(FD_SETSIZE, &RawFD, NULL, NULL, &to); if(ss <= 0){ if(ss < 0) fprintf(stderr, "select error: %s\n", strerror(errno)); /* If we timeout or err, set increment time counter */ gettimeofday(&now, NULL); continue; } /* If we didn't timeout, reset timers */ gettimeofday(&start, NULL); now.tv_sec = start.tv_sec; now.tv_usec = start.tv_usec; ss = read(RawSock, &recvpack, sizeof(recvpack)); if(ss > 0 && ss <= 20){ fprintf(stderr, "Unusually small packet. Possible attack\n"); continue; } sip = (struct ip *) recvpack; if(sip->ip_p == IPPROTO_ICMP){ sicp = (struct icmp *) ( recvpack + (sip->ip_hl << 2)); if(sicp->icmp_type == ICMP_ECHOREPLY && sicp->icmp_id == PidSender){ if(sip->ip_src.s_addr == ToPing[sicp->icmp_seq].sad.sin_addr.s_addr) { seq = sicp->icmp_seq; ToPing[seq].alive++; } } } } while(TIMEVAL_SUBTRACT(now, start) < TO); } /* End for loop */ process_alive(numhosts); NumToPing = 0; } /* * We call this to build our linklist of hosts that responded to ping. These * are the host we'll try our nefarious against to see if they are infected */ void process_alive(int num_hosts) { struct host *newentry; int i; for(i=0; i=1){ NumAlive++; if(ToPing[i].alive > 1){ printf("Smurf: %s (%d replies)\n", inet_ntoa(ToPing[i].sad.sin_addr), ToPing[i].alive); } newentry = (struct host *)malloc(sizeof(struct host)); memcpy(newentry, &ToPing[i].sad, sizeof(struct host)); if(newentry==NULL) perror("Malloc error"), exit(FAILURE); newentry->Next=NULL; if(Head==NULL){ Head=newentry; } else { newentry->Next=Head; Head=newentry; } } } /* End for */ } /* Standard checksum routine */ inline unsigned short ip_cksum(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); } /* Debugging function - prints linklist of alive hosts */ void printlist() { struct host *current; current = Head; printf("List of alive hosts:\n"); while(current){ printf("\t%s\n", inet_ntoa(current->sad.sin_addr)); current=current->Next; } }