/* * Copyright (c) 2012 Red Hat. * Copyright (c) 1995-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "./cisco.h" int port = 23; int seen_fr = 0; char *prompt = ">"; /* unique suffix to IOS prompt */ char * mygetfirstwd(FILE *f) { char *p; int c; char line[1024]; char *lp; for ( ; ; ) { c = fgetc(f); if (c == EOF) break; if (c == '\r' || c == '\n') continue; if (c != ' ') { ungetc(c, f); break; } lp = line; while ((c = fgetc(f)) != EOF) { *lp++ = c; if (c == '\r' || c == '\n') { *lp = '\0'; break; } } /* * some interesting things to look for here ... */ if (strncmp(&line[1], "Encapsulation FRAME-RELAY", strlen("Encapsulation FRAME-RELAY")) == 0) { seen_fr = 1; } } /* either EOF, or line starts with a non-space */ p = mygetwd(f, prompt); if (p != NULL && (strlen(p) < strlen(prompt) || strcmp(&p[strlen(p)-strlen(prompt)], prompt)) != 0) { /* skip to end of line, ready for next one */ while ((c = fgetc(f)) != EOF) { if (c == '\r' || c == '\n') break; } } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "mygetfirstwd: %s\n", p == NULL ? "" : p); #endif return p; } #define PREAMBLE 1 #define IN_BODY 2 static void probe_cisco(cisco_t * cp) { char *w; int fd; int fd2; int first = 1; char *pass = NULL; int defer = 0; int state = PREAMBLE; int i; int namelen; char *ctype = NULL; char *name = NULL; if (cp->fin == NULL) { fd = conn_cisco(cp); if (fd == -1) { fprintf(stderr, "grab_cisco(%s): connect failed: %s\n", cp->host, osstrerror()); return; } else { cp->fin = fdopen (fd, "r"); if ((fd2 = dup(fd)) < 0) { perror("dup"); exit(1); } cp->fout = fdopen (fd2, "w"); if (cp->username != NULL) { /* * Username stuff ... */ if (dousername(cp, &pass) == 0) { exit(1); } } if (cp->passwd != NULL) { /* * User-level password stuff ... */ if (dopasswd(cp, pass) == 0) { exit(1); } } } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { fprintf(stderr, "Send: \n"); fprintf(stderr, "Send: terminal length 0\n"); } #endif fprintf(cp->fout, "\n"); fflush(cp->fout); fprintf(cp->fout, "terminal length 0\n"); fflush(cp->fout); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { fprintf(stderr, "Send: show int\n"); } #endif fprintf(cp->fout, "show int\n"); fflush(cp->fout); } else { /* * parsing text from a file, not a TCP/IP connection to a * Cisco device */ ; } for ( ; ; ) { w = mygetfirstwd(cp->fin); if (defer && ctype != NULL && name != NULL) { if (seen_fr) { if (first) first = 0; else putchar(' '); printf("%s%s", ctype, name); free(name); name = NULL; } } defer = 0; if (w == NULL) { /* * End of File (telenet timeout?) */ fprintf(stderr, "grab_cisco(%s): forced disconnect fin=%d\n", cp->host, fileno(cp->fin)); return; } if (*w == '\0') continue; if (state == PREAMBLE) { if (strcmp(w, "show") == 0) state = IN_BODY; else if (strcmp(w, PWPROMPT) == 0) { fprintf(stderr, "Error: user-level password required for \"%s\"\n", cp->host); exit(1); } continue; } else { if (strlen(w) >= strlen(prompt) && strcmp(&w[strlen(w)-strlen(prompt)], prompt) == 0) break; ctype = NULL; for (i = 0; i < num_intf_tab; i++) { namelen = strlen(intf_tab[i].name); if (strncmp(w, intf_tab[i].name, namelen) == 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { fprintf(stderr, "Match: if=%s word=%s\n", intf_tab[i].name, w); } #endif name = strdup(&w[namelen]); ctype = intf_tab[i].type; if (intf_tab[i].type != NULL && strcmp(intf_tab[i].type, "a") == 0) { /* * skip ATMN.M ... need ATMN */ if (strchr(&w[namelen], '.') != NULL) ctype = NULL; } else if (intf_tab[i].type != NULL && strcmp(intf_tab[i].type, "s") == 0) { /* * skip SerialN.M ... need SerialN, unless frame-relay */ if (strchr(&w[namelen], '.') != NULL) defer = 1; } break; } } if (i == num_intf_tab) fprintf(stderr, "%s: Warning, unknown interface: %s\n", pmProgname, w); if (ctype != NULL && name != NULL && !defer) { if (first) first = 0; else putchar(' '); printf("%s%s", ctype, name); free(name); name = NULL; } } } putchar('\n'); /* close CISCO telnet session */ #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { fprintf(stderr, "Send: exit\n"); } #endif fprintf(cp->fout, "exit\n"); fflush(cp->fout); return; } int main(int argc, char **argv) { int errflag = 0; int Nflag = 0; int c; int sts; char *endnum; char *passwd = NULL; char *username = NULL; __pmHostEnt *hostInfo = NULL; __pmSetProgname(argv[0]); while ((c = getopt(argc, argv, "ND:P:s:U:x:?")) != EOF) { switch (c) { case 'N': /* check flag */ Nflag = 1; break; case 'D': /* debug flag */ sts = __pmParseDebug(optarg); if (sts < 0) { fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n", pmProgname, optarg); errflag++; } else pmDebug |= sts; break; case 'P': /* passwd */ passwd = optarg; break; case 's': /* prompt */ prompt = optarg; break; case 'U': /* username */ username = optarg; break; case 'x': port = (int)strtol(optarg, &endnum, 10); if (*endnum != '\0') { fprintf(stderr, "%s: -x requires numeric argument\n", pmProgname); errflag++; } break; case '?': errflag++; } } if (errflag || optind != argc-1) { fprintf(stderr, "Usage: %s [-U username] [-P passwd] [-s prompt] [-x port] host\n\n", pmProgname); exit(1); } if (!Nflag) hostInfo = __pmGetAddrInfo(argv[optind]); if (hostInfo == NULL) { FILE *f; if ((f = fopen(argv[optind], "r")) == NULL) { fprintf(stderr, "%s: unknown hostname or filename %s: %s\n", pmProgname, argv[optind], hoststrerror()); exit(1); } else { cisco_t c; fprintf(stderr, "%s: assuming file %s contains output from \"show int\" command\n", pmProgname, argv[optind]); c.host = argv[optind]; c.username = NULL; c.passwd = NULL; c.fin = f; c.fout = fopen("/dev/null", "w"); c.prompt = prompt; probe_cisco(&c); } } else { cisco_t c; c.host = argv[optind]; c.username = username; c.passwd = passwd; c.fin = NULL; c.fout = NULL; c.prompt = prompt; c.hostinfo = hostInfo; c.port = 23; /* telnet */ probe_cisco(&c); } exit(0); }