pass.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:16k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #if HAVE_STDLIB_H
  3. #include <stdlib.h>
  4. #endif
  5. #include <stdio.h>
  6. #if HAVE_STRING_H
  7. #include <string.h>
  8. #else
  9. #include <strings.h>
  10. #endif
  11. #if HAVE_UNISTD_H
  12. #include <unistd.h>
  13. #endif
  14. #include <ctype.h>
  15. #include <sys/types.h>
  16. #if HAVE_NETINET_IN_H
  17. #include <netinet/in.h>
  18. #endif
  19. #if HAVE_SYS_WAIT_H
  20. # include <sys/wait.h>
  21. #endif
  22. #if HAVE_WINSOCK_H
  23. #include <winsock.h>
  24. #endif
  25. #if HAVE_DMALLOC_H
  26. #include <dmalloc.h>
  27. #endif
  28. #include <net-snmp/net-snmp-includes.h>
  29. #include <net-snmp/agent/net-snmp-agent-includes.h>
  30. #include "struct.h"
  31. #include "pass.h"
  32. #include "extensible.h"
  33. #include "util_funcs.h"
  34. struct extensible *passthrus = NULL;
  35. int             numpassthrus = 0;
  36. /*
  37.  * the relocatable extensible commands variables 
  38.  */
  39. struct variable2 extensible_passthru_variables[] = {
  40.     /*
  41.      * bogus entry.  Only some of it is actually used. 
  42.      */
  43.     {MIBINDEX, ASN_INTEGER, RWRITE, var_extensible_pass, 0, {MIBINDEX}},
  44. };
  45. /*
  46.  * lexicographical compare two object identifiers.
  47.  * * Returns -1 if name1 < name2,
  48.  * *          0 if name1 = name2,
  49.  * *          1 if name1 > name2
  50.  * *
  51.  * * This method differs from snmp_oid_compare
  52.  * * in that the comparison stops at the length
  53.  * * of the smallest object identifier.
  54.  */
  55. int
  56. snmp_oid_min_compare(const oid * in_name1,
  57.                      size_t len1, const oid * in_name2, size_t len2)
  58. {
  59.     register int    len;
  60.     register const oid *name1 = in_name1;
  61.     register const oid *name2 = in_name2;
  62.     /*
  63.      * len = minimum of len1 and len2 
  64.      */
  65.     if (len1 < len2)
  66.         len = len1;
  67.     else
  68.         len = len2;
  69.     /*
  70.      * find first non-matching OID 
  71.      */
  72.     while (len-- > 0) {
  73.         /*
  74.          * these must be done in seperate comparisons, since
  75.          * subtracting them and using that result has problems with
  76.          * subids > 2^31. 
  77.          */
  78.         if (*(name1) < *(name2))
  79.             return -1;
  80.         if (*(name1++) > *(name2++))
  81.             return 1;
  82.     }
  83.     /*
  84.      * both OIDs equal up to length of shorter OID 
  85.      */
  86.     return 0;
  87. }
  88. /*
  89.  * This is also called from pass_persist.c 
  90.  */
  91. int
  92. asc2bin(char *p)
  93. {
  94.     char           *r, *q = p;
  95.     char            c;
  96.     int             n = 0;
  97.     for (;;) {
  98.         c = (char) strtol(q, &r, 16);
  99.         if (r == q)
  100.             break;
  101.         *p++ = c;
  102.         q = r;
  103.         n++;
  104.     }
  105.     return n;
  106. }
  107. /*
  108.  * This is also called from pass_persist.c 
  109.  */
  110. int
  111. bin2asc(char *p, size_t n)
  112. {
  113.     int             i, flag = 0;
  114.     char            buffer[SNMP_MAXBUF];
  115.     /* prevent buffer overflow */
  116.     if ((int)n > (sizeof(buffer) - 1))
  117.         n = sizeof(buffer) - 1;
  118.     for (i = 0; i < (int) n; i++) {
  119.         buffer[i] = p[i];
  120.         if (!isprint(p[i]))
  121.             flag = 1;
  122.     }
  123.     if (flag == 0) {
  124.         p[n] = 0;
  125.         return n;
  126.     }
  127.     for (i = 0; i < (int) n; i++) {
  128.         sprintf(p, "%02x ", (unsigned char) (buffer[i] & 0xff));
  129.         p += 3;
  130.     }
  131.     *--p = 0;
  132.     return 3 * n - 1;
  133. }
  134. void
  135. init_pass(void)
  136. {
  137.     snmpd_register_config_handler("pass", pass_parse_config,
  138.                                   pass_free_config, "miboid command");
  139. }
  140. void
  141. pass_parse_config(const char *token, char *cptr)
  142. {
  143.     struct extensible **ppass = &passthrus, **etmp, *ptmp;
  144.     char           *tcptr;
  145.     int             i;
  146.     if (*cptr == '.')
  147.         cptr++;
  148.     if (!isdigit(*cptr)) {
  149.         config_perror("second token is not a OID");
  150.         return;
  151.     }
  152.     numpassthrus++;
  153.     while (*ppass != NULL)
  154.         ppass = &((*ppass)->next);
  155.     (*ppass) = (struct extensible *) malloc(sizeof(struct extensible));
  156.     if (*ppass == NULL)
  157.         return;
  158.     (*ppass)->type = PASSTHRU;
  159.     (*ppass)->miblen = parse_miboid(cptr, (*ppass)->miboid);
  160.     while (isdigit(*cptr) || *cptr == '.')
  161.         cptr++;
  162.     /*
  163.      * name 
  164.      */
  165.     cptr = skip_white(cptr);
  166.     if (cptr == NULL) {
  167.         config_perror("No command specified on pass line");
  168.         (*ppass)->command[0] = 0;
  169.     } else {
  170.         for (tcptr = cptr; *tcptr != 0 && *tcptr != '#' && *tcptr != ';';
  171.              tcptr++);
  172.         strncpy((*ppass)->command, cptr, tcptr - cptr);
  173.         (*ppass)->command[tcptr - cptr] = 0;
  174.     }
  175.     strncpy((*ppass)->name, (*ppass)->command, sizeof((*ppass)->name));
  176.     (*ppass)->name[ sizeof((*ppass)->name)-1 ] = 0;
  177.     (*ppass)->next = NULL;
  178.     register_mib("pass", (struct variable *) extensible_passthru_variables,
  179.                  sizeof(struct variable2),
  180.                  1, (*ppass)->miboid, (*ppass)->miblen);
  181.     /*
  182.      * argggg -- pasthrus must be sorted 
  183.      */
  184.     if (numpassthrus > 1) {
  185.         etmp = (struct extensible **)
  186.             malloc(((sizeof(struct extensible *)) * numpassthrus));
  187.         if (etmp == NULL)
  188.             return;
  189.         for (i = 0, ptmp = (struct extensible *) passthrus;
  190.              i < numpassthrus && ptmp != 0; i++, ptmp = ptmp->next)
  191.             etmp[i] = ptmp;
  192.         qsort(etmp, numpassthrus, sizeof(struct extensible *),
  193.               pass_compare);
  194.         passthrus = (struct extensible *) etmp[0];
  195.         ptmp = (struct extensible *) etmp[0];
  196.         for (i = 0; i < numpassthrus - 1; i++) {
  197.             ptmp->next = etmp[i + 1];
  198.             ptmp = ptmp->next;
  199.         }
  200.         ptmp->next = NULL;
  201.         free(etmp);
  202.     }
  203. }
  204. void
  205. pass_free_config(void)
  206. {
  207.     struct extensible *etmp, *etmp2;
  208.     for (etmp = passthrus; etmp != NULL;) {
  209.         etmp2 = etmp;
  210.         etmp = etmp->next;
  211.         unregister_mib(etmp2->miboid, etmp2->miblen);
  212.         free(etmp2);
  213.     }
  214.     passthrus = NULL;
  215.     numpassthrus = 0;
  216. }
  217. u_char         *
  218. var_extensible_pass(struct variable *vp,
  219.                     oid * name,
  220.                     size_t * length,
  221.                     int exact,
  222.                     size_t * var_len, WriteMethod ** write_method)
  223. {
  224.     oid             newname[MAX_OID_LEN];
  225.     int             i, rtest, fd, newlen;
  226.     static long     long_ret;
  227.     char            buf[SNMP_MAXBUF];
  228.     static char     buf2[SNMP_MAXBUF];
  229.     static oid      objid[MAX_OID_LEN];
  230.     struct extensible *passthru;
  231.     FILE           *file;
  232.     long_ret = *length;
  233.     for (i = 1; i <= numpassthrus; i++) {
  234.         passthru = get_exten_instance(passthrus, i);
  235.         rtest = snmp_oid_min_compare(name, *length,
  236.                                      passthru->miboid, passthru->miblen);
  237.         if ((exact && rtest == 0) || (!exact && rtest <= 0)) {
  238.             /*
  239.              * setup args 
  240.              */
  241.             if (passthru->miblen >= *length || rtest < 0)
  242.                 sprint_mib_oid(buf, passthru->miboid, passthru->miblen);
  243.             else
  244.                 sprint_mib_oid(buf, name, *length);
  245.             if (exact)
  246.                 snprintf(passthru->command, sizeof(passthru->command),
  247.                          "%s -g %s", passthru->name, buf);
  248.             else
  249.                 snprintf(passthru->command, sizeof(passthru->command),
  250.                          "%s -n %s", passthru->name, buf);
  251.             passthru->command[ sizeof(passthru->command)-1 ] = 0;
  252.             DEBUGMSGTL(("ucd-snmp/pass", "pass-running:  %sn",
  253.                         passthru->command));
  254.             /*
  255.              * valid call.  Exec and get output 
  256.              */
  257.             if ((fd = get_exec_output(passthru)) != -1) {
  258.                 file = fdopen(fd, "r");
  259.                 if (fgets(buf, sizeof(buf), file) == NULL) {
  260.                     fclose(file);
  261.                     wait_on_exec(passthru);
  262.                     if (exact) {
  263.                         /*
  264.                          * to enable creation
  265.                          */
  266.                         *write_method = setPass;
  267.                         *var_len = 0;
  268.                         return (NULL);
  269.                     }
  270.                     continue;
  271.                 }
  272.                 newlen = parse_miboid(buf, newname);
  273.                 /*
  274.                  * its good, so copy onto name/length 
  275.                  */
  276.                 memcpy((char *) name, (char *) newname,
  277.                        (int) newlen * sizeof(oid));
  278.                 *length = newlen;
  279.                 /*
  280.                  * set up return pointer for setable stuff 
  281.                  */
  282.                 *write_method = setPass;
  283.                 if (newlen == 0 || fgets(buf, sizeof(buf), file) == NULL
  284.                     || fgets(buf2, sizeof(buf2), file) == NULL) {
  285.                     *var_len = 0;
  286.                     fclose(file);
  287.                     wait_on_exec(passthru);
  288.                     return (NULL);
  289.                 }
  290.                 fclose(file);
  291.                 wait_on_exec(passthru);
  292.                 /*
  293.                  * buf contains the return type, and buf2 contains the data 
  294.                  */
  295.                 if (!strncasecmp(buf, "string", 6)) {
  296.                     buf2[strlen(buf2) - 1] = 0; /* zap the linefeed */
  297.                     *var_len = strlen(buf2);
  298.                     vp->type = ASN_OCTET_STR;
  299.                     return ((unsigned char *) buf2);
  300.                 } else if (!strncasecmp(buf, "integer", 7)) {
  301.                     *var_len = sizeof(long_ret);
  302.                     long_ret = strtol(buf2, NULL, 10);
  303.                     vp->type = ASN_INTEGER;
  304.                     return ((unsigned char *) &long_ret);
  305.                 } else if (!strncasecmp(buf, "unsigned", 8)) {
  306.                     *var_len = sizeof(long_ret);
  307.                     long_ret = strtoul(buf2, NULL, 10);
  308.                     vp->type = ASN_UNSIGNED;
  309.                     return ((unsigned char *) &long_ret);
  310.                 } else if (!strncasecmp(buf, "counter", 7)) {
  311.                     *var_len = sizeof(long_ret);
  312.                     long_ret = strtoul(buf2, NULL, 10);
  313.                     vp->type = ASN_COUNTER;
  314.                     return ((unsigned char *) &long_ret);
  315.                 } else if (!strncasecmp(buf, "octet", 5)) {
  316.                     *var_len = asc2bin(buf2);
  317.                     vp->type = ASN_OCTET_STR;
  318.                     return ((unsigned char *) buf2);
  319.                 } else if (!strncasecmp(buf, "opaque", 6)) {
  320.                     *var_len = asc2bin(buf2);
  321.                     vp->type = ASN_OPAQUE;
  322.                     return ((unsigned char *) buf2);
  323.                 } else if (!strncasecmp(buf, "gauge", 5)) {
  324.                     *var_len = sizeof(long_ret);
  325.                     long_ret = strtoul(buf2, NULL, 10);
  326.                     vp->type = ASN_GAUGE;
  327.                     return ((unsigned char *) &long_ret);
  328.                 } else if (!strncasecmp(buf, "objectid", 8)) {
  329.                     newlen = parse_miboid(buf2, objid);
  330.                     *var_len = newlen * sizeof(oid);
  331.                     vp->type = ASN_OBJECT_ID;
  332.                     return ((unsigned char *) objid);
  333.                 } else if (!strncasecmp(buf, "timetick", 8)) {
  334.                     *var_len = sizeof(long_ret);
  335.                     long_ret = strtoul(buf2, NULL, 10);
  336.                     vp->type = ASN_TIMETICKS;
  337.                     return ((unsigned char *) &long_ret);
  338.                 } else if (!strncasecmp(buf, "ipaddress", 9)) {
  339.                     newlen = parse_miboid(buf2, objid);
  340.                     if (newlen != 4) {
  341.                         snmp_log(LOG_ERR,
  342.                                  "invalid ipaddress returned:  %sn",
  343.                                  buf2);
  344.                         *var_len = 0;
  345.                         return (NULL);
  346.                     }
  347.                     long_ret =
  348.                         (objid[0] << (8 * 3)) + (objid[1] << (8 * 2)) +
  349.                         (objid[2] << 8) + objid[3];
  350.                     long_ret = htonl(long_ret);
  351.                     *var_len = sizeof(long_ret);
  352.                     vp->type = ASN_IPADDRESS;
  353.                     return ((unsigned char *) &long_ret);
  354.                 }
  355.             }
  356.             *var_len = 0;
  357.             return (NULL);
  358.         }
  359.     }
  360.     if (var_len)
  361.         *var_len = 0;
  362.     *write_method = NULL;
  363.     return (NULL);
  364. }
  365. int
  366. setPass(int action,
  367.         u_char * var_val,
  368.         u_char var_val_type,
  369.         size_t var_val_len, u_char * statP, oid * name, size_t name_len)
  370. {
  371.     int             i, rtest;
  372.     struct extensible *passthru;
  373.     char            buf[SNMP_MAXBUF], buf2[SNMP_MAXBUF];
  374.     long            tmp;
  375.     unsigned long   utmp;
  376.     for (i = 1; i <= numpassthrus; i++) {
  377.         passthru = get_exten_instance(passthrus, i);
  378.         rtest = snmp_oid_min_compare(name, name_len,
  379.                                      passthru->miboid, passthru->miblen);
  380.         if (rtest <= 0) {
  381.             if (action != ACTION)
  382.                 return SNMP_ERR_NOERROR;
  383.             /*
  384.              * setup args 
  385.              */
  386.             if (passthru->miblen >= name_len || rtest < 0)
  387.                 sprint_mib_oid(buf, passthru->miboid, passthru->miblen);
  388.             else
  389.                 sprint_mib_oid(buf, name, name_len);
  390.             snprintf(passthru->command, sizeof(passthru->command),
  391.                      "%s -s %s ", passthru->name, buf);
  392.             passthru->command[ sizeof(passthru->command)-1 ] = 0;
  393.             switch (var_val_type) {
  394.             case ASN_INTEGER:
  395.             case ASN_COUNTER:
  396.             case ASN_GAUGE:
  397.             case ASN_TIMETICKS:
  398.                 tmp = *((long *) var_val);
  399.                 switch (var_val_type) {
  400.                 case ASN_INTEGER:
  401.                     sprintf(buf, "integer %dn", (int) tmp);
  402.                     break;
  403.                 case ASN_COUNTER:
  404.                     sprintf(buf, "counter %dn", (int) tmp);
  405.                     break;
  406.                 case ASN_GAUGE:
  407.                     sprintf(buf, "gauge %dn", (int) tmp);
  408.                     break;
  409.                 case ASN_TIMETICKS:
  410.                     sprintf(buf, "timeticks %dn", (int) tmp);
  411.                     break;
  412.                 }
  413.                 break;
  414.             case ASN_IPADDRESS:
  415.                 utmp = *((u_long *) var_val);
  416.                 utmp = ntohl(utmp);
  417.                 sprintf(buf, "ipaddress %d.%d.%d.%dn",
  418.                         (int) ((utmp & 0xff000000) >> (8 * 3)),
  419.                         (int) ((utmp & 0xff0000) >> (8 * 2)),
  420.                         (int) ((utmp & 0xff00) >> (8)),
  421.                         (int) ((utmp & 0xff)));
  422.                 break;
  423.             case ASN_OCTET_STR:
  424.                 memcpy(buf2, var_val, var_val_len);
  425.                 if (var_val_len == 0)
  426.                     sprintf(buf, "string ""n");
  427.                 else if (bin2asc(buf2, var_val_len) == (int) var_val_len)
  428.                     snprintf(buf, sizeof(buf), "string "%s"n", buf2);
  429.                 else
  430.                     snprintf(buf, sizeof(buf), "octet "%s"n", buf2);
  431.                 buf[ sizeof(buf)-1 ] = 0;
  432.                 break;
  433.             case ASN_OBJECT_ID:
  434.                 sprint_mib_oid(buf2, (oid *) var_val, var_val_len);
  435.                 snprintf(buf, sizeof(buf), "objectid "%s"n", buf2);
  436.                 buf[ sizeof(buf)-1 ] = 0;
  437.                 break;
  438.             }
  439.             strncat(passthru->command, buf, sizeof(passthru->command));
  440.             passthru->command[ sizeof(passthru->command)-1 ] = 0;
  441.             DEBUGMSGTL(("ucd-snmp/pass", "pass-running:  %s",
  442.                         passthru->command));
  443.             exec_command(passthru);
  444.             DEBUGMSGTL(("ucd-snmp/pass", "pass-running returned: %s",
  445.                         passthru->output));
  446.             if (!strncasecmp(passthru->output, "not-writable", 12)) {
  447.                 return SNMP_ERR_NOTWRITABLE;
  448.             } else if (!strncasecmp(passthru->output, "wrong-type", 10)) {
  449.                 return SNMP_ERR_WRONGTYPE;
  450.             }
  451.             return SNMP_ERR_NOERROR;
  452.         }
  453.     }
  454.     if (snmp_get_do_debugging()) {
  455.         sprint_mib_oid(buf2, name, name_len);
  456.         DEBUGMSGTL(("ucd-snmp/pass", "pass-notfound:  %sn", buf2));
  457.     }
  458.     return SNMP_ERR_NOSUCHNAME;
  459. }
  460. int
  461. pass_compare(const void *a, const void *b)
  462. {
  463.     const struct extensible *const *ap, *const *bp;
  464.     ap = (const struct extensible * const *) a;
  465.     bp = (const struct extensible * const *) b;
  466.     return snmp_oid_compare((*ap)->miboid, (*ap)->miblen, (*bp)->miboid,
  467.                             (*bp)->miblen);
  468. }