www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / userapps / opensource / net-snmp / perl / SNMP / SNMP.xs
diff --git a/userapps/opensource/net-snmp/perl/SNMP/SNMP.xs b/userapps/opensource/net-snmp/perl/SNMP/SNMP.xs
deleted file mode 100644 (file)
index ae3e044..0000000
+++ /dev/null
@@ -1,4935 +0,0 @@
-/* -*- C -*-
-     SNMP.xs -- Perl 5 interface to the UCD SNMP toolkit
-
-     written by G. S. Marzot (gmarzot@nortelnetworks.com)
-
-     Copyright (c) 1995-1999 G. S. Marzot. All rights reserved.
-     This program is free software; you can redistribute it and/or
-     modify it under the same terms as Perl itself.
-*/
-#define WIN32SCK_IS_STDSCK
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-#include <sys/types.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <ctype.h>
-#ifdef I_SYS_TIME
-#include <sys/time.h>
-#endif
-#include <netdb.h>
-#include <stdlib.h>
-#include <unistd.h>
-/* XXX This is a problem if regex.h is not on the system. */
-#include <regex.h>
-
-#ifndef __P
-#define __P(x) x
-#endif
-
-#ifndef na
-#define na PL_na
-#endif
-
-#ifndef sv_undef
-#define sv_undef PL_sv_undef
-#endif
-
-#ifndef stack_base
-#define stack_base PL_stack_base
-#endif
-
-#ifndef G_VOID
-#define G_VOID G_DISCARD
-#endif
-
-#ifdef WIN32
-#define SOCK_STARTUP winsock_startup()
-#define SOCK_CLEANUP winsock_cleanup()
-#define DLL_IMPORT   __declspec( dllimport )
-#define strcasecmp _stricmp
-#define strncasecmp _strnicmp
-#else
-#define SOCK_STARTUP
-#define SOCK_CLEANUP
-#define DLL_IMPORT
-#endif
-
-DLL_IMPORT extern struct tree *Mib;
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-
-#include "perlsnmp.h"
-
-#define SUCCESS 1
-#define FAILURE 0
-
-#define ZERO_BUT_TRUE "0 but true"
-
-#define VARBIND_TAG_F 0
-#define VARBIND_IID_F 1
-#define VARBIND_VAL_F 2
-#define VARBIND_TYPE_F 3
-
-#define TYPE_UNKNOWN 0
-#define MAX_TYPE_NAME_LEN 16
-#define STR_BUF_SIZE 1024
-#define ENG_ID_BUF_SIZE 32
-
-#define SYS_UPTIME_OID_LEN 9
-#define SNMP_TRAP_OID_LEN 11
-#define NO_RETRY_NOSUCH 0
-static oid sysUpTime[SYS_UPTIME_OID_LEN] = {1, 3, 6, 1, 2, 1, 1, 3, 0};
-static oid snmpTrapOID[SNMP_TRAP_OID_LEN] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0};
-
-/* Internal flag to determine snmp_main_loop() should return after callback */
-static int mainloop_finish = 0;
-
-/* these should be part of transform_oids.h ? */
-#define USM_AUTH_PROTO_MD5_LEN 10
-#define USM_AUTH_PROTO_SHA_LEN 10
-#define USM_PRIV_PROTO_DES_LEN 10
-
-/* why does ucd-snmp redefine sockaddr_in ??? */
-#define SIN_ADDR(snmp_addr) (((struct sockaddr_in *) &(snmp_addr))->sin_addr)
-
-typedef netsnmp_session SnmpSession;
-typedef struct tree SnmpMibNode;
-typedef struct snmp_xs_cb_data {
-    SV* perl_cb;
-    SV* sess_ref;
-} snmp_xs_cb_data;
-
-static void __recalc_timeout _((struct timeval*,struct timeval*,
-                                struct timeval*,struct timeval*, int* ));
-static in_addr_t __parse_address _((char*));
-static int __is_numeric_oid _((char*));
-static int __is_leaf _((struct tree*));
-static int __translate_appl_type _((char*));
-static int __translate_asn_type _((int));
-static int __snprint_value _((char *, size_t,
-                              netsnmp_variable_list*, struct tree *,
-                             int, int));
-static int __sprint_num_objid _((char *, oid *, int));
-static int __scan_num_objid _((char *, oid *, int *));
-static int __get_type_str _((int, char *));
-static int __get_label_iid _((char *, char **, char **, int));
-static int __oid_cmp _((oid *, int, oid *, int));
-static int __tp_sprint_num_objid _((char*,SnmpMibNode *));
-static SnmpMibNode * __get_next_mib_node _((SnmpMibNode *));
-static struct tree * __oid2tp _((oid*, int, struct tree *, int*));
-static struct tree * __tag2oid _((char *, char *, oid  *, int  *, int *, int));
-static int __concat_oid_str _((oid *, int *, char *));
-static int __add_var_val_str _((netsnmp_pdu *, oid *, int, char *,
-                                 int, int));
-static int __send_sync_pdu _((netsnmp_session *, netsnmp_pdu *,
-                              netsnmp_pdu **, int , SV *, SV *, SV *));
-static int __snmp_xs_cb __P((int, netsnmp_session *, int,
-                             netsnmp_pdu *, void *));
-static int __callback_wrapper __P((int, netsnmp_session *, int,
-                                    netsnmp_pdu *, void *));
-static SV* __push_cb_args2 _((SV * sv, SV * esv, SV * tsv));
-#define __push_cb_args(a,b) __push_cb_args2(a,b,NULL)
-static int __call_callback _((SV * sv, int flags));
-static char* __av_elem_pv _((AV * av, I32 key, char *dflt));
-static u_int compute_match _((const char *, const char *));
-
-#define USE_NUMERIC_OIDS 0x08
-#define NON_LEAF_NAME 0x04
-#define USE_LONG_NAMES 0x02
-#define FAIL_ON_NULL_IID 0x01
-#define NO_FLAGS 0x00
-
-/* Structures used by snmp_bulkwalk method to track requested OID's/subtrees. */
-typedef struct bulktbl {
-   oid req_oid[MAX_OID_LEN];   /* The OID originally requested.    */
-   oid last_oid[MAX_OID_LEN];  /* Last-seen OID under this branch. */
-   AV  *vars;                  /* Array of Varbinds for this OID.  */
-   char        req_len;                /* Length of requested OID.         */
-   char        last_len;               /* Length of last-seen OID.         */
-   char norepeat;              /* Is this a non-repeater OID?      */
-   char        complete;               /* Non-zero if this tree complete.  */
-   char        ignore;                 /* Ignore this OID, not requested.  */
-} bulktbl;
-
-/* Context for bulkwalk() sessions.  Used to store state across callbacks. */
-typedef struct walk_context {
-   SV          *sess_ref;      /* Reference to Perl SNMP session object.   */
-   SV          *perl_cb;       /* Pointer to Perl callback func or array.  */
-   bulktbl     *req_oids;      /* Pointer to bulktbl[] for requested OIDs. */
-   bulktbl     *repbase;       /* Pointer to first repeater in req_oids[]. */
-   bulktbl     *reqbase;       /* Pointer to start of requests req_oids[]. */
-   int         nreq_oids;      /* Number of valid bulktbls in req_oids[].  */
-   int         req_remain;     /* Number of outstanding requests remaining */
-   int         non_reps;       /* Number of nonrepeater vars in req_oids[] */
-   int         repeaters;      /* Number of repeater vars in req_oids[].   */
-   int         max_reps;       /* Maximum repetitions of variable per PDU. */
-   int         exp_reqid;      /* Expect a response to this request only.  */
-   int         getlabel_f;     /* Flag long/numeric names for get_label(). */
-   int         sprintval_f;    /* Flag enum/sprint values for sprintval(). */
-   int         pkts_exch;      /* Number of packet exchanges with agent.   */
-   int         oid_total;      /* Total number of OIDs received this walk. */
-   int         oid_saved;      /* Total number of OIDs saved as results.   */
-} walk_context;
-
-/* Prototypes for bulkwalk support functions. */
-static netsnmp_pdu *_bulkwalk_send_pdu _((walk_context *context));
-static int _bulkwalk_done     _((walk_context *context));
-static int _bulkwalk_recv_pdu _((walk_context *context, netsnmp_pdu *pdu));
-static int _bulkwalk_finish   _((walk_context *context, int okay));
-static int _bulkwalk_async_cb _((int op, SnmpSession *ss, int reqid,
-                                    netsnmp_pdu *pdu, void *context_ptr));
-
-/* Structure to hold valid context sessions. */
-struct valid_contexts {
-   walk_context        **valid;        /* Array of valid walk_context pointers.    */
-   int         sz_valid;       /* Maximum size of valid contexts array.    */
-   int         num_valid;      /* Count of valid contexts in the array.    */
-};
-static struct valid_contexts  *_valid_contexts = NULL;
-static int _context_add       _((walk_context *context));
-static int _context_del       _((walk_context *context));
-static int _context_okay      _((walk_context *context));
-
-/* Wrapper around fprintf(stderr, ...) for clean and easy debug output. */
-#ifdef DEBUGGING
-static int _debug_level = 0;
-#define DBOUT PerlIO_stderr(),
-#define        DBPRT(severity, otherargs)                                      \
-       do {                                                            \
-           if (_debug_level && severity <= _debug_level) {             \
-               (void)PerlIO_fprintf(PerlIO_stderr(), otherargs);               \
-           }                                                           \
-       } while (/*CONSTCOND*/0)
-
-char   _debugx[1024];  /* Space to sprintf() into - used by sprint_objid(). */
-
-#else  /* DEBUGGING */
-#define DBOUT
-#define        DBPRT(severity, otherargs)      /* Ignore */
-
-#endif /* DEBUGGING */
-
-void
-__libraries_init(char *appname)
-    {
-        static int have_inited = 0;
-
-        if (have_inited)
-            return;
-        have_inited = 1;
-
-        snmp_set_quick_print(1);
-        init_snmp(appname);
-    
-        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS, 1);
-        netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 1);
-
-        SOCK_STARTUP;
-    
-    }
-
-static void
-__recalc_timeout (tvp, ctvp, ltvp, itvp, block)
-struct timeval* tvp;
-struct timeval* ctvp;
-struct timeval* ltvp;
-struct timeval* itvp;
-int *block;
-{
-   struct timeval now;
-
-   if (!timerisset(itvp)) return;  /* interval zero means loop forever */
-   *block = 0;
-   gettimeofday(&now,(struct timezone *)0);
-
-   if (ctvp->tv_sec < 0) { /* first time or callback just fired */
-      timersub(&now,ltvp,ctvp);
-      timersub(ctvp,itvp,ctvp);
-      timersub(itvp,ctvp,ctvp);
-      timeradd(ltvp,itvp,ltvp);
-   } else {
-      timersub(&now,ltvp,ctvp);
-      timersub(itvp,ctvp,ctvp);
-   }
-
-   /* flag is set for callback but still hasnt fired so set to something
-    * small and we will service packets first if there are any ready
-    * (also guard against negative timeout - should never happen?)
-    */
-   if (!timerisset(ctvp) || ctvp->tv_sec < 0 || ctvp->tv_usec < 0) {
-      ctvp->tv_sec = 0;
-      ctvp->tv_usec = 10;
-   }
-
-   /* if snmp timeout > callback timeout or no more requests to process */
-   if (timercmp(tvp, ctvp, >) || !timerisset(tvp)) {
-      *tvp = *ctvp; /* use the smaller non-zero timeout */
-      timerclear(ctvp); /* used as a flag to let callback fire on timeout */
-   }
-}
-
-static in_addr_t
-__parse_address(address)
-char *address;
-{
-    in_addr_t addr;
-    struct sockaddr_in saddr;
-    struct hostent *hp;
-
-    if ((addr = inet_addr(address)) != -1)
-       return addr;
-    hp = gethostbyname(address);
-    if (hp == NULL){
-        return (-1); /* error value */
-    } else {
-       memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
-       return saddr.sin_addr.s_addr;
-    }
-
-}
-
-static int
-__is_numeric_oid (oidstr)
-char* oidstr;
-{
-  if (!oidstr) return 0;
-  for (; *oidstr; oidstr++) {
-     if (isalpha((int)*oidstr)) return 0;
-  }
-  return(1);
-}
-
-static int
-__is_leaf (tp)
-struct tree* tp;
-{
-   char buf[MAX_TYPE_NAME_LEN];
-   return (tp && __get_type_str(tp->type,buf));
-}
-
-static SnmpMibNode*
-__get_next_mib_node (tp)
-SnmpMibNode* tp;
-{
-   /* printf("tp = %lX, parent = %lX, peer = %lX, child = %lX\n",
-              tp, tp->parent, tp->next_peer, tp->child_list); */
-   if (tp->child_list) return(tp->child_list);
-   if (tp->next_peer) return(tp->next_peer);
-   if (!tp->parent) return(NULL);
-   for (tp = tp->parent; !tp->next_peer; tp = tp->parent) {
-      if (!tp->parent) return(NULL);
-   }
-   return(tp->next_peer);
-}
-
-static int
-__translate_appl_type(typestr)
-char* typestr;
-{
-       if (typestr == NULL || *typestr == '\0') return TYPE_UNKNOWN;
-
-       if (!strncasecmp(typestr,"INTEGER32",8))
-            return(TYPE_INTEGER32);
-       if (!strncasecmp(typestr,"INTEGER",3))
-            return(TYPE_INTEGER);
-       if (!strncasecmp(typestr,"UNSIGNED32",3))
-            return(TYPE_UNSIGNED32);
-       if (!strcasecmp(typestr,"COUNTER")) /* check all in case counter64 */
-            return(TYPE_COUNTER);
-       if (!strncasecmp(typestr,"GAUGE",3))
-            return(TYPE_GAUGE);
-       if (!strncasecmp(typestr,"IPADDR",3))
-            return(TYPE_IPADDR);
-       if (!strncasecmp(typestr,"OCTETSTR",3))
-            return(TYPE_OCTETSTR);
-       if (!strncasecmp(typestr,"TICKS",3))
-            return(TYPE_TIMETICKS);
-       if (!strncasecmp(typestr,"OPAQUE",3))
-            return(TYPE_OPAQUE);
-       if (!strncasecmp(typestr,"OBJECTID",3))
-            return(TYPE_OBJID);
-       if (!strncasecmp(typestr,"NETADDR",3))
-           return(TYPE_NETADDR);
-       if (!strncasecmp(typestr,"COUNTER64",3))
-           return(TYPE_COUNTER64);
-       if (!strncasecmp(typestr,"NULL",3))
-           return(TYPE_NULL);
-       if (!strncasecmp(typestr,"BITS",3))
-           return(TYPE_BITSTRING);
-       if (!strncasecmp(typestr,"ENDOFMIBVIEW",3))
-           return(SNMP_ENDOFMIBVIEW);
-       if (!strncasecmp(typestr,"NOSUCHOBJECT",7))
-           return(SNMP_NOSUCHOBJECT);
-       if (!strncasecmp(typestr,"NOSUCHINSTANCE",7))
-           return(SNMP_NOSUCHINSTANCE);
-       if (!strncasecmp(typestr,"UINTEGER",3))
-           return(TYPE_UINTEGER); /* historic - should not show up */
-                                   /* but it does?                  */
-       if (!strncasecmp(typestr, "NOTIF", 3))
-               return(TYPE_NOTIFTYPE);
-       if (!strncasecmp(typestr, "TRAP", 4))
-               return(TYPE_TRAPTYPE);
-        return(TYPE_UNKNOWN);
-}
-
-static int
-__translate_asn_type(type)
-int type;
-{
-   switch (type) {
-        case ASN_INTEGER:
-            return(TYPE_INTEGER);
-           break;
-       case ASN_OCTET_STR:
-            return(TYPE_OCTETSTR);
-           break;
-       case ASN_OPAQUE:
-            return(TYPE_OPAQUE);
-           break;
-       case ASN_OBJECT_ID:
-            return(TYPE_OBJID);
-           break;
-       case ASN_TIMETICKS:
-            return(TYPE_TIMETICKS);
-           break;
-       case ASN_GAUGE:
-            return(TYPE_GAUGE);
-           break;
-       case ASN_COUNTER:
-            return(TYPE_COUNTER);
-           break;
-       case ASN_IPADDRESS:
-            return(TYPE_IPADDR);
-           break;
-       case ASN_BIT_STR:
-            return(TYPE_BITSTRING);
-           break;
-       case ASN_NULL:
-            return(TYPE_NULL);
-           break;
-       /* no translation for these exception type values */
-       case SNMP_ENDOFMIBVIEW:
-       case SNMP_NOSUCHOBJECT:
-       case SNMP_NOSUCHINSTANCE:
-           return(type);
-           break;
-       case ASN_UINTEGER:
-            return(TYPE_UINTEGER);
-           break;
-       case ASN_COUNTER64:
-            return(TYPE_COUNTER64);
-           break;
-       default:
-            warn("translate_asn_type: unhandled asn type (%d)\n",type);
-            return(TYPE_OTHER);
-            break;
-        }
-}
-
-#define USE_BASIC 0
-#define USE_ENUMS 1
-#define USE_SPRINT_VALUE 2
-static int
-__snprint_value (buf, buf_len, var, tp, type, flag)
-char * buf;
-size_t buf_len;
-netsnmp_variable_list * var;
-struct tree * tp;
-int type;
-int flag;
-{
-   int len = 0;
-   u_char* ip;
-   struct enum_list *ep;
-
-
-   buf[0] = '\0';
-   if (flag == USE_SPRINT_VALUE) {
-       snprint_value(buf, buf_len, var->name, var->name_length, var);
-       len = strlen(buf);
-   } else {
-     switch (var->type) {
-        case ASN_INTEGER:
-           if (flag == USE_ENUMS) {
-              for(ep = tp->enums; ep; ep = ep->next) {
-                 if (ep->value == *var->val.integer) {
-                    strcpy(buf, ep->label);
-                    len = strlen(buf);
-                    break;
-                 }
-              }
-           }
-           if (!len) {
-              sprintf(buf,"%ld", *var->val.integer);
-              len = strlen(buf);
-           }
-           break;
-
-        case ASN_GAUGE:
-        case ASN_COUNTER:
-        case ASN_TIMETICKS:
-        case ASN_UINTEGER:
-           sprintf(buf,"%lu", (unsigned long) *var->val.integer);
-           len = strlen(buf);
-           break;
-
-        case ASN_OCTET_STR:
-        case ASN_OPAQUE:
-           memcpy(buf, (char*)var->val.string, var->val_len);
-           len = var->val_len;
-           break;
-
-        case ASN_IPADDRESS:
-          ip = (u_char*)var->val.string;
-          sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
-          len = strlen(buf);
-          break;
-
-        case ASN_NULL:
-           break;
-
-        case ASN_OBJECT_ID:
-          __sprint_num_objid(buf, (oid *)(var->val.objid),
-                             var->val_len/sizeof(oid));
-          len = strlen(buf);
-          break;
-
-       case SNMP_ENDOFMIBVIEW:
-          sprintf(buf,"%s", "ENDOFMIBVIEW");
-         break;
-       case SNMP_NOSUCHOBJECT:
-         sprintf(buf,"%s", "NOSUCHOBJECT");
-         break;
-       case SNMP_NOSUCHINSTANCE:
-         sprintf(buf,"%s", "NOSUCHINSTANCE");
-         break;
-
-        case ASN_COUNTER64:
-          printU64(buf,(struct counter64 *)var->val.counter64);
-          len = strlen(buf);
-          break;
-
-        case ASN_BIT_STR:
-            snprint_bitstring(buf, sizeof(buf), var, NULL, NULL, NULL);
-            len = strlen(buf);
-            break;
-
-        case ASN_NSAP:
-        default:
-           warn("snprint_value: asn type not handled %d\n",var->type);
-     }
-   }
-   return(len);
-}
-
-static int
-__sprint_num_objid (buf, objid, len)
-char *buf;
-oid *objid;
-int len;
-{
-   int i;
-   buf[0] = '\0';
-   for (i=0; i < len; i++) {
-       sprintf(buf,".%lu",*objid++);
-       buf += strlen(buf);
-   }
-   return SUCCESS;
-}
-
-static int
-__tp_sprint_num_objid (buf, tp)
-char *buf;
-SnmpMibNode *tp;
-{
-   oid newname[MAX_OID_LEN], *op;
-   /* code taken from get_node in snmp_client.c */
-   for (op = newname + MAX_OID_LEN - 1; op >= newname; op--) {
-      *op = tp->subid;
-      tp = tp->parent;
-      if (tp == NULL) break;
-   }
-   return __sprint_num_objid(buf, op, newname + MAX_OID_LEN - op);
-}
-
-static int
-__scan_num_objid (buf, objid, len)
-char *buf;
-oid *objid;
-int *len;
-{
-   char *cp;
-   *len = 0;
-   if (*buf == '.') buf++;
-   cp = buf;
-   while (*buf) {
-      if (*buf++ == '.') {
-         sscanf(cp, "%lu", objid++);
-         /* *objid++ = atoi(cp); */
-         (*len)++;
-         cp = buf;
-      } else {
-         if (isalpha((int)*buf)) {
-           return FAILURE;
-         }
-      }
-   }
-   sscanf(cp, "%lu", objid++);
-   /* *objid++ = atoi(cp); */
-   (*len)++;
-   return SUCCESS;
-}
-
-static int
-__get_type_str (type, str)
-int type;
-char * str;
-{
-   switch (type) {
-       case TYPE_OBJID:
-                       strcpy(str, "OBJECTID");
-               break;
-       case TYPE_OCTETSTR:
-                       strcpy(str, "OCTETSTR");
-               break;
-       case TYPE_INTEGER:
-                       strcpy(str, "INTEGER");
-               break;
-       case TYPE_INTEGER32:
-                       strcpy(str, "INTEGER32");
-               break;
-       case TYPE_UNSIGNED32:
-                       strcpy(str, "UNSIGNED32");
-               break;
-       case TYPE_NETADDR:
-                       strcpy(str, "NETADDR");
-               break;
-       case TYPE_IPADDR:
-                       strcpy(str, "IPADDR");
-               break;
-       case TYPE_COUNTER:
-                       strcpy(str, "COUNTER");
-               break;
-       case TYPE_GAUGE:
-                       strcpy(str, "GAUGE");
-               break;
-       case TYPE_TIMETICKS:
-                       strcpy(str, "TICKS");
-               break;
-       case TYPE_OPAQUE:
-                       strcpy(str, "OPAQUE");
-               break;
-       case TYPE_COUNTER64:
-                       strcpy(str, "COUNTER64");
-               break;
-       case TYPE_NULL:
-                strcpy(str, "NULL");
-                break;
-       case SNMP_ENDOFMIBVIEW:
-                strcpy(str, "ENDOFMIBVIEW");
-                break;
-       case SNMP_NOSUCHOBJECT:
-                strcpy(str, "NOSUCHOBJECT");
-                break;
-       case SNMP_NOSUCHINSTANCE:
-                strcpy(str, "NOSUCHINSTANCE");
-                break;
-       case TYPE_UINTEGER:
-                strcpy(str, "UINTEGER"); /* historic - should not show up */
-                                          /* but it does?                  */
-                break;
-       case TYPE_NOTIFTYPE:
-               strcpy(str, "NOTIF");
-               break;
-       case TYPE_BITSTRING:
-               strcpy(str, "BITS");
-               break;
-       case TYPE_TRAPTYPE:
-               strcpy(str, "TRAP");
-               break;
-       case TYPE_OTHER: /* not sure if this is a valid leaf type?? */
-       case TYPE_NSAPADDRESS:
-        default: /* unsupported types for now */
-           strcpy(str, "");
-           return(FAILURE);
-   }
-   return SUCCESS;
-}
-
-/* does a destructive disection of <label1>...<labeln>.<iid> returning
-   <labeln> and <iid> in seperate strings (note: will destructively
-   alter input string, 'name') */
-static int
-__get_label_iid (name, last_label, iid, flag)
-char * name;
-char ** last_label;
-char ** iid;
-int flag;
-{
-   char *lcp;
-   char *icp;
-   int len = strlen(name);
-   int found_label = 0;
-
-   *last_label = *iid = NULL;
-
-   if (len == 0) return(FAILURE);
-
-   /* Handle case where numeric oid's have been requested.  The input 'name'
-   ** in this case should be a numeric OID -- return failure if not.
-   */
-   if ((flag & USE_NUMERIC_OIDS)) {
-      if (!__is_numeric_oid(name))
-       return(FAILURE);
-
-      /* Walk backward through the string, looking for first two '.' chars */
-      lcp = &(name[len]);
-      icp = NULL;
-      while (lcp > name) {
-       if (*lcp == '.') {
-
-          /* If this is the first occurence of '.', note it in icp.
-          ** Otherwise, this must be the second occurrence, so break
-          ** out of the loop.
-          */
-          if (icp == NULL)
-             icp = lcp;
-          else
-             break;
-       }
-       lcp --;
-      }
-
-      /* Make sure we found at least a label and index. */
-      if (!icp)
-         return(FAILURE);
-
-      /* Push forward past leading '.' chars and separate the strings. */
-      lcp ++;
-      *icp ++ = '\0';
-
-      *last_label = (flag & USE_LONG_NAMES) ? name : lcp;
-      *iid        = icp;
-
-      return(SUCCESS);
-   }
-
-   lcp = icp = &(name[len]);
-
-   while (lcp > name) {
-      if (*lcp == '.') {
-       if (found_label) {
-          lcp++;
-           break;
-        } else {
-           icp = lcp;
-        }
-      }
-      if (!found_label && isalpha((int)*lcp)) found_label = 1;
-      lcp--;
-   }
-
-   if (!found_label || (!isdigit((int)*(icp+1)) && (flag & FAIL_ON_NULL_IID)))
-      return(FAILURE);
-
-   if (flag & NON_LEAF_NAME) { /* dont know where to start instance id */
-     /* put the whole thing in label */
-     icp = &(name[len]);
-     flag |= USE_LONG_NAMES;
-     /* special hack in case no mib loaded - object identifiers will
-      * start with .iso.<num>.<num>...., in which case it is preferable
-      * to make the label entirely numeric (i.e., convert "iso" => "1")
-      */
-      if (*lcp == '.' && lcp == name) {
-         if (!strncmp(".ccitt.",lcp,7)) {
-            name += 2;
-            *name = '.';
-            *(name+1) = '0';
-         } else if (!strncmp(".iso.",lcp,5)) {
-            name += 2;
-            *name = '.';
-            *(name+1) = '1';
-         } else if (!strncmp(".joint-iso-ccitt.",lcp,17)) {
-            name += 2;
-            *name = '.';
-            *(name+1) = '2';
-         }
-      }
-   } else if (*icp) {
-      *(icp++) = '\0';
-   }
-   *last_label = (flag & USE_LONG_NAMES ? name : lcp);
-
-   *iid = icp;
-
-   return(SUCCESS);
-}
-
-
-static int
-__oid_cmp(oida_arr, oida_arr_len, oidb_arr, oidb_arr_len)
-oid *oida_arr;
-int oida_arr_len;
-oid *oidb_arr;
-int oidb_arr_len;
-{
-   for (;oida_arr_len && oidb_arr_len;
-       oida_arr++, oida_arr_len--, oidb_arr++, oidb_arr_len--) {
-       if (*oida_arr == *oidb_arr) continue;
-       return(*oida_arr > *oidb_arr ? 1 : -1);
-   }
-   if (oida_arr_len == oidb_arr_len) return(0);
-   return(oida_arr_len > oidb_arr_len ? 1 : -1);
-}
-
-#define MAX_BAD 0xffffff
-
-static u_int
-compute_match(search_base, key)
-const char *search_base;
-const char *key;
-{
-   int rc;
-   regex_t parsetree;
-   regmatch_t pmatch;
-
-   rc = regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED);
-   if (rc == 0)
-      rc = regexec(&parsetree, search_base, 1, &pmatch, 0);
-   regfree(&parsetree);
-   if (rc == 0) {
-      return pmatch.rm_so;
-   }
-
-   return MAX_BAD;
-}
-
-static struct tree *
-__tag2oid(tag, iid, oid_arr, oid_arr_len, type, best_guess)
-char * tag;
-char * iid;
-oid  * oid_arr;
-int  * oid_arr_len;
-int  * type;
-int    best_guess;
-{
-   struct tree *tp = NULL;
-   struct tree *rtp = NULL;
-   DLL_IMPORT extern struct tree *tree_head;
-   oid newname[MAX_OID_LEN], *op;
-   int newname_len = 0;
-
-   if (type) *type = TYPE_UNKNOWN;
-   if (oid_arr_len) *oid_arr_len = 0;
-   if (!tag) goto done;
-
-   if (best_guess) {
-      tp = rtp = find_best_tree_node(tag, tree_head, NULL);
-      if (tp) {
-        if (type) *type = tp->type;
-        if ((oid_arr == NULL) || (oid_arr_len == NULL)) return rtp;
-        for (op = newname + MAX_OID_LEN - 1; op >= newname; op--) {
-            *op = tp->subid;
-           tp = tp->parent;
-           if (tp == NULL)
-              break;
-        }
-        *oid_arr_len = newname + MAX_OID_LEN - op;
-        memcpy(oid_arr, op, *oid_arr_len * sizeof(oid));
-      }
-      return(rtp);
-   }
-
-   if (strchr(tag,'.')) { /* if multi part tag  */
-      if (!__scan_num_objid(tag, newname, &newname_len)) { /* numeric tag */
-         newname_len = MAX_OID_LEN;
-         read_objid(tag, newname, &newname_len); /* long name */
-      }
-      if (type) *type = (tp ? tp->type : TYPE_UNKNOWN);
-      if ((oid_arr == NULL) || (oid_arr_len == NULL)) return rtp;
-      memcpy(oid_arr,(char*)newname,newname_len*sizeof(oid));
-      *oid_arr_len = newname_len;
-   } else { /* else it is a leaf */
-      rtp = tp = find_node(tag, Mib);
-      if (tp) {
-         if (type) *type = tp->type;
-         if ((oid_arr == NULL) || (oid_arr_len == NULL)) return rtp;
-         /* code taken from get_node in snmp_client.c */
-         for(op = newname + MAX_OID_LEN - 1; op >= newname; op--){
-           *op = tp->subid;
-          tp = tp->parent;
-          if (tp == NULL)
-             break;
-         }
-         *oid_arr_len = newname + MAX_OID_LEN - op;
-         memcpy(oid_arr, op, *oid_arr_len * sizeof(oid));
-      } else {
-         return(rtp);   /* HACK: otherwise, concat_oid_str confuses things */
-      }
-   }
- done:
-   if (iid && *iid) __concat_oid_str(oid_arr, oid_arr_len, iid);
-   return(rtp);
-}
-/* searches down the mib tree for the given oid
-   returns the last found tp and its index in lastind
- */
-static struct tree *
-__oid2tp (oidp, len, subtree, lastind)
-oid* oidp;
-int len;
-struct tree * subtree;
-int* lastind;
-{
-    struct tree    *return_tree = NULL;
-
-
-    for (; subtree; subtree = subtree->next_peer) {
-       if (*oidp == subtree->subid){
-           goto found;
-       }
-    }
-    *lastind=0;
-    return NULL;
-
-found:
-    if (len > 1){
-       return_tree =
-          __oid2tp(oidp + 1, len - 1, subtree->child_list, lastind);
-       (*lastind)++;
-    } else {
-       *lastind=1;
-    }
-    if (return_tree)
-       return return_tree;
-    else
-       return subtree;
-}
-
-/* function: __concat_oid_str
- *
- * This function converts a dotted-decimal string, soid_str, to an array
- * of oid types and concatenates them on doid_arr begining at the index
- * specified by doid_arr_len.
- *
- * returns : SUCCESS, FAILURE
- */
-static int
-__concat_oid_str(doid_arr, doid_arr_len, soid_str)
-oid *doid_arr;
-int *doid_arr_len;
-char * soid_str;
-{
-   char soid_buf[STR_BUF_SIZE];
-   char *cp;
-
-   if (!soid_str || !*soid_str) return SUCCESS;/* successfully added nothing */
-   if (*soid_str == '.') soid_str++;
-   strcpy(soid_buf, soid_str);
-   cp = strtok(soid_buf,".");
-   while (cp) {
-     sscanf(cp, "%lu", &(doid_arr[(*doid_arr_len)++]));
-     /* doid_arr[(*doid_arr_len)++] =  atoi(cp); */
-     cp = strtok(NULL,".");
-   }
-   return(SUCCESS);
-}
-
-/*
- * add a varbind to PDU
- */
-static int
-__add_var_val_str(pdu, name, name_length, val, len, type)
-    netsnmp_pdu *pdu;
-    oid *name;
-    int name_length;
-    char * val;
-    int len;
-    int type;
-{
-    netsnmp_variable_list *vars;
-    oid oidbuf[MAX_OID_LEN];
-    int ret = SUCCESS;
-    struct tree *tp;
-
-    if (pdu->variables == NULL){
-       pdu->variables = vars =
-           (netsnmp_variable_list *)calloc(1,sizeof(netsnmp_variable_list));
-    } else {
-       for(vars = pdu->variables;
-            vars->next_variable;
-            vars = vars->next_variable)
-           /*EXIT*/;
-       vars->next_variable =
-           (netsnmp_variable_list *)calloc(1,sizeof(netsnmp_variable_list));
-       vars = vars->next_variable;
-    }
-
-    vars->next_variable = NULL;
-    vars->name = (oid *)malloc(name_length * sizeof(oid));
-    memcpy((char *)vars->name, (char *)name, name_length * sizeof(oid));
-    vars->name_length = name_length;
-    switch (type) {
-      case TYPE_INTEGER:
-      case TYPE_INTEGER32:
-        vars->type = ASN_INTEGER;
-        vars->val.integer = (long *)malloc(sizeof(long));
-        if (val)
-            *(vars->val.integer) = strtol(val,NULL,0);
-        else {
-            ret = FAILURE;
-            *(vars->val.integer) = 0;
-        }
-        vars->val_len = sizeof(long);
-        break;
-
-      case TYPE_GAUGE:
-      case TYPE_UNSIGNED32:
-        vars->type = ASN_GAUGE;
-        goto UINT;
-      case TYPE_COUNTER:
-        vars->type = ASN_COUNTER;
-        goto UINT;
-      case TYPE_TIMETICKS:
-        vars->type = ASN_TIMETICKS;
-        goto UINT;
-      case TYPE_UINTEGER:
-        vars->type = ASN_UINTEGER;
-UINT:
-        vars->val.integer = (long *)malloc(sizeof(long));
-        if (val)
-            sscanf(val,"%lu",vars->val.integer);
-        else {
-            ret = FAILURE;
-            *(vars->val.integer) = 0;
-        }
-        vars->val_len = sizeof(long);
-        break;
-
-      case TYPE_OCTETSTR:
-       vars->type = ASN_OCTET_STR;
-       goto OCT;
-
-      case TYPE_BITSTRING:
-       vars->type = ASN_OCTET_STR;
-       goto OCT;
-
-      case TYPE_OPAQUE:
-        vars->type = ASN_OCTET_STR;
-OCT:
-        vars->val.string = (u_char *)malloc(len);
-        vars->val_len = len;
-        if (val && len)
-            memcpy((char *)vars->val.string, val, len);
-        else {
-            ret = FAILURE;
-            vars->val.string = strdup("");
-            vars->val_len = 0;
-        }
-        break;
-
-      case TYPE_IPADDR:
-        vars->type = ASN_IPADDRESS;
-        vars->val.integer = (long *)malloc(sizeof(long));
-        if (val)
-            *(vars->val.integer) = inet_addr(val);
-        else {
-            ret = FAILURE;
-            *(vars->val.integer) = 0;
-        }
-        vars->val_len = sizeof(long);
-        break;
-
-      case TYPE_OBJID:
-        vars->type = ASN_OBJECT_ID;
-       vars->val_len = MAX_OID_LEN;
-        /* if (read_objid(val, oidbuf, &(vars->val_len))) { */
-       /* tp = __tag2oid(val,NULL,oidbuf,&(vars->val_len),NULL,0); */
-        if (!val || !snmp_parse_oid(val, oidbuf, &vars->val_len)) {
-            vars->val.objid = NULL;
-           ret = FAILURE;
-        } else {
-            vars->val_len *= sizeof(oid);
-            vars->val.objid = (oid *)malloc(vars->val_len);
-            memcpy((char *)vars->val.objid, (char *)oidbuf, vars->val_len);
-        }
-        break;
-
-      default:
-        vars->type = ASN_NULL;
-       vars->val_len = 0;
-       vars->val.string = NULL;
-       ret = FAILURE;
-    }
-
-     return ret;
-}
-
-/* takes ss and pdu as input and updates the 'response' argument */
-/* the input 'pdu' argument will be freed */
-static int
-__send_sync_pdu(ss, pdu, response, retry_nosuch,
-               err_str_sv, err_num_sv, err_ind_sv)
-netsnmp_session *ss;
-netsnmp_pdu *pdu;
-netsnmp_pdu **response;
-int retry_nosuch;
-SV * err_str_sv;
-SV * err_num_sv;
-SV * err_ind_sv;
-{
-   int status;
-   long command = pdu->command;
-   *response = NULL;
-retry:
-
-   status = snmp_synch_response(ss, pdu, response);
-
-   if ((*response == NULL) && (status == STAT_SUCCESS)) status = STAT_ERROR;
-
-   switch (status) {
-      case STAT_SUCCESS:
-        switch ((*response)->errstat) {
-           case SNMP_ERR_NOERROR:
-              break;
-
-            case SNMP_ERR_NOSUCHNAME:
-               if (retry_nosuch && (pdu = snmp_fix_pdu(*response, command))) {
-                  if (*response) snmp_free_pdu(*response);
-                  goto retry;
-               }
-
-            /* Pv1, SNMPsec, Pv2p, v2c, v2u, v2*, and SNMPv3 PDUs */
-            case SNMP_ERR_TOOBIG:
-            case SNMP_ERR_BADVALUE:
-            case SNMP_ERR_READONLY:
-            case SNMP_ERR_GENERR:
-            /* in SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */
-            case SNMP_ERR_NOACCESS:
-            case SNMP_ERR_WRONGTYPE:
-            case SNMP_ERR_WRONGLENGTH:
-            case SNMP_ERR_WRONGENCODING:
-            case SNMP_ERR_WRONGVALUE:
-            case SNMP_ERR_NOCREATION:
-            case SNMP_ERR_INCONSISTENTVALUE:
-            case SNMP_ERR_RESOURCEUNAVAILABLE:
-            case SNMP_ERR_COMMITFAILED:
-            case SNMP_ERR_UNDOFAILED:
-            case SNMP_ERR_AUTHORIZATIONERROR:
-            case SNMP_ERR_NOTWRITABLE:
-            /* in SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */
-            case SNMP_ERR_INCONSISTENTNAME:
-            default:
-               sv_catpv(err_str_sv,
-                        (char*)snmp_errstring((*response)->errstat));
-               sv_setiv(err_num_sv, (*response)->errstat);
-              sv_setiv(err_ind_sv, (*response)->errindex);
-               status = (*response)->errstat;
-               break;
-        }
-         break;
-
-      case STAT_TIMEOUT:
-      case STAT_ERROR:
-          sv_catpv(err_str_sv, (char*)snmp_api_errstring(ss->s_snmp_errno));
-          sv_setiv(err_num_sv, ss->s_snmp_errno);
-         break;
-
-      default:
-         sv_catpv(err_str_sv, "send_sync_pdu: unknown status");
-         sv_setiv(err_num_sv, ss->s_snmp_errno);
-         break;
-   }
-
-   return(status);
-}
-
-static int
-__callback_wrapper (op, ss, reqid, pdu, cb_data)
-int op;
-netsnmp_session *ss;
-int reqid;
-netsnmp_pdu *pdu;
-void *cb_data;
-{
-  /* we should probably just increment the reference counter... */
-  /*  sv_inc(cb_data); */
-  return __snmp_xs_cb(op, ss, reqid, pdu, newSVsv(cb_data));
-}
-
-
-static int
-__snmp_xs_cb (op, ss, reqid, pdu, cb_data)
-int op;
-netsnmp_session *ss;
-int reqid;
-netsnmp_pdu *pdu;
-void *cb_data;
-{
-  SV *varlist_ref;
-  AV *varlist;
-  SV *varbind_ref;
-  AV *varbind;
-  SV *traplist_ref = NULL;
-  AV *traplist = NULL;
-  netsnmp_variable_list *vars;
-  struct tree *tp;
-  int len;
-  SV *tmp_sv;
-  int type;
-  char tmp_type_str[MAX_TYPE_NAME_LEN];
-  u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
-  size_t str_buf_len = sizeof(str_buf);
-  size_t out_len = 0;
-  int buf_over = 0;
-  char *label;
-  char *iid;
-  char *cp;
-  int getlabel_flag = NO_FLAGS;
-  int sprintval_flag = USE_BASIC;
-  netsnmp_pdu *reply_pdu;
-  int old_numeric, old_printfull;
-  netsnmp_transport *transport = NULL;
-
-  SV* cb = ((struct snmp_xs_cb_data*)cb_data)->perl_cb;
-  SV* sess_ref = ((struct snmp_xs_cb_data*)cb_data)->sess_ref;
-  SV **err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-  SV **err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-  SV **err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-
-  dSP;
-  ENTER;
-  SAVETMPS;
-
-  free(cb_data);
-
-  sv_setpv(*err_str_svp, (char*)snmp_errstring(pdu->errstat));
-  sv_setiv(*err_num_svp, pdu->errstat);
-  sv_setiv(*err_ind_svp, pdu->errindex);
-
-  varlist_ref = &sv_undef;     /* Prevent unintialized use below. */
-
-  switch (op) {
-  case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
-    traplist_ref = NULL;
-    switch (pdu->command) {
-    case SNMP_MSG_INFORM:
-      /*
-       * Ideally, we would use the return value from the callback to
-       * decide what response, if any, we send, and what the error status
-       * and error index should be.
-       */
-      reply_pdu = snmp_clone_pdu(pdu);
-      if (reply_pdu) {
-        reply_pdu->command = SNMP_MSG_RESPONSE;
-        reply_pdu->reqid = pdu->reqid;
-        reply_pdu->errstat = reply_pdu->errindex = 0;
-        snmp_send(ss, reply_pdu);
-      } else {
-        warn("Couldn't clone PDU for inform response");
-      }
-      /* FALLTHRU */
-    case SNMP_MSG_TRAP2:
-      traplist = newAV();
-      traplist_ref = newRV_noinc((SV*)traplist);
-#if 0
-      /* of dubious utility... */
-      av_push(traplist, newSViv(pdu->command));
-#endif
-      av_push(traplist, newSViv(pdu->reqid));
-      if ((transport = snmp_sess_transport(snmp_sess_pointer(ss))) != NULL) {
-       cp = transport->f_fmtaddr(transport, pdu->transport_data,
-                                 pdu->transport_data_length);
-       av_push(traplist, newSVpv(cp, strlen(cp)));
-       free(cp);
-      } else {
-       /*  This shouldn't ever happen; every session has a transport.  */
-       av_push(traplist, newSVpv("", 0));
-      }
-      av_push(traplist, newSVpv((char*) pdu->community, pdu->community_len));
-      /* FALLTHRU */
-    case SNMP_MSG_RESPONSE:
-      {
-      varlist = newAV();
-      varlist_ref = newRV_noinc((SV*)varlist);
-
-      /*
-      ** Set up for numeric OID's, if necessary.  Save the old values
-      ** so that they can be restored when we finish -- these are
-      ** library-wide globals, and have to be set/restored for each
-      ** session.
-      */
-      old_numeric = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS);
-      old_printfull = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID);
-      if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1))) {
-         getlabel_flag |= USE_NUMERIC_OIDS;
-         netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS, 1);
-      }
-      if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1))) {
-         getlabel_flag |= USE_LONG_NAMES;
-         netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID, 1);
-      }
-
-      sv_bless(varlist_ref, gv_stashpv("SNMP::VarList",0));
-      for(vars = (pdu?pdu->variables:NULL); vars; vars = vars->next_variable) {
-         varbind = newAV();
-         varbind_ref = newRV_noinc((SV*)varbind);
-         sv_bless(varbind_ref, gv_stashpv("SNMP::Varbind",0));
-         av_push(varlist, varbind_ref);
-         *str_buf = '.';
-         *(str_buf+1) = '\0';
-         out_len = 0;
-         tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
-                                                &out_len, 0, &buf_over,
-                                                vars->name,vars->name_length);
-         str_buf[sizeof(str_buf)-1] = '\0';
-         if (__is_leaf(tp)) {
-            type = tp->type;
-         } else {
-            getlabel_flag |= NON_LEAF_NAME;
-            type = __translate_asn_type(vars->type);
-         }
-         __get_label_iid(str_buf,&label,&iid,getlabel_flag);
-         av_store(varbind, VARBIND_TAG_F,
-                  newSVpv(label, strlen(label)));
-         av_store(varbind, VARBIND_IID_F,
-                  newSVpv(iid, strlen(iid)));
-         __get_type_str(type, tmp_type_str);
-         tmp_sv = newSVpv(tmp_type_str, strlen(tmp_type_str));
-         av_store(varbind, VARBIND_TYPE_F, tmp_sv);
-         len = __snprint_value(str_buf, sizeof(str_buf),
-                              vars, tp, type, sprintval_flag);
-         tmp_sv = newSVpv((char*)str_buf, len);
-         av_store(varbind, VARBIND_VAL_F, tmp_sv);
-      } /* for */
-
-      /* Reset the library's behavior for numeric/symbolic OID's. */
-      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS, old_numeric );
-      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID, old_printfull);
-
-      } /* case SNMP_MSG_RESPONSE */
-      break;
-    default:;
-    } /* switch pdu->command */
-    break;
-
-  case NETSNMP_CALLBACK_OP_TIMED_OUT:
-    varlist_ref = &sv_undef;
-    break;
-  default:;
-  } /* switch op */
-  sv_2mortal(cb);
-  cb = __push_cb_args2(cb,
-                 (SvTRUE(varlist_ref) ? sv_2mortal(varlist_ref):varlist_ref),
-                (SvTRUE(traplist_ref) ? sv_2mortal(traplist_ref):traplist_ref));
-  __call_callback(cb, G_DISCARD);
-
-  FREETMPS;
-  LEAVE;
-  sv_2mortal(sess_ref);
-  return 1;
-}
-
-static SV *
-__push_cb_args2(sv,esv,tsv)
-SV *sv;
-SV *esv;
-SV *tsv;
-{
-   dSP;
-   if (SvTYPE(SvRV(sv)) != SVt_PVCV) sv = SvRV(sv);
-
-   PUSHMARK(sp);
-   if (SvTYPE(sv) == SVt_PVAV) {
-      AV *av = (AV *) sv;
-      int n = av_len(av) + 1;
-      SV **x = av_fetch(av, 0, 0);
-      if (x) {
-         int i = 1;
-         sv = *x;
-
-         for (i = 1; i < n; i++) {
-            x = av_fetch(av, i, 0);
-            if (x) {
-               SV *arg = *x;
-               XPUSHs(sv_mortalcopy(arg));
-            } else {
-               XPUSHs(&sv_undef);
-            }
-         }
-      } else {
-         sv = &sv_undef;
-      }
-   }
-   if (esv) XPUSHs(sv_mortalcopy(esv));
-   if (tsv) XPUSHs(sv_mortalcopy(tsv));
-   PUTBACK;
-   return sv;
-}
-
-static int
-__call_callback(sv, flags)
-SV *sv;
-int flags;
-{
- dSP;
- I32 myframe = TOPMARK;
- I32 count;
- ENTER;
- if (SvTYPE(sv) == SVt_PVCV)
-  {
-   count = perl_call_sv(sv, flags);
-  }
- else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV)
-  {
-   count = perl_call_sv(SvRV(sv), flags);
-  }
- else
-  {
-
-   SV **top = stack_base + myframe + 1;
-   SV *obj = *top;
-   if (SvPOK(sv) && SvROK(obj) && SvOBJECT(SvRV(obj)))
-    {
-     count = perl_call_method(SvPV(sv, na), flags);
-    }
-   else if (SvPOK(obj) && SvROK(sv) && SvOBJECT(SvRV(sv)))
-    {
-     /* We have obj method ...
-        Used to be used instead of LangMethodCall()
-      */
-     *top = sv;
-     count = perl_call_method(SvPV(obj, na), flags);
-    }
-   else
-    {
-     count = perl_call_sv(sv, flags);
-    }
- }
- LEAVE;
- return count;
-}
-
-/* Bulkwalk support routines */
-
-/* Add a context pointer to the list of valid pointers.  Place it in the first
-** NULL slot in the array.
-*/
-static int
-_context_add(walk_context *context)
-{
-    int i, j, new_sz;
-
-    if ((i = _context_okay(context)) != 0)     /* Already exists?  Okay. */
-       return i;
-
-    /* Initialize the array if necessary. */
-    if (_valid_contexts == NULL) {
-
-       /* Create the _valid_contexts structure. */
-       Newz(0, _valid_contexts, 1, struct valid_contexts);
-       assert(_valid_contexts != NULL);
-
-       /* Populate the original valid contexts array. */
-       Newz(0, _valid_contexts->valid, 4, walk_context *);
-       assert(_valid_contexts->valid != NULL);
-
-       /* Computer number of slots in the array. */
-       _valid_contexts->sz_valid = sizeof(*_valid_contexts->valid) /
-                                                       sizeof(walk_context *);
-
-       for (i = 0; i < _valid_contexts->sz_valid; i++)
-           _valid_contexts->valid[i] = NULL;
-
-       DBPRT(3, (DBOUT "Created valid_context array 0x%p (%d slots)\n",
-                           _valid_contexts->valid, _valid_contexts->sz_valid));
-    }
-
-    /* Search through the list, looking for NULL's -- unused slots. */
-    for (i = 0; i < _valid_contexts->sz_valid; i++)
-       if (_valid_contexts->valid[i] == NULL)
-           break;
-
-    /* Did we walk off the end of the list?  Need to grow the list.  Double
-    ** it for now.
-    */
-    if (i == _valid_contexts->sz_valid) {
-       new_sz = _valid_contexts->sz_valid * 2;
-
-       Renew(_valid_contexts->valid, new_sz, walk_context *);
-       assert(_valid_contexts->valid != NULL);
-
-       DBPRT(3, (DBOUT "Resized valid_context array 0x%p from %d to %d slots\n",
-                   _valid_contexts->valid, _valid_contexts->sz_valid, new_sz));
-
-       _valid_contexts->sz_valid = new_sz;
-
-       /* Initialize the new half of the resized array. */
-       for (j = i; j < new_sz; j++)
-           _valid_contexts->valid[j] = NULL;
-    }
-
-    /* Store the context pointer in the array and return 0 (success). */
-    _valid_contexts->valid[i] = context;
-    DBPRT(3,( "Add context 0x%p to valid context list\n", context));
-    return 0;
-}
-
-/* Remove a context pointer from the valid list.  Replace the pointer with
-** NULL in the valid pointer list.
-*/
-static int
-_context_del(walk_context *context)
-{
-    int i;
-
-    if (_valid_contexts == NULL)       /* Make sure it was initialized. */
-       return 1;
-
-    for (i = 0; i < _valid_contexts->sz_valid; i++) {
-       if (_valid_contexts->valid[i] == context) {
-           DBPRT(3,( "Remove context 0x%p from valid context list\n", context));
-           _valid_contexts->valid[i] = NULL;   /* Remove it from the list.  */
-           return 0;                           /* Return successful status. */
-       }
-    }
-    return 1;
-}
-
-/* Check if a specific context pointer is in the valid list.  Return true (1)
-** if the context is still in the valid list, or 0 if not (or context is NULL).
-*/
-static int
-_context_okay(walk_context *context)
-{
-    int i;
-
-    if (_valid_contexts == NULL)       /* Make sure it was initialized. */
-       return 0;
-
-    if (context == NULL)               /* Asked about a NULL context? Fail. */
-       return 0;
-
-    for (i = 0; i < _valid_contexts->sz_valid; i++)
-       if (_valid_contexts->valid[i] == context)
-           return 1;                   /* Found it! */
-
-    return 0;                          /* No match -- return failure. */
-}
-
-/* Check if the walk is completed, based upon the context.  Also set the
-** ignore flag on any completed variables -- this prevents them from being
-** being sent in later packets.
-*/
-static int
-_bulkwalk_done(walk_context *context)
-{
-   int is_done = 1;
-   int i;
-   bulktbl *bt_entry;          /* bulktbl requested OID entry */
-
-   /* Don't consider walk done until at least one packet has been exchanged. */
-   if (context->pkts_exch == 0)
-      return 0;
-
-   /* Fix up any requests that have completed.  If the complete flag is set,
-   ** or it is a non-repeater OID, set the ignore flag so that it will not
-   ** be considered further.  Assume we are done with the walk, and note
-   ** otherwise if we aren't.  Return 1 if all requests are complete, or 0
-   ** if there's more to do.
-   */
-   for (i = 0; i < context->nreq_oids; i ++) {
-      bt_entry = &context->req_oids[i];
-
-      if (bt_entry->complete || bt_entry->norepeat) {
-
-       /* This request is complete.  Remove it from list of
-       ** walks still in progress.
-       */
-       DBPRT(1, (DBOUT "Ignoring %s request oid %s\n",
-             bt_entry->norepeat? "nonrepeater" : "completed",
-             snprint_objid(_debugx, sizeof(_debugx), bt_entry->req_oid,
-                                   bt_entry->req_len)));
-
-       /* Ignore this OID in any further packets. */
-       bt_entry->ignore = 1;
-      }
-
-      /* If any OID is not being ignored, the walk is not done.  Must loop
-      ** through all requests to do the fixup -- no early return possible.
-      */
-      if (!bt_entry->ignore)
-        is_done = 0;
-   }
-
-   return is_done;             /* Did the walk complete? */
-}
-
-/* Callback registered with SNMP.  Return 1 from this callback to cause the
-** current request to be deleted from the retransmit queue.
-*/
-static int
-_bulkwalk_async_cb(int         op,
-                 SnmpSession   *ss,
-                 int           reqid,
-                 netsnmp_pdu *pdu,
-                 void          *context_ptr)
-{
-   walk_context *context;
-   int done = 0;
-   int npushed;
-   SV **err_str_svp;
-   SV **err_num_svp;
-
-   /* Handle callback request for asynchronous bulkwalk.  If the bulkwalk has
-   ** not completed, and has not timed out, send the next request packet in
-   ** the walk.
-   **
-   ** Return 0 to indicate success (caller ignores return value).
-   */
-
-   DBPRT(2, (DBOUT "bulkwalk_async_cb(op %d, reqid 0x%08X, context 0x%p)\n",
-                                                       op, reqid, context_ptr));
-
-   context = (walk_context *)context_ptr;
-
-   /* Make certain this is a valid context pointer.  This pdu may
-   ** have been retransmitted after the bulkwalk was completed
-   ** (and the context was destroyed).  If so, just return.
-   */
-   if (!_context_okay(context)) {
-      DBPRT(2,( "Ignoring PDU for dead context 0x%p...\n", context));
-      return 1;
-   }
-
-   /* Is this a retransmission of a request we've already seen or some
-   ** unexpected request id?  If so, just ignore it.
-   */
-   if (reqid != context->exp_reqid) {
-       DBPRT(2,
-             ("Got reqid 0x%08X, expected reqid 0x%08X.  Ignoring...\n", reqid,
-              context->exp_reqid));
-      return 1;
-   }
-   /* Ignore any future packets for this reqid. */
-   context->exp_reqid = -1;
-
-   err_str_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorStr", 8, 1);
-   err_num_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorNum", 8, 1);
-
-   switch (op) {
-      case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
-      {
-        DBPRT(1,( "Received message for reqid 0x%08X ...\n", reqid));
-
-        switch (pdu->command)
-        {
-           case SNMP_MSG_RESPONSE:
-           {
-              DBPRT(2, (DBOUT "Calling bulkwalk_recv_pdu(context 0x%p, pdu 0x%p)\n",
-                                                          context_ptr, pdu));
-
-              /* Handle the response PDU.  If an error occurs or there were
-              ** no variables in the response, consider the walk done.  If
-              ** the response was okay, check if we have any more to do after
-              ** this response.
-              */
-              if (_bulkwalk_recv_pdu(context, pdu) <= 0)
-                 done = 1;
-              else
-                 done = _bulkwalk_done(context); /* Also set req ignore flags */
-              break;
-           }
-           default:
-           {
-              DBPRT(1,( "unexpected pdu->command %d\n", pdu->command));
-              done = 1;   /* "This can't happen!", so bail out when it does. */
-              break;
-           }
-        }
-
-        break;
-      }
-
-      case NETSNMP_CALLBACK_OP_TIMED_OUT:
-      {
-        DBPRT(1,( "\n*** Timeout for reqid 0x%08X\n\n", reqid));
-
-         sv_setpv(*err_str_svp, (char*)snmp_api_errstring(SNMPERR_TIMEOUT));
-         sv_setiv(*err_num_svp, SNMPERR_TIMEOUT);
-
-        /* Timeout means something bad has happened.  Return a not-okay
-        ** result to the async callback.
-        */
-        npushed = _bulkwalk_finish(context, 0 /* NOT OKAY */);
-        return 1;
-      }
-
-      default:
-      {
-        DBPRT(1,( "unexpected callback op %d\n", op));
-         sv_setpv(*err_str_svp, (char*)snmp_api_errstring(SNMPERR_GENERR));
-         sv_setiv(*err_num_svp, SNMPERR_GENERR);
-        npushed = _bulkwalk_finish(context, 0 /* NOT OKAY */);
-        return 1;
-      }
-   }
-
-   /* We have either timed out, or received and parsed in a response.  Now,
-   ** if we have more variables to test, call bulkwalk_send_pdu() to enqueue
-   ** another async packet, and return.
-   **
-   ** If, however, the bulkwalk has completed (or an error has occurred that
-   ** cuts the walk short), call bulkwalk_finish() to push the results onto
-   ** the Perl call stack.  Then explicitly call the Perl callback that was
-   ** passed in by the user oh-so-long-ago.
-   */
-   if (!done) {
-      DBPRT(1,( "bulkwalk not complete -- send next pdu from callback\n"));
-
-      if (_bulkwalk_send_pdu(context) != NULL)
-        return 1;
-
-      DBPRT(1,( "send_pdu() failed!\n"));
-      /* Fall through and return what we have so far. */
-   }
-
-   /* Call the perl callback with the return values and we're done. */
-   npushed = _bulkwalk_finish(context, 1 /* OKAY */);
-
-   return 1;
-}
-
-static netsnmp_pdu *
-_bulkwalk_send_pdu(walk_context *context)
-{
-   netsnmp_pdu *pdu = NULL;
-   netsnmp_pdu *response = NULL;
-   struct bulktbl  *bt_entry;
-   int nvars = 0;
-   int reqid;
-   int status;
-   int i;
-
-   /* Send a pdu requesting any remaining variables in the context.
-   **
-   ** In synchronous mode, returns a pointer to the response packet.
-   **
-   ** In asynchronous mode, it returns the request ID, cast to a struct snmp *,
-   **   not a valid SNMP response packet.  The async code should not be trying
-   **   to get variables out of this "response".
-   **
-   ** In either case, return a NULL pointer on error or failure.
-   */
-
-   SV **sess_ptr_sv = hv_fetch((HV*)SvRV(context->sess_ref), "SessPtr", 7, 1);
-   netsnmp_session *ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-   SV **err_str_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorStr", 8, 1);
-   SV **err_num_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorNum", 8, 1);
-   SV **err_ind_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorInd", 8, 1);
-
-   /* Create a new PDU and send the remaining set of requests to the agent. */
-   pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
-   if (pdu == NULL) {
-      sv_setpv(*err_str_svp, "snmp_pdu_create(GETBULK) failed: ");
-      sv_catpv(*err_str_svp, strerror(errno));
-      sv_setiv(*err_num_svp, SNMPERR_MALLOC);
-      goto err;
-   }
-
-   /* Request non-repeater variables only in the first packet exchange. */
-   pdu->errstat  = (context->pkts_exch == 0) ? context->non_reps : 0;
-   pdu->errindex = context->max_reps;
-
-   for (i = 0; i < context->nreq_oids; i++) {
-      bt_entry = &context->req_oids[i];
-      if (bt_entry->ignore)
-        continue;
-
-      assert(bt_entry->complete == 0);
-
-      if (!snmp_add_null_var(pdu, bt_entry->last_oid, bt_entry->last_len)) {
-        sv_setpv(*err_str_svp, "snmp_add_null_var() failed");
-        sv_setiv(*err_num_svp, SNMPERR_GENERR);
-        sv_setiv(*err_ind_svp, i);
-        goto err;
-      }
-
-      nvars ++;
-
-      DBPRT(1, (DBOUT "   Add %srepeater %s\n", bt_entry->norepeat ? "non" : "",
-                snprint_objid(_debugx, sizeof(_debugx), bt_entry->last_oid, bt_entry->last_len)));
-   }
-
-   /* Make sure variables are actually being requested in the packet. */
-   assert (nvars != 0);
-
-   context->pkts_exch ++;
-
-   DBPRT(1, (DBOUT "Sending %ssynchronous request %d...\n",
-                    SvTRUE(context->perl_cb) ? "a" : "", context->pkts_exch));
-
-   /* We handle the asynchronous and synchronous requests differently here.
-   ** For async, we simply enqueue the packet with a callback to handle the
-   ** returned response, then return.  Note that this we call the bulkwalk
-   ** callback, and hand it the walk_context, not the Perl callback.  The
-   ** snmp_async_send() function returns the reqid on success, 0 on failure.
-   */
-   if (SvTRUE(context->perl_cb)) {
-      reqid = snmp_async_send(ss, pdu, _bulkwalk_async_cb, (void *)context);
-
-      DBPRT(2,( "bulkwalk_send_pdu(): snmp_async_send => 0x%08X\n", reqid));
-
-      if (reqid == 0) {
-        sv_setpv(*err_str_svp, (char*)snmp_api_errstring(ss->s_snmp_errno));
-        sv_setiv(*err_num_svp, ss->s_snmp_errno);
-        goto err;
-      }
-
-      /* Make a note of the request we expect to be answered. */
-      context->exp_reqid = reqid;
-
-      /* Callbacks take care of the rest.  Let the caller know how many vars
-      ** we sent in this request.  Note that this is not a valid SNMP PDU,
-      ** but that's because a response has not yet been received.
-      */
-      return (netsnmp_pdu *)reqid;
-   }
-
-   /* This code is for synchronous mode support.
-   **
-   ** Send the PDU and block awaiting the response.  Return the response
-   ** packet back to the caller.  Note that snmp_sess_read() frees the pdu.
-   */
-   status = __send_sync_pdu(ss, pdu, &response, NO_RETRY_NOSUCH,
-                                   *err_str_svp, *err_num_svp, *err_ind_svp);
-
-   pdu = NULL;
-
-   /* Check for a failed request.  __send_sync_pdu() will set the appropriate
-   ** values in the error string and number SV's.
-   */
-   if (status != STAT_SUCCESS) {
-      DBPRT(1,( "__send_sync_pdu() -> %d\n",(int)status));
-      goto err;
-   }
-
-   DBPRT(1, (DBOUT "%d packets exchanged, response 0x%p\n", context->pkts_exch,
-                                                                   response));
-   return response;
-
-
-   err:
-   if (pdu)
-      snmp_free_pdu(pdu);
-   return NULL;
-}
-
-/* Handle an incoming GETBULK response PDU.  This function just pulls the
-** variables off of the PDU and builds up the arrays of returned values
-** that are stored in the context.
-**
-** Returns the number of variables found in this packet, or -1 on error.
-** Note that the caller is expected to free the pdu.
-*/
-static int
-_bulkwalk_recv_pdu(walk_context *context, netsnmp_pdu *pdu)
-{
-   netsnmp_variable_list *vars;
-   struct tree *tp;
-   char                type_str[MAX_TYPE_NAME_LEN];
-   u_char      str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
-   size_t str_buf_len = sizeof(str_buf);
-   size_t out_len = 0;
-   int buf_over = 0;
-   char                *label;
-   char                *iid;
-   bulktbl     *expect = NULL;
-   int         old_numeric;
-   int         old_printfull;
-   int         old_format;
-   int         getlabel_flag;
-   int         type;
-   int         pix;
-   int         len;
-   int         i;
-   AV          *varbind;
-   SV          *rv;
-   SV **sess_ptr_sv = hv_fetch((HV*)SvRV(context->sess_ref), "SessPtr", 7, 1);
-   SV **err_str_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorStr", 8, 1);
-   SV **err_num_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorNum", 8, 1);
-   SV **err_ind_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorInd", 8, 1);
-
-   DBPRT(3, (DBOUT "bulkwalk: sess_ref = 0x%p, sess_ptr_sv = 0x%p\n",
-             context->sess_ref, sess_ptr_sv));
-
-   /* Set up for numeric OID's, if necessary.  Save the old values
-   ** so that they can be restored when we finish -- these are
-   ** library-wide globals, and have to be set/restored for each
-   ** session.
-   */
-   old_numeric   = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS);
-   old_printfull = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID);
-   old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
-   if (context->getlabel_f & USE_NUMERIC_OIDS) {
-      DBPRT(2,( "Using numeric oid's\n"));
-      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS, 1);
-      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID, 1);
-      netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC);
-   }
-
-   /* Parse through the list of variables returned, adding each return to
-   ** the appropriate array (as a VarBind).  Also keep track of which
-   ** repeated OID we're expecting to see, and check if that tree walk has
-   ** been completed (i.e. we've walked past the root of our request).  If
-   ** so, mark the request complete so that we don't send it again in any
-   ** subsequent request packets.
-   */
-   if (context->pkts_exch == 1)
-      context->reqbase = context->req_oids;    /* Request with non-repeaters */
-   else
-      context->reqbase = context->repbase;     /* Request only repeater vars */
-
-   /* Note the first variable we expect to see.  Should be reqbase. */
-   expect = context->reqbase;
-
-   for (vars = pdu->variables, pix = 0;
-       vars != NULL;
-       vars = vars->next_variable, pix ++)
-   {
-
-      /* If no outstanding requests remain, we're done.  This works, but it
-      ** causes the reported total variable count to be wrong (since the
-      ** remaining vars on the last packet are not counted).  In practice
-      ** this is probably worth the win, but for debugging it's not.
-      */
-      if (context->req_remain == 0) {
-        DBPRT(2,( "No outstanding requests remain.  Terminating processing.\n"));
-        while (vars) {
-           pix ++;
-           vars = vars->next_variable;
-        }
-        break;
-      }
-
-      /* Determine which OID we expect to see next.  We assert that the OID's
-      ** must be returned in the expected order.  The first nreq_oids returns
-      ** should match the req_oids array, after that, we must cycle through
-      ** the repeaters in order.  Non-repeaters are not included in later
-      ** packets, so cannot have the "ignore" flag set.
-      */
-
-      if (context->oid_saved < context->non_reps) {
-        assert(context->pkts_exch == 1);
-
-        expect = context->reqbase ++;
-        assert(expect->norepeat);
-
-      } else {
-        /* Must be a repeater.  Look for the first one that is not being
-        ** ignored.  Make sure we don't loop around to where we started.
-        ** If we get here but everything is being ignored, there's a problem.
-        **
-        ** Note that we *do* accept completed but not ignored OID's -- these
-        ** are OID's for trees that have been completed sometime in this
-        ** response, but must be looked at to maintain ordering.
-        */
-
-        if (pix == 0) {
-           /* Special case code for no non-repeater case.  This
-           ** is necessary because expect normally points to the
-           ** last non-repeater upon entry to this code (so the
-           ** '++expect' below increments it into the repeaters
-           ** section of the req_oids[] array).
-           ** If there are no non-repeaters, the expect pointer
-           ** is never initialized.  This addresses this problem.
-           */
-           expect = context->reqbase;
-
-        } else {
-
-           /* Find the repeater OID we expect to see.  Ignore any
-           ** OID's marked 'ignore' -- these have been completed
-           ** and were not requested in this iteration.
-           */
-           for (i = 0; i < context->repeaters; i++) {
-
-              /* Loop around to first repeater if we hit the end. */
-              if (++ expect == &context->req_oids[context->nreq_oids])
-                 expect = context->reqbase = context->repbase;
-
-              /* Stop if this OID is not being ignored. */
-              if (!expect->ignore)
-                 break;
-           }
-
-           /* Make sure we did find an expected OID. */
-           assert(i <= context->repeaters);
-        }
-      }
-
-      DBPRT(2, (DBOUT "Var %03d request %s\n", pix, snprint_objid(_debugx, sizeof(_debugx), 
-                                            expect->req_oid, expect->req_len)));
-
-      /* Did we receive an error condition for this variable?
-      ** If it's a repeated variable, mark it as complete and
-      ** fall through to the block below.
-      */
-      if ((vars->type == SNMP_ENDOFMIBVIEW) ||
-         (vars->type == SNMP_NOSUCHOBJECT) ||
-         (vars->type == SNMP_NOSUCHINSTANCE))
-      {
-        DBPRT(2,( "error type %d\n", (int)vars->type));
-
-        /* ENDOFMIBVIEW should be okay for a repeater - just walked off the
-        ** end of the tree.  Mark the request as complete, and go on to the
-        ** next one.
-        */
-        if ((context->oid_saved >= context->non_reps) &&
-            (vars->type == SNMP_ENDOFMIBVIEW))
-        {
-           expect->complete = 1;
-           DBPRT(2, (DBOUT "Ran out of tree for oid %s\n",
-                          snprint_objid(_debugx, sizeof(_debugx), vars->name,vars->name_length)));
-
-           context->req_remain --;
-
-           /* Go on to the next variable. */
-           continue;
-
-        }
-        sv_setpv(*err_str_svp,
-                             (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
-        sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
-        sv_setiv(*err_ind_svp, pix);
-        goto err;
-      }
-
-      /* If this is not the first packet, skip any duplicated OID values, if
-      ** present.  These should be the seed values copied from the last OID's
-      ** of the previous packet.  In practice we don't see this, but it is
-      ** easy enough to do, and will avoid confusion for the caller from mis-
-      ** behaving agents (badly misbehaving... ;^).
-      */
-      if ((context->pkts_exch > 1) && (pix < context->repeaters)) {
-        if (__oid_cmp(vars->name, vars->name_length,
-                                  context->reqbase[pix].last_oid,
-                                  context->reqbase[pix].last_len) == 0)
-        {
-           DBPRT(2, (DBOUT "Ignoring repeat oid: %s\n",
-                       snprint_objid(_debugx, sizeof(_debugx), vars->name,vars->name_length)));
-
-           continue;
-        }
-      }
-
-      context->oid_total ++;   /* Count each variable received. */
-
-      /* If this is a non-repeater, handle it.  Otherwise, if it is a
-      ** repeater, has the walk wandered off of the requested tree?  If so,
-      ** this request is complete, so mark it as such.  Ignore any other
-      ** variables in a completed request.  In order to maintain the correct
-      ** ordering of which variables we expect to see in this packet, we must
-      ** not set the ignore flags immediately.  It is done in bulkwalk_done().
-      ** XXX Can we use 'expect' instead of 'context->req_oids[pix]'?
-      */
-      if (context->oid_saved < context->non_reps) {
-        DBPRT(2, (DBOUT "   expected var %s (nonrepeater %d/%d)\n",
-                    snprint_objid(_debugx, sizeof(_debugx), context->req_oids[pix].req_oid,
-                                          context->req_oids[pix].req_len),
-                    pix, context->non_reps));
-        DBPRT(2, (DBOUT "   received var %s\n",
-                    snprint_objid(_debugx, sizeof(_debugx), vars->name, vars->name_length)));
-
-        /* This non-repeater has now been seen, so mark the sub-tree as
-        ** completed.  Note that this may not be the same oid as requested,
-        ** since non-repeaters act like GETNEXT requests, not GET's. <sigh>
-        */
-        context->req_oids[pix].complete = 1;
-        context->req_remain --;
-
-      } else {         /* Must be a repeater variable. */
-
-        DBPRT(2, (DBOUT "   received oid %s\n",
-              snprint_objid(_debugx, sizeof(_debugx), vars->name, vars->name_length)));
-
-        /* Are we already done with this tree?  If so, just ignore this
-        ** variable and move on to the next expected variable.
-        */
-        if (expect->complete) {
-           DBPRT(2,( "      this branch is complete - ignoring.\n"));
-           continue;
-        }
-
-        /* If the base oid of this variable doesn't match the expected oid,
-        ** assume that we've walked past the end of the subtree.  Set this
-        ** subtree to be completed, and go on to the next variable.
-        */
-        if ((vars->name_length < expect->req_len) ||
-            (memcmp(vars->name, expect->req_oid, expect->req_len*sizeof(oid))))
-        {
-           DBPRT(2,( "      walked off branch - marking subtree as complete.\n"));
-           expect->complete = 1;
-           context->req_remain --;
-           continue;
-        }
-
-        /* Still interested in the tree -- we need to keep track of the
-        ** last-seen value in case we need to send an additional request
-        ** packet.
-        */
-        (void)memcpy(expect->last_oid, vars->name,
-                                            vars->name_length * sizeof(oid));
-        expect->last_len = vars->name_length;
-
-      }
-
-      /* Create a new Varbind and populate it with the parsed information
-      ** returned by the agent.  This Varbind is then pushed onto the arrays
-      ** maintained for each request OID in the context.  These varbinds are
-      ** collected into a return array by bulkwalk_finish().
-      */
-      varbind = (AV*) newAV();
-      if (varbind == NULL) {
-        sv_setpv(*err_str_svp, "newAV() failed: ");
-        sv_catpv(*err_str_svp, (char*)strerror(errno));
-        sv_setiv(*err_num_svp, SNMPERR_MALLOC);
-        goto err;
-      }
-
-      *str_buf = '.';
-      *(str_buf+1) = '\0';
-      out_len = 0;
-      tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
-                                             &out_len, 0, &buf_over,
-                                             vars->name,vars->name_length);
-      str_buf[sizeof(str_buf)-1] = '\0';
-
-      getlabel_flag = context->getlabel_f;
-
-      if (__is_leaf(tp)) {
-        type = tp->type;
-      } else {
-        getlabel_flag |= NON_LEAF_NAME;
-        type = __translate_asn_type(vars->type);
-      }
-      if (__get_label_iid(str_buf, &label, &iid, getlabel_flag) == FAILURE) {
-          label = str_buf;
-          iid = label + strlen(label);
-      }
-
-      DBPRT(2,( "       save var %s.%s = ", label, iid));
-
-      av_store(varbind, VARBIND_TAG_F, newSVpv(label, strlen(label)));
-      av_store(varbind, VARBIND_IID_F, newSVpv(iid, strlen(iid)));
-
-      __get_type_str(type, type_str);
-      av_store(varbind, VARBIND_TYPE_F, newSVpv(type_str, strlen(type_str)));
-
-      len=__snprint_value(str_buf, sizeof(str_buf),
-                         vars, tp, type, context->sprintval_f);
-      av_store(varbind, VARBIND_VAL_F, newSVpv((char*)str_buf, len));
-
-      str_buf[len] = '\0';
-      DBPRT(3,( "'%s' (%s)\n", str_buf, type_str));
-
-#if 0
-    /* huh? */
-      /* If necessary, store a timestamp as the semi-documented 5th element. */
-      if (sv_timestamp)
-         av_store(varbind, VARBIND_TIME_F, SvREFCNT_inc(sv_timestamp));
-#endif
-
-      /* Push ref to the varbind onto the list of vars for OID. */
-      rv = newRV_noinc((SV *)varbind);
-      sv_bless(rv, gv_stashpv("SNMP::Varbind", 0));
-      av_push(expect->vars, rv);
-
-      context->oid_saved ++;   /* Count this as a saved variable. */
-
-   } /* next variable in response packet */
-
-   DBPRT(1, (DBOUT "-- pkt %d saw %d vars, total %d (%d saved)\n", context->pkts_exch,
-                          pix, context->oid_total, context->oid_saved));
-
-   /* We assert that all non-repeaters must be returned in
-   ** the initial response (they are not repeated in additional
-   ** packets, so would be dropped).  If nonrepeaters still
-   ** exist, consider it a fatal error.
-   */
-   if ((context->pkts_exch == 1) && (context->oid_saved < context->non_reps)) {
-      /* Re-use space from the value string for error message. */
-      sprintf(str_buf, "%d non-repeaters went unanswered", context->non_reps);
-      sv_setpv(*err_str_svp, str_buf);
-      sv_setiv(*err_num_svp, SNMPERR_GENERR);
-      sv_setiv(*err_num_svp, context->oid_saved);
-      goto err;
-   }
-
-   /* Reset the library's behavior for numeric/symbolic OID's. */
-   if (context->getlabel_f & USE_NUMERIC_OIDS) {
-      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS, old_numeric);
-      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID, old_printfull);
-      netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, old_format);
-   }
-
-   return pix;
-
-   err:
-   if (pdu)
-      snmp_free_pdu(pdu);
-   return -1;
-
-}
-
-/* Once the bulkwalk has completed, extend the stack and push references to
-** each of the arrays of SNMP::Varbind's onto the stack.  Return the number
-** of arrays pushed on the stack.  The caller should return to Perl, or call
-** the Perl callback function.
-**
-** Note that this function free()'s the walk_context and request bulktbl's.
-*/
-static int
-_bulkwalk_finish(walk_context *context, int okay)
-{
-   int         npushed = 0;
-   int         i;
-   int         async = 0;
-   bulktbl     *bt_entry;
-   AV          *ary = NULL;
-   SV          *rv;
-   SV          *perl_cb;
-
-   SV **err_str_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorStr", 8, 1);
-   SV **err_num_svp = hv_fetch((HV*)SvRV(context->sess_ref), "ErrorNum", 8, 1);
-
-   dXSARGS;
-
-   async = SvTRUE(context->perl_cb);
-
-   /* Successfully completed the bulkwalk.  For synchronous calls, push each
-   ** of the request value arrays onto the stack, and return the number of
-   ** items pushed onto the stack.  For async, create a new array and push
-   ** the references onto it.  The array is then passed to the Perl callback.
-   */
-   if (!async)
-      SP -= items;
-
-   DBPRT(1, (DBOUT "Bulwalk %s (saved %d/%d), ", okay ? "completed" : "had error",
-                                       context->oid_saved, context->oid_total));
-
-   if (okay) {
-       DBPRT(1, (DBOUT "%s %d varbind refs %s\n",
-                               async ? "pass ref to array of" : "return",
-                               context->nreq_oids,
-                               async ? "to callback" : "on stack to caller"));
-
-       /* Create the array to hold the responses for the asynchronous callback,
-       ** or pre-extend the stack enough to hold responses for synch return.
-       */
-       if (async) {
-          ary = (AV *)newAV();
-         if (ary == NULL) {
-            sv_setpv(*err_str_svp, "newAV(): ");
-            sv_catpv(*err_str_svp, (char *)strerror(errno));
-            sv_setiv(*err_num_svp, errno);
-         }
-
-         /* NULL ary pointer is okay -- we'll handle it below... */
-
-       } else {
-          EXTEND(sp, context->nreq_oids);
-
-       }
-
-       /* Push a reference to each array of varbinds onto the stack, in
-       ** the order requested.  Note that these arrays may be empty.
-       */
-       for (i = 0; i < context->nreq_oids; i++) {
-         bt_entry = &context->req_oids[i];
-
-         DBPRT(2, (DBOUT "  %sreq #%d (%s) => %d var%s\n",
-                bt_entry->complete ? "" : "incomplete ", i,
-                snprint_objid(_debugx, sizeof(_debugx), bt_entry->req_oid, bt_entry->req_len),
-                (int)av_len(bt_entry->vars) + 1,
-                (int)av_len(bt_entry->vars) > 0 ? "s" : ""));
-
-         if (async && ary == NULL) {
-            DBPRT(2,( "    [dropped due to newAV() failure]\n"));
-            continue;
-         }
-
-         /* Get a reference to the varlist, and push it onto array or stack */
-         rv = newRV_noinc((SV *)bt_entry->vars);
-         sv_bless(rv, gv_stashpv("SNMP::VarList",0));
-
-         if (async)
-            av_push(ary, rv);
-         else
-            PUSHs(sv_2mortal((SV *)rv));
-
-         npushed ++;
-       }
-
-   } else {    /* Not okay -- push a single undef on the stack if not async */
-
-      if (!async) {
-        XPUSHs(&sv_undef);
-        npushed = 1;
-      }
-   }
-
-   /* XXX Future enhancement -- make statistics (pkts exchanged, vars
-   ** saved vs. received, total time, etc) available to caller so they
-   ** can adjust their request parameters and/or re-order requests.
-   */
-
-   PUTBACK;
-
-   if (async) {
-       /* Asynchronous callback.  Push the caller's arglist onto the stack,
-       ** and follow it with the contents of the array (or undef if newAV()
-       ** failed or the session had an error).  Then mortalize the Perl
-       ** callback pointer, and call the callback.
-       */
-       if (!okay || ary == NULL)
-          rv = &sv_undef;
-       else
-         rv = newRV_noinc((SV *)ary);
-
-       sv_2mortal(perl_cb = context->perl_cb);
-       perl_cb = __push_cb_args(perl_cb, (SvTRUE(rv) ? sv_2mortal(rv) : rv));
-
-       __call_callback(perl_cb, G_DISCARD);
-   }
-   sv_2mortal(context->sess_ref);
-
-   /* Free the allocated space for the request states and return number of
-   ** variables found.  Remove the context from the valid context list.
-   */
-   _context_del(context);
-   DBPRT(2,( "Free() context->req_oids\n"));
-   Safefree(context->req_oids);
-   DBPRT(2,( "Free() context 0x%p\n", context));
-   Safefree(context);
-   return npushed;
-}
-
-/* End of bulkwalk support routines */
-
-static char *
-__av_elem_pv(AV *av, I32 key, char *dflt)
-{
-   SV **elem = av_fetch(av, key, 0);
-
-   return (elem && SvOK(*elem)) ? SvPV(*elem, na) : dflt;
-}
-
-static int
-not_here(s)
-char *s;
-{
-    croak("%s not implemented on this architecture", s);
-    return -1;
-}
-
-static double
-constant(name, arg)
-char *name;
-int arg;
-{
-    errno = 0;
-    switch (*name) {
-    case 'R':
-       if (strEQ(name, "NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE"))
-#ifdef NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE
-           return NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE;
-#else
-           goto not_there;
-#endif
-       break;
-    case 'S':
-       if (strEQ(name, "SNMPERR_BAD_ADDRESS"))
-#ifdef SNMPERR_BAD_ADDRESS
-           return SNMPERR_BAD_ADDRESS;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMPERR_BAD_LOCPORT"))
-#ifdef SNMPERR_BAD_LOCPORT
-           return SNMPERR_BAD_LOCPORT;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMPERR_BAD_SESSION"))
-#ifdef SNMPERR_BAD_SESSION
-           return SNMPERR_BAD_SESSION;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMPERR_GENERR"))
-#ifdef SNMPERR_GENERR
-           return SNMPERR_GENERR;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMPERR_TOO_LONG"))
-#ifdef SNMPERR_TOO_LONG
-           return SNMPERR_TOO_LONG;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_ADDRESS"))
-#ifdef SNMP_DEFAULT_ADDRESS
-           return SNMP_DEFAULT_ADDRESS;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_COMMUNITY_LEN"))
-#ifdef SNMP_DEFAULT_COMMUNITY_LEN
-           return SNMP_DEFAULT_COMMUNITY_LEN;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_ENTERPRISE_LENGTH"))
-#ifdef SNMP_DEFAULT_ENTERPRISE_LENGTH
-           return SNMP_DEFAULT_ENTERPRISE_LENGTH;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_ERRINDEX"))
-#ifdef SNMP_DEFAULT_ERRINDEX
-           return SNMP_DEFAULT_ERRINDEX;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_ERRSTAT"))
-#ifdef SNMP_DEFAULT_ERRSTAT
-           return SNMP_DEFAULT_ERRSTAT;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_PEERNAME"))
-#ifdef SNMP_DEFAULT_PEERNAME
-           return 0;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_REMPORT"))
-#ifdef SNMP_DEFAULT_REMPORT
-           return SNMP_DEFAULT_REMPORT;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_REQID"))
-#ifdef SNMP_DEFAULT_REQID
-           return SNMP_DEFAULT_REQID;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_RETRIES"))
-#ifdef SNMP_DEFAULT_RETRIES
-           return SNMP_DEFAULT_RETRIES;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_TIME"))
-#ifdef SNMP_DEFAULT_TIME
-           return SNMP_DEFAULT_TIME;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_TIMEOUT"))
-#ifdef SNMP_DEFAULT_TIMEOUT
-           return SNMP_DEFAULT_TIMEOUT;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "SNMP_DEFAULT_VERSION"))
-#ifdef DEFAULT_SNMP_VERSION
-           return DEFAULT_SNMP_VERSION;
-#else
-#ifdef SNMP_DEFAULT_VERSION
-           return SNMP_DEFAULT_VERSION;
-#else
-           goto not_there;
-#endif
-#endif
-       break;
-    case 'T':
-       if (strEQ(name, "NETSNMP_CALLBACK_OP_TIMED_OUT"))
-#ifdef NETSNMP_CALLBACK_OP_TIMED_OUT
-           return NETSNMP_CALLBACK_OP_TIMED_OUT;
-#else
-           goto not_there;
-#endif
-       break;
-    default:
-       break;
-    }
-    errno = EINVAL;
-    return 0;
-
-#ifndef NETSNMP_CALLBACK_OP_TIMED_OUT
-not_there:
-#endif
-    errno = ENOENT;
-    return 0;
-}
-
-
-MODULE = SNMP          PACKAGE = SNMP          PREFIX = snmp
-
-BOOT:
-# first blank line terminates bootstrap code
-    Mib = 0;
-
-
-double
-constant(name,arg)
-       char *          name
-       int             arg
-
-long
-snmp_sys_uptime()
-       CODE:
-       RETVAL = get_uptime();
-       OUTPUT:
-       RETVAL
-
-void
-init_snmp(appname)
-        char *appname
-    CODE:
-        __libraries_init(appname);
-
-
-SnmpSession *
-snmp_new_session(version, community, peer, lport, retries, timeout)
-        char * version
-        char * community
-        char * peer
-        int    lport
-        int    retries
-        int    timeout
-       CODE:
-       {
-          SnmpSession session = {0};
-          SnmpSession *ss = NULL;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-           __libraries_init("perl");
-           
-          if (!strcmp(version, "1")) {
-               session.version = SNMP_VERSION_1;
-           } else if ((!strcmp(version, "2")) || (!strcmp(version, "2c"))) {
-               session.version = SNMP_VERSION_2c;
-           } else if (!strcmp(version, "3")) {
-               session.version = SNMP_VERSION_3;
-          } else {
-               if (verbose)
-                   warn("error:snmp_new_session:Unsupported SNMP version (%s)\n", version);
-                goto end;
-          }
-
-           session.community_len = strlen((char *)community);
-           session.community = (u_char *)community;
-          session.peername = peer;
-          session.local_port = lport;
-           session.retries = retries; /* 5 */
-           session.timeout = timeout; /* 1000000L */
-           session.authenticator = NULL;
-
-           ss = snmp_open(&session);
-
-           if (ss == NULL) {
-             if (verbose) warn("error:snmp_new_session: Couldn't open SNMP session");
-           }
-        end:
-           RETVAL = ss;
-       }
-        OUTPUT:
-        RETVAL
-
-SnmpSession *
-snmp_new_v3_session(version, peer, retries, timeout, sec_name, sec_level, sec_eng_id, context_eng_id, context, auth_proto, auth_pass, priv_proto, priv_pass, eng_boots, eng_time)
-        int    version
-        char * peer
-        int    retries
-        int    timeout
-        char *  sec_name
-        int     sec_level
-        char *  sec_eng_id
-        char *  context_eng_id
-        char *  context
-        char *  auth_proto
-        char *  auth_pass
-        char *  priv_proto
-        char *  priv_pass
-       int     eng_boots
-       int     eng_time
-       CODE:
-       {
-/*             u_char sec_eng_id_buf[ENG_ID_BUF_SIZE]; */
-/*             u_char context_eng_id_buf[ENG_ID_BUF_SIZE]; */
-          SnmpSession session = {0};
-          SnmpSession *ss = NULL;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-           __libraries_init("perl");
-
-          if (version == 3) {
-               session.version = SNMP_VERSION_3;
-           } else {
-               if (verbose)
-                   warn("error:snmp_new_v3_session:Unsupported SNMP version (%d)\n", version);
-                goto end;
-          }
-
-          session.peername = strdup(peer);
-           session.retries = retries; /* 5 */
-           session.timeout = timeout; /* 1000000L */
-           session.authenticator = NULL;
-           session.contextNameLen = strlen(context);
-           session.contextName = context;
-           session.securityNameLen = strlen(sec_name);
-           session.securityName = sec_name;
-           session.securityLevel = sec_level;
-           session.securityModel = USM_SEC_MODEL_NUMBER;
-           /* session.securityEngineID = sec_eng_id_buf;*/
-           session.securityEngineIDLen =
-              hex_to_binary2(sec_eng_id, strlen(sec_eng_id),
-                             (char **) &session.securityEngineID);
-           /* session.contextEngineID = context_eng_id_buf; */
-           session.contextEngineIDLen =
-              hex_to_binary2(sec_eng_id, strlen(sec_eng_id),
-                             (char **) &session.contextEngineID);
-           session.engineBoots = eng_boots;
-           session.engineTime = eng_time;
-           if (!strcmp(auth_proto, "MD5")) {
-               session.securityAuthProto = 
-                  snmp_duplicate_objid(usmHMACMD5AuthProtocol,
-                                          USM_AUTH_PROTO_MD5_LEN);
-              session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
-           } else if (!strcmp(auth_proto, "SHA")) {
-               session.securityAuthProto = 
-                   snmp_duplicate_objid(usmHMACSHA1AuthProtocol,
-                                        USM_AUTH_PROTO_SHA_LEN);
-              session.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
-           } else {
-              if (verbose)
-                 warn("error:snmp_new_v3_session:Unsupported authentication protocol(%s)\n", auth_proto);
-              goto end;
-           }
-           if (session.securityLevel >= SNMP_SEC_LEVEL_AUTHNOPRIV) {
-              session.securityAuthKeyLen = USM_AUTH_KU_LEN;
-              if (generate_Ku(session.securityAuthProto,
-                              session.securityAuthProtoLen,
-                              (u_char *)auth_pass, strlen(auth_pass),
-                              session.securityAuthKey,
-                              &session.securityAuthKeyLen) != SNMPERR_SUCCESS) {
-                 if (verbose)
-                    warn("error:snmp_new_v3_session:Error generating Ku from authentication password.\n");
-                 goto end;
-              }
-           }
-           if (!strcmp(priv_proto, "DES")) {
-              session.securityPrivProto =
-                  snmp_duplicate_objid(usmDESPrivProtocol,
-                                       USM_PRIV_PROTO_DES_LEN);
-              session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
-           } else {
-              if (verbose)
-                 warn("error:snmp_new_v3_session:Unsupported privacy protocol(%s)\n", priv_proto);
-              goto end;
-           }
-           if (session.securityLevel >= SNMP_SEC_LEVEL_AUTHPRIV) {
-             session.securityPrivKeyLen = USM_PRIV_KU_LEN;
-              if (generate_Ku(session.securityAuthProto,
-                              session.securityAuthProtoLen,
-                              (u_char *)priv_pass, strlen(priv_pass),
-                              session.securityPrivKey,
-                              &session.securityPrivKeyLen) != SNMPERR_SUCCESS) {
-                 if (verbose)
-                    warn("error:snmp_new_v3_session:Error generating Ku from privacy pass phrase.\n");
-                 goto end;
-               }
-            }
-
-           ss = snmp_open(&session);
-
-           if (ss == NULL) {
-             if (verbose) warn("error:snmp_new_v3_session:Couldn't open SNMP session");
-           }
-        end:
-           RETVAL = ss;
-          free (session.contextEngineID);
-       }
-        OUTPUT:
-        RETVAL
-
-
-SnmpSession *
-snmp_update_session(sess_ref, version, community, peer, lport, retries, timeout)
-        SV *   sess_ref
-        char * version
-        char * community
-        char * peer
-        int    lport
-        int    retries
-        int    timeout
-       CODE:
-       {
-           SV **sess_ptr_sv;
-          SnmpSession *ss;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-           sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-           ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-
-           if (!ss) goto update_end;
-
-           if (!strcmp(version, "1")) {
-               ss->version = SNMP_VERSION_1;
-           } else if (!strcmp(version, "2") || !strcmp(version, "2c")) {
-               ss->version = SNMP_VERSION_2c;
-          } else if (!strcmp(version, "3")) {
-               ss->version = SNMP_VERSION_3;
-          } else {
-               if (verbose)
-                   warn("Unsupported SNMP version (%s)\n", version);
-                goto update_end;
-          }
-           /* WARNING LEAKAGE but I cant free lib memory under win32 */
-           ss->community_len = strlen((char *)community);
-           ss->community = (u_char *)strdup(community);
-          ss->peername = strdup(peer);
-          ss->local_port = lport;
-           ss->retries = retries; /* 5 */
-           ss->timeout = timeout; /* 1000000L */
-           ss->authenticator = NULL;
-
-    update_end:
-          RETVAL = ss;
-        }
-        OUTPUT:
-           RETVAL
-
-int
-snmp_add_mib_dir(mib_dir,force=0)
-       char *          mib_dir
-       int             force
-       CODE:
-        {
-       int result = 0;      /* Avoid use of uninitialized variable below. */
-        int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-        if (mib_dir && *mib_dir) {
-          result = add_mibdir(mib_dir);
-        }
-        if (result) {
-           if (verbose) warn("Added mib dir %s\n", mib_dir);
-        } else {
-           if (verbose) warn("Failed to add %s\n", mib_dir);
-        }
-        RETVAL = (I32)result;
-        }
-        OUTPUT:
-        RETVAL
-
-void
-snmp_init_mib_internals()
-       CODE:
-        {
-        int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-        /* should test better to see if it has been done already */
-       if (Mib == NULL) {
-           if (verbose) warn("initializing MIB internals (empty)\n");
-           /* init_mib_internals(); */
-        }
-        }
-
-
-int
-snmp_read_mib(mib_file, force=0)
-       char *          mib_file
-       int             force
-       CODE:
-        {
-        int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-        /* if (Mib && force) __free_tree(Mib); needs more work to cleanup */
-
-        if ((mib_file == NULL) || (*mib_file == '\0')) {
-           if (Mib == NULL) {
-              if (verbose) warn("initializing MIB\n");
-              /* init_mib_internals(); */
-              init_mib();
-              if (Mib) {
-                 if (verbose) warn("done\n");
-              } else {
-                 if (verbose) warn("failed\n");
-              }
-          }
-        } else {
-           if (verbose) warn("reading MIB: %s [%s:%s]\n", mib_file, DEFAULT_MIBDIRS, DEFAULT_MIBS);
-           /* if (Mib == NULL) init_mib_internals();*/
-           if (strcmp("ALL",mib_file))
-              read_mib(mib_file);
-           else
-             read_all_mibs();
-           if (Mib) {
-              if (verbose) warn("done\n");
-           } else {
-              if (verbose) warn("failed\n");
-           }
-        }
-        RETVAL = (I32)Mib;
-        }
-        OUTPUT:
-        RETVAL
-
-
-int
-snmp_read_module(module)
-       char *          module
-       CODE:
-        {
-        int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-        if (!strcmp(module,"ALL")) {
-           read_all_mibs();
-        } else {
-           read_module(module);
-        }
-        if (Mib) {
-           if (verbose) warn("Read %s\n", module);
-        } else {
-           if (verbose) warn("Failed reading %s\n", module);
-        }
-        RETVAL = (I32)Mib;
-        }
-        OUTPUT:
-        RETVAL
-
-
-int
-snmp_set(sess_ref, varlist_ref, perl_callback)
-        SV *   sess_ref
-        SV *   varlist_ref
-        SV *   perl_callback
-       PPCODE:
-       {
-           AV *varlist;
-           SV **varbind_ref;
-           SV **varbind_val_f;
-           AV *varbind;
-          I32 varlist_len;
-          I32 varlist_ind;
-           SnmpSession *ss;
-           netsnmp_pdu *pdu, *response;
-           struct tree *tp;
-          oid *oid_arr;
-          int oid_arr_len = MAX_OID_LEN;
-           char *tag_pv;
-           snmp_xs_cb_data *xs_cb_data;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int status = 0;
-           int type;
-          int res;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-           int use_enums;
-           struct enum_list *ep;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
-
-             use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-
-              pdu = snmp_pdu_create(SNMP_MSG_SET);
-
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-             for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-                    tag_pv = __av_elem_pv(varbind, VARBIND_TAG_F,NULL);
-                    tp=__tag2oid(tag_pv,
-                                 __av_elem_pv(varbind, VARBIND_IID_F,NULL),
-                                 oid_arr, &oid_arr_len, &type,0);
-
-                    if (oid_arr_len==0) {
-                       if (verbose)
-                          warn("error: set: unknown object ID (%s)",
-                                (tag_pv?tag_pv:"<null>"));
-                      sv_catpv(*err_str_svp,
-                               (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
-                       sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
-                       XPUSHs(&sv_undef); /* unknown OID */
-                      snmp_free_pdu(pdu);
-                      goto done;
-                   }
-
-
-                    if (type == TYPE_UNKNOWN) {
-                      type = __translate_appl_type(
-                                __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
-                      if (type == TYPE_UNKNOWN) {
-                         if (verbose)
-                            warn("error: set: no type found for object");
-                        sv_catpv(*err_str_svp,
-                                  (char*)snmp_api_errstring(SNMPERR_VAR_TYPE));
-                         sv_setiv(*err_num_svp, SNMPERR_VAR_TYPE);
-                         XPUSHs(&sv_undef); /* unknown OID */
-                        snmp_free_pdu(pdu);
-                        goto done;
-                      }
-                    }
-
-                   varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
-
-                    if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
-                      for(ep = tp->enums; ep; ep = ep->next) {
-                        if (varbind_val_f && SvOK(*varbind_val_f) &&
-                            !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
-                          sv_setiv(*varbind_val_f, ep->value);
-                          break;
-                        }
-                      }
-                    }
-
-                    res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
-                                    (varbind_val_f && SvOK(*varbind_val_f) ?
-                                     SvPV(*varbind_val_f,na):NULL),
-                                     (varbind_val_f && SvOK(*varbind_val_f) ?
-                                      SvCUR(*varbind_val_f):0), type);
-
-                   if (verbose && res == FAILURE)
-                     warn("error: adding variable/value to PDU");
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-
-              if (SvTRUE(perl_callback)) {
-                  xs_cb_data =
-                      (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
-                 xs_cb_data->perl_cb = newSVsv(perl_callback);
-                 xs_cb_data->sess_ref = newRV_inc(SvRV(sess_ref));
-
-                 status = snmp_async_send(ss, pdu, __snmp_xs_cb,
-                                          (void*)xs_cb_data);
-                 if (status != 0) {
-                    XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
-                 } else {
-                    snmp_free_pdu(pdu);
-                    sv_catpv(*err_str_svp,
-                             (char*)snmp_api_errstring(ss->s_snmp_errno));
-                    sv_setiv(*err_num_svp, ss->s_snmp_errno);
-                    XPUSHs(&sv_undef);
-                 }
-                goto done;
-              }
-
-             status = __send_sync_pdu(ss, pdu, &response,
-                                      NO_RETRY_NOSUCH,
-                                       *err_str_svp, *err_num_svp,
-                                       *err_ind_svp);
-
-              if (response) snmp_free_pdu(response);
-
-              if (status) {
-                XPUSHs(&sv_undef);
-             } else {
-                 XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
-              }
-           } else {
-
-              /* BUG!!! need to return an error value */
-              XPUSHs(&sv_undef); /* no mem or bad args */
-           }
-done:
-           Safefree(oid_arr);
-        }
-
-void
-snmp_catch(sess_ref, perl_callback)
-       SV *    sess_ref
-        SV *    perl_callback
-       PPCODE:
-       {
-          netsnmp_session *ss;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-
-           if (SvROK(sess_ref)) {
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-
-              snmp_synch_reset(ss);
-              ss->callback = NULL;
-              ss->callback_magic = NULL;
-
-              if (SvTRUE(perl_callback)) {
-                 perl_callback = newSVsv(perl_callback);
-                 # it might be more efficient to pass the varbind_ref to
-                 # __snmp_xs_cb as part of perl_callback so it is not freed
-                 # and reconstructed for each call
-                 ss->callback = __callback_wrapper;
-                 ss->callback_magic = perl_callback;
-                 sv_2mortal(newSViv(1));
-                 goto done;
-              }
-           }
-           sv_2mortal(newSViv(0));
-        done:
-           ;
-        }
-
-void
-snmp_get(sess_ref, retry_nosuch, varlist_ref, perl_callback)
-        SV *    sess_ref
-        int     retry_nosuch
-        SV *    varlist_ref
-        SV *    perl_callback
-        PPCODE:
-        {
-           AV *varlist;
-           SV **varbind_ref;
-           AV *varbind;
-           I32 varlist_len;
-           I32 varlist_ind;
-           netsnmp_session *ss;
-           netsnmp_pdu *pdu, *response;
-           netsnmp_variable_list *vars;
-           netsnmp_variable_list *last_vars;
-           struct tree *tp;
-           int len;
-           oid *oid_arr = NULL;
-           int oid_arr_len = MAX_OID_LEN;
-           SV *tmp_sv;
-           char *tag_pv;
-           int type;
-           char tmp_type_str[MAX_TYPE_NAME_LEN];
-           char str_buf[STR_BUF_SIZE];
-           snmp_xs_cb_data *xs_cb_data;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int status;
-           int sprintval_flag = USE_BASIC;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-          SV *sv_timestamp = NULL;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
-
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-              ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-              if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
-                 sprintval_flag = USE_ENUMS;
-              if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
-                 sprintval_flag = USE_SPRINT_VALUE;
-
-              pdu = snmp_pdu_create(SNMP_MSG_GET);
-
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-              for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-                    tag_pv = __av_elem_pv(varbind, VARBIND_TAG_F,NULL);
-                    tp = __tag2oid(tag_pv,
-                                   __av_elem_pv(varbind, VARBIND_IID_F,NULL),
-                                   oid_arr, &oid_arr_len, NULL,0);
-
-                    if (oid_arr_len) {
-                       snmp_add_null_var(pdu, oid_arr, oid_arr_len);
-                    } else {
-                       if (verbose)
-                          warn("error: get: unknown object ID (%s)",
-                                (tag_pv?tag_pv:"<null>"));
-                      sv_catpv(*err_str_svp,
-                                (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
-                       sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
-                       XPUSHs(&sv_undef); /* unknown OID */
-                      snmp_free_pdu(pdu);
-                      goto done;
-                    }
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-
-              if (perl_callback && SvTRUE(perl_callback)) {
-                  xs_cb_data =
-                      (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
-                 xs_cb_data->perl_cb = newSVsv(perl_callback);
-                 xs_cb_data->sess_ref = newSVsv(sess_ref);
-
-                 status = snmp_async_send(ss, pdu, __snmp_xs_cb,
-                                          (void*)xs_cb_data);
-                 if (status != 0) {
-                    XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
-                 } else {
-                    snmp_free_pdu(pdu);
-                    sv_catpv(*err_str_svp,
-                             (char*)snmp_api_errstring(ss->s_snmp_errno));
-                    sv_setiv(*err_num_svp, ss->s_snmp_errno);
-                    XPUSHs(&sv_undef);
-                 }
-                 goto done;
-              }
-
-              status = __send_sync_pdu(ss, pdu, &response, retry_nosuch,
-                                       *err_str_svp,*err_num_svp,*err_ind_svp);
-
-              last_vars = (response ? response->variables : NULL);
-
-             if (SvIOK(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)) &&
-                  SvIV(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)))
-                sv_timestamp = newSViv((IV)time(NULL));
-
-              for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-
-                    tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F,NULL),
-                                 __av_elem_pv(varbind, VARBIND_IID_F,NULL),
-                                 oid_arr, &oid_arr_len, &type,0);
-
-                    for (vars = last_vars; vars; vars=vars->next_variable) {
-                   if (__oid_cmp(oid_arr, oid_arr_len, vars->name,
-                                     vars->name_length) == 0) {
-                          if (type == TYPE_UNKNOWN)
-                             type = __translate_asn_type(vars->type);
-                          last_vars = vars->next_variable;
-                          break;
-                       }
-                    }
-                    if (vars) {
-                       __get_type_str(type, tmp_type_str);
-                       tmp_sv = newSVpv(tmp_type_str,strlen(tmp_type_str));
-                       av_store(varbind, VARBIND_TYPE_F, tmp_sv);
-                       len=__snprint_value(str_buf,sizeof(str_buf),
-                                          vars,tp,type,sprintval_flag);
-                       tmp_sv=newSVpv((char*)str_buf, len);
-                       av_store(varbind, VARBIND_VAL_F, tmp_sv);
-                      if (sv_timestamp)
-                          av_store(varbind, VARBIND_TYPE_F, sv_timestamp);
-                       XPUSHs(sv_mortalcopy(tmp_sv));
-                    } else {
-                       av_store(varbind, VARBIND_VAL_F, &sv_undef);
-                       av_store(varbind, VARBIND_TYPE_F, &sv_undef);
-                       XPUSHs(&sv_undef);
-                    }
-                 }
-              }
-              if (response) snmp_free_pdu(response);
-           } else {
-              XPUSHs(&sv_undef); /* no mem or bad args */
-           }
-     done:
-           Safefree(oid_arr);
-        }
-
-int
-snmp_getnext(sess_ref, varlist_ref, perl_callback)
-        SV *    sess_ref
-        SV *    varlist_ref
-        SV *    perl_callback
-        PPCODE:
-        {
-           AV *varlist;
-           SV **varbind_ref;
-           AV *varbind;
-           I32 varlist_len;
-           I32 varlist_ind;
-           netsnmp_session *ss;
-           netsnmp_pdu *pdu, *response;
-           netsnmp_variable_list *vars;
-           struct tree *tp;
-           int len;
-          oid *oid_arr;
-          int oid_arr_len = MAX_OID_LEN;
-           SV *tmp_sv;
-           int type;
-          char tmp_type_str[MAX_TYPE_NAME_LEN];
-           snmp_xs_cb_data *xs_cb_data;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int status;
-          u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
-           size_t str_buf_len = sizeof(str_buf);
-           size_t out_len = 0;
-           int buf_over = 0;
-           char *label;
-           char *iid;
-           int getlabel_flag = NO_FLAGS;
-           int sprintval_flag = USE_BASIC;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-          int old_numeric, old_printfull;      /* Old values of globals */
-          SV *sv_timestamp = NULL;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
-
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
-                 getlabel_flag |= USE_LONG_NAMES;
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
-                 sprintval_flag = USE_ENUMS;
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
-                 sprintval_flag = USE_SPRINT_VALUE;
-
-              pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
-
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-             for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-
-                    tp = __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, ".0"),
-                              __av_elem_pv(varbind, VARBIND_IID_F, NULL),
-                              oid_arr, &oid_arr_len, NULL,0);
-
-                   if (oid_arr_len) {
-                      snmp_add_null_var(pdu, oid_arr, oid_arr_len);
-                   } else {
-                       if (verbose)
-                          warn("error: set: unknown object ID");
-                      sv_catpv(*err_str_svp,
-                               (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
-                       sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
-                       XPUSHs(&sv_undef); /* unknown OID */
-                      snmp_free_pdu(pdu);
-                      goto done;
-                   }
-
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-
-              if (SvTRUE(perl_callback)) {
-                  xs_cb_data =
-                      (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
-                 xs_cb_data->perl_cb = newSVsv(perl_callback);
-                 xs_cb_data->sess_ref = newSVsv(sess_ref);
-
-                 status = snmp_async_send(ss, pdu, __snmp_xs_cb,
-                                          (void*)xs_cb_data);
-                 if (status != 0) {
-                    XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
-                 } else {
-                    snmp_free_pdu(pdu);
-                    sv_catpv(*err_str_svp,
-                             (char*)snmp_api_errstring(ss->s_snmp_errno));
-                    sv_setiv(*err_num_svp, ss->s_snmp_errno);
-                    XPUSHs(&sv_undef);
-                 }
-                goto done;
-              }
-
-             status = __send_sync_pdu(ss, pdu, &response,
-                                      NO_RETRY_NOSUCH,
-                                       *err_str_svp, *err_num_svp,
-                                      *err_ind_svp);
-
-             /*
-             ** Set up for numeric OID's, if necessary.  Save the old values
-             ** so that they can be restored when we finish -- these are
-             ** library-wide globals, and have to be set/restored for each
-             ** session.
-             */
-             old_numeric = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
-                                                   NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS);
-             old_printfull = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
-                                                   NETSNMP_DS_LIB_PRINT_FULL_OID);
-
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1))) {
-                getlabel_flag |= USE_NUMERIC_OIDS;
-
-                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS, 1);
-                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID, 1);
-             }
-
-             if (SvIOK(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)) &&
-                  SvIV(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)))
-                sv_timestamp = newSViv((IV)time(NULL));
-
-              for(vars = (response?response->variables:NULL), varlist_ind = 0;
-                  vars && (varlist_ind <= varlist_len);
-                  vars = vars->next_variable, varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-
-                    *str_buf = '.';
-                    *(str_buf+1) = '\0';
-                    out_len = 0;
-                    tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
-                                                           &out_len, 0, &buf_over,
-                                                           vars->name,vars->name_length);
-                    str_buf[sizeof(str_buf)-1] = '\0';
-
-                    if (__is_leaf(tp)) {
-                       type = tp->type;
-                    } else {
-                       getlabel_flag |= NON_LEAF_NAME;
-                       type = __translate_asn_type(vars->type);
-                    }
-                    __get_label_iid(str_buf,&label,&iid,getlabel_flag);
-                    if (label) {
-                        av_store(varbind, VARBIND_TAG_F,
-                                 newSVpv(label, strlen(label)));
-                    } else {
-                        av_store(varbind, VARBIND_TAG_F,
-                                 newSVpv("", 0));
-                    }
-                    if (iid) {
-                        av_store(varbind, VARBIND_IID_F,
-                                 newSVpv(iid, strlen(iid)));
-                    } else {
-                        av_store(varbind, VARBIND_IID_F,
-                                 newSVpv("", 0));
-                    }                        
-                    __get_type_str(type, tmp_type_str);
-                    tmp_sv = newSVpv(tmp_type_str, strlen(tmp_type_str));
-                    av_store(varbind, VARBIND_TYPE_F, tmp_sv);
-                    len=__snprint_value(str_buf,sizeof(str_buf),
-                                       vars,tp,type,sprintval_flag);
-                    tmp_sv = newSVpv((char*)str_buf, len);
-                    av_store(varbind, VARBIND_VAL_F, tmp_sv);
-                   if (sv_timestamp)
-                       av_store(varbind, VARBIND_TYPE_F, sv_timestamp);
-                    XPUSHs(sv_mortalcopy(tmp_sv));
-                 } else {
-                   /* Return undef for this variable. */
-                    XPUSHs(&sv_undef);
-                 }
-              }
-
-             /* Reset the library's behavior for numeric/symbolic OID's. */
-             if (getlabel_flag & USE_NUMERIC_OIDS) {
-                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS,
-                                                                old_numeric );
-                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID,
-                                                                old_printfull);
-             }
-
-              if (response) snmp_free_pdu(response);
-
-           } else {
-              XPUSHs(&sv_undef); /* no mem or bad args */
-          }
-done:
-       Safefree(oid_arr);
-       }
-
-int
-snmp_getbulk(sess_ref, nonrepeaters, maxrepetitions, varlist_ref, perl_callback)
-        SV *   sess_ref
-       int nonrepeaters
-       int maxrepetitions
-        SV *   varlist_ref
-        SV *   perl_callback
-       PPCODE:
-       {
-           AV *varlist;
-           SV **varbind_ref;
-           AV *varbind;
-          I32 varlist_len;
-          I32 varlist_ind;
-           netsnmp_session *ss;
-           netsnmp_pdu *pdu, *response;
-           netsnmp_variable_list *vars;
-           struct tree *tp;
-           int len;
-          oid *oid_arr;
-          int oid_arr_len = MAX_OID_LEN;
-           SV *tmp_sv;
-           int type;
-          char tmp_type_str[MAX_TYPE_NAME_LEN];
-           snmp_xs_cb_data *xs_cb_data;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int status;
-          u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
-           size_t str_buf_len = sizeof(str_buf);
-           size_t out_len = 0;
-           int buf_over = 0;
-           char *label;
-           char *iid;
-           int getlabel_flag = NO_FLAGS;
-           int sprintval_flag = USE_BASIC;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-          int old_numeric, old_printfull;      /* Old values of globals */
-          SV *rv;
-          SV *sv_timestamp = NULL;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
-
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
-                 getlabel_flag |= USE_LONG_NAMES;
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
-                getlabel_flag |= USE_NUMERIC_OIDS;
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
-                 sprintval_flag = USE_ENUMS;
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
-                 sprintval_flag = USE_SPRINT_VALUE;
-
-              pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
-
-             pdu->errstat = nonrepeaters;
-             pdu->errindex = maxrepetitions;
-
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-             for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-                    __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, "0"),
-                              __av_elem_pv(varbind, VARBIND_IID_F, NULL),
-                              oid_arr, &oid_arr_len, NULL,0);
-
-
-                    if (oid_arr_len) {
-                      snmp_add_null_var(pdu, oid_arr, oid_arr_len);
-                   } else {
-                       if (verbose)
-                          warn("error: set: unknown object ID");
-                      sv_catpv(*err_str_svp,
-                               (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
-                       sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
-                       XPUSHs(&sv_undef); /* unknown OID */
-                      snmp_free_pdu(pdu);
-                      goto done;
-                   }
-
-
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-
-              if (SvTRUE(perl_callback)) {
-                  xs_cb_data =
-                      (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
-                 xs_cb_data->perl_cb = newSVsv(perl_callback);
-                 xs_cb_data->sess_ref = newSVsv(sess_ref);
-
-                 status = snmp_async_send(ss, pdu, __snmp_xs_cb,
-                                          (void*)xs_cb_data);
-                 if (status != 0) {
-                    XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
-                 } else {
-                    snmp_free_pdu(pdu);
-                    sv_catpv(*err_str_svp,
-                             (char*)snmp_api_errstring(ss->s_snmp_errno));
-                    sv_setiv(*err_num_svp, ss->s_snmp_errno);
-                    XPUSHs(&sv_undef);
-                 }
-                goto done;
-              }
-
-             status = __send_sync_pdu(ss, pdu, &response,
-                                      NO_RETRY_NOSUCH,
-                                       *err_str_svp, *err_num_svp,
-                                      *err_ind_svp);
-
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)))
-                sv_timestamp = newSViv((IV)time(NULL));
-
-             av_clear(varlist);
-
-             /*
-             ** Set up for numeric OID's, if necessary.  Save the old values
-             ** so that they can be restored when we finish -- these are
-             ** library-wide globals, and have to be set/restored for each
-             ** session.
-             */
-             old_numeric = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
-                                                 NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS);
-             old_printfull = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
-                                                 NETSNMP_DS_LIB_PRINT_FULL_OID);
-             if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1))) {
-                getlabel_flag |= USE_NUMERIC_OIDS;
-
-                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS, 1);
-                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID, 1);
-             }
-
-             if(response && response->variables) {
-              for(vars = response->variables;
-                  vars;
-                  vars = vars->next_variable) {
-
-                    varbind = (AV*) newAV();
-                    *str_buf = '.';
-                    *(str_buf+1) = '\0';
-                    out_len = 0;
-                    tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
-                                                           &out_len, 0, &buf_over,
-                                                           vars->name,vars->name_length);
-                    str_buf[sizeof(str_buf)-1] = '\0';
-                    if (__is_leaf(tp)) {
-                       type = tp->type;
-                    } else {
-                       getlabel_flag |= NON_LEAF_NAME;
-                       type = __translate_asn_type(vars->type);
-                    }
-                    __get_label_iid(str_buf,&label,&iid,getlabel_flag);
-
-                   av_store(varbind, VARBIND_TAG_F,
-                            newSVpv(label, strlen(label)));
-                   av_store(varbind, VARBIND_IID_F,
-                            newSVpv(iid, strlen(iid)));
-
-                    __get_type_str(type, tmp_type_str);
-                   av_store(varbind, VARBIND_TYPE_F, newSVpv(tmp_type_str,
-                                    strlen(tmp_type_str)));
-
-                    len=__snprint_value(str_buf,sizeof(str_buf),
-                                       vars,tp,type,sprintval_flag);
-                    tmp_sv = newSVpv((char*)str_buf, len);
-                   av_store(varbind, VARBIND_VAL_F, tmp_sv);
-                   if (sv_timestamp)
-                      av_store(varbind, VARBIND_TYPE_F, SvREFCNT_inc(sv_timestamp));
-
-                   rv = newRV_noinc((SV *)varbind);
-                   sv_bless(rv, gv_stashpv("SNMP::Varbind",0));
-                   av_push(varlist, rv);
-
-                    XPUSHs(sv_mortalcopy(tmp_sv));
-                 }
-              } else {
-                    XPUSHs(&sv_undef);
-             }
-
-             /* Reset the library's behavior for numeric/symbolic OID's. */
-             if (getlabel_flag & USE_NUMERIC_OIDS) {
-                 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS,
-                                                             old_numeric );
-                 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID,
-                                                             old_printfull);
-             }
-
-              if (response) snmp_free_pdu(response);
-
-           } else {
-              XPUSHs(&sv_undef); /* no mem or bad args */
-          }
-done:
-       Safefree(oid_arr);
-       }
-
-int
-snmp_bulkwalk(sess_ref, nonrepeaters, maxrepetitions, varlist_ref,perl_callback)
-        SV *   sess_ref
-       int nonrepeaters
-       int maxrepetitions
-        SV *   varlist_ref
-        SV *   perl_callback
-       PPCODE:
-       {
-           AV *varlist;
-           SV **varbind_ref;
-           AV *varbind;
-          I32 varlist_len;
-          I32 varlist_ind;
-           netsnmp_session *ss;
-           netsnmp_pdu *pdu = NULL;
-          oid oid_arr[MAX_OID_LEN];
-          int oid_arr_len;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-          char str_buf[STR_BUF_SIZE];
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-          walk_context *context = NULL;        /* Context for this bulkwalk */
-          bulktbl *bt_entry;                   /* Current bulktbl/OID entry */
-          int i;                               /* General purpose iterator  */
-          int npushed;                         /* Number of return arrays   */
-          int okay;                            /* Did bulkwalk complete okay */
-
-           if (!SvROK(sess_ref) || !SvROK(varlist_ref)) {
-             if (verbose)
-                warn("Bad session or varlist reference!\n");
-
-             XSRETURN_UNDEF;
-          }
-
-          sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-          ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-          err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-          err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-          err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-          sv_setpv(*err_str_svp, "");
-          sv_setiv(*err_num_svp, 0);
-          sv_setiv(*err_ind_svp, 0);
-
-          /* Create and initialize a new session context for this bulkwalk.
-          ** This will be used to carry state between callbacks.
-          */
-          Newz(0x57616b6c /* "Walk" */, context, 1, walk_context);
-          if (context == NULL) {
-             sprintf(str_buf, "malloc(context) failed (%s)", strerror(errno));
-             sv_setpv(*err_str_svp, str_buf);
-             sv_setiv(*err_num_svp, SNMPERR_MALLOC);
-             goto err;
-          }
-
-          /* Store the Perl callback and session reference in the context. */
-          context->perl_cb  = newSVsv(perl_callback);
-          context->sess_ref = newSVsv(sess_ref);
-
-          DBPRT(3,("bulkwalk: sess_ref = 0x%p, sess_ptr_sv = 0x%p, ss = 0x%p\n",
-                                                   sess_ref, sess_ptr_sv, ss));
-
-           context->getlabel_f  = NO_FLAGS;    /* long/numeric name flags */
-           context->sprintval_f = USE_BASIC;   /* Don't do fancy printing */
-          context->req_oids    = NULL;         /* List of oid's requested */
-          context->repbase     = NULL;         /* Repeaters in req_oids[] */
-          context->reqbase     = NULL;         /* Ptr to start of requests */
-          context->nreq_oids   = 0;            /* Number of oid's in list */
-          context->repeaters   = 0;            /* Repeater count (see below) */
-          context->non_reps    = nonrepeaters; /* Non-repeater var count */
-          context->max_reps    = maxrepetitions; /* Max repetition/var count */
-          context->pkts_exch   = 0;            /* Packets exchanged in walk */
-          context->oid_total   = 0;            /* OID's received during walk */
-          context->oid_saved   = 0;            /* OID's saved as results */
-
-          if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
-             context->getlabel_f |= USE_LONG_NAMES;
-          if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
-             context->getlabel_f |= USE_NUMERIC_OIDS;
-          if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
-             context->sprintval_f = USE_ENUMS;
-          if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
-             context->sprintval_f = USE_SPRINT_VALUE;
-
-          /* Set up an array of bulktbl's to hold the original list of
-          ** requested OID's.  This is used to populate the PDU's with
-          ** oid values, to contain/sort the return values, and (through
-          ** last_oid/last_len) to determine when the bulkwalk for each
-          ** variable has completed.
-          */
-          varlist = (AV*) SvRV(varlist_ref);
-          varlist_len = av_len(varlist) + 1;   /* XXX av_len returns index of
-                                               ** last element not #elements */
-
-          Newz(0, context->req_oids, varlist_len, bulktbl);
-
-          if (context->req_oids == NULL) {
-             sprintf(str_buf, "Newz(req_oids) failed (%s)", strerror(errno));
-             if (verbose)
-                warn(str_buf);
-             sv_setpv(*err_str_svp, str_buf);
-             sv_setiv(*err_num_svp, SNMPERR_MALLOC);
-             goto err;
-          }
-
-          /* Walk through the varbind_list, parsing and copying each OID
-          ** into a bulktbl slot in the req_oids array.  Bail if there's
-          ** some error.  Create the initial packet to send out, which
-          ** includes the non-repeaters.
-          */
-          DBPRT(1,( "Building request table:\n"));
-          for (varlist_ind = 0; varlist_ind < varlist_len; varlist_ind++) {
-             /* Get a handle on this entry in the request table. */
-             bt_entry = &context->req_oids[context->nreq_oids];
-
-             DBPRT(1,( "  request %d: ", (int)varlist_ind));
-
-             /* Get the request varbind from the varlist, parse it out to
-             ** tag and index, and copy it to the req_oid[] array slots.
-             */
-             varbind_ref = av_fetch(varlist, varlist_ind, 0);
-             if (!SvROK(*varbind_ref)) {
-                sv_setpv(*err_str_svp, \
-                      (char*)snmp_api_errstring(SNMPERR_BAD_NAME));
-                sv_setiv(*err_num_svp, SNMPERR_BAD_NAME);
-                goto err;
-             }
-
-             varbind = (AV*) SvRV(*varbind_ref);
-             __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, "0"),
-                       __av_elem_pv(varbind, VARBIND_IID_F, NULL),
-                       oid_arr, &oid_arr_len, NULL, 0);
-
-             if ((oid_arr_len == 0) || (oid_arr_len > MAX_OID_LEN)) {
-                if (verbose)
-                   warn("error: bulkwalk(): unknown object ID");
-                sv_setpv(*err_str_svp, \
-                      (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
-                sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
-                goto err;
-             }
-
-             /* Copy the now-parsed OID into the first available slot
-             ** in the req_oids[] array.  Set both the req_oid (original
-             ** request) and the last_oid (last requested/seen oid) to
-             ** the initial value.  We build packets using last_oid (see
-             ** below), so initialize last_oid to the initial request.
-             */
-             Copy((void *)oid_arr, (void *)bt_entry->req_oid,
-                                                       oid_arr_len, oid);
-             Copy((void *)oid_arr, (void *)bt_entry->last_oid,
-                                                       oid_arr_len, oid);
-
-             bt_entry->req_len  = oid_arr_len;
-             bt_entry->last_len = oid_arr_len;
-
-             /* Adjust offset to and count of repeaters.  Note non-repeater
-             ** OID's in the list, if appropriate.
-             */
-             if (varlist_ind >= context->non_reps) {
-
-                /* Store a pointer to the first repeater value. */
-                if (context->repbase == NULL)
-                   context->repbase = bt_entry;
-
-                context->repeaters ++;
-
-             } else {
-                bt_entry->norepeat = 1;
-                DBPRT(1,( "(nonrepeater) "));
-             }
-
-             /* Initialize the array in which to hold the Varbinds to be
-             ** returned for the OID or subtree.
-             */
-             if ((bt_entry->vars = (AV*) newAV()) == NULL) {
-                sv_setpv(*err_str_svp, "newAV() failed: ");
-                sv_catpv(*err_str_svp, strerror(errno));
-                sv_setiv(*err_num_svp, SNMPERR_MALLOC);
-                goto err;
-             }
-
-             DBPRT(1,( "%s\n", snprint_objid(_debugx, sizeof(_debugx), oid_arr, oid_arr_len)));
-
-             context->nreq_oids ++;
-          }
-
-          /* Keep track of the number of outstanding requests.  This lets us
-          ** finish processing early if we're done with all requests.
-          */
-          context->req_remain = context->nreq_oids;
-          DBPRT(1,( "Total %d variable requests added\n", context->nreq_oids));
-
-          /* If no good variable requests were found, return an error. */
-          if (context->nreq_oids == 0) {
-                sv_setpv(*err_str_svp, "No variables found in varlist");
-                sv_setiv(*err_num_svp, SNMPERR_NO_VARS);
-                goto err;
-          }
-
-          /* Note that this is a good context.  This allows later callbacks
-          ** to ignore re-sent PDU's that correspond to completed (and hence
-          ** destroyed) bulkwalk contexts.
-          */
-          _context_add(context);
-
-          /* For asynchronous bulkwalk requests, all we have to do at this
-          ** point is enqueue the asynchronous GETBULK request with our
-          ** bulkwalk-specific callback and return.  Remember that the
-          ** bulkwalk_send_pdu() function returns the reqid cast to an
-          ** snmp_pdu pointer, or NULL on failure.  Return undef if the
-          ** initial send fails; bulkwalk_send_pdu() takes care of setting
-          ** the various error values.
-          **
-          ** From here, the callbacks do all the work, including sending
-          ** requests for variables and handling responses.  The caller's
-          ** callback will be invoked as soon as the walk completes.
-          */
-          if (SvTRUE(perl_callback)) {
-             DBPRT(1,( "Starting asynchronous bulkwalk...\n"));
-
-             pdu = _bulkwalk_send_pdu(context);
-
-             if (pdu == NULL) {
-                DBPRT(1,( "Initial asynchronous send failed...\n"));
-                XSRETURN_UNDEF;
-             }
-
-             /* Sent okay...  Return the request ID in 'pdu' as an SvIV. */
-             DBPRT(1,( "Okay, request id is %d\n", (int)pdu));
-/*           XSRETURN_IV((int)pdu); */
-             XPUSHs(sv_2mortal(newSViv((int)pdu)));
-             XSRETURN(1);
-          }
-
-          /* For synchronous bulkwalk, we perform the basic send/receive
-          ** iteration right here.  Once the walk has been completed, the
-          ** bulkwalk_finish() function will push the return values onto
-          ** the Perl call stack, and we return.
-          */
-          DBPRT(1,( "Starting synchronous bulkwalk...\n"));
-
-          while (!(okay = _bulkwalk_done(context))) {
-
-             /* Send a request for the next batch of variables. */
-             DBPRT(1, (DBOUT "Building %s GETBULK bulkwalk PDU (%d)...\n",
-                                       context->pkts_exch ? "next" : "first",
-                                       context->pkts_exch));
-             pdu = _bulkwalk_send_pdu(context);
-
-             /* If the request failed, consider the walk done. */
-             if (pdu == NULL) {
-                DBPRT(1,( "bulkwalk_send_pdu() failed!\n"));
-                break;
-             }
-
-             /* Handle the variables in this response packet.  Break out
-             ** of the loop if an error occurs or no variables are found
-             ** in the response.
-             */
-             if ((i = _bulkwalk_recv_pdu(context, pdu)) <= 0) {
-                DBPRT(2,( "bulkwalk_recv_pdu() returned %d (error/empty)\n", i));
-                break;
-             }
-
-              /* Free the returned pdu.  Don't bother to do this for the async
-             ** case, since the SNMP callback mechanism itself does the free
-             ** for us.
-             */
-             snmp_free_pdu(pdu);
-
-             /* And loop.  The call to bulkwalk_done() sets the ignore flags
-             ** for any completed request subtrees.  Next time around, they
-             ** won't be added to the request sent to the agent.
-             */
-             continue;
-          }
-
-          DBPRT(1, (DBOUT "Bulkwalk done... calling bulkwalk_finish(%s)...\n",
-              okay ? "okay" : "error"));
-          npushed = _bulkwalk_finish(context, okay);
-
-          DBPRT(2,( "Returning %d values on the stack.\n", npushed));
-          XSRETURN(npushed);
-
-       /* Handle error cases and clean up after ourselves. */
-        err:
-          if (context->req_oids && context->nreq_oids) {
-             bt_entry = context->req_oids;
-             for (i = 0; i < context->nreq_oids; i++, bt_entry++)
-                av_clear(bt_entry->vars);
-          }
-          if (context->req_oids)
-             Safefree(context->req_oids);
-          if (context)
-             Safefree(context);
-          if (pdu)
-             snmp_free_pdu(pdu);
-
-           XSRETURN_UNDEF;
-       }
-
-
-int
-snmp_trapV1(sess_ref,enterprise,agent,generic,specific,uptime,varlist_ref)
-        SV *   sess_ref
-        char * enterprise
-        char * agent
-        int    generic
-        int    specific
-        long   uptime
-        SV *   varlist_ref
-       PPCODE:
-       {
-           AV *varlist;
-           SV **varbind_ref;
-           SV **varbind_val_f;
-           AV *varbind;
-          I32 varlist_len;
-          I32 varlist_ind;
-           SnmpSession *ss;
-           netsnmp_pdu *pdu = NULL;
-           struct tree *tp;
-          oid *oid_arr;
-          int oid_arr_len = MAX_OID_LEN;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int type;
-           int res;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-           int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
-           struct enum_list *ep;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref)) {
-
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-
-              pdu = snmp_pdu_create(SNMP_MSG_TRAP);
-
-              if (SvROK(varlist_ref)) {
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-             for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-
-                    tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, NULL),
-                                 __av_elem_pv(varbind, VARBIND_IID_F, NULL),
-                                 oid_arr, &oid_arr_len, &type,0);
-
-                    if (oid_arr_len == 0) {
-                       if (verbose)
-                        warn("error:trap: unable to determine oid for object");
-                       goto err;
-                    }
-
-                    if (type == TYPE_UNKNOWN) {
-                      type = __translate_appl_type(
-                              __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
-                      if (type == TYPE_UNKNOWN) {
-                         if (verbose)
-                            warn("error:trap: no type found for object");
-                         goto err;
-                      }
-                    }
-
-                   varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
-
-                    if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
-                      for(ep = tp->enums; ep; ep = ep->next) {
-                        if (varbind_val_f && SvOK(*varbind_val_f) &&
-                            !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
-                          sv_setiv(*varbind_val_f, ep->value);
-                          break;
-                        }
-                      }
-                    }
-
-                    res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
-                                  (varbind_val_f && SvOK(*varbind_val_f) ?
-                                   SvPV(*varbind_val_f,na):NULL),
-                                  (varbind_val_f && SvOK(*varbind_val_f) ?
-                                   SvCUR(*varbind_val_f):0),
-                                  type);
-
-                    if(res == FAILURE) {
-                        if(verbose) warn("error:trap: adding varbind");
-                        goto err;
-                    }
-
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-              }
-
-             pdu->enterprise = (oid *)malloc( MAX_OID_LEN * sizeof(oid));
-              tp = __tag2oid(enterprise,NULL, pdu->enterprise,
-                             &pdu->enterprise_length, NULL,0);
-             if (pdu->enterprise_length == 0) {
-                 if (verbose) warn("error:trap:invalid enterprise id: %s", enterprise);
-                  goto err;
-             }
-             /*  If agent is given then set the v1-TRAP specific
-                 agent-address field to that.  Otherwise set it to
-                 our address.  */
-              if (agent && strlen(agent)) {
-                 if (__parse_address(agent) == -1 && verbose) {
-                  warn("error:trap:invalid agent address: %s", agent);
-                  goto err;
-                 } else {
-                  *((in_addr_t *)pdu->agent_addr) = __parse_address(agent);
-                }
-              } else {
-                 *((in_addr_t *)pdu->agent_addr) = get_myaddr();
-              }
-              pdu->trap_type = generic;
-              pdu->specific_type = specific;
-              pdu->time = uptime;
-
-              if (snmp_send(ss, pdu) == 0) {
-                snmp_free_pdu(pdu);
-              }
-              XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
-           } else {
-err:
-              XPUSHs(&sv_undef); /* no mem or bad args */
-              if (pdu) snmp_free_pdu(pdu);
-           }
-       Safefree(oid_arr);
-        }
-
-
-int
-snmp_trapV2(sess_ref,uptime,trap_oid,varlist_ref)
-        SV *   sess_ref
-        char * uptime
-        char * trap_oid
-        SV *   varlist_ref
-       PPCODE:
-       {
-           AV *varlist;
-           SV **varbind_ref;
-           SV **varbind_val_f;
-           AV *varbind;
-          I32 varlist_len;
-          I32 varlist_ind;
-           SnmpSession *ss;
-           netsnmp_pdu *pdu = NULL;
-           struct tree *tp;
-          oid *oid_arr;
-          int oid_arr_len = MAX_OID_LEN;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int type;
-           int res;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-           int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
-           struct enum_list *ep;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
-
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-
-              pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
-
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-             /************************************************/
-              res = __add_var_val_str(pdu, sysUpTime, SYS_UPTIME_OID_LEN,
-                               uptime, strlen(uptime), TYPE_TIMETICKS);
-
-              if(res == FAILURE) {
-                if(verbose) warn("error:trap v2: adding sysUpTime varbind");
-               goto err;
-              }
-
-             res = __add_var_val_str(pdu, snmpTrapOID, SNMP_TRAP_OID_LEN,
-                               trap_oid ,strlen(trap_oid) ,TYPE_OBJID);
-
-              if(res == FAILURE) {
-                if(verbose) warn("error:trap v2: adding snmpTrapOID varbind");
-               goto err;
-              }
-
-
-             /******************************************************/
-
-             for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-
-                    tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F,NULL),
-                                 __av_elem_pv(varbind, VARBIND_IID_F,NULL),
-                                 oid_arr, &oid_arr_len, &type,0);
-
-                    if (oid_arr_len == 0) {
-                       if (verbose)
-                        warn("error:trap v2: unable to determine oid for object");
-                       goto err;
-                    }
-
-                    if (type == TYPE_UNKNOWN) {
-                      type = __translate_appl_type(
-                                 __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
-                      if (type == TYPE_UNKNOWN) {
-                         if (verbose)
-                            warn("error:trap v2: no type found for object");
-                         goto err;
-                      }
-                    }
-
-                   varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
-
-                    if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
-                      for(ep = tp->enums; ep; ep = ep->next) {
-                        if (varbind_val_f && SvOK(*varbind_val_f) &&
-                            !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
-                          sv_setiv(*varbind_val_f, ep->value);
-                          break;
-                        }
-                      }
-                    }
-
-                    res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
-                                  (varbind_val_f && SvOK(*varbind_val_f) ?
-                                   SvPV(*varbind_val_f,na):NULL),
-                                  (varbind_val_f && SvOK(*varbind_val_f) ?
-                                   SvCUR(*varbind_val_f):0),
-                                  type);
-
-                    if(res == FAILURE) {
-                        if(verbose) warn("error:trap v2: adding varbind");
-                        goto err;
-                    }
-
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-
-              if (snmp_send(ss, pdu) == 0) {
-                snmp_free_pdu(pdu);
-              }
-
-              XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
-           } else {
-err:
-              XPUSHs(&sv_undef); /* no mem or bad args */
-              if (pdu) snmp_free_pdu(pdu);
-           }
-       Safefree(oid_arr);
-        }
-
-
-
-int
-snmp_inform(sess_ref,uptime,trap_oid,varlist_ref,perl_callback)
-        SV *   sess_ref
-        char * uptime
-        char * trap_oid
-        SV *   varlist_ref
-        SV *   perl_callback
-       PPCODE:
-       {
-           AV *varlist;
-           SV **varbind_ref;
-           SV **varbind_val_f;
-           AV *varbind;
-          I32 varlist_len;
-          I32 varlist_ind;
-           SnmpSession *ss;
-           netsnmp_pdu *pdu = NULL;
-           netsnmp_pdu *response;
-           struct tree *tp;
-          oid *oid_arr;
-          int oid_arr_len = MAX_OID_LEN;
-           snmp_xs_cb_data *xs_cb_data;
-           SV **sess_ptr_sv;
-           SV **err_str_svp;
-           SV **err_num_svp;
-           SV **err_ind_svp;
-           int status = 0;
-           int type;
-           int res;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-           int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
-           struct enum_list *ep;
-
-           New (0, oid_arr, MAX_OID_LEN, oid);
-
-           if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
-
-              sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
-             ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
-              err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
-              err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
-              err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
-              sv_setpv(*err_str_svp, "");
-              sv_setiv(*err_num_svp, 0);
-              sv_setiv(*err_ind_svp, 0);
-
-              pdu = snmp_pdu_create(SNMP_MSG_INFORM);
-
-              varlist = (AV*) SvRV(varlist_ref);
-              varlist_len = av_len(varlist);
-             /************************************************/
-              res = __add_var_val_str(pdu, sysUpTime, SYS_UPTIME_OID_LEN,
-                               uptime, strlen(uptime), TYPE_TIMETICKS);
-
-              if(res == FAILURE) {
-                if(verbose) warn("error:inform: adding sysUpTime varbind");
-               goto err;
-              }
-
-             res = __add_var_val_str(pdu, snmpTrapOID, SNMP_TRAP_OID_LEN,
-                               trap_oid ,strlen(trap_oid) ,TYPE_OBJID);
-
-              if(res == FAILURE) {
-                if(verbose) warn("error:inform: adding snmpTrapOID varbind");
-               goto err;
-              }
-
-
-             /******************************************************/
-
-             for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
-                 varbind_ref = av_fetch(varlist, varlist_ind, 0);
-                 if (SvROK(*varbind_ref)) {
-                    varbind = (AV*) SvRV(*varbind_ref);
-
-                    tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F,NULL),
-                                 __av_elem_pv(varbind, VARBIND_IID_F,NULL),
-                                 oid_arr, &oid_arr_len, &type,0);
-
-                    if (oid_arr_len == 0) {
-                       if (verbose)
-                        warn("error:inform: unable to determine oid for object");
-                       goto err;
-                    }
-
-                    if (type == TYPE_UNKNOWN) {
-                      type = __translate_appl_type(
-                                 __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
-                      if (type == TYPE_UNKNOWN) {
-                         if (verbose)
-                            warn("error:inform: no type found for object");
-                         goto err;
-                      }
-                    }
-
-                   varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
-
-                    if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
-                      for(ep = tp->enums; ep; ep = ep->next) {
-                        if (varbind_val_f && SvOK(*varbind_val_f) &&
-                            !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
-                          sv_setiv(*varbind_val_f, ep->value);
-                          break;
-                        }
-                      }
-                    }
-
-                    res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
-                                  (varbind_val_f && SvOK(*varbind_val_f) ?
-                                   SvPV(*varbind_val_f,na):NULL),
-                                  (varbind_val_f && SvOK(*varbind_val_f) ?
-                                   SvCUR(*varbind_val_f):0),
-                                  type);
-
-                    if(res == FAILURE) {
-                        if(verbose) warn("error:inform: adding varbind");
-                        goto err;
-                    }
-
-                 } /* if var_ref is ok */
-              } /* for all the vars */
-
-
-              if (SvTRUE(perl_callback)) {
-                  xs_cb_data =
-                      (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
-                 xs_cb_data->perl_cb = newSVsv(perl_callback);
-                 xs_cb_data->sess_ref = newRV_inc(SvRV(sess_ref));
-
-                 status = snmp_async_send(ss, pdu, __snmp_xs_cb,
-                                          (void*)xs_cb_data);
-                 if (status != 0) {
-                    XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
-                 } else {
-                    snmp_free_pdu(pdu);
-                    sv_catpv(*err_str_svp,
-                             (char*)snmp_api_errstring(ss->s_snmp_errno));
-                    sv_setiv(*err_num_svp, ss->s_snmp_errno);
-                    XPUSHs(&sv_undef);
-                 }
-                goto done;
-              }
-
-             status = __send_sync_pdu(ss, pdu, &response,
-                                      NO_RETRY_NOSUCH,
-                                       *err_str_svp, *err_num_svp,
-                                       *err_ind_svp);
-
-              if (response) snmp_free_pdu(response);
-
-              if (status) {
-                XPUSHs(&sv_undef);
-             } else {
-                 XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
-              }
-           } else {
-err:
-              XPUSHs(&sv_undef); /* no mem or bad args */
-              if (pdu) snmp_free_pdu(pdu);
-           }
-done:
-       Safefree(oid_arr);
-        }
-
-
-
-char *
-snmp_get_type(tag)
-       char *          tag
-       CODE:
-       {
-          struct tree *tp  = NULL;
-          static char type_str[MAX_TYPE_NAME_LEN];
-           char *ret = NULL;
-
-           if (tag && *tag) tp = __tag2oid(tag, NULL, NULL, NULL, NULL,0);
-           if (tp) __get_type_str(tp->type, ret = type_str);
-          RETVAL = ret;
-       }
-       OUTPUT:
-        RETVAL
-
-
-void
-snmp_dump_packet(flag)
-       int             flag
-       CODE:
-       {
-          snmp_set_dump_packet(flag);
-       }
-
-
-char *
-snmp_map_enum(tag, val, iflag)
-       char *          tag
-       char *          val
-       int             iflag
-       CODE:
-       {
-          struct tree *tp  = NULL;
-           struct enum_list *ep;
-           char str_buf[STR_BUF_SIZE];
-           int ival;
-
-           RETVAL = NULL;
-
-           if (tag && *tag) tp = __tag2oid(tag, NULL, NULL, NULL, NULL,0);
-
-           if (tp) {
-              if (iflag) {
-                 ival = atoi(val);
-                 for(ep = tp->enums; ep; ep = ep->next) {
-                    if (ep->value == ival) {
-                       RETVAL = ep->label;
-                       break;
-                    }
-                 }
-              } else {
-                 for(ep = tp->enums; ep; ep = ep->next) {
-                    if (strEQ(ep->label, val)) {
-                       sprintf(str_buf,"%d", ep->value);
-                       RETVAL = str_buf;
-                       break;
-                    }
-                 }
-              }
-           }
-       }
-       OUTPUT:
-        RETVAL
-
-#define SNMP_XLATE_MODE_OID2TAG 1
-#define SNMP_XLATE_MODE_TAG2OID 0
-
-char *
-snmp_translate_obj(var,mode,use_long,auto_init,best_guess)
-       char *          var
-       int             mode
-       int             use_long
-       int             auto_init
-       int             best_guess
-       CODE:
-       {
-          char str_buf[STR_BUF_SIZE];
-          oid oid_arr[MAX_OID_LEN];
-           int oid_arr_len = MAX_OID_LEN;
-           char * label;
-           char * iid;
-           int status = FAILURE;
-           int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
-
-           str_buf[0] = '\0';
-          switch (mode) {
-              case SNMP_XLATE_MODE_TAG2OID:
-               if (!__tag2oid(var, NULL, oid_arr, &oid_arr_len, NULL, best_guess)) {
-                  if (verbose) warn("error:snmp_translate_obj:Unknown OID %s\n",var);
-                } else {
-                   status = __sprint_num_objid(str_buf, oid_arr, oid_arr_len);
-                }
-                break;
-             case SNMP_XLATE_MODE_OID2TAG:
-               oid_arr_len = 0;
-               __concat_oid_str(oid_arr, &oid_arr_len, var);
-               snprint_objid(str_buf, sizeof(str_buf), oid_arr, oid_arr_len);
-               if (!use_long) {
-                  label = NULL; iid = NULL;
-                 if (((status=__get_label_iid(str_buf,
-                      &label, &iid, NO_FLAGS)) == SUCCESS)
-                     && label) {
-                    strcpy(str_buf, label);
-                    if (iid && *iid) {
-                      strcat(str_buf, ".");
-                      strcat(str_buf, iid);
-                    }
-                 }
-               }
-                break;
-             default:
-              if (verbose) warn("snmp_translate_obj:unknown translation mode: %s\n", mode);
-           }
-           if (*str_buf) {
-              RETVAL = (char*)str_buf;
-           } else {
-              RETVAL = (char*)NULL;
-           }
-       }
-        OUTPUT:
-        RETVAL
-
-void
-snmp_set_replace_newer(val)
-       int val
-       CODE:
-       {
-          netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_REPLACE);
-       }
-
-void
-snmp_set_save_descriptions(val)
-       int     val
-       CODE:
-       {
-          snmp_set_save_descriptions(val);
-       }
-
-void
-snmp_set_debugging(val)
-       int     val
-       CODE:
-       {
-          snmp_set_do_debugging(val);
-       }
-
-void
-snmp_debug_internals(val)
-       int     val
-       CODE:
-       {
-#ifdef         DEBUGGING
-          _debug_level = val;
-#endif         /* DEBUGGING */
-       }
-
-
-void
-snmp_sock_cleanup()
-       CODE:
-       {
-          SOCK_CLEANUP;
-       }
-
-void
-snmp_mainloop_finish()
-       CODE:
-       {
-           mainloop_finish = 1;
-       }
-
-
-void
-snmp_main_loop(timeout_sec,timeout_usec,perl_callback)
-       int     timeout_sec
-       int     timeout_usec
-       SV *    perl_callback
-       CODE:
-       {
-        int numfds, fd_count;
-        fd_set fdset;
-        struct timeval time_val, *tvp;
-        struct timeval last_time, *ltvp;
-        struct timeval ctimeout, *ctvp;
-        struct timeval interval, *itvp;
-        int block;
-       SV *cb;
-
-
-       mainloop_finish = 0;
-
-       itvp = &interval;
-       itvp->tv_sec = timeout_sec;
-       itvp->tv_usec = timeout_usec;
-        ctvp = &ctimeout;
-        ctvp->tv_sec = -1;
-        ltvp = &last_time;
-        gettimeofday(ltvp,(struct timezone*)0);
-       timersub(ltvp,itvp,ltvp);
-        while (1) {
-           numfds = 0;
-           FD_ZERO(&fdset);
-           block = 1;
-           tvp = &time_val;
-           timerclear(tvp);
-           snmp_select_info(&numfds, &fdset, tvp, &block);
-           __recalc_timeout(tvp,ctvp,ltvp,itvp,&block);
-           # printf("pre-select: numfds = %ld, block = %ld\n", numfds, block);
-           if (block == 1) tvp = NULL; /* block without timeout */
-           fd_count = select(numfds, &fdset, 0, 0, tvp);
-           #printf("post-select: fd_count = %ld,block = %ld\n",fd_count,block);
-           if (fd_count > 0) {
-                       dSP;
-                       ENTER;
-                       SAVETMPS;
-              snmp_read(&fdset);
-                       FREETMPS;
-                       LEAVE;
-
-           } else switch(fd_count) {
-              case 0:
-                SPAGAIN;
-                ENTER;
-                SAVETMPS;
-                 snmp_timeout();
-                 if (!timerisset(ctvp)) {
-                    if (SvTRUE(perl_callback)) {
-                       /* sv_2mortal(perl_callback); */
-                       cb = __push_cb_args(perl_callback, NULL);
-                       __call_callback(cb, G_DISCARD);
-                       ctvp->tv_sec = -1;
-
-                    } else {
-                       FREETMPS;
-                       LEAVE;
-                       goto done;
-                    }
-                 }
-                 FREETMPS;
-                 LEAVE;
-                 break;
-              case -1:
-                 if (errno == EINTR) {
-                    continue;
-                 } else {
-                    /* snmp_set_detail(strerror(errno)); */
-                    /* snmp_errno = SNMPERR_GENERR; */
-                 }
-              default:;
-           }
-
-          /* A call to snmp_mainloop_finish() in the callback sets the
-          ** mainloop_finish flag.  Exit the loop after the callback returns.
-          */
-          if (mainloop_finish)
-             goto done;
-
-        }
-     done:
-           return;
-       }
-
-
-void
-snmp_get_select_info()
-       PPCODE:
-       {
-        int numfds;
-        fd_set fdset;
-        struct timeval time_val, *tvp;
-        int block;
-       int i;
-
-        numfds = 0;
-        block = 1;
-        tvp = &time_val;
-        FD_ZERO(&fdset);
-        snmp_select_info(&numfds, &fdset, tvp, &block);
-       XPUSHs(sv_2mortal(newSViv(block)));
-       if(block){
-            XPUSHs(sv_2mortal(newSViv(0)));
-            XPUSHs(sv_2mortal(newSViv(0)));
-       } else {
-            XPUSHs(sv_2mortal(newSViv(tvp->tv_sec)));
-            XPUSHs(sv_2mortal(newSViv(tvp->tv_usec)));
-       }
-       if ( numfds ) {
-            for(i=0; i<numfds ; i++) {
-                if(FD_ISSET(i, &fdset)){
-                    XPUSHs(sv_2mortal(newSViv(i)));
-                }
-            }
-       } else {
-            XPUSHs(&sv_undef);  /* no mem or bad args */
-       }
-       }
-
-void
-snmp_read_on_fd(fd)
-       int fd
-       CODE:
-       {
-           fd_set fdset;
-
-           FD_ZERO(&fdset);
-           FD_SET(fd, &fdset);
-
-           snmp_read(&fdset);
-       }
-
-void
-snmp_check_timeout()
-       CODE:
-       {
-          snmp_timeout();
-       }
-
-MODULE = SNMP  PACKAGE = SNMP::MIB::NODE       PREFIX = snmp_mib_node_
-SV *
-snmp_mib_node_TIEHASH(class,key,tp=0)
-       char *  class
-       char *  key
-        IV tp
-       CODE:
-       {
-            __libraries_init("perl");
-           if (!tp) tp = (IV)__tag2oid(key, NULL, NULL, NULL, NULL,0);
-           if (tp) {
-              ST(0) = sv_newmortal();
-              sv_setref_iv(ST(0), class, tp);
-           } else {
-              ST(0) = &sv_undef;
-           }
-
-       }
-
-SV *
-snmp_mib_node_FETCH(tp_ref, key)
-       SV *    tp_ref
-       char *  key
-       CODE:
-       {
-          char c = *key;
-          char str_buf[STR_BUF_SIZE];
-           SnmpMibNode *tp = NULL;
-           struct index_list *ip;
-           struct enum_list *ep;
-           struct range_list *rp;
-          struct varbind_list *vp;
-           struct module *mp;
-           SV *child_list_aref, *next_node_href, *mib_tied_href = NULL;
-          SV **nn_hrefp;
-           HV *mib_hv, *enum_hv, *range_hv;
-           AV *index_av, *varbind_av, *ranges_av;
-           MAGIC *mg = NULL;
-
-           if (SvROK(tp_ref)) tp = (SnmpMibNode*)SvIV((SV*)SvRV(tp_ref));
-
-          ST(0) = sv_newmortal();
-           if (tp)
-          switch (c) {
-             case 'a': /* access */
-                 if (strncmp("access", key, strlen(key))) break;
-                 switch        (tp->access) {
-                   case MIB_ACCESS_READONLY:
-                     sv_setpv(ST(0),"ReadOnly");
-                     break;
-                   case MIB_ACCESS_READWRITE:
-                     sv_setpv(ST(0),"ReadWrite");
-                     break;
-                   case MIB_ACCESS_WRITEONLY:
-                     sv_setpv(ST(0),"WriteOnly");
-                     break;
-                   case MIB_ACCESS_NOACCESS:
-                     sv_setpv(ST(0),"NoAccess");
-                     break;
-                   case MIB_ACCESS_NOTIFY:
-                     sv_setpv(ST(0),"Notify");
-                     break;
-                   case MIB_ACCESS_CREATE:
-                     sv_setpv(ST(0),"Create");
-                     break;
-                   default:
-                     break;
-                 }
-                 break;
-             case 'c': /* children */
-                 if (strncmp("children", key, strlen(key))) break;
-                 child_list_aref = newRV((SV*)newAV());
-                 for (tp = tp->child_list; tp; tp = tp->next_peer) {
-                    mib_hv = perl_get_hv("SNMP::MIB", FALSE);
-                    if (SvMAGICAL(mib_hv)) mg = mg_find((SV*)mib_hv, 'P');
-                    if (mg) mib_tied_href = (SV*)mg->mg_obj;
-                    next_node_href = newRV((SV*)newHV());
-                    __tp_sprint_num_objid(str_buf, tp);
-                    nn_hrefp = hv_fetch((HV*)SvRV(mib_tied_href),
-                                        str_buf, strlen(str_buf), 1);
-                    if (!SvROK(*nn_hrefp)) {
-                       sv_setsv(*nn_hrefp, next_node_href);
-                       ENTER ;
-                       SAVETMPS ;
-                       PUSHMARK(sp) ;
-                       XPUSHs(SvRV(*nn_hrefp));
-                       XPUSHs(sv_2mortal(newSVpv("SNMP::MIB::NODE",0)));
-                       XPUSHs(sv_2mortal(newSVpv(str_buf,0)));
-                       XPUSHs(sv_2mortal(newSViv((IV)tp)));
-                       PUTBACK ;
-                       perl_call_pv("SNMP::_tie",G_VOID);
-                       /* pp_tie(ARGS); */
-                       SPAGAIN ;
-                       FREETMPS ;
-                       LEAVE ;
-                    } /* if SvROK */
-                    av_push((AV*)SvRV(child_list_aref), *nn_hrefp);
-                 } /* for child_list */
-                 sv_setsv(ST(0), child_list_aref);
-                 break;
-             case 'v':
-                if (strncmp("varbinds", key, strlen(key))) break;
-                varbind_av = newAV();
-                for (vp = tp->varbinds; vp; vp = vp->next) {
-                   av_push(varbind_av, newSVpv((vp->vblabel),strlen(vp->vblabel)));
-                }
-                sv_setsv(ST(0), newRV((SV*)varbind_av));
-                break;
-             case 'd': /* description */
-                  if (strncmp("description", key, strlen(key))) {
-                      if(!(strncmp("defaultValue",key,strlen(key)))) {
-                          /* We're looking at defaultValue */
-                          sv_setpv(ST(0), tp->defaultValue);
-                          break;
-                      } /* end if */
-                  } /* end if */
-                 /* we must be looking at description */
-                 sv_setpv(ST(0),tp->description);
-                 break;
-              case 'i': /* indexes */
-                 if (strncmp("indexes", key, strlen(key))) break;
-                 index_av = newAV();
-                 for(ip=tp->indexes; ip != NULL; ip = ip->next) {
-                    av_push(index_av,newSVpv((ip->ilabel),strlen(ip->ilabel)));
-                 }
-                sv_setsv(ST(0), newRV((SV*)index_av));
-                break;
-             case 'l': /* label */
-                 if (strncmp("label", key, strlen(key))) break;
-                 sv_setpv(ST(0),tp->label);
-                 break;
-             case 'm': /* moduleID */
-                 if (strncmp("moduleID", key, strlen(key))) break;
-                 mp = find_module(tp->modid);
-                 if (mp) sv_setpv(ST(0), mp->name);
-                 break;
-             case 'n': /* nextNode */
-                 if (strncmp("nextNode", key, strlen(key))) break;
-                 tp = __get_next_mib_node(tp);
-                 if (tp == NULL) {
-                    sv_setsv(ST(0), &sv_undef);
-                    break;
-                 }
-                 mib_hv = perl_get_hv("SNMP::MIB", FALSE);
-                 if (SvMAGICAL(mib_hv)) mg = mg_find((SV*)mib_hv, 'P');
-                 if (mg) mib_tied_href = (SV*)mg->mg_obj;
-                 __tp_sprint_num_objid(str_buf, tp);
-
-                 nn_hrefp = hv_fetch((HV*)SvRV(mib_tied_href),
-                                     str_buf, strlen(str_buf), 1);
-                 /* if (!SvROK(*nn_hrefp)) { */ /* bug in ucd - 2 .0.0 nodes */
-                 next_node_href = newRV((SV*)newHV());
-                 sv_setsv(*nn_hrefp, next_node_href);
-                 ENTER ;
-                 SAVETMPS ;
-                 PUSHMARK(sp) ;
-                 XPUSHs(SvRV(*nn_hrefp));
-                 XPUSHs(sv_2mortal(newSVpv("SNMP::MIB::NODE",0)));
-                 XPUSHs(sv_2mortal(newSVpv(str_buf,0)));
-                 XPUSHs(sv_2mortal(newSViv((IV)tp)));
-                 PUTBACK ;
-                 perl_call_pv("SNMP::_tie",G_VOID);
-                 /* pp_tie(ARGS); */
-                 SPAGAIN ;
-                 FREETMPS ;
-                 LEAVE ;
-                 /* } */
-                 sv_setsv(ST(0), *nn_hrefp);
-                 break;
-             case 'o': /* objectID */
-                 if (strncmp("objectID", key, strlen(key))) break;
-                 __tp_sprint_num_objid(str_buf, tp);
-                 sv_setpv(ST(0),str_buf);
-                 break;
-             case 'p': /* parent */
-                 if (strncmp("parent", key, strlen(key))) break;
-                 tp = tp->parent;
-                 if (tp == NULL) {
-                    sv_setsv(ST(0), &sv_undef);
-                    break;
-                 }
-                 mib_hv = perl_get_hv("SNMP::MIB", FALSE);
-                 if (SvMAGICAL(mib_hv)) mg = mg_find((SV*)mib_hv, 'P');
-                 if (mg) mib_tied_href = (SV*)mg->mg_obj;
-                 next_node_href = newRV((SV*)newHV());
-                 __tp_sprint_num_objid(str_buf, tp);
-                 nn_hrefp = hv_fetch((HV*)SvRV(mib_tied_href),
-                                     str_buf, strlen(str_buf), 1);
-                 if (!SvROK(*nn_hrefp)) {
-                 sv_setsv(*nn_hrefp, next_node_href);
-                 ENTER ;
-                 SAVETMPS ;
-                 PUSHMARK(sp) ;
-                 XPUSHs(SvRV(*nn_hrefp));
-                 XPUSHs(sv_2mortal(newSVpv("SNMP::MIB::NODE",0)));
-                 XPUSHs(sv_2mortal(newSVpv(str_buf,0)));
-                 XPUSHs(sv_2mortal(newSViv((IV)tp)));
-                 PUTBACK ;
-                 perl_call_pv("SNMP::_tie",G_VOID);
-                 /* pp_tie(ARGS); */
-                 SPAGAIN ;
-                 FREETMPS ;
-                 LEAVE ;
-                 }
-                 sv_setsv(ST(0), *nn_hrefp);
-                 break;
-             case 'r': /* ranges */
-                 if (strncmp("ranges", key, strlen(key))) break;
-                 ranges_av = newAV();
-                 for(rp=tp->ranges; rp ; rp = rp->next) {
-                  range_hv = newHV();
-                   hv_store(range_hv, "low", strlen("low"), newSViv(rp->low), 0);
-                   hv_store(range_hv, "high", strlen("high"), newSViv(rp->high), 0);
-                  av_push(ranges_av, newRV((SV*)range_hv));
-                 }
-                 sv_setsv(ST(0), newRV((SV*)ranges_av));
-                 break;
-             case 's': /* subID */
-                 if (strncmp("subID", key, strlen(key))) {
-                   if (strncmp("status", key, strlen(key))) {
-                      if (strncmp("syntax", key, strlen(key))) break;
-                      if (tp->tc_index >= 0) {
-                         sv_setpv(ST(0), get_tc_descriptor(tp->tc_index));
-                      } else {
-                         __get_type_str(tp->type, str_buf);
-                         sv_setpv(ST(0), str_buf);
-                      }
-                      break;
-                   }
-
-                   switch(tp->status) {
-                     case MIB_STATUS_MANDATORY:
-                       sv_setpv(ST(0),"Mandatory");
-                       break;
-                     case MIB_STATUS_OPTIONAL:
-                       sv_setpv(ST(0),"Optional");
-                       break;
-                     case MIB_STATUS_OBSOLETE:
-                       sv_setpv(ST(0),"Obsolete");
-                       break;
-                     case MIB_STATUS_DEPRECATED:
-                       sv_setpv(ST(0),"Deprecated");
-                       break;
-                    case MIB_STATUS_CURRENT:
-                       sv_setpv(ST(0),"Current");
-                       break;
-                     default:
-                       break;
-                   }
-                 } else {
-                   sv_setiv(ST(0),(I32)tp->subid);
-                 }
-                 break;
-             case 't': /* type */
-                 if (strncmp("type", key, strlen(key))) {
-                    if (strncmp("textualConvention", key, strlen(key))) break;
-                    sv_setpv(ST(0), get_tc_descriptor(tp->tc_index));
-                    break;
-                 }
-                 __get_type_str(tp->type, str_buf);
-                 sv_setpv(ST(0), str_buf);
-                 break;
-             case 'u': /* units */
-                 if (strncmp("units", key, strlen(key))) break;
-                 sv_setpv(ST(0),tp->units);
-                 break;
-             case 'h': /* hint */
-                 if (strncmp("hint", key, strlen(key))) break;
-                 sv_setpv(ST(0),tp->hint);
-                 break;
-             case 'e': /* enums */
-                 if (strncmp("enums", key, strlen(key))) break;
-                 enum_hv = newHV();
-                 for(ep=tp->enums; ep != NULL; ep = ep->next) {
-                   hv_store(enum_hv, ep->label, strlen(ep->label),
-                                newSViv(ep->value), 0);
-                 }
-                 sv_setsv(ST(0), newRV((SV*)enum_hv));
-                 break;
-              default:
-                 break;
-          }
-       }
-
-MODULE = SNMP  PACKAGE = SnmpSessionPtr        PREFIX = snmp_session_
-void
-snmp_session_DESTROY(sess_ptr)
-       SnmpSession *sess_ptr
-       CODE:
-       {
-           snmp_close( sess_ptr );
-       }
-