[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-logonpy/usr/share/se3/src/ -> tcpcheck.c (source)

   1  /*
   2   * tcpcheck.c - checks to see if a TCP connection can be established
   3   *              to the specified host/port.  Prints a success message
   4   *              or a failure message for each host.
   5   *
   6   * Think of it as 'fping' for TCP connections.  Maximum
   7   * parallelism.
   8   *
   9   * Designed to be as non-blocking as possible, but DNS FAILURES WILL
  10   * CAUSE IT TO PAUSE.  You have been warned.
  11   *
  12   * Timeout handling:
  13   * 
  14   * Uses the depricated alarm() syntax for simple compatability between
  15   * BSD systems.
  16   *
  17   * Copyright (C) 1998 David G. Andersen <angio@aros.net>
  18   *
  19   * This information is subject to change without notice and does not
  20   * represent a commitment on the part of David G. Andersen
  21   * This software is furnished under a license and a nondisclosure agreement.
  22   * This software may be used or copied only in accordance with the terms of
  23   * this agreement.  It is against Federal Law to copy this software on magnetic
  24   * tape, disk, or any other medium for any purpose other than the purchaser's
  25   * use.  David G. Andersen makes no warranty of any kind, expressed
  26   * or implied, with regard to these programs or documentation.  David G. 
  27   * Andersen shall not be liable in any event for incidental or consequential
  28   * damages in connection with, or arising out of, the furnishing, performance,
  29   * or use of these programs.
  30   */
  31  
  32  
  33  #include <unistd.h>
  34  #include <stdio.h>
  35  #include <stdlib.h>
  36  #include <string.h>
  37  #include <sys/types.h>
  38  #include <sys/time.h>
  39  #include <sys/socket.h>
  40  #include <netinet/in.h>
  41  #include <netdb.h>
  42  #include <errno.h>
  43  #include <fcntl.h>
  44  #include <signal.h>
  45  #include <time.h>
  46  
  47  #define ERR_SUCCESS 0
  48  #define ERR_REFUSED 1
  49  #define ERR_TIMEOUT 2
  50  #define ERR_OTHER   3
  51  
  52  #define MAXTRIES 220;  /* Max number of connection attempts we can
  53                try at once.  Must be lower than the
  54                max number of sockets we can have open... */
  55  
  56  int numcons;
  57  int consused; /* Number actually used */
  58  int timeout = 20; /* 20 second default timeout */
  59  struct connectinfo **cons;
  60  
  61  struct connectinfo {
  62    char *hostname;
  63    char *portname;
  64    short port;
  65    int status;
  66    int socket;
  67    struct sockaddr_in *sockaddr;
  68    int socklen;
  69  };
  70  
  71  /*
  72   * setupsocket:  Configures a socket to make it go away quickly:
  73   *
  74   * SO_REUSEADDR - allow immediate reuse of the address
  75   * not SO_LINGER - Don't wait for data to be delivered.
  76   */
  77  
  78  int setupsocket(int sock) {
  79    int flags;
  80    struct linger nolinger;
  81  
  82    nolinger.l_onoff = 0;
  83    if (setsockopt(sock, SOL_SOCKET,
  84           SO_LINGER, (char *) &nolinger, sizeof(nolinger)) == -1)
  85      return -1;
  86  
  87    flags = 1;
  88    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flags,
  89           sizeof(flags)) == -1)
  90      return -1;
  91  
  92    /* Last thing we do:  Set it nonblocking */
  93  
  94    flags = O_NONBLOCK | fcntl(sock, F_GETFL);
  95    fcntl(sock, F_SETFL, flags);
  96    
  97    return 0;
  98  }
  99  
 100  /*
 101   * setuphost:  Configures a struct connectinfo for
 102   *             connecting to a host.  Opens a socket for it.
 103   *
 104   * returns 0 on success, -1 on failure
 105   */
 106  
 107  int setuphost(struct connectinfo *cinfo, char *hostport)
 108  {
 109    struct hostent *tmp;
 110    char *port;
 111    struct servent *serv;
 112  
 113    if (!hostport) {
 114      fprintf(stderr, "null hostname passed to setuphost.  bailing\n");
 115      exit(-1);
 116    }
 117  
 118    port = strchr(hostport, ':');
 119    if (!port || *(++port) == 0) {
 120      return -1;
 121    }
 122  
 123    if (port[0] < '0' || port[0] > '9') {
 124      serv = getservbyname(port, "tcp");
 125      if (!serv) {
 126        return -1;
 127      }
 128      cinfo->port = ntohs(serv->s_port);
 129    } else {
 130      cinfo->port = atoi(port);
 131    }
 132    cinfo->portname = strdup(port);
 133  
 134    cinfo->hostname = strdup(hostport);
 135    port = strchr(cinfo->hostname, ':');
 136    *port = 0;
 137    
 138    tmp = gethostbyname(cinfo->hostname);
 139  
 140    /* If DNS fails, skip this puppy */
 141    if (tmp == NULL) { 
 142      cinfo->status = -1;
 143      return -1;
 144    }
 145  
 146    cinfo->status = 0;
 147  
 148    /* Groovy.  DNS stuff worked, now open a socket for it */
 149    cinfo->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 150    if (cinfo->socket == -1) {
 151      return -1;
 152    }
 153  
 154    /* Set the socket stuff */
 155    setupsocket(cinfo->socket);
 156    
 157    cinfo->socklen = sizeof(struct sockaddr_in);
 158    cinfo->sockaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
 159    bzero(cinfo->sockaddr, cinfo->socklen);
 160  
 161    bcopy(tmp->h_addr_list[0],
 162      &(cinfo->sockaddr->sin_addr),
 163      sizeof(cinfo->sockaddr->sin_addr));
 164  #ifdef DA_HAS_STRUCT_SINLEN
 165    cinfo->sockaddr->sin_len = cinfo->socklen;
 166  #endif
 167    cinfo->sockaddr->sin_family = AF_INET;
 168    cinfo->sockaddr->sin_port = htons(cinfo->port);
 169    
 170    return 0;
 171  }
 172  
 173  void usage()
 174  {
 175    fprintf(stderr, "usage:  tcpcheck <timeout> <host:port> [host:port]\n");
 176    exit(1);
 177  }
 178  
 179  void wakeme(int sig)
 180  {
 181    printf("Got a timeout.  Will fail all outstanding connections.\n");
 182    exit(ERR_TIMEOUT);
 183  }
 184  
 185  void goodconnect(int i) {
 186    printf("%s:%s is alive\n", cons[i]->hostname, cons[i]->portname);
 187    cons[i]->status = 1;
 188    close(cons[i]->socket);
 189  }
 190  
 191  void failedconnect(int i) {
 192    printf("%s:%s failed\n", cons[i]->hostname, cons[i]->portname);
 193    cons[i]->status = -1;
 194  }
 195  
 196  
 197  /*
 198   * utility function to set res = a - b
 199   * for timeval structs
 200   * Assumes that a > b
 201   */
 202  
 203  void subtime(struct timeval *a, struct timeval *b, struct timeval *res)
 204  {
 205  
 206    res->tv_sec = a->tv_sec - b->tv_sec;
 207    if (b->tv_usec > a->tv_usec) {
 208      a->tv_usec += 1000000;
 209      res->tv_sec -= 1;
 210    }
 211    res->tv_usec = a->tv_usec - b->tv_usec;
 212  }
 213  
 214  /*
 215   * set up our fd sets
 216   */
 217  
 218  void setupset(fd_set *theset, int *numfds)
 219  {
 220    int i;
 221    int fds_used = 0;
 222    
 223    *numfds = 0;
 224    for (i = 0; i < numcons; i++) {
 225      if (cons[i] == NULL) continue;
 226      if (cons[i]->status == 0 && cons[i]->socket != -1) {
 227        FD_SET(cons[i]->socket, theset);
 228        fds_used++;
 229        if (cons[i]->socket > *numfds)
 230      *numfds = cons[i]->socket;
 231      }
 232    }
 233    if (!fds_used) {
 234      exit(0);            /* Success! */
 235    }
 236  }
 237  
 238  /*
 239   * We've initiated all connection attempts.
 240   * Here we sit and wait for them to complete.
 241   */
 242  
 243  
 244  void waitforconnects()
 245  {
 246    fd_set writefds, exceptfds;
 247    struct timeval timeleft;
 248    struct timeval starttime;
 249    struct timeval curtime;
 250    struct timeval timeoutval;
 251    struct timeval timeused;
 252    struct sockaddr_in dummysock;
 253    int dummyint = sizeof(dummysock);
 254    int numfds;
 255    int res;
 256    int i;
 257  
 258    gettimeofday(&starttime, NULL);
 259  
 260    
 261    timeoutval.tv_sec = timeout;
 262    timeoutval.tv_usec = 0;
 263  
 264    timeleft = timeoutval;
 265    
 266    while (1)
 267    {
 268      FD_ZERO(&writefds);
 269      FD_ZERO(&exceptfds);
 270      setupset(&writefds, &numfds);
 271      setupset(&exceptfds, &numfds);
 272      res = select(numfds+1, NULL, &writefds, &exceptfds, &timeleft);
 273  
 274      if (res == -1) {
 275        perror("select barfed, bailing");
 276        exit(-1);
 277      }
 278  
 279      if (res == 0)        /* We timed out */
 280        break;
 281  
 282      /* Oooh.  We have some successes */
 283      /* First test the exceptions */
 284  
 285      for (i = 0; i < numcons; i++)
 286      {
 287        if (cons[i] == NULL) continue;
 288        if (FD_ISSET(cons[i]->socket, &exceptfds)) {
 289      failedconnect(i);
 290        } else if (FD_ISSET(cons[i]->socket, &writefds)) {
 291      /* Boggle.  It's not always good.  select() is weird. */
 292      if (getpeername(cons[i]->socket, (struct sockaddr *)&dummysock,
 293              &dummyint))
 294        failedconnect(i);
 295      else
 296        goodconnect(i);
 297        }
 298      }
 299      
 300      /* now, timeleft = timeoutval - timeused */
 301        
 302      gettimeofday(&curtime, NULL);
 303      subtime(&curtime, &starttime, &timeused);
 304      subtime(&timeoutval, &timeused, &timeleft);
 305    }
 306  
 307    /* Now clean up the remainder... they timed out. */
 308    for (i = 0; i < numcons; i++) {
 309      if (cons[i]->status == 0) {
 310        printf("%s:%d failed:  timed out\n",
 311           cons[i]->hostname, cons[i]->port);
 312      }
 313    }
 314  }
 315  
 316  
 317  int main(int argc, char **argv) 
 318  {
 319    struct connectinfo *pending;
 320    int i;
 321    int res;
 322    
 323    signal(SIGALRM, wakeme);
 324  
 325    if (argc <= 2) usage();
 326    if (argv == NULL || argv[1] == NULL || argv[2] == NULL) usage();
 327  
 328    timeout = atoi(argv[1]);
 329  
 330    numcons = argc-2;
 331    cons = malloc(sizeof(struct connectinfo *) * (numcons+1));
 332    bzero((char *)cons, sizeof(struct connectinfo *) * (numcons+1));
 333  
 334    pending = NULL;
 335    consused = 0;
 336    
 337    /* Create a bunch of connection management structs */
 338    for (i = 2; i < argc; i++) {
 339      if (pending == NULL)
 340        pending = malloc(sizeof(struct connectinfo));
 341      if (setuphost(pending, argv[i])) {
 342        printf("%s failed.  could not resolve address\n", pending->hostname);
 343      } else {
 344        cons[consused++]  = pending;
 345        pending = NULL;
 346      }
 347    }
 348  
 349    for (i = 0; i < consused; i++) {
 350      if (cons[i] == NULL) continue;
 351      res = connect(cons[i]->socket, (struct sockaddr *)(cons[i]->sockaddr),
 352            cons[i]->socklen);
 353  
 354      if (res && errno != EINPROGRESS) {
 355        failedconnect(i);
 356      }
 357    }
 358  
 359    /* Okay, we've initiated all of our connection attempts.
 360     * Now we just have to wait for them to timeout or complete
 361     */
 362  
 363    waitforconnects();
 364    
 365    exit(0);
 366  }


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1