AUTOPORTFIND source code example

This section provides an example of the source code to produce the port number for tunnelling with ssh.

This script should compile with little or no modification and does not need to be run as root.
Autoportfind.c/*
Written by John A. Hobach, Dallas Texas, May 5th, 2004
The purpose of the application is to return a port number that
will not be used for awhile.  This port number can then be used
by the Genero client for port forwarding.
The operating system assigns ports in a round
robin fashion so the port assigned is unlikely to be used again
very soon.  This will give the GDC time to start ssh and use
that port.  The OS will automatically skip ports in use.
Revised 08/25/2004 Ver 2.1 to use bind() to get a port number
    assigned.  It is assigned a port automatically from the
    operating system and we immediatly get it and return it.       
    Revised 10/25/2005 Ver 2.2 to support returning a port number
    within a given range.  This is accomplished by requesting ports
    from the OS until it is within the range specified.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h> 
#define USE_SOCKETS
#include "util.h"
char *progname; 
static char *ver="autoportfind - Version 2.2, 2005-10-20"; 
static char *help=
"autoportfind [OPTION]\n"
"\n"
"Generate a port number for use with port forwarding.\n"
"\n"
"    -e, --env\n"
"           Send FJSPORTFORWARD=<port> to stdout.\n"
"\n"
"    -r     Cycle through port assignments to determine which ports\n"
"           the OS assigns to ports when originating connections.\n"
"    -u n   Upper limit. Request port numbers until one is returned\n"
"           below 'n'.\n"
"    -l n   Lower limit. Request port numbers until one is returned\n"
"           above 'n'.\n"
"    -h     Display this help message.\n"
"    -v     Display the version number.\n"
; 
main(int argc, char **argv) {
      int sockfd, connected_socket, retval;
      int size, x, outofrange;
      int range_flag=0, env_flag=0;
      unsigned int      port, startport, highest,
                  lowest, cycle, direction,
                  llimit=0, ulimit=~0;
      int reuse_addr=1;
      char **arg;
      struct sockaddr_in serv_addr;
      progname=argv[0];
      arg=argv;
      while (--argc) {
            ++arg;
            if (!strcmp(*arg,"-r") || !strcmp(*arg,"--range")) {
                  range_flag=1;
            } else if (!strcmp(*arg,"-e") || !strcmp(*arg,"--env")) {
                  env_flag=1;
            } else if (!strcmp(*arg,"-u")) {
                  ++arg;
                  if (argc == 1 || *arg[0] == '-') {
                        fprintf(stderr,"%s: Value missing for -u\n",progname);
                        exit(1);
                  }
                  --argc;
                  ulimit=atol(*arg);
            } else if (!strcmp(*arg,"-l")) {
                  ++arg;
                  if (argc == 1 || *arg[0] == '-') {
                        fprintf(stderr,"%s: Value missing for -l\n",progname);
                        exit(1);
                  }
                  --argc;
                  llimit=atol(*arg);\
            } else if (!strcmp(*arg,"-v")) {
                  printf("%s\n",ver);
                  exit(0);
            } else if (!strcmp(*arg,"-h") || !strcmp(*arg,"--help")) {
                  printf("%s",help);
                  exit(0);
            } else {
                  fprintf(stderr,"%s:Unknown argument '%s'\n",
                    progname, *arg);
                  exit(1);
            }
      }
      lowest=~0;
      highest=0;
      startport=0;
      cycle=0;
      direction=1;
       do {
            outofrange=0;
            memset((char*) &serv_addr,0,sizeof(serv_addr));
            serv_addr.sin_family=AF_INET;
            serv_addr.sin_port=0;         /* allow system to assign */
            serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
 sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (sockfd < 0) {
                  perror("socket");
                  close(sockfd);
                  exit(1);
            }
 if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) {
                  perror("bind");
                  close(sockfd);
                  exit(1);
            }
 size=sizeof(serv_addr);
            if (getsockname(sockfd, (struct sockaddr *) &serv_addr,
              &size) == -1) {
                  perror("getsockname");
                  exit(errno);
            }
 if (range_flag) {
                  port=ntohs(serv_addr.sin_port);
 if (!startport) startport=port;
                  if (port > highest) highest=port;
                  if (port < lowest) lowest=port;
 if (direction==0 && port <= startport) {
                        cycle++;
                        direction=1;
                  } else if (direction==1 && port >= startport) {
                        cycle++;
                        direction=0;
                  }
 } else {
                  port=ntohs(serv_addr.sin_port);
 if (port > llimit && port < ulimit) {
                        if (env_flag) printf("FJSPORTFORWARD=");
                        printf("%d\n",ntohs(serv_addr.sin_port));
                  } else
                        outofrange=1;
            }
 close(sockfd);
 } while ((range_flag && cycle < 3) || outofrange);
 if (range_flag)
            printf("Lowest port: %lu\nHighest port: %lu\n",lowest,highest);
 exit(0);
}
 
---
Util.h
#ifndef UTIL_H
#define UTIL_H
#ifndef MAX
#  define MAX(a,b) a>b?a:b
#endif
#ifdef USE_SOCKETS
#  ifdef _WIN32
#    include <winsock.h>
#  else
#    include <sys/types.h>
#    include <sys/socket.h>
#    include <netinet/in.h>   /* struct sockaddr_in, ... */
#    include <netinet/tcp.h>  /* TCP_NODELAY, ... */
#    include <arpa/inet.h>    /* inet_addr, inet_ntoa, inet_aton */
#    include <netdb.h>        /* gethostbyname */
#  endif
#endif
 
#ifdef _WIN32
#  define SOCKLEN_T int
#endif
 
#ifdef __osf__
#  define SOCKLEN_T int
#endif
 
#ifdef _AIX
#  ifdef USE_SOCKETS
#   include <sys/ioctl.h>
#   include <sys/time.h>
#   include <sys/select.h>
#  endif
# define SOCKLEN_T socklen_t
#endif
 
#if defined  (M_I386)
/*  SCO */
#  ifdef USE_SOCKETS
#    include <sys/ioctl.h>
#    include <sys/time.h>
#    include <sys/select.h>
#  endif
#  define SOCKLEN_T int
#endif
 
#ifdef linux
#  define SOCKLEN_T socklen_t
#endif
 
#ifdef sun
#  if defined USE_SOCKETS
#    undef USE_SYS_SOCKIO
#    define USE_SYS_SOCKIO
#  endif
#  define SOCKLEN_T  int
#endif
 
#ifdef __hpux
#  define SOCKLEN_T int
#endif
 
#ifndef SOCKLEN_T
#  define SOCKLEN_T size_t
#endif
 
#ifndef MSG_DONTWAIT
#  define MSG_DONTWAIT 0
#endif
 
#endif