8
\$\begingroup\$

I have been writing a Simple Port scanner in C, once I got it to work I decided I wanted to make it faster because it takes a very long time for it to get done with scanning all of the ports.Is there anything I can improve on in my code to make it faster? Here is my Code :

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#define MAX 65536

int main(int argc, char ** argv)
{
    time_t begin, end;
    time(&begin);

    printf("Scanning ports 0 - 65535 for IP address : %s\n", argv[1]);

    FILE * file = fopen("/home/ether/Desktop/Projects/Ports_log.txt", "w");//open log file

    for (unsigned short port = 0; port < MAX; port++)//loop through and scan all ports
    {
        int Connection = socket(AF_INET,SOCK_STREAM, 0);
        sockaddr_in temp = { 0 };

        //fill the struct with information on the computer you wish to scan
        temp.sin_addr.s_addr = inet_addr(argv[1]);
        temp.sin_family = AF_INET;
        temp.sin_port = htons(port);

        int error = connect(Connection, (sockaddr*)&temp, sizeof temp);
        if(error != -1) 
        {
            //if the port is open then get information about that port and print it to the log file
            char host[128];
            char service[128];
            getnameinfo((sockaddr*)&temp, sizeof temp, host, (sizeof host), service, sizeof service, 0);
            printf("Port : %d, Service : %s, Open\n", port, service);
            fprintf(file, "Port : %d, Service : %s, Open\n", port, service);
        }
        close(Connection); //Destroy socket
    }
    fclose(file);//Close the file

    //calculate the time that elapsed since the program was started and rint it
    time(&end);
    double elapsed_secs = difftime(end, begin);
    printf("Elapsed Seconds : %lf", elapsed_secs);
    return 0;
}
\$\endgroup\$
3
  • \$\begingroup\$ Use non-blocking sockets and select/poll to handle a number of connect calls at the same time. \$\endgroup\$ – Aleksey Demakov Apr 1 '15 at 2:24
  • \$\begingroup\$ @AlekseyDemakov I've been looking at examples of how to use select with non blocking sockets and all I have found are some when you are accepting multiple clients which is not what I wan't to do. Do you have an example that you could link me to? \$\endgroup\$ – user3000477 Apr 2 '15 at 5:07
  • \$\begingroup\$ Why does it endlessly loop? And why does sometimes return different open ports? \$\endgroup\$ – elmazzun Dec 4 '16 at 6:07
6
\$\begingroup\$

After creating a socket make it non-blocking. Then call connect(). If connect returns 0 then the connection has been established and you can use it already. If it retuned -1 and errno is equal to EINPROGRESS then you need to wait until it becomes write-ready using select() or poll(). When it becomes write-ready use getsockopt(sock, SOL_SOCKET, SO_ERROR, ...) to tell if the connection has failed or succeeded. The example code for using non-blocking connect is here:

http://developerweb.net/viewtopic.php?id=3196

But this sample shows waiting on single socket only. You need to wait on a bunch of them at the same time. So have a table of socket connections with some fixed size, e.g. 32:

#define MAX_CONNECT 32

struct socket_info {
    int sock;    /* the socket */
    int ready;   /* initialize to 0 when filling the table, set to 1 when the connection has established or failed */
    int error;   /* set to errno got with getsockopt() for failed connections, set to 0 if connection succeeded */
    sockaddr_in addr;
};

struct socket_info pending_connect[MAX_CONNECT];

First fill this table in a loop calling socket/connect. Then wait in another loop with select until all of the sockets become ready. Set appropriate flags in the table as the sockets become ready.

After the select loop you have info about 32 ports. Print it. Close the sockets. Then proceed with a next bunch of 32 ports.

This approach could be further optimised. You could close a socket as soon as you get info about it, print that info, and immediately open another socket in its place in the table. This will be faster but perhaps this also requires more careful coding.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.