Writing a Small Port Checker in C in 40 Lines (or Less)

by Pantos

It happens.

You need to be able to check a single port, or perhaps many, but for some strange reason you:

  • Do not have a port checker on the system and cannot get one.
  • But, you do have a C compiler available.

The scenario usually plays out when you're a regular user, on a system without package management, or do not have the needed libraries to compile a scanner.

The fix: write a single port single host port check program in C.

So easy to do, it isn't funny.  Additionally, know inghow to do this could pay off in other areas such as if you wrote your own server and would like a cheap check or a pre-connect check.

Pre-requisites for a quick and dirty (and I do mean dirty) scanner are simple:

For argument's sake (ha ha) we will make the usage like so: program <port> <address>

That's it.

No libraries, no make, just those three very simple items.  Even though this program will only check one port and host at a time, I will demonstrate a simple wrapper script that turns it into a full-blown scanner.

First, the code.

Let's knock out the header files first:

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

We could go into what all those are for, but we won't.

Suffice it to say, they do the job.  There is only one routine in this tiny fellow, main(), so let's setup the program:

int main (int argc, char **argv)
{
  u_short port;         /* user specified port number */
  char addr[1023];      /* will be a copy of address entered by u */
  struct sockaddr_in address;   /* the libc network address data structure */
  short int sock = -1;      /* file descriptor for the network socket */

So far, so good.

It is worth noting that we need a file descriptor for the socket.  Socket programming comes from UNIX, where "everything is a file."  With this descriptor we open a "network connection" to the address via the specified port.

Now, onto setting up the information, here is the next chunk of code:

  port = atoi (argv[1]);
  strncpy(addr, argv[2], 1023);
  bzero ((char *) &address, sizeof (address));  /* init addr struct */
  address.sin_addr.s_addr = inet_addr (addr);   /* assign the address */
  address.sin_port = htons (port);      /* translate int2port num */

Let's have a closer look...

Using libc string utilities, we convert the ASCII to a number:

port = atoi (argv[1]);

Next, we copy in the address specified to the addr character array:

strncpy(addr, argv[2], 1023);

Now we clear out the network data structure, then set the the address to be checked.

The inet_addr (addr) function converts the string to an internal address for the libraries to use:

  bzero ((char *) &address, sizeof (address));  /* init addr struct */
  address.sin_addr.s_addr = inet_addr (addr);   /* assign the address */

And finally, we set the port to connect to:

 address.sin_port = htons (port);      /* translate int2port num */

Pretty cool, huh?

Now it is time to make the connection.  The next bit of code looks a little crazy, but this is w hat we are doing:

  1. Open the master socket locally.
  2. Try to connect to host by port.  If it works, print the successful message.
  3. If no route, then complain with vulgarity (it is just a rapid prototype after all).
  sock = socket (AF_INET, SOCK_STREAM, 0);
  if (connect (sock, (struct sockaddr *) &address, sizeof (address)) == 0)
    printf ("%i is open on %s\n", port, argv[2]);
  if (errno == 113)
    fprintf (stderr, "F*^k - no route to host\n");

All that is left is to close the socket and exit:

  close (sock);
  return 0;
}

Now it is time to compile and use the program:

$ cc myscan.c -o myscan
$ host www.2600.com
www.2600.com has address 184.105.226.26
$ ./myscan 80 184.105.226.26
80 is open on 184.105.226.26

Pretty sweet, eh?

But what if we wanted to scan many ports?  Easy enough to do in Perl.  In the same directory, create a Perl wrapper like this:

#!/usr/bin/env perl
$host = $ARGV[0];
for ($i = 1; $i <= 1024; $i++) {
  system("./myscan $i $host");
}

Of course, feel free to wrap it with any scripting language you like.  This program does have a few weaknesses I left out for brevity:

For the time being, I leave those up to the bored to look into, but for a quick and dirty port-checker, this program will do the job and can be run as a regular user.

C programming and network programming are not voo-doo.  Small, efficient programs are often very easy to write, once one gets into the habit, and make for lots of hacking fun.  Enjoy.

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

int main(int argc, char **argv)
{
  u_short port;                 /* user specified port number */
  char addr[1023];              /* will be a copy of address entered by u */
  struct sockaddr_in address;   /* the libc network address data structure */
  short int sock = -1;          /* file descriptor for the network socket */
  port = atoi(argv[1]);
  /* addr = strncpy(addr, argv[2], 1023); */
  strncpy(addr, argv[2], 1023);
  bzero((char *) &address, sizeof(address));    /* init addr struct */
  address.sin_addr.s_addr = inet_addr(addr);    /* assign the address */
  address.sin_port = htons(port);       /* translate int2port num */
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (connect(sock, (struct sockaddr *) &address, sizeof(address)) == 0)
    printf("%i is open on %s\n", port, argv[2]);
  if (errno == 113)
    fprintf(stderr, "F*^k - no route to host\n");
  close(sock);
  return 0;
}

Code: myscan.c

Return to $2600 Index