Re: script to log into cisco csm load balancer

From: Darby Weaver (ccie.weaver@gmail.com)
Date: Fri Jan 23 2009 - 05:07:02 ARST


If you really need something that's quick and clean and does the job - is
free less your own blood sweat and tears...

Why not try: CNCT

It's been around since the day of the dog, but hey - simple, fast, and
efficient is a good thing in scripting and it is well documented:

/*
 * Program to connect to the telnet port of a Cisco router or terminal
 * server, log in, run a series of commands contained in a command file,
 * and log out. The session is displayed to stdout.
 *
 * Usage: cnct [-l] [-p <pw1>] [-e [<epw>]] [-c <cmd-file>] [--] <host>
 *
 * The command-line arguments are:
 *
 * host - the host name of the router or terminal server (required).
 * -l - if -l is specified then pw1 and epw are interpreted
 * as username and password respectively.
 *
 * pw1 - the first-level password for the router. If this argument
 * is not specified, the connection to the Cisco will fail
 * if a "Password:" prompt is received.
 *
 * epw - the "enable" password for the router. If the "-e" option
 * is specified, the "enable" command will be issued after
 * successful login (using the password specified with the "-p"
 * option if appropriate). If a "Password:" prompt is received
 * in response to the "enable" command and the "<epw>" argument
 * is not specified, the connection will fail.
 *
 * cmd-file - the file containing the list of Cisco commands that
 * will be executed after successful login (possibly at the
 * "enable" level). The command "terminal length 0" is
 * automatically entered if either or both of the "-p" and
 * "-e" options are specified, and need not be included in the
 * command file. This argument is optional. If not specified,
 * commands will be read from stdin. The "exit" command is
 * automatically issued to close the connection if EOF is
 * encountered when reading the command file or stdin.
 *
 * -- - Two consecutive hyphens indicates the end of the options
 * list. This allows the "-e" option to be specified without
 * a corresponding password so that enable mode can be entered
 * even if there is no enable password.
 *
 * For simplicity, the above arguments are used to build an initial login
 * command sequence that is sent to the Cisco without any attempt to parse
 * or otherwise interpret the response text from the Cisco. Thus, assuming
 * both the "-p" and "-e" options are specified, this is the command sequence
 * that will be sent to the Cisco:
 *
 * pw1
 * enable
 * epw
 * terminal length 0
 *
 * Assuming the above commands are successful, the contents of the command
 * file are sent to the Cisco, followed by an "exit" command. The program
 * then copies output from the Cisco to stdout until the Cisco closes the
 * connection, and then terminates. The exit status is two ("2") if the
 * connection times out, one ("1") if there are other problems, and zero
 * ("0") otherwise.
 *
 *
 * Written by: Dana J. Dawson
 * Sr. Network Analyst
 * Corporate Computing & Networks
 * Cray Research, Inc.
 * (612) 683-3056
 * dana@cray.com
 * March, 1993
 */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>

void usage(name)
char *name;
{
  fprintf(stderr,
        "USAGE: %s [-l] [-p <pw1>] [-e [<epw>]] [-c <cmd-file>] [--] <host>\n",
          name);
  exit(1);
}

main(argc, argv)
int argc;
char **argv;
{
  int c; /* temporary work variable */
  int n; /* temporary work variable */

  int enable = 0; /* flag for 'enable' mode */
  char *me = *argv; /* name of this executable */
  int user = 0; /* non-zero if user/passwd scenario */
  char *pw1 = NULL; /* first-level password string */
  char *epw = NULL; /* enable password string */
  char *cmdfile = NULL; /* name of command file */
  char *host = NULL; /* host name or IP address string */
  int nc; /* number of characters in "cmds" */
  char cmds[BUFSIZ]; /* buffer for initial login commands */
  char buf[BUFSIZ]; /* buffer for copying data and error messages */

  int s; /* file descriptor for socket */
  int cf = 0; /* file descriptor for input command file */
  int ceof = 0; /* EOF indicator for input command file */
  fd_set readset; /* read mask for "select()" */

  int dport = 23; /* destination port - "telnet" */
  unsigned long ipaddr; /* 32-bit numeric IP address of 'host' */
  struct hostent *hp; /* host information structure for 'host' */
  struct sockaddr_in dsa; /* socket address structure */
  struct timeval timeout; /* connection timeout structure */

/* First, figure out the command line arguments... */
/* It's not pretty, but it works (besides, I'm new at this) */

  while (--argc > 0) {
    switch (c = **++argv) {
    case '-':
            if (host != NULL) usage(me);
            switch (c = *++*argv) {
            case '-':
                    if (host != NULL || !--argc || *++*argv) usage(me);
                    host = *++argv;
                    break;
            case 'l':
                    if (user) usage(me);
                    user = 1;
                    break;
            case 'p':
                    if (pw1 != NULL || !--argc || *++*argv) usage(me);
                    pw1 = *++argv;
                    break;
            case 'e':
                    if (enable || !--argc || *++*argv) usage(me);
                    enable = 1;
                    epw = *++argv;
                    if (!strcmp(epw, "--") ||
                        !strcmp(epw, "-c") ||
                        !strcmp(epw, "-p") ) {
                      epw = NULL;
                      argc++;
                      argv--;
                    }
                    break;
            case 'c':
                    if (cmdfile != NULL || !--argc || *++*argv) usage(me);
                    cmdfile = *++argv;
                    break;
            default:
                    usage(me);
                    break;
            }
            break;
    default:
            if (host != NULL || --argc ) usage(me);
            host = *argv;
            break;
    }
  }

  if (host == NULL) usage(me);

  if (user && (!pw1 || !epw)) usage(me);

/* Now, open the input command file if it's not 'stdin'... */

  if ((cmdfile != NULL) && ((cf = open(cmdfile, O_RDONLY, 0)) == -1)) {
    sprintf(buf, "%s: Error opening command file for '%s'", me, host);
    perror(buf);
    exit(1);
  }

/* Figure out the IP address for 'host' and open the socket... */

  bzero((char *)&dsa, sizeof(dsa));

  if ((ipaddr = inet_addr(host)) == -1) { /* 'host' is not an IP address */
    if ((hp = gethostbyname(host)) == NULL) {
      sprintf(buf, "%s: Unknown host for '%s'", me, host);
      perror(buf);
      exit(1);
    }
    bcopy((char *)*hp->h_addr_list, (char *)&dsa.sin_addr.s_addr, hp->h_length);
  } else { /* 'host' was an IP address */
    dsa.sin_addr.s_addr = ipaddr;
  }

  dsa.sin_family = AF_INET;
  dsa.sin_port = htons(dport);

  if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    sprintf(buf, "%s: Error opening socket for '%s'", me, host);
    perror(buf);
    exit(1);
  }

  if (connect(s, &dsa, sizeof(dsa)) == -1) {
    sprintf(buf, "%s: Error connecting to socket for '%s'", me, host);
    perror(buf);
    exit(1);
  }

/* Build the login command sequence... */
  nc = 0;
  if (user) {
     nc += strlen(sprintf(&cmds[nc], "%s\n", pw1));
     nc += strlen(sprintf(&cmds[nc], "%s\n", epw));
     nc += strlen(sprintf(&cmds[nc], "login\n"));
     nc += strlen(sprintf(&cmds[nc], "%s\n", pw1));
     nc += strlen(sprintf(&cmds[nc], "%s\n", epw));
  } else {
     if (pw1 != NULL) {
        nc += strlen(sprintf(&cmds[nc], "%s\n", pw1));
     }
     if (enable) {
        nc += strlen(sprintf(&cmds[nc], "enable\n"));
     }
     if (epw != NULL) {
        nc += strlen(sprintf(&cmds[nc], "%s\n", epw));
     }
  }
  if (nc) {
     nc += strlen(sprintf(&cmds[nc], "terminal length 0\n\0"));
  }

/* Now start reading and writing as necessary... */

  for (;;) {

    timeout.tv_sec = 60; /* timeout the connection after 1 minute */
    timeout.tv_usec = 0;

    FD_ZERO(&readset);
    FD_SET(s, &readset);
    if (!ceof) FD_SET(cf, &readset);

    switch (select(FD_SETSIZE, &readset, (fd_set *)NULL,
               (fd_set *)NULL, &timeout)) {
      case -1:
             sprintf(buf, "%s: Error selecting input for '%s'", me, host);
             perror(buf);
             exit(1);
             break;
      case 0:
             sprintf(buf, "%s: Connection timed out for '%s'", me, host);
             perror(buf);
             exit(2);
             break;
      default:
             break;
    }

    if (FD_ISSET(s, &readset)) {
      switch (n = read(s, buf, BUFSIZ)) {
        case -1:
               sprintf(buf, "%s: Error reading socket for '%s'", me, host);
               perror(buf);
               exit(1);
        case 0:
               exit(0);
        default:
               write(1, buf, n);
               break;
      }
    }

    if (nc) {
      if (write(s, cmds, nc) == -1) {
        sprintf(buf, "%s: Error writing to socket for '%s'", me, host);
        perror(buf);
        exit(1);
      }
      nc = 0;
    } else if (FD_ISSET(cf, &readset)) {
             switch (n = read(cf, buf, 1)) {
               case -1:
                      sprintf(buf, "%s: Error reading command file for
'%s'", me, host);
                      perror(buf);
                      exit(1);
               case 0:
                      ceof = 1;
                      if (write(s, "exit\n", 5) == -1) {
                        sprintf(buf, "%s: Error writing to socket for
'%s'", me, host);
                        perror(buf);
                        exit(1);
                      }
                      break;
               default:
                      if (write(s, buf, 1) == -1) {
                        sprintf(buf, "%s: Error writing to socket for
'%s'", me, host);
                        perror(buf);
                        exit(1);
                      }
                      break;
             }
           }
  }
}

Blogs and organic groups at http://www.ccie.net



This archive was generated by hypermail 2.1.4 : Sun Mar 01 2009 - 09:43:39 ARST