Пример #1
0
int
fixExecError(int action,
             u_char * var_val,
             u_char var_val_type,
             size_t var_val_len,
             u_char * statP, oid * name, size_t name_len)
{

    struct extensible *exten;
    long            tmp = 0;
    int             fd;
    static struct extensible ex;
    FILE           *file;

    if ((exten = get_exten_instance(extens, name[10]))) {
        if (var_val_type != ASN_INTEGER) {
            snmp_log(LOG_ERR, "Wrong type != int\n");
            return SNMP_ERR_WRONGTYPE;
        }
        tmp = *((long *) var_val);
        if ((tmp == 1) && (action == COMMIT) && (exten->fixcmd[0] != 0)) {
            sprintf(ex.command, exten->fixcmd);
            if ((fd = get_exec_output(&ex)) != -1) {
                file = fdopen(fd, "r");
                while (fgets(ex.output, sizeof(ex.output), file) != NULL);
                fclose(file);
                wait_on_exec(&ex);
            }
        }
        return SNMP_ERR_NOERROR;
    }
    return SNMP_ERR_WRONGTYPE;
}
Пример #2
0
struct subtree *find_extensible(struct subtree	*tp,
				oid tname[],
				int tnamelen,
				int exact)
{
  int i,tmp;
  struct extensible *exten = 0;
  struct variable myvp;
  oid name[MAX_OID_LEN];
  static struct subtree mysubtree[2];

  for(i=1; i<= numrelocs; i++) {
    exten = get_exten_instance(relocs,i);
    if (exten->miblen != 0){
      memcpy(myvp.name,exten->miboid,exten->miblen*sizeof(oid));
      memcpy(name,tname,tnamelen*sizeof(oid));
      myvp.name[exten->miblen] = name[exten->miblen];
      myvp.namelen = exten->miblen+1;
      tmp = exten->miblen+1;
      if (!header_simple_table(&myvp,name,&tmp,-1,NULL,NULL, numrelocs))
        break;
    }
  }
  if (i > numrelocs || exten == NULL)
    return(tp);
  memcpy(mysubtree[0].name,exten->miboid,exten->miblen*sizeof(oid));
  mysubtree[0].namelen = exten->miblen;
  mysubtree[0].variables = (struct variable *)extensible_relocatable_variables;
  mysubtree[0].variables_len =
    sizeof(extensible_relocatable_variables)/sizeof(*extensible_relocatable_variables);
  mysubtree[0].variables_width = sizeof(*extensible_relocatable_variables);
  mysubtree[1].namelen = 0;
  return(mysubtree);
}
Пример #3
0
unsigned char *var_extensible_shell(struct variable *vp,
				    oid *name,
				    int *length,
				    int exact,
				    int *var_len,
				    WriteMethod **write_method)
{

  static struct extensible *exten = 0;
  static long long_ret;

  if (header_simple_table(vp,name,length,exact,var_len,write_method,numextens))
    return(NULL);

  if ((exten = get_exten_instance(extens,name[*length-1]))) {
    switch (vp->magic) {
      case MIBINDEX:
        long_ret = name[*length-1];
        return((u_char *) (&long_ret));
      case ERRORNAME: /* name defined in config file */
        *var_len = strlen(exten->name);
        return((u_char *) (exten->name));
      case SHELLCOMMAND:
        *var_len = strlen(exten->command);
        return((u_char *) (exten->command));
      case ERRORFLAG:  /* return code from the process */
        if (exten->type == EXECPROC)
          exec_command(exten);
        else
          shell_command(exten);
        long_ret = exten->result;
        return((u_char *) (&long_ret));
      case ERRORMSG:   /* first line of text returned from the process */
        if (exten->type == EXECPROC)
          exec_command(exten);
        else
          shell_command(exten);
        *var_len = strlen(exten->output);
        return((u_char *) (exten->output));
      case ERRORFIX:
        *write_method = fixExecError;
        long_return = 0;
        return ((u_char *) &long_return);

      case ERRORFIXCMD:
        *var_len = strlen(exten->fixcmd);
        return ((u_char *) exten->fixcmd);
    }
    return NULL;
  }
  return NULL;
}
Пример #4
0
netsnmp_subtree *
find_extensible(netsnmp_subtree *tp, oid *tname, size_t tnamelen, int exact)
{
    size_t          tmp;
    int             i;
    struct extensible *exten = 0;
    struct variable myvp;
    oid             name[MAX_OID_LEN];
    static netsnmp_subtree mysubtree[2] =
	{ { NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL, 0, 0, 0,
	    NULL, NULL, NULL, 0, 0, NULL, 0, 0 },
	  { NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL, 0, 0, 0,
	    NULL, NULL, NULL, 0, 0, NULL, 0, 0 } };

    for (i = 1; i <= (int) numrelocs; i++) {
        exten = get_exten_instance(relocs, i);
        if (!exten)
            continue;
        if (exten->miblen != 0) {
            memcpy(myvp.name, exten->miboid, exten->miblen * sizeof(oid));
            memcpy(name, tname, tnamelen * sizeof(oid));
            myvp.name[exten->miblen] = name[exten->miblen];
            myvp.namelen = exten->miblen + 1;
            tmp = exten->miblen + 1;
            if (!header_simple_table(&myvp, name, &tmp, -1, 
				     NULL, NULL, numrelocs)) {
                break;
	    }
        }
    }
    if (i > (int)numrelocs || exten == NULL) {
        return (tp);
    }

    if (mysubtree[0].name_a != NULL) {
	free(mysubtree[0].name_a);
	mysubtree[0].name_a = NULL;
    }
    mysubtree[0].name_a  = snmp_duplicate_objid(exten->miboid, exten->miblen);
    mysubtree[0].namelen = exten->miblen;
    mysubtree[0].variables = (struct variable *)extensible_relocatable_variables;
    mysubtree[0].variables_len = sizeof(extensible_relocatable_variables) /
        sizeof(*extensible_relocatable_variables);
    mysubtree[0].variables_width = sizeof(*extensible_relocatable_variables);
    mysubtree[1].namelen = 0;
    return (mysubtree);
}
Пример #5
0
int
setPass(int action, u_char * var_val, u_char var_val_type,
        size_t var_val_len, u_char * statP, oid * name, size_t name_len)
{
    int             i, rtest;
    struct extensible *passthru;
    char            buf[SNMP_MAXBUF], buf2[SNMP_MAXBUF];

    for (i = 1; i <= numpassthrus; i++) {
        passthru = get_exten_instance(passthrus, i);
        rtest = snmp_oidtree_compare(name, name_len,
                                     passthru->miboid, passthru->miblen);
        if (rtest <= 0) {
            if (action != ACTION)
                return SNMP_ERR_NOERROR;
            /*
             * setup args 
             */
            if (passthru->miblen >= name_len || rtest < 0)
                sprint_mib_oid(buf, passthru->miboid, passthru->miblen);
            else
                sprint_mib_oid(buf, name, name_len);
            snprintf(passthru->command, sizeof(passthru->command),
                     "%s -s %s ", passthru->name, buf);
            passthru->command[ sizeof(passthru->command)-1 ] = 0;
            netsnmp_internal_pass_set_format(buf, var_val, var_val_type, var_val_len);
            strlcat(passthru->command, buf, sizeof(passthru->command));
            DEBUGMSGTL(("ucd-snmp/pass", "pass-running:  %s",
                        passthru->command));
            exec_command(passthru);
            DEBUGMSGTL(("ucd-snmp/pass", "pass-running returned: %s",
                        passthru->output));
            return netsnmp_internal_pass_str_to_errno(passthru->output);
        }
    }
    if (snmp_get_do_debugging()) {
        sprint_mib_oid(buf2, name, name_len);
        DEBUGMSGTL(("ucd-snmp/pass", "pass-notfound:  %s\n", buf2));
    }
    return SNMP_ERR_NOSUCHNAME;
}
Пример #6
0
int
fixExecError(int action,
	     u_char *var_val,
	     u_char var_val_type,
	     int var_val_len,
	     u_char *statP,
	     oid *name,
	     int name_len)
{
  
  struct extensible *exten;
  long tmp=0;
  int tmplen=1000, fd;
  static struct extensible ex;
  FILE *file;

  if ((exten = get_exten_instance(extens,name[10]))) {
    if (var_val_type != ASN_INTEGER) {
      printf("Wrong type != int\n");
      return SNMP_ERR_WRONGTYPE;
    }
    asn_parse_int(var_val,&tmplen,&var_val_type,&tmp,sizeof(int));
    if ((tmp == 1) && (action == COMMIT) && (exten->fixcmd[0] != 0)) {
      sprintf(ex.command, exten->fixcmd);
      if ((fd = get_exec_output(&ex))) {
        file = fdopen(fd,"r");
        while (fgets(ex.output,STRMAX,file) != NULL);
        fclose(file);
        close(fd);
        wait_on_exec(&ex);
      }
    }
    return SNMP_ERR_NOERROR;
  }
  return SNMP_ERR_WRONGTYPE;
}
Пример #7
0
u_char         *
var_extensible_relocatable(struct variable *vp,
                           oid * name,
                           size_t * length,
                           int exact,
                           size_t * var_len, WriteMethod ** write_method)
{

    int             i;
    int             len;
    struct extensible *exten = 0;
    static long     long_ret;
    static char     errmsg[STRMAX];
    char            *cp, *cp1;
    struct variable myvp;
    oid             tname[MAX_OID_LEN];

    memcpy(&myvp, vp, sizeof(struct variable));

    long_ret = *length;
    for (i = 1; i <= (int) numrelocs; i++) {
        exten = get_exten_instance(relocs, i);
        if (!exten)
            continue;
        if ((int) exten->miblen == (int) vp->namelen - 1) {
            memcpy(myvp.name, exten->miboid, exten->miblen * sizeof(oid));
            myvp.namelen = exten->miblen;
            *length = vp->namelen;
            memcpy(tname, vp->name, vp->namelen * sizeof(oid));
            if (!header_simple_table
                (&myvp, tname, length, -1, var_len, write_method, -1))
                break;
            else
                exten = NULL;
        }
    }
    if (i > (int) numrelocs || exten == NULL) {
        *length = long_ret;
        *var_len = 0;
        *write_method = NULL;
        return (NULL);
    }

    *length = long_ret;
    if (header_simple_table(vp, name, length, exact, var_len, write_method,
                            ((vp->magic == ERRORMSG) ? MAXMSGLINES : 1)))
        return (NULL);

    switch (vp->magic) {
    case MIBINDEX:
        long_ret = name[*length - 1];
        return ((u_char *) (&long_ret));
    case ERRORNAME:            /* name defined in config file */
        *var_len = strlen(exten->name);
        return ((u_char *) (exten->name));
    case SHELLCOMMAND:
        *var_len = strlen(exten->command);
        return ((u_char *) (exten->command));
    case ERRORFLAG:            /* return code from the process */
        len = sizeof(exten->output);
        if (exten->type == EXECPROC)
            exten->result = run_exec_command( exten->command, NULL,
                                              exten->output, &len);
	else
            exten->result = run_shell_command(exten->command, NULL,
                                              exten->output, &len);
        long_ret = exten->result;
        return ((u_char *) (&long_ret));
    case ERRORMSG:             /* first line of text returned from the process */
        len = sizeof(exten->output);
        if (exten->type == EXECPROC)
            exten->result = run_exec_command( exten->command, NULL,
                                              exten->output, &len);
	else
            exten->result = run_shell_command(exten->command, NULL,
                                              exten->output, &len);

        /*
         *  Pick the output string apart into individual lines,
         *  and extract the one being asked for....
         */
        cp1 = exten->output;
        for (i = 1; i != (int) name[*length - 1]; i++) {
            cp = strchr(cp1, '\n');
            if (!cp) {
	        *var_len = 0;
	        /* wait_on_exec(exten);		??? */
	        return NULL;
	    }
	    cp1 = ++cp;
	}
        /*
         *  ... and quit if we've run off the end of the output
         */
        if (!*cp1) {
            *var_len = 0;
	    return NULL;
	}
        cp = strchr(cp1, '\n');
        if (cp)
            *cp = 0;
        strlcpy(errmsg, cp1, sizeof(errmsg));
        *var_len = strlen(errmsg);
        if (errmsg[*var_len - 1] == '\n')
            errmsg[--(*var_len)] = '\0';
        return ((u_char *) (errmsg));
    case ERRORFIX:
        *write_method = fixExecError;
        long_return = 0;
        return ((u_char *) & long_return);

    case ERRORFIXCMD:
        *var_len = strlen(exten->fixcmd);
        return ((u_char *) exten->fixcmd);
    }
    return NULL;
}
Пример #8
0
int
setPassPersist(int action,
               u_char * var_val,
               u_char var_val_type,
               size_t var_val_len,
               u_char * statP, oid * name, size_t name_len)
{
    int             i, rtest;
    struct extensible *persistpassthru;

    char            buf[SNMP_MAXBUF], buf2[SNMP_MAXBUF];

    /*
     * Make sure that our basic pipe structure is malloced 
     */
    init_persist_pipes();

    for (i = 1; i <= numpersistpassthrus; i++) {
        persistpassthru = get_exten_instance(persistpassthrus, i);
        rtest = snmp_oidtree_compare(name, name_len,
                                     persistpassthru->miboid,
                                     persistpassthru->miblen);
        if (rtest <= 0) {
            if (action != ACTION)
                return SNMP_ERR_NOERROR;
            /*
             * setup args 
             */
            if (persistpassthru->miblen >= name_len || rtest < 0)
                sprint_mib_oid(buf, persistpassthru->miboid,
                               persistpassthru->miblen);
            else
                sprint_mib_oid(buf, name, name_len);
            snprintf(persistpassthru->command,
                     sizeof(persistpassthru->command), "set\n%s\n", buf);
            persistpassthru->command[ sizeof(persistpassthru->command)-1 ] = 0;
            netsnmp_internal_pass_set_format(buf, var_val, var_val_type, var_val_len);
            strlcat(persistpassthru->command, buf,
                    sizeof(persistpassthru->command));
            persistpassthru->command[ sizeof(persistpassthru->command)-2 ] = '\n';
            persistpassthru->command[ sizeof(persistpassthru->command)-1 ] = 0;

            if (!open_persist_pipe(i, persistpassthru->name)) {
                return SNMP_ERR_NOTWRITABLE;
            }

            DEBUGMSGTL(("ucd-snmp/pass_persist",
                        "persistpass-writing:  %s\n",
                        persistpassthru->command));
            if (!write_persist_pipe(i, persistpassthru->command)) {
                close_persist_pipe(i);
                return SNMP_ERR_NOTWRITABLE;
            }

            if (fgets(buf, sizeof(buf), persist_pipes[i].fIn) == NULL) {
                close_persist_pipe(i);
                return SNMP_ERR_NOTWRITABLE;
            }

            return netsnmp_internal_pass_str_to_errno(buf);
        }
    }
    if (snmp_get_do_debugging()) {
        sprint_mib_oid(buf2, name, name_len);
        DEBUGMSGTL(("ucd-snmp/pass_persist", "persistpass-notfound:  %s\n",
                    buf2));
    }
    return SNMP_ERR_NOSUCHNAME;
}
Пример #9
0
u_char         *
var_extensible_pass_persist(struct variable *vp,
                            oid * name,
                            size_t * length,
                            int exact,
                            size_t * var_len, WriteMethod ** write_method)
{
    oid             newname[MAX_OID_LEN];
    int             i, rtest, newlen;
    char            buf[SNMP_MAXBUF];
    static char     buf2[SNMP_MAXBUF];
    struct extensible *persistpassthru;
    FILE           *file;

    /*
     * Make sure that our basic pipe structure is malloced 
     */
    init_persist_pipes();

    for (i = 1; i <= numpersistpassthrus; i++) {
        persistpassthru = get_exten_instance(persistpassthrus, i);
        rtest = snmp_oidtree_compare(name, *length,
                                     persistpassthru->miboid,
                                     persistpassthru->miblen);
        if ((exact && rtest == 0) || (!exact && rtest <= 0)) {
            /*
             * setup args 
             */
            if (persistpassthru->miblen >= *length || rtest < 0)
                sprint_mib_oid(buf, persistpassthru->miboid,
                               persistpassthru->miblen);
            else
                sprint_mib_oid(buf, name, *length);

            /*
             * Open our pipe if necessary 
             */
            if (!open_persist_pipe(i, persistpassthru->name)) {
                return (NULL);
            }

            if (exact)
                snprintf(persistpassthru->command,
                  sizeof(persistpassthru->command), "get\n%s\n", buf);
            else
                snprintf(persistpassthru->command,
                  sizeof(persistpassthru->command), "getnext\n%s\n", buf);
            persistpassthru->command[ sizeof(persistpassthru->command)-1 ] = 0;

            DEBUGMSGTL(("ucd-snmp/pass_persist",
                        "persistpass-sending:\n%s",
                        persistpassthru->command));
            if (!write_persist_pipe(i, persistpassthru->command)) {
                *var_len = 0;
                /*
                 * close_persist_pipes is called in write_persist_pipe 
                 */
                return (NULL);
            }

            /*
             * valid call.  Exec and get output 
             */
		
            if ((file = persist_pipes[i].fIn)) {
                if (fgets(buf, sizeof(buf), file) == NULL) {
                    *var_len = 0;
                    close_persist_pipe(i);
                    return (NULL);
                }
                /*
                 * persistent scripts return "NONE\n" on invalid items 
                 */
                if (!strncmp(buf, "NONE", 4)) {
                    if (exact) {
                        *var_len = 0;
                        return (NULL);
                    }
                    continue;
                }
                newlen = parse_miboid(buf, newname);

                /*
                 * its good, so copy onto name/length 
                 */
                memcpy((char *) name, (char *) newname,
                       (int) newlen * sizeof(oid));
                *length = newlen;

                /*
                 * set up return pointer for setable stuff 
                 */
                *write_method = setPassPersist;

                if (newlen == 0 || fgets(buf, sizeof(buf), file) == NULL
                    || fgets(buf2, sizeof(buf2), file) == NULL) {
                    *var_len = 0;
                    close_persist_pipe(i);
                    return (NULL);
                }
                return netsnmp_internal_pass_parse(buf, buf2, var_len, vp);
            }
            *var_len = 0;
            return (NULL);
        }
    }
    if (var_len)
        *var_len = 0;
    *write_method = NULL;
    return (NULL);
}
Пример #10
0
u_char         *
var_extensible_pass(struct variable *vp,
                    oid * name,
                    size_t * length,
                    int exact,
                    size_t * var_len, WriteMethod ** write_method)
{
    oid             newname[MAX_OID_LEN];
    int             i, rtest, fd, newlen;
    static long     long_ret;
    static in_addr_t addr_ret;
    char            buf[SNMP_MAXBUF];
    static char     buf2[SNMP_MAXBUF];
    static oid      objid[MAX_OID_LEN];
    struct extensible *passthru;
    FILE           *file;

    long_ret = *length;
    for (i = 1; i <= numpassthrus; i++) {
        passthru = get_exten_instance(passthrus, i);
        rtest = snmp_oid_min_compare(name, *length,
                                     passthru->miboid, passthru->miblen);
        if ((exact && rtest == 0) || (!exact && rtest <= 0)) {
            /*
             * setup args
             */
            if (passthru->miblen >= *length || rtest < 0)
                sprint_mib_oid(buf, passthru->miboid, passthru->miblen);
            else
                sprint_mib_oid(buf, name, *length);
            if (exact)
                snprintf(passthru->command, sizeof(passthru->command),
                         "%s -g %s", passthru->name, buf);
            else
                snprintf(passthru->command, sizeof(passthru->command),
                         "%s -n %s", passthru->name, buf);
            passthru->command[ sizeof(passthru->command)-1 ] = 0;
            DEBUGMSGTL(("ucd-snmp/pass", "pass-running:  %s\n",
                        passthru->command));
            /*
             * valid call.  Exec and get output
             */
            if ((fd = get_exec_output(passthru)) != -1) {
                file = fdopen(fd, "r");
                if (fgets(buf, sizeof(buf), file) == NULL) {
                    fclose(file);
                    wait_on_exec(passthru);
                    if (exact) {
                        /*
                         * to enable creation
                         */
                        *write_method = setPass;
                        *var_len = 0;
                        return (NULL);
                    }
                    continue;
                }
                newlen = parse_miboid(buf, newname);

                /*
                 * its good, so copy onto name/length
                 */
                memcpy((char *) name, (char *) newname,
                       (int) newlen * sizeof(oid));
                *length = newlen;

                /*
                 * set up return pointer for setable stuff
                 */
                *write_method = setPass;

                if (newlen == 0 || fgets(buf, sizeof(buf), file) == NULL
                        || fgets(buf2, sizeof(buf2), file) == NULL) {
                    *var_len = 0;
                    fclose(file);
                    wait_on_exec(passthru);
                    return (NULL);
                }
                fclose(file);
                wait_on_exec(passthru);

                /*
                 * buf contains the return type, and buf2 contains the data
                 */
                if (!strncasecmp(buf, "string", 6)) {
                    buf2[strlen(buf2) - 1] = 0; /* zap the linefeed */
                    *var_len = strlen(buf2);
                    vp->type = ASN_OCTET_STR;
                    return ((unsigned char *) buf2);
                }
                else if (!strncasecmp(buf, "integer64", 9)) {
                    static struct counter64 c64;
                    uint64_t v64 = strtoull(buf2, NULL, 10);

                    void * _c64 = (void *)&c64;
                    if (sizeof(long) > 4) {    /* 64-bit machine */
                        c64.high = v64 >> 32;
                        c64.low = v64 & 0xffffffff;
                    }
                    else {    /* 32-bit machine */
                        *(uint64_t *)_c64 = v64;
                    }
                    *var_len = sizeof(c64);
                    vp->type = ASN_INTEGER64;
                    return ((unsigned char *) &c64);
                }
                else if (!strncasecmp(buf, "integer", 7)) {
Пример #11
0
unsigned char *var_extensible_relocatable(struct variable *vp,
					  oid *name,
					  int *length,
					  int exact,
					  int *var_len,
					  WriteMethod **write_method)
{

  int i, fd;
  FILE *file;
  struct extensible *exten = 0;
  static long long_ret;
  static char errmsg[STRMAX];
  struct variable myvp;
  oid tname[MAX_OID_LEN];

  memcpy(&myvp,vp,sizeof(struct variable));

  long_ret = *length;
  for(i=1; i<= numrelocs; i++) {
    exten = get_exten_instance(relocs,i);
    if (exten->miblen == vp->namelen-1){
      memcpy(myvp.name,exten->miboid,exten->miblen*sizeof(oid));
      myvp.namelen = exten->miblen;
      *length = vp->namelen;
      memcpy(tname,vp->name,vp->namelen*sizeof(oid));
      if (!header_simple_table(&myvp,tname,length,-1,var_len,write_method, -1))
        break;
      else
        exten = NULL;
    }
  }
  if (i > numrelocs || exten == NULL) {
    *length = long_ret;
    *var_len = 0;
    *write_method = NULL;
    return(NULL);
  }

  *length = long_ret;
  if (header_simple_table(vp,name,length,exact,var_len,write_method,
               ((vp->magic == ERRORMSG) ? MAXMSGLINES : 1)))
    return(NULL);
  
  switch (vp->magic) {
    case MIBINDEX:
      long_ret = name[*length-1];
      return((u_char *) (&long_ret));
    case ERRORNAME: /* name defined in config file */
      *var_len = strlen(exten->name);
      return((u_char *) (exten->name));
    case SHELLCOMMAND:
      *var_len = strlen(exten->command);
      return((u_char *) (exten->command));
    case ERRORFLAG:  /* return code from the process */
      if (exten->type == EXECPROC)
        exec_command(exten);
      else
        shell_command(exten);
      long_ret = exten->result;
      return((u_char *) (&long_ret));
    case ERRORMSG:   /* first line of text returned from the process */
      if (exten->type == EXECPROC) {
        if ((fd = get_exec_output(exten))){
          file = fdopen(fd,"r");
          for (i=0;i != name[*length-1];i++) {
            if (fgets(errmsg,sizeof(errmsg),file) == NULL) {
              *var_len = 0;
              fclose(file);
              close(fd);
              wait_on_exec(exten);
              return(NULL);
            }
          }
          fclose(file);
          close(fd);
          wait_on_exec(exten);
        } else
          errmsg[0] = 0;
      }
      else {
        if (*length > 1) {
          *var_len = 0;
          return(NULL);
        }
        shell_command(exten);
        strcpy(errmsg,exten->output);
      }
      *var_len = strlen(errmsg);
      return((u_char *) (errmsg));
    case ERRORFIX:
      *write_method = fixExecError;
      long_return = 0;
      return ((u_char *) &long_return);
  }
  return NULL;
}
Пример #12
0
u_char         *
var_extensible_pass(struct variable *vp,
                    oid * name,
                    size_t * length,
                    int exact,
                    size_t * var_len, WriteMethod ** write_method)
{
    oid             newname[MAX_OID_LEN];
    int             i, rtest, fd, newlen;
    char            buf[SNMP_MAXBUF];
    static char     buf2[SNMP_MAXBUF];
    struct extensible *passthru;
    FILE           *file;

    for (i = 1; i <= numpassthrus; i++) {
        passthru = get_exten_instance(passthrus, i);
        rtest = snmp_oidtree_compare(name, *length,
                                     passthru->miboid, passthru->miblen);
        if ((exact && rtest == 0) || (!exact && rtest <= 0)) {
            /*
             * setup args 
             */
            if (passthru->miblen >= *length || rtest < 0)
                sprint_mib_oid(buf, passthru->miboid, passthru->miblen);
            else
                sprint_mib_oid(buf, name, *length);
            if (exact)
                snprintf(passthru->command, sizeof(passthru->command),
                         "%s -g %s", passthru->name, buf);
            else
                snprintf(passthru->command, sizeof(passthru->command),
                         "%s -n %s", passthru->name, buf);
            passthru->command[ sizeof(passthru->command)-1 ] = 0;
            DEBUGMSGTL(("ucd-snmp/pass", "pass-running:  %s\n",
                        passthru->command));
            /*
             * valid call.  Exec and get output 
             */
            if ((fd = get_exec_output(passthru)) != -1) {
                file = fdopen(fd, "r");
                if (fgets(buf, sizeof(buf), file) == NULL) {
                    fclose(file);
                    wait_on_exec(passthru);
                    if (exact) {
                        /*
                         * to enable creation
                         */
                        *write_method = setPass;
                        *var_len = 0;
                        return (NULL);
                    }
                    continue;
                }
                newlen = parse_miboid(buf, newname);

                /*
                 * its good, so copy onto name/length 
                 */
                memcpy((char *) name, (char *) newname,
                       (int) newlen * sizeof(oid));
                *length = newlen;

                /*
                 * set up return pointer for setable stuff 
                 */
                *write_method = setPass;

                if (newlen == 0 || fgets(buf, sizeof(buf), file) == NULL
                    || fgets(buf2, sizeof(buf2), file) == NULL) {
                    *var_len = 0;
                    fclose(file);
                    wait_on_exec(passthru);
                    return (NULL);
                }
                fclose(file);
                wait_on_exec(passthru);

                return netsnmp_internal_pass_parse(buf, buf2, var_len, vp);
            }
            *var_len = 0;
            return (NULL);
        }
    }
    if (var_len)
        *var_len = 0;
    *write_method = NULL;
    return (NULL);
}