Talguy 0 Junior Poster in Training

I have been coding an IP scanner for god knows what reason. The program kind of works. It does find active computers on the network but for some reason it does not find my computer using its network ip or its internal ip (127.0.0.1). Also it can not find any of my fios set top boxes. Ping is able to find every computer or device that is active on the network. Another problem I have been seeing with the program is that it finds the two active device that it is able to connect with right away then pause for a long long time (a minute or three) before printing out information about not being able to connect to ip x.x.x.x. I think part of this reason is due to not getting a lock to print to the console but i'm not sure this is the first time I'm using threads. I looked in the task manager and it shows 0% usage of the CPU when the program stalls. Could someone take a look at my code and suggest and changes or enhancements to it.

Thanks in advance

#include <string>
#include <sstream>
#include <iostream>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

void ipStrToInt(unsigned int (&ip)[4], std::string);
const std::string get_ip();
const std::string inttostr(const unsigned int);
void *scan(void *ptr);

unsigned int IP[4] = {0,0,0,0};
unsigned int beginIP[4] = {0,0,0,0};
unsigned int endIP[4] = {0,0,0,0};
unsigned int startPort=0, stopPort=0;
unsigned int thread_cnt = 0, upIPcnt = 0;
bool done = false, first = true;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t cntMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t prtMutex = PTHREAD_MUTEX_INITIALIZER;


int main(void) {
	std::string startIP, stopIP;
	std::string mPorts;
	
	std::cout << "Enter IP Range <start end> ";
	std::cin >> startIP >> stopIP;
	
	while(1) {
		std::cout << "Scan Multiple Ports (Y/N) ";
		std::cin >> mPorts;
		if(mPorts == "Y" || mPorts == "y") {
			std::cout << "Enter port range <start end> ";
			std::cin >> startPort >> stopPort;
			break;
		} else if(mPorts == "N" || mPorts == "n") {
			std::cout << "Setting scan port to default (80)\n";
			startPort = stopPort = 80;
			break;
		} else {
			std::cout << "Bad Input try again";
		}
	}
	
	// Parse begin IP
	ipStrToInt(beginIP, startIP);
	// Parse end IP
	ipStrToInt(endIP, stopIP);
	
	// Set IP to starting value
	IP[0] = beginIP[0];
	IP[1] = beginIP[1];
	IP[2] = beginIP[2];
	IP[3] = beginIP[3];
	
	const unsigned int max_threads = 100;
	pthread_t thread[100];
	
	while(thread_cnt < max_threads && !done) {
		pthread_create(&thread[thread_cnt], NULL, &scan, &thread_cnt);
			
		// Lock thread_cnt before incrementing
		pthread_mutex_lock(&cntMutex);
			thread_cnt++;
		pthread_mutex_unlock(&cntMutex);	
	}

	// wait for threads to finish before cleaning up
	for(unsigned int x=0; x < thread_cnt; ++x) {
		pthread_join(thread[x], NULL);
	}
	
	std::cout << "Finished\nNumber of Active IPs: " << upIPcnt << std::endl;
	
	pthread_mutex_destroy(&mutex);
	pthread_mutex_destroy(&cntMutex);
	pthread_mutex_destroy(&prtMutex);
	pthread_exit(NULL);
	
	return 0;	
}

void *scan(void *arg) {
	unsigned int port = startPort;
	std::string curIP = "";
	int sock, cnx;
	struct sockaddr_in host;
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock < 0) {
		std::cout << "ERROR: Could not open socket\n";
	} else {
		while(1) {
			pthread_mutex_lock(&mutex);
				curIP = get_ip(); // get the next ip address
			pthread_mutex_unlock(&mutex);
			
			if(curIP.empty()) {
				done = true;
				break;	
			}
			
			host.sin_family = AF_INET;
			host.sin_addr.s_addr = inet_addr(curIP.c_str());
			
			if(!curIP.empty()) {
				while(port <= stopPort) {
					host.sin_port = htons(port);
					
					cnx = connect(sock, (struct sockaddr*)&host, sizeof(host));
					pthread_mutex_lock(&prtMutex);
					if(cnx < 0) {
						std::cout << inet_ntoa(host.sin_addr) << " ... connection failed. Host possibly down\n";
					} else {
						std::cout << inet_ntoa(host.sin_addr) << " ... Host appears to be up.\n";
						
						pthread_mutex_lock(&cntMutex);
							upIPcnt++;
						pthread_mutex_unlock(&cntMutex);
					}
					pthread_mutex_unlock(&prtMutex);
					port++;	
				}
			}
		}
	}
	close(sock);

	// lock thread_cnt before decrementing
	pthread_mutex_lock(&cntMutex);
		thread_cnt--;
	pthread_mutex_unlock(&cntMutex);
	
	pthread_exit((void*)0);
}

void ipStrToInt(unsigned int (&ip)[4], std::string strIP) {
	int found=0, cnt=0;
	std::string temp;
	temp = strIP;
	
	found = temp.find_first_of(".");
	
	while(found != std::string::npos && cnt < 4) {
		if(found > 0) {
			ip[cnt] = (unsigned)atoi(temp.substr(0,found).c_str());
		}
		temp = temp.substr(found+1);
		found = temp.find_first_of(".");
		cnt++;
	}
	if(temp.length() > 0 && cnt < 4) {
		ip[cnt]	= atoi(temp.c_str());
	}
}

// Works
const std::string get_ip() {
	if(!first) {
		if(memcmp(&IP, &endIP, 4*sizeof(int)) != 0) {
			if(IP[3] == 255 || IP[3] == endIP[3]) {
				if(IP[2] == 255 || IP[2] == endIP[2]) {
					if(IP[1] == 255 || IP[1] == endIP[1]) {
						if(IP[0] <= 255 || IP[0] <= endIP[0]) {
							IP[0]++;
							IP[1] = IP[2] = IP[3] = 0;
						} else {
							return "";
						}
					} else {
						IP[1]++;
						IP[2] = IP[3] = 0;
					}
				} else {
					IP[2]++;
					IP[3] = 0;
				}
			} else {
				IP[3]++;	
			}
		} else {
			done = true;
			return "";
		}
	} else
		first = false;
	return inttostr(IP[0]) + "." + inttostr(IP[1]) + "." + inttostr(IP[2]) + "." + inttostr(IP[3]);
}

const std::string inttostr(const unsigned int x) {
    std::ostringstream o;
    if (!(o << x)) 
    	return "";
	return o.str();
}