I'm programming a multi-threaded, simple port scanner to try and familiarize myself with multi-threading, and I've run into a problem. I'm passing a pointer to a struct(Allocated on the heap) as the argument, then dereferencing the pointer in the thread callback and trying to use it to pass info to the thread, such as IP, ports and so on. However, I *think* the threads are segfaulting when it tries to dereference the pointer, but I can't really debug it, as I've never debugged threads and even when I tried doing so with gdb in codeblocks, it seemed to return fine.
The way it 'doesn't work' is basically by not even printing the sPort and ePort variables, or anything else after that, as if it's shut down.
Here's the code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>
#define ecs() EnterCriticalSection(&cSection);
#define lcs() LeaveCriticalSection(&cSection);
struct sInfo
{
unsigned int startPort;
unsigned int noPorts;
char *host;
};
CRITICAL_SECTION cSection;
__stdcall void scanThread(void * Param)
{
struct sockaddr_in remoteHost;
struct sInfo sinfo = *((struct sInfo*)Param); // Dereferencing the pointer. Wrong ? Cast to struct pointer, dereference pointer?
int sPort = sinfo.startPort,
ePort = sPort + sinfo.noPorts,
theSocket;
WSADATA wsaData;
WSAStartup(MAKEWORD(2,0), &wsaData);
ecs();
printf("Starting port: %d\n", sPort);
lcs();
remoteHost.sin_family = AF_INET;
if ((remoteHost.sin_addr.s_addr = inet_addr(sinfo.host)) == -1)
{
ecs();
printf("Could not resolve host.\n");
lcs();
_endthreadex(0);
}
memset(remoteHost.sin_zero, 0, 8);
theSocket = socket(AF_INET, SOCK_STREAM, 0);
if (theSocket == INVALID_SOCKET)
{
ecs();
printf("Could not create socket: %d\n", WSAGetLastError());
lcs();
_endthreadex(0);
}
for (; sPort < ePort; sPort++)
{
remoteHost.sin_port = htons(sPort);
if (connect(theSocket, (struct sockaddr*)&remoteHost, sizeof(struct sockaddr)))
{
ecs();
printf("Port %d: CLOSED\n", sPort);
lcs();
}
else
{
printf("Port %d: OPEN\n", sPort);
}
}
closesocket(theSocket);
WSACleanup();
_endthreadex(0);
}
int main(int argc, char **argv)
{
if (argc < 4)
{
printf("Usage:\n"\
"\tportscanner IP STARTPORT ENDPORT [NO.THREADS]\n\n");
return 0;
}
int startPort = atoi(argv[2]), endPort = atoi(argv[3]),
portsPerThread, noThreads = 5, i = 0, x = 0;
HANDLE *threadHandles;
if (startPort > endPort)
{
printf("The start port must be smaller than the end port.\n");
return 0;
}
if (argc >= 5) noThreads = atoi(argv[4]);
threadHandles = malloc(noThreads * sizeof(HANDLE));
portsPerThread = ((endPort - startPort)+1) / noThreads;
printf("Number of threads: %d\n"
"Ports per thread: %d\n", noThreads, portsPerThread);
// Array of pointers to struct sInfo.
struct sInfo *scanInfo[noThreads];
InitializeCriticalSection(&cSection);
for (i = 0; x < noThreads; i += portsPerThread )
{
// Allocate memory at each pointer.
scanInfo[x] = malloc(sizeof(struct sInfo));
scanInfo[x]->noPorts = portsPerThread;
scanInfo[x]->host = malloc(sizeof(char) * 100);
strcpy(scanInfo[x]->host, argv[1]);
scanInfo[x]->startPort = i;
threadHandles[x++] = (HANDLE)_beginthreadex(NULL,
0,
scanThread,
(void*)scanInfo[x], // Pass pointer to thread, here. 0,
NULL);
}
WaitForMultipleObjects(noThreads,
threadHandles,
TRUE,
INFINITE);
free(threadHandles);
for(i = 0; i < noThreads; i++)
{
free(scanInfo[x]->host);
free(scanInfo[x]);
}
//free(scanInfo);
DeleteCriticalSection(&cSection);
return 1;
}