Skip to content

Basic Port Scanning #7

Description

@niki-mardari

Open / Closed / Refused Port Scanner (Synchronous, Single-Threaded)

Description

This is a simple TCP port scanner written in C.
It performs synchronous scanning (no multithreading) and checks ports sequentially.

The program:

  • Resolves a host using getaddrinfo()
  • Iterates through a range of ports
  • Attempts a TCP connection
  • Reports:
    • Open ports
    • Closed (refused) ports
    • Other connection failures and error codes

Build

Compile using gcc:

gcc scanner.c -o scanner

Usage

./scanner <host>

Example:

./scanner gagool.com

Source Code

// LIBC header for I/O fprintf()
#include <stdio.h>

// LIBC header for memory control and error handling
#include <stdlib.h>

// LIBC header for string manipulation functionality memset()
#include <string.h>

// POSIX header for protocol definitions for getaddrinfo(), struct addrinfo, gai_strerror()
#include <netdb.h>

// POSIX header for handling numerical IP addresses for inet_ntop()
#include <arpa/inet.h>

// POSIX header for socket definitions for struct sockaddr_in
#include <sys/socket.h>

// POSIX header for miscellaneous symbolic constants and types like NULL
#include <unistd.h>

// POSIX header for error number definitions for errno
#include <errno.h>

// POSIX header for fixed width integer types for uint16_t
#include <stdint.h>

int main(int argc, char **argv) {

    // check if an argument was passed for host
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <host domain>\n", argv[0]);
        return EXIT_FAILURE;
    }

    /*
     * hint: hints of the type of address or format we expect
     * res: linked list iterator
     * res0: linked list head of all found responses
     */
    struct addrinfo hint, *res, *res0;
    int error; // return code holder for getaddrinfo()

    memset(&hint, 0, sizeof(hint));

    // set our hints:
    hint.ai_family = AF_INET;        // IPv4
    hint.ai_protocol = IPPROTO_TCP;  // TCP protocol

    // attempt to retrieve linked list of resolutions
    error = getaddrinfo(argv[1], NULL, &hint, &res0);
    if (error) {
        fprintf(stderr, "Error: %s\n", gai_strerror(error));
        return EXIT_FAILURE;
    }

    // iterate through linked list
    for (res = res0; res; res = res->ai_next) {

        char ip_str[INET_ADDRSTRLEN];

        // cast to sockaddr_in
        struct sockaddr_in *psockaddr =
            (struct sockaddr_in *)res->ai_addr;

        if (inet_ntop(psockaddr->sin_family,
                      &(psockaddr->sin_addr),
                      ip_str,
                      sizeof(ip_str)) == NULL) {
            fprintf(stderr, "Failed to convert IP to string!\n");
            continue;
        }

        // Cycle through ports
        for (uint16_t port = 4990; port <= 65535; port++) {

            // Set port
            psockaddr->sin_port = htons(port);

            // Create socket
            int fd = socket(res->ai_family,
                            res->ai_socktype,
                            res->ai_protocol);
            if (fd == -1) continue;

            // Attempt connection
            int rc = connect(fd, res->ai_addr, res->ai_addrlen);

            if (rc == 0) {
                printf("Connection open  %s:%u\n", ip_str, port);
            } else {
                int saved_errno = errno;
                if (saved_errno == ECONNREFUSED) {
                    printf("Connection closed %s:%u (refused)\n",
                           ip_str, port);
                } else {
                    printf("Connection failed %s:%u (errno=%d)\n",
                           ip_str, port, saved_errno);
                }
            }

            close(fd);
        }
    }

    // free dynamically allocated memory
    freeaddrinfo(res0);

    return 0;
}

Notes

  • Single-threaded → slow for large scans.
  • Uses blocking connect().
  • IPv4 only (AF_INET).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions