'Scan for Open ports

I tried to scan for open ports on my ip using following snippet, it is taking more than 20 mins to complete but I need things to be done in less than a minute.

- (void)scanForOpenPorts
{
    struct hostent *host;
    int err, i, sock;
    char hostname[100] = "192.168.1.17";
    struct sockaddr_in sa;
    
    //Initialise the sockaddr_in structure
    memcpy((char*)&sa , "" , sizeof sa);
    sa.sin_family = AF_INET;
    
    //direct ip address, use it
    if(isdigit(hostname[0]))
    {
        printf("Doing inet_addr...");
        sa.sin_addr.s_addr = inet_addr(hostname);
        printf("Done\n");
    }
    //Resolve hostname to ip address
    else if( (host = gethostbyname(hostname)) != 0)
    {
        printf("Doing gethostbyname...");
        memcpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);
        printf("Done\n");
    }
    else
    {
        herror(hostname);
        exit(2);
    }
    
    //Start the port scan loop
    printf("Starting the portscan loop : \n");
    
    NSLog(@"Start Time: %@", [NSDate date]);
    
    for(i = 0; i <= 65536; i++)
    {
        //Fill in the port number
        sa.sin_port = htons(i);
        //Create a socket of type internet
        sock = socket(AF_INET , SOCK_STREAM , 0);
        
        //Check whether socket created fine or not
        if(sock < 0)
        {
            perror("\nSocket");
            exit(1);
        }
        //Connect using that socket and sockaddr structure
        err = connect(sock , (struct sockaddr*)&sa , sizeof sa);
        
        //not connected
        if( err < 0 )
        {
            //printf("%s %-5d %s\r" , hostname , i, strerror(errno));
            fflush(stdout);
        }
        //connected
        else
        {
            printf("%-5d open\n",  i);
        }
        
        close(sock);
    }
    
    NSLog(@"End Time: %@", [NSDate date]);
    
    printf("\r");
    fflush(stdout);
}


Solution 1:[1]

You are using sockets in blocking mode, and testing the ports one at a time in a serial manner with no timeout on connect(). So, of course it is going to take a long time to scan such a large range of ports. You need to parallelize your code so you can connect to multiple ports at the same time, reducing the time it takes to scan the range of ports.

Use non-blocking sockets, with select() or poll() or equivalent providing a timeout for connect() (most platforms do not provide a way to specify a timeout for connect() in blocking mode, so you are subject to the socket stack's internal timeout).

Have multiple sockets connecting to a different port at the same time, either in individual worker threads, or at least in a select()/poll() loop.

Run a limited number of connects at any given time, so as not to overwhelm the device or the network. Start a few connects to begin. When any given socket has finished connecting to its current port, have that thread/slot choose the next available port, close+recreate its socket if needed, and try again. Repeat as needed until the range of ports has been exhausted.

Each time connect() fails without a timeout, you can reuse that same socket for the next connect(), you do not need to close() it. But, if connect() succeeds, or fails with a timeout, you have to to close() that socket and create a new one for the next connect().

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Remy Lebeau