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

SNMP编程

开发平台:

Unix_Linux

  1.            session.community = (u_char *)community;
  2.    session.peername = peer;
  3.    session.local_port = lport;
  4.            session.retries = retries; /* 5 */
  5.            session.timeout = timeout; /* 1000000L */
  6.            session.authenticator = NULL;
  7.            ss = snmp_open(&session);
  8.            if (ss == NULL) {
  9.       if (verbose) warn("error:snmp_new_session: Couldn't open SNMP session");
  10.            }
  11.         end:
  12.            RETVAL = ss;
  13. }
  14.         OUTPUT:
  15.         RETVAL
  16. SnmpSession *
  17. 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, auth_master_key, auth_master_key_len, priv_master_key, priv_master_key_len, auth_localized_key, auth_localized_key_len, priv_localized_key, priv_localized_key_len)
  18.         int version
  19.         char * peer
  20.         int retries
  21.         int timeout
  22.         char *  sec_name
  23.         int     sec_level
  24.         char *  sec_eng_id
  25.         char *  context_eng_id
  26.         char *  context
  27.         char *  auth_proto
  28.         char *  auth_pass
  29.         char *  priv_proto
  30.         char *  priv_pass
  31. int     eng_boots
  32. int     eng_time
  33.         char *  auth_master_key
  34.         size_t  auth_master_key_len
  35.         char *  priv_master_key
  36.         size_t  priv_master_key_len
  37.         char *  auth_localized_key
  38.         size_t  auth_localized_key_len
  39.         char *  priv_localized_key
  40.         size_t  priv_localized_key_len
  41. CODE:
  42. {
  43. /*             u_char sec_eng_id_buf[ENG_ID_BUF_SIZE]; */
  44. /*             u_char context_eng_id_buf[ENG_ID_BUF_SIZE]; */
  45.    SnmpSession session = {0};
  46.    SnmpSession *ss = NULL;
  47.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  48.            __libraries_init("perl");
  49.    if (version == 3) {
  50. session.version = SNMP_VERSION_3;
  51.            } else {
  52. if (verbose)
  53.                    warn("error:snmp_new_v3_session:Unsupported SNMP version (%d)n", version);
  54.                 goto end;
  55.    }
  56.    session.peername = strdup(peer);
  57.            session.retries = retries; /* 5 */
  58.            session.timeout = timeout; /* 1000000L */
  59.            session.authenticator = NULL;
  60.            session.contextNameLen = strlen(context);
  61.            session.contextName = context;
  62.            session.securityNameLen = strlen(sec_name);
  63.            session.securityName = sec_name;
  64.            session.securityLevel = sec_level;
  65.            session.securityModel = USM_SEC_MODEL_NUMBER;
  66.            /* session.securityEngineID = sec_eng_id_buf;*/
  67.            session.securityEngineIDLen =
  68.               hex_to_binary2(sec_eng_id, strlen(sec_eng_id),
  69.                              (char **) &session.securityEngineID);
  70.            /* session.contextEngineID = context_eng_id_buf; */
  71.            session.contextEngineIDLen =
  72.               hex_to_binary2(sec_eng_id, strlen(sec_eng_id),
  73.                              (char **) &session.contextEngineID);
  74.            session.engineBoots = eng_boots;
  75.            session.engineTime = eng_time;
  76. #ifndef DISABLE_MD5
  77.            if (!strcmp(auth_proto, "MD5")) {
  78.                session.securityAuthProto = 
  79.                   snmp_duplicate_objid(usmHMACMD5AuthProtocol,
  80.                                           USM_AUTH_PROTO_MD5_LEN);
  81.               session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
  82.            } else
  83. #endif
  84.                if (!strcmp(auth_proto, "SHA")) {
  85.                session.securityAuthProto = 
  86.                    snmp_duplicate_objid(usmHMACSHA1AuthProtocol,
  87.                                         USM_AUTH_PROTO_SHA_LEN);
  88.               session.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
  89.            } else if (!strcmp(auth_proto, "DEFAULT")) {
  90.                const oid *theoid =
  91.                    get_default_authtype(&session.securityAuthProtoLen);
  92.                session.securityAuthProto = 
  93.                    snmp_duplicate_objid(theoid, session.securityAuthProtoLen);
  94.            } else {
  95.               if (verbose)
  96.                  warn("error:snmp_new_v3_session:Unsupported authentication protocol(%s)n", auth_proto);
  97.               goto end;
  98.            }
  99.            if (session.securityLevel >= SNMP_SEC_LEVEL_AUTHNOPRIV) {
  100.                if (auth_localized_key_len) {
  101.                    memdup(&session.securityAuthLocalKey,
  102.                           auth_localized_key,
  103.                           auth_localized_key_len);
  104.                    session.securityAuthLocalKeyLen = auth_localized_key_len;
  105.                } else if (auth_master_key_len) {
  106.                    session.securityAuthKeyLen =
  107.                        SNMP_MIN(auth_master_key_len,
  108.                                 sizeof(session.securityAuthKey));
  109.                    memcpy(session.securityAuthKey, auth_master_key,
  110.                           session.securityAuthKeyLen);
  111.                } else {
  112.                    if (strlen(auth_pass) > 0) {
  113.                        session.securityAuthKeyLen = USM_AUTH_KU_LEN;
  114.                        if (generate_Ku(session.securityAuthProto,
  115.                                        session.securityAuthProtoLen,
  116.                                        (u_char *)auth_pass, strlen(auth_pass),
  117.                                        session.securityAuthKey,
  118.                                        &session.securityAuthKeyLen) != SNMPERR_SUCCESS) {
  119.                            if (verbose)
  120.                                warn("error:snmp_new_v3_session:Error generating Ku from authentication password.n");
  121.                            goto end;
  122.                        }
  123.                    }
  124.                }
  125.            }
  126. #ifndef DISABLE_DES
  127.            if (!strcmp(priv_proto, "DES")) {
  128.               session.securityPrivProto =
  129.                   snmp_duplicate_objid(usmDESPrivProtocol,
  130.                                        USM_PRIV_PROTO_DES_LEN);
  131.               session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
  132.            } else
  133. #endif
  134.                if (!strncmp(priv_proto, "AES", 3)) {
  135.               session.securityPrivProto =
  136.                   snmp_duplicate_objid(usmAESPrivProtocol,
  137.                                        USM_PRIV_PROTO_AES_LEN);
  138.               session.securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
  139.            } else if (!strcmp(priv_proto, "DEFAULT")) {
  140.                const oid *theoid =
  141.                    get_default_privtype(&session.securityPrivProtoLen);
  142.                session.securityPrivProto = 
  143.                    snmp_duplicate_objid(theoid, session.securityPrivProtoLen);
  144.            } else {
  145.               if (verbose)
  146.                  warn("error:snmp_new_v3_session:Unsupported privacy protocol(%s)n", priv_proto);
  147.               goto end;
  148.            }
  149.            if (session.securityLevel >= SNMP_SEC_LEVEL_AUTHPRIV) {
  150.                if (priv_localized_key_len) {
  151.                    memdup(&session.securityPrivLocalKey,
  152.                           priv_localized_key,
  153.                           priv_localized_key_len);
  154.                    session.securityPrivLocalKeyLen = priv_localized_key_len;
  155.                } else if (priv_master_key_len) {
  156.                    session.securityPrivKeyLen =
  157.                        SNMP_MIN(auth_master_key_len,
  158.                                 sizeof(session.securityPrivKey));
  159.                    memcpy(session.securityPrivKey, priv_master_key,
  160.                           session.securityPrivKeyLen);
  161.                } else {
  162.                    session.securityPrivKeyLen = USM_PRIV_KU_LEN;
  163.                    if (generate_Ku(session.securityAuthProto,
  164.                                    session.securityAuthProtoLen,
  165.                                    (u_char *)priv_pass, strlen(priv_pass),
  166.                                    session.securityPrivKey,
  167.                                    &session.securityPrivKeyLen) != SNMPERR_SUCCESS) {
  168.                        if (verbose)
  169.                            warn("error:snmp_new_v3_session:Error generating Ku from privacy pass phrase.n");
  170.                        goto end;
  171.                    }
  172.                }
  173.             }
  174.            ss = snmp_open(&session);
  175.            if (ss == NULL) {
  176.       if (verbose) warn("error:snmp_new_v3_session:Couldn't open SNMP session");
  177.            }
  178.         end:
  179.            RETVAL = ss;
  180.    free (session.contextEngineID);
  181. }
  182.         OUTPUT:
  183.         RETVAL
  184. SnmpSession *
  185. snmp_update_session(sess_ref, version, community, peer, lport, retries, timeout)
  186.         SV * sess_ref
  187.         char * version
  188.         char * community
  189.         char * peer
  190.         int lport
  191.         int retries
  192.         int timeout
  193. CODE:
  194. {
  195.            SV **sess_ptr_sv;
  196.    SnmpSession *ss;
  197.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  198.            sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  199.            ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  200.            if (!ss) goto update_end;
  201.            ss->version = -1;
  202. #ifndef DISABLE_SNMPV1
  203.            if (!strcmp(version, "1")) {
  204. ss->version = SNMP_VERSION_1;
  205.            }
  206. #endif
  207. #ifndef DISABLE_SNMPV2C
  208.            if (!strcmp(version, "2") || !strcmp(version, "2c")) {
  209. ss->version = SNMP_VERSION_2c;
  210.    }
  211. #endif
  212.            if (!strcmp(version, "3")) {
  213.         ss->version = SNMP_VERSION_3;
  214.    }
  215.            if (ss->version == -1) {
  216. if (verbose)
  217.                    warn("Unsupported SNMP version (%s)n", version);
  218.                 goto update_end;
  219.    }
  220.            /* WARNING LEAKAGE but I cant free lib memory under win32 */
  221.            ss->community_len = strlen((char *)community);
  222.            ss->community = (u_char *)strdup(community);
  223.    ss->peername = strdup(peer);
  224.    ss->local_port = lport;
  225.            ss->retries = retries; /* 5 */
  226.            ss->timeout = timeout; /* 1000000L */
  227.            ss->authenticator = NULL;
  228.     update_end:
  229.    RETVAL = ss;
  230.         }
  231.         OUTPUT:
  232.            RETVAL
  233. int
  234. snmp_add_mib_dir(mib_dir,force=0)
  235. char * mib_dir
  236. int force
  237. CODE:
  238.         {
  239. int result = 0;      /* Avoid use of uninitialized variable below. */
  240.         int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  241.         if (mib_dir && *mib_dir) {
  242.    result = add_mibdir(mib_dir);
  243.         }
  244.         if (result) {
  245.            if (verbose) warn("Added mib dir %sn", mib_dir);
  246.         } else {
  247.            if (verbose) warn("Failed to add %sn", mib_dir);
  248.         }
  249.         RETVAL = (I32)result;
  250.         }
  251.         OUTPUT:
  252.         RETVAL
  253. void
  254. snmp_init_mib_internals()
  255. CODE:
  256.         {
  257. int notused = 1;
  258. /* this function does nothing */
  259. /* it is kept only for backwards compatibility */
  260.         }
  261. int
  262. snmp_read_mib(mib_file, force=0)
  263. char * mib_file
  264. int force
  265. CODE:
  266.         {
  267.         int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  268.         if ((mib_file == NULL) || (*mib_file == '')) {
  269.            if (get_tree_head() == NULL) {
  270.               if (verbose) warn("initializing MIBn");
  271.               init_mib();
  272.               if (get_tree_head()) {
  273.                  if (verbose) warn("donen");
  274.               } else {
  275.                  if (verbose) warn("failedn");
  276.               }
  277.    }
  278.         } else {
  279.            if (verbose) warn("reading MIB: %sn", mib_file);
  280.            if (strcmp("ALL",mib_file))
  281.               read_mib(mib_file);
  282.            else
  283.              read_all_mibs();
  284.            if (get_tree_head()) {
  285.               if (verbose) warn("donen");
  286.            } else {
  287.               if (verbose) warn("failedn");
  288.            }
  289.         }
  290.         RETVAL = (I32)get_tree_head();
  291.         }
  292.         OUTPUT:
  293.         RETVAL
  294. int
  295. snmp_read_module(module)
  296. char * module
  297. CODE:
  298.         {
  299.         int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  300.         if (!strcmp(module,"ALL")) {
  301.            read_all_mibs();
  302.         } else {
  303.            read_module(module);
  304.         }
  305.         if (get_tree_head()) {
  306.            if (verbose) warn("Read %sn", module);
  307.         } else {
  308.            if (verbose) warn("Failed reading %sn", module);
  309.         }
  310.         RETVAL = (I32)get_tree_head();
  311.         }
  312.         OUTPUT:
  313.         RETVAL
  314. int
  315. snmp_set(sess_ref, varlist_ref, perl_callback)
  316.         SV * sess_ref
  317.         SV * varlist_ref
  318.         SV * perl_callback
  319. PPCODE:
  320. {
  321.            AV *varlist;
  322.            SV **varbind_ref;
  323.            SV **varbind_val_f;
  324.            AV *varbind;
  325.    I32 varlist_len;
  326.    I32 varlist_ind;
  327.            SnmpSession *ss;
  328.            netsnmp_pdu *pdu, *response;
  329.            struct tree *tp;
  330.    oid *oid_arr;
  331.    int oid_arr_len = MAX_OID_LEN;
  332.            char *tag_pv;
  333.            snmp_xs_cb_data *xs_cb_data;
  334.            SV **sess_ptr_sv;
  335.            SV **err_str_svp;
  336.            SV **err_num_svp;
  337.            SV **err_ind_svp;
  338.            int status = 0;
  339.            int type;
  340.    int res;
  341.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  342.            int use_enums;
  343.            struct enum_list *ep;
  344.            int best_guess;    
  345.            New (0, oid_arr, MAX_OID_LEN, oid);
  346.            if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
  347.       use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
  348.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  349.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  350.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  351.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  352.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  353.               sv_setpv(*err_str_svp, "");
  354.               sv_setiv(*err_num_svp, 0);
  355.               sv_setiv(*err_ind_svp, 0);
  356.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  357.               pdu = snmp_pdu_create(SNMP_MSG_SET);
  358.               varlist = (AV*) SvRV(varlist_ref);
  359.               varlist_len = av_len(varlist);
  360.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  361.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  362.                  if (SvROK(*varbind_ref)) {
  363.                     varbind = (AV*) SvRV(*varbind_ref);
  364.                     tag_pv = __av_elem_pv(varbind, VARBIND_TAG_F,NULL);
  365.                     tp=__tag2oid(tag_pv,
  366.                                  __av_elem_pv(varbind, VARBIND_IID_F,NULL),
  367.                                  oid_arr, &oid_arr_len, &type, best_guess);
  368.                     if (oid_arr_len==0) {
  369.                        if (verbose)
  370.                           warn("error: set: unknown object ID (%s)",
  371.                                 (tag_pv?tag_pv:"<null>"));
  372.                sv_catpv(*err_str_svp,
  373.                                (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
  374.                        sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
  375.                        XPUSHs(&sv_undef); /* unknown OID */
  376.        snmp_free_pdu(pdu);
  377.        goto done;
  378.     }
  379.                     if (type == TYPE_UNKNOWN) {
  380.                       type = __translate_appl_type(
  381.                                 __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
  382.                       if (type == TYPE_UNKNOWN) {
  383.                          if (verbose)
  384.                             warn("error: set: no type found for object");
  385.                  sv_catpv(*err_str_svp,
  386.                                   (char*)snmp_api_errstring(SNMPERR_VAR_TYPE));
  387.                          sv_setiv(*err_num_svp, SNMPERR_VAR_TYPE);
  388.                          XPUSHs(&sv_undef); /* unknown OID */
  389.          snmp_free_pdu(pdu);
  390.          goto done;
  391.                       }
  392.                     }
  393.             varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
  394.                     if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
  395.                       for(ep = tp->enums; ep; ep = ep->next) {
  396.                         if (varbind_val_f && SvOK(*varbind_val_f) &&
  397.                             !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
  398.                           sv_setiv(*varbind_val_f, ep->value);
  399.                           break;
  400.                         }
  401.                       }
  402.                     }
  403.                     res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
  404.      (varbind_val_f && SvOK(*varbind_val_f) ?
  405.       SvPV(*varbind_val_f,na):NULL),
  406.       (varbind_val_f && SvOK(*varbind_val_f) ?
  407.        SvCUR(*varbind_val_f):0), type);
  408.     if (verbose && res == FAILURE)
  409.       warn("error: adding variable/value to PDU");
  410.                  } /* if var_ref is ok */
  411.               } /* for all the vars */
  412.               if (SvTRUE(perl_callback)) {
  413.                   xs_cb_data =
  414.                       (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
  415.                  xs_cb_data->perl_cb = newSVsv(perl_callback);
  416.                  xs_cb_data->sess_ref = newRV_inc(SvRV(sess_ref));
  417.                  status = snmp_async_send(ss, pdu, __snmp_xs_cb,
  418.                                           (void*)xs_cb_data);
  419.                  if (status != 0) {
  420.                     XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
  421.                  } else {
  422.                     snmp_free_pdu(pdu);
  423.                     sv_catpv(*err_str_svp,
  424.                              (char*)snmp_api_errstring(ss->s_snmp_errno));
  425.                     sv_setiv(*err_num_svp, ss->s_snmp_errno);
  426.                     XPUSHs(&sv_undef);
  427.                  }
  428.  goto done;
  429.               }
  430.       status = __send_sync_pdu(ss, pdu, &response,
  431.        NO_RETRY_NOSUCH,
  432.                                        *err_str_svp, *err_num_svp,
  433.                                        *err_ind_svp);
  434.               if (response) snmp_free_pdu(response);
  435.               if (status) {
  436.  XPUSHs(&sv_undef);
  437.       } else {
  438.                  XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
  439.               }
  440.            } else {
  441.               /* BUG!!! need to return an error value */
  442.               XPUSHs(&sv_undef); /* no mem or bad args */
  443.            }
  444. done:
  445.            Safefree(oid_arr);
  446.         }
  447. void
  448. snmp_catch(sess_ref, perl_callback)
  449. SV * sess_ref
  450.         SV *    perl_callback
  451. PPCODE:
  452. {
  453.    netsnmp_session *ss;
  454.            SV **sess_ptr_sv;
  455.            SV **err_str_svp;
  456.            SV **err_num_svp;
  457.            SV **err_ind_svp;
  458.            if (SvROK(sess_ref)) {
  459.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  460.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  461.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  462.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  463.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  464.               sv_setpv(*err_str_svp, "");
  465.               sv_setiv(*err_num_svp, 0);
  466.               sv_setiv(*err_ind_svp, 0);
  467.               snmp_synch_reset(ss);
  468.               ss->callback = NULL;
  469.               ss->callback_magic = NULL;
  470.               if (SvTRUE(perl_callback)) {
  471.                  perl_callback = newSVsv(perl_callback);
  472.                  # it might be more efficient to pass the varbind_ref to
  473.                  # __snmp_xs_cb as part of perl_callback so it is not freed
  474.                  # and reconstructed for each call
  475.                  ss->callback = __callback_wrapper;
  476.                  ss->callback_magic = perl_callback;
  477.                  sv_2mortal(newSViv(1));
  478.                  goto done;
  479.               }
  480.            }
  481.            sv_2mortal(newSViv(0));
  482.         done:
  483.            ;
  484.         }
  485. int
  486. snmp_get(sess_ref, retry_nosuch, varlist_ref, perl_callback)
  487.         SV *    sess_ref
  488.         int     retry_nosuch
  489.         SV *    varlist_ref
  490.         SV *    perl_callback
  491.         PPCODE:
  492.         {
  493.            AV *varlist;
  494.            SV **varbind_ref;
  495.            AV *varbind;
  496.            I32 varlist_len;
  497.            I32 varlist_ind;
  498.            netsnmp_session *ss;
  499.            netsnmp_pdu *pdu, *response;
  500.            netsnmp_variable_list *vars;
  501.            struct tree *tp;
  502.            int len;
  503.    oid *oid_arr;
  504.    int oid_arr_len = MAX_OID_LEN;
  505.            SV *tmp_sv;
  506.            int type;
  507.    char tmp_type_str[MAX_TYPE_NAME_LEN];
  508.            snmp_xs_cb_data *xs_cb_data;
  509.            SV **sess_ptr_sv;
  510.            SV **err_str_svp;
  511.            SV **err_num_svp;
  512.            SV **err_ind_svp;
  513.            int status;
  514.    u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
  515.            size_t str_buf_len = sizeof(str_buf);
  516.            size_t out_len = 0;
  517.            int buf_over = 0;
  518.            char *label;
  519.            char *iid;
  520.            int getlabel_flag = NO_FLAGS;
  521.            int sprintval_flag = USE_BASIC;
  522.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  523.    int old_format;
  524.    SV *sv_timestamp = NULL;
  525.            int best_guess;
  526.    
  527.            New (0, oid_arr, MAX_OID_LEN, oid);
  528.            if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
  529.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  530.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  531.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  532.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  533.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  534.               sv_setpv(*err_str_svp, "");
  535.               sv_setiv(*err_num_svp, 0);
  536.               sv_setiv(*err_ind_svp, 0);
  537.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
  538.                  getlabel_flag |= USE_LONG_NAMES;
  539.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
  540.                  getlabel_flag |= USE_NUMERIC_OIDS;
  541.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
  542.                  sprintval_flag = USE_ENUMS;
  543.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
  544.                  sprintval_flag = USE_SPRINT_VALUE;
  545.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  546.       
  547.               pdu = snmp_pdu_create(SNMP_MSG_GET);
  548.               varlist = (AV*) SvRV(varlist_ref);
  549.               varlist_len = av_len(varlist);
  550.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  551.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  552.                  if (SvROK(*varbind_ref)) {
  553.                     varbind = (AV*) SvRV(*varbind_ref);
  554.                     tp = __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, ".0"),
  555.                               __av_elem_pv(varbind, VARBIND_IID_F, NULL),
  556.                               oid_arr, &oid_arr_len, NULL, best_guess);
  557.            if (oid_arr_len) {
  558.           snmp_add_null_var(pdu, oid_arr, oid_arr_len);
  559.     } else {
  560.                        if (verbose)
  561.                           warn("error: set: unknown object ID");
  562.                sv_catpv(*err_str_svp,
  563.                                (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
  564.                        sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
  565.                        XPUSHs(&sv_undef); /* unknown OID */
  566.        snmp_free_pdu(pdu);
  567.        goto done;
  568.     }
  569.                  } /* if var_ref is ok */
  570.               } /* for all the vars */
  571.               if (perl_callback && SvTRUE(perl_callback)) {
  572.                   xs_cb_data =
  573.                       (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
  574.                  xs_cb_data->perl_cb = newSVsv(perl_callback);
  575.                  xs_cb_data->sess_ref = newSVsv(sess_ref);
  576.                  status = snmp_async_send(ss, pdu, __snmp_xs_cb,
  577.                                           (void*)xs_cb_data);
  578.                  if (status != 0) {
  579.                     XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
  580.                  } else {
  581.                     snmp_free_pdu(pdu);
  582.                     sv_catpv(*err_str_svp,
  583.                              (char*)snmp_api_errstring(ss->s_snmp_errno));
  584.                     sv_setiv(*err_num_svp, ss->s_snmp_errno);
  585.                     XPUSHs(&sv_undef);
  586.                  }
  587.  goto done;
  588.               }
  589.       status = __send_sync_pdu(ss, pdu, &response,
  590.        retry_nosuch,
  591.                                        *err_str_svp, *err_num_svp,
  592.        *err_ind_svp);
  593.       /*
  594.       ** Set up for numeric or full OID's, if necessary.  Save the old
  595.       ** output format so that it can be restored when we finish -- this
  596.       ** is a library-wide global, and has to be set/restored for each
  597.       ** session.
  598.       */
  599.       old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  600.                                               NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
  601.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1))) {
  602.          getlabel_flag |= USE_LONG_NAMES;
  603.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  604.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  605.                                     NETSNMP_OID_OUTPUT_FULL);
  606.       }
  607.               /* Setting UseNumeric forces UseLongNames on so check for UseNumeric
  608.                  after UseLongNames (above) to make sure the final outcome of 
  609.                  NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is NETSNMP_OID_OUTPUT_NUMERIC */
  610.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1))) {
  611.          getlabel_flag |= USE_LONG_NAMES;
  612.          getlabel_flag |= USE_NUMERIC_OIDS;
  613.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  614.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  615.                                     NETSNMP_OID_OUTPUT_NUMERIC);
  616.       }
  617.       if (SvIOK(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)) &&
  618.                   SvIV(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)))
  619.          sv_timestamp = newSViv((IV)time(NULL));
  620.               for(vars = (response?response->variables:NULL), varlist_ind = 0;
  621.                   vars && (varlist_ind <= varlist_len);
  622.                   vars = vars->next_variable, varlist_ind++) {
  623.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  624.                  if (SvROK(*varbind_ref)) {
  625.                     varbind = (AV*) SvRV(*varbind_ref);
  626.                     *str_buf = '.';
  627.                     *(str_buf+1) = '';
  628.                     out_len = 0;
  629.                     tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
  630.                                                            &out_len, 0, &buf_over,
  631.                                                            vars->name,vars->name_length);
  632.                     str_buf[sizeof(str_buf)-1] = '';
  633.                     if (__is_leaf(tp)) {
  634.                        type = tp->type;
  635.                     } else {
  636.                        getlabel_flag |= NON_LEAF_NAME;
  637.                        type = __translate_asn_type(vars->type);
  638.                     }
  639.                     __get_label_iid(str_buf,&label,&iid,getlabel_flag);
  640.                     if (label) {
  641.                         av_store(varbind, VARBIND_TAG_F,
  642.                                  newSVpv(label, strlen(label)));
  643.                     } else {
  644.                         av_store(varbind, VARBIND_TAG_F,
  645.                                  newSVpv("", 0));
  646.                     }
  647.                     if (iid) {
  648.                         av_store(varbind, VARBIND_IID_F,
  649.                                  newSVpv(iid, strlen(iid)));
  650.                     } else {
  651.                         av_store(varbind, VARBIND_IID_F,
  652.                                  newSVpv("", 0));
  653.                     }                        
  654.                     __get_type_str(type, tmp_type_str);
  655.                     tmp_sv = newSVpv(tmp_type_str, strlen(tmp_type_str));
  656.                     av_store(varbind, VARBIND_TYPE_F, tmp_sv);
  657.                     len=__snprint_value(str_buf,sizeof(str_buf),
  658.                                        vars,tp,type,sprintval_flag);
  659.                     tmp_sv = newSVpv((char*)str_buf, len);
  660.                     av_store(varbind, VARBIND_VAL_F, tmp_sv);
  661.     if (sv_timestamp)
  662.                        av_store(varbind, VARBIND_TYPE_F, sv_timestamp);
  663.                     XPUSHs(sv_mortalcopy(tmp_sv));
  664.                  } else {
  665.     /* Return undef for this variable. */
  666.                     XPUSHs(&sv_undef);
  667.                  }
  668.               }
  669.       /* Reset the library's behavior for numeric/symbolic OID's. */
  670.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  671.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  672.                                     old_format);
  673.               if (response) snmp_free_pdu(response);
  674.            } else {
  675.               XPUSHs(&sv_undef); /* no mem or bad args */
  676.    }
  677. done:
  678. Safefree(oid_arr);
  679. }
  680. int
  681. snmp_getnext(sess_ref, varlist_ref, perl_callback)
  682.         SV *    sess_ref
  683.         SV *    varlist_ref
  684.         SV *    perl_callback
  685.         PPCODE:
  686.         {
  687.            AV *varlist;
  688.            SV **varbind_ref;
  689.            AV *varbind;
  690.            I32 varlist_len;
  691.            I32 varlist_ind;
  692.            netsnmp_session *ss;
  693.            netsnmp_pdu *pdu, *response;
  694.            netsnmp_variable_list *vars;
  695.            struct tree *tp;
  696.            int len;
  697.    oid *oid_arr;
  698.    int oid_arr_len = MAX_OID_LEN;
  699.            SV *tmp_sv;
  700.            int type;
  701.    char tmp_type_str[MAX_TYPE_NAME_LEN];
  702.            snmp_xs_cb_data *xs_cb_data;
  703.            SV **sess_ptr_sv;
  704.            SV **err_str_svp;
  705.            SV **err_num_svp;
  706.            SV **err_ind_svp;
  707.            int status;
  708.    u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
  709.            size_t str_buf_len = sizeof(str_buf);
  710.            u_char tmp_buf_prefix[STR_BUF_SIZE];
  711.            u_char str_buf_prefix[STR_BUF_SIZE];
  712.            size_t out_len = 0;
  713.            int buf_over = 0;
  714.            char *label;
  715.            char *iid;
  716.            int getlabel_flag = NO_FLAGS;
  717.            int sprintval_flag = USE_BASIC;
  718.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  719.    int old_format;
  720.    SV *sv_timestamp = NULL;
  721.            int best_guess;
  722.            char *tmp_prefix_ptr;
  723.            char *st;
  724.    
  725.            New (0, oid_arr, MAX_OID_LEN, oid);
  726.            if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
  727.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  728.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  729.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  730.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  731.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  732.               sv_setpv(*err_str_svp, "");
  733.               sv_setiv(*err_num_svp, 0);
  734.               sv_setiv(*err_ind_svp, 0);
  735.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
  736.                  getlabel_flag |= USE_LONG_NAMES;
  737.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
  738.                  getlabel_flag |= USE_NUMERIC_OIDS;
  739.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
  740.                  sprintval_flag = USE_ENUMS;
  741.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
  742.                  sprintval_flag = USE_SPRINT_VALUE;
  743.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  744.       
  745.               pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
  746.               varlist = (AV*) SvRV(varlist_ref);
  747.               varlist_len = av_len(varlist);
  748.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  749.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  750.                  if (SvROK(*varbind_ref)) {
  751.                     varbind = (AV*) SvRV(*varbind_ref);
  752.                     /* If the varbind includes the module prefix, capture it for use later */
  753.                     strncpy(tmp_buf_prefix, __av_elem_pv(varbind, VARBIND_TAG_F, ".0"), STR_BUF_SIZE);
  754.                     tmp_prefix_ptr = strstr(tmp_buf_prefix,"::");
  755.                     if (tmp_prefix_ptr) {
  756.                       tmp_prefix_ptr = strtok_r(tmp_buf_prefix, "::", &st);
  757.                       strncpy(str_buf_prefix, tmp_prefix_ptr, STR_BUF_SIZE);
  758.                     }
  759.                     else {
  760.                       *str_buf_prefix = '';
  761.                     }
  762.                     tp = __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, ".0"),
  763.                               __av_elem_pv(varbind, VARBIND_IID_F, NULL),
  764.                               oid_arr, &oid_arr_len, NULL, best_guess);
  765.            if (oid_arr_len) {
  766.           snmp_add_null_var(pdu, oid_arr, oid_arr_len);
  767.     } else {
  768.                        if (verbose)
  769.                           warn("error: set: unknown object ID");
  770.                sv_catpv(*err_str_svp,
  771.                                (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
  772.                        sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
  773.                        XPUSHs(&sv_undef); /* unknown OID */
  774.        snmp_free_pdu(pdu);
  775.        goto done;
  776.     }
  777.                  } /* if var_ref is ok */
  778.               } /* for all the vars */
  779.               if (SvTRUE(perl_callback)) {
  780.                   xs_cb_data =
  781.                       (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
  782.                  xs_cb_data->perl_cb = newSVsv(perl_callback);
  783.                  xs_cb_data->sess_ref = newSVsv(sess_ref);
  784.                  status = snmp_async_send(ss, pdu, __snmp_xs_cb,
  785.                                           (void*)xs_cb_data);
  786.                  if (status != 0) {
  787.                     XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
  788.                  } else {
  789.                     snmp_free_pdu(pdu);
  790.                     sv_catpv(*err_str_svp,
  791.                              (char*)snmp_api_errstring(ss->s_snmp_errno));
  792.                     sv_setiv(*err_num_svp, ss->s_snmp_errno);
  793.                     XPUSHs(&sv_undef);
  794.                  }
  795.  goto done;
  796.               }
  797.       status = __send_sync_pdu(ss, pdu, &response,
  798.        NO_RETRY_NOSUCH,
  799.                                        *err_str_svp, *err_num_svp,
  800.        *err_ind_svp);
  801.       /*
  802.       ** Set up for numeric or full OID's, if necessary.  Save the old
  803.       ** output format so that it can be restored when we finish -- this
  804.       ** is a library-wide global, and has to be set/restored for each
  805.       ** session.
  806.       */
  807.       old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  808.                                               NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
  809.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1))) {
  810.          getlabel_flag |= USE_LONG_NAMES;
  811.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  812.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  813.                                     NETSNMP_OID_OUTPUT_FULL);
  814.       }
  815.               /* Setting UseNumeric forces UseLongNames on so check
  816.                  for UseNumeric after UseLongNames (above) to make
  817.                  sure the final outcome of
  818.                  NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is
  819.                  NETSNMP_OID_OUTPUT_NUMERIC */
  820.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1))) {
  821.          getlabel_flag |= USE_LONG_NAMES;
  822.          getlabel_flag |= USE_NUMERIC_OIDS;
  823.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  824.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  825.                                     NETSNMP_OID_OUTPUT_NUMERIC);
  826.       }
  827.       if (SvIOK(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)) &&
  828.                   SvIV(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)))
  829.          sv_timestamp = newSViv((IV)time(NULL));
  830.               for(vars = (response?response->variables:NULL), varlist_ind = 0;
  831.                   vars && (varlist_ind <= varlist_len);
  832.                   vars = vars->next_variable, varlist_ind++) {
  833.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  834.                  if (SvROK(*varbind_ref)) {
  835.                     varbind = (AV*) SvRV(*varbind_ref);
  836.                     *str_buf = '.';
  837.                     *(str_buf+1) = '';
  838.                     out_len = 0;
  839.                     tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
  840.                                                            &out_len, 0, &buf_over,
  841.                                                            vars->name,vars->name_length);
  842.                     str_buf[sizeof(str_buf)-1] = '';
  843.                     /* Prepend the module prefix to the next OID if needed */
  844.                     if (*str_buf_prefix) {
  845.                       strncat(str_buf_prefix, "::", STR_BUF_SIZE - strlen(str_buf_prefix) - 2);
  846.                       strncat(str_buf_prefix, str_buf, STR_BUF_SIZE - strlen(str_buf_prefix));
  847.                       strncpy(str_buf, str_buf_prefix, STR_BUF_SIZE);
  848.                     }
  849.                     
  850.                     if (__is_leaf(tp)) {
  851.                        type = tp->type;
  852.                     } else {
  853.                        getlabel_flag |= NON_LEAF_NAME;
  854.                        type = __translate_asn_type(vars->type);
  855.                     }
  856.                     __get_label_iid(str_buf,&label,&iid,getlabel_flag);
  857.                     if (label) {
  858.                         av_store(varbind, VARBIND_TAG_F,
  859.                                  newSVpv(label, strlen(label)));
  860.                     } else {
  861.                         av_store(varbind, VARBIND_TAG_F,
  862.                                  newSVpv("", 0));
  863.                     }
  864.                     if (iid) {
  865.                         av_store(varbind, VARBIND_IID_F,
  866.                                  newSVpv(iid, strlen(iid)));
  867.                     } else {
  868.                         av_store(varbind, VARBIND_IID_F,
  869.                                  newSVpv("", 0));
  870.                     }                        
  871.                     __get_type_str(type, tmp_type_str);
  872.                     tmp_sv = newSVpv(tmp_type_str, strlen(tmp_type_str));
  873.                     av_store(varbind, VARBIND_TYPE_F, tmp_sv);
  874.                     len=__snprint_value(str_buf,sizeof(str_buf),
  875.                                        vars,tp,type,sprintval_flag);
  876.                     tmp_sv = newSVpv((char*)str_buf, len);
  877.                     av_store(varbind, VARBIND_VAL_F, tmp_sv);
  878.     if (sv_timestamp)
  879.                        av_store(varbind, VARBIND_TYPE_F, sv_timestamp);
  880.                     XPUSHs(sv_mortalcopy(tmp_sv));
  881.                  } else {
  882.     /* Return undef for this variable. */
  883.                     XPUSHs(&sv_undef);
  884.                  }
  885.               }
  886.       /* Reset the library's behavior for numeric/symbolic OID's. */
  887.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  888.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  889.                                     old_format);
  890.               if (response) snmp_free_pdu(response);
  891.            } else {
  892.               XPUSHs(&sv_undef); /* no mem or bad args */
  893.    }
  894. done:
  895. Safefree(oid_arr);
  896. }
  897. int
  898. snmp_getbulk(sess_ref, nonrepeaters, maxrepetitions, varlist_ref, perl_callback)
  899.         SV * sess_ref
  900. int nonrepeaters
  901. int maxrepetitions
  902.         SV * varlist_ref
  903.         SV * perl_callback
  904. PPCODE:
  905. {
  906.            AV *varlist;
  907.            SV **varbind_ref;
  908.            AV *varbind;
  909.    I32 varlist_len;
  910.    I32 varlist_ind;
  911.            netsnmp_session *ss;
  912.            netsnmp_pdu *pdu, *response;
  913.            netsnmp_variable_list *vars;
  914.            struct tree *tp;
  915.            int len;
  916.    oid *oid_arr;
  917.    int oid_arr_len = MAX_OID_LEN;
  918.            SV *tmp_sv;
  919.            int type;
  920.    char tmp_type_str[MAX_TYPE_NAME_LEN];
  921.            snmp_xs_cb_data *xs_cb_data;
  922.            SV **sess_ptr_sv;
  923.            SV **err_str_svp;
  924.            SV **err_num_svp;
  925.            SV **err_ind_svp;
  926.            int status;
  927.    u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
  928.            size_t str_buf_len = sizeof(str_buf);
  929.            size_t out_len = 0;
  930.            int buf_over = 0;
  931.            char *label;
  932.            char *iid;
  933.            int getlabel_flag = NO_FLAGS;
  934.            int sprintval_flag = USE_BASIC;
  935.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  936.    int old_format;
  937.    SV *rv;
  938.    SV *sv_timestamp = NULL;
  939.            int best_guess;
  940.    New (0, oid_arr, MAX_OID_LEN, oid);
  941.            if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
  942.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  943.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  944.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  945.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  946.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  947.               sv_setpv(*err_str_svp, "");
  948.               sv_setiv(*err_num_svp, 0);
  949.               sv_setiv(*err_ind_svp, 0);
  950.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
  951.                  getlabel_flag |= USE_LONG_NAMES;
  952.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
  953.  getlabel_flag |= USE_NUMERIC_OIDS;
  954.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
  955.                  sprintval_flag = USE_ENUMS;
  956.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
  957.                  sprintval_flag = USE_SPRINT_VALUE;
  958.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  959.       
  960.               pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
  961.       pdu->errstat = nonrepeaters;
  962.       pdu->errindex = maxrepetitions;
  963.               varlist = (AV*) SvRV(varlist_ref);
  964.               varlist_len = av_len(varlist);
  965.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  966.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  967.                  if (SvROK(*varbind_ref)) {
  968.                     varbind = (AV*) SvRV(*varbind_ref);
  969.                     __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, "0"),
  970.                               __av_elem_pv(varbind, VARBIND_IID_F, NULL),
  971.                               oid_arr, &oid_arr_len, NULL, best_guess);
  972.                     if (oid_arr_len) {
  973.           snmp_add_null_var(pdu, oid_arr, oid_arr_len);
  974.     } else {
  975.                        if (verbose)
  976.                           warn("error: set: unknown object ID");
  977.                sv_catpv(*err_str_svp,
  978.                                (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
  979.                        sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
  980.                        XPUSHs(&sv_undef); /* unknown OID */
  981.        snmp_free_pdu(pdu);
  982.        goto done;
  983.     }
  984.                  } /* if var_ref is ok */
  985.               } /* for all the vars */
  986.               if (SvTRUE(perl_callback)) {
  987.                   xs_cb_data =
  988.                       (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
  989.                  xs_cb_data->perl_cb = newSVsv(perl_callback);
  990.                  xs_cb_data->sess_ref = newSVsv(sess_ref);
  991.                  status = snmp_async_send(ss, pdu, __snmp_xs_cb,
  992.                                           (void*)xs_cb_data);
  993.                  if (status != 0) {
  994.                     XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
  995.                  } else {
  996.                     snmp_free_pdu(pdu);
  997.                     sv_catpv(*err_str_svp,
  998.                              (char*)snmp_api_errstring(ss->s_snmp_errno));
  999.                     sv_setiv(*err_num_svp, ss->s_snmp_errno);
  1000.                     XPUSHs(&sv_undef);
  1001.                  }
  1002.  goto done;
  1003.               }
  1004.       status = __send_sync_pdu(ss, pdu, &response,
  1005.        NO_RETRY_NOSUCH,
  1006.                                        *err_str_svp, *err_num_svp,
  1007.        *err_ind_svp);
  1008.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"TimeStamp", 9, 1)))
  1009.          sv_timestamp = newSViv((IV)time(NULL));
  1010.       av_clear(varlist);
  1011.       /*
  1012.       ** Set up for numeric or full OID's, if necessary.  Save the old
  1013.       ** output format so that it can be restored when we finish -- this
  1014.       ** is a library-wide global, and has to be set/restored for each
  1015.       ** session.
  1016.       */
  1017.       old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  1018.                                               NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
  1019.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1))) {
  1020.          getlabel_flag |= USE_LONG_NAMES;
  1021.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  1022.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  1023.                                     NETSNMP_OID_OUTPUT_FULL);
  1024.       }
  1025.               /* Setting UseNumeric forces UseLongNames on so check for UseNumeric
  1026.                  after UseLongNames (above) to make sure the final outcome of 
  1027.                  NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is NETSNMP_OID_OUTPUT_NUMERIC */
  1028.       if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1))) {
  1029.          getlabel_flag |= USE_LONG_NAMES;
  1030.          getlabel_flag |= USE_NUMERIC_OIDS;
  1031.          netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  1032.                                     NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  1033.                                     NETSNMP_OID_OUTPUT_NUMERIC);
  1034.       }
  1035.       
  1036.       if(response && response->variables) {
  1037.               for(vars = response->variables;
  1038.                   vars;
  1039.                   vars = vars->next_variable) {
  1040.                     varbind = (AV*) newAV();
  1041.                     *str_buf = '.';
  1042.                     *(str_buf+1) = '';
  1043.                     out_len = 0;
  1044.                     buf_over = 0;
  1045.                     str_bufp = str_buf;
  1046.                     tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len,
  1047.                                                            &out_len, 0, &buf_over,
  1048.                                                            vars->name,vars->name_length);
  1049.                     str_buf[sizeof(str_buf)-1] = '';
  1050.                     if (__is_leaf(tp)) {
  1051.                        type = tp->type;
  1052.                     } else {
  1053.                        getlabel_flag |= NON_LEAF_NAME;
  1054.                        type = __translate_asn_type(vars->type);
  1055.                     }
  1056.                     __get_label_iid(str_buf,&label,&iid,getlabel_flag);
  1057.                     if (label) {
  1058.                         av_store(varbind, VARBIND_TAG_F,
  1059.                                  newSVpv(label, strlen(label)));
  1060.                     } else {
  1061.                         av_store(varbind, VARBIND_TAG_F,
  1062.                                  newSVpv("", 0));
  1063.                     }
  1064.                     if (iid) {
  1065.                         av_store(varbind, VARBIND_IID_F,
  1066.                                  newSVpv(iid, strlen(iid)));
  1067.                     } else {
  1068.                         av_store(varbind, VARBIND_IID_F,
  1069.                                  newSVpv("", 0));
  1070.                     }
  1071.                     __get_type_str(type, tmp_type_str);
  1072.     av_store(varbind, VARBIND_TYPE_F, newSVpv(tmp_type_str,
  1073.      strlen(tmp_type_str)));
  1074.                     len=__snprint_value(str_buf,sizeof(str_buf),
  1075.                                        vars,tp,type,sprintval_flag);
  1076.                     tmp_sv = newSVpv((char*)str_buf, len);
  1077.     av_store(varbind, VARBIND_VAL_F, tmp_sv);
  1078.     if (sv_timestamp)
  1079.        av_store(varbind, VARBIND_TYPE_F, SvREFCNT_inc(sv_timestamp));
  1080.     rv = newRV_noinc((SV *)varbind);
  1081.     sv_bless(rv, gv_stashpv("SNMP::Varbind",0));
  1082.     av_push(varlist, rv);
  1083.                     XPUSHs(sv_mortalcopy(tmp_sv));
  1084.                  }
  1085.               } else {
  1086.                     XPUSHs(&sv_undef);
  1087.       }
  1088.       /* Reset the library's behavior for numeric/symbolic OID's. */
  1089.               netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
  1090.                                  NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
  1091.                                  old_format);
  1092.               if (response) snmp_free_pdu(response);
  1093.            } else {
  1094.               XPUSHs(&sv_undef); /* no mem or bad args */
  1095.    }
  1096. done:
  1097. Safefree(oid_arr);
  1098. }
  1099. int
  1100. snmp_bulkwalk(sess_ref, nonrepeaters, maxrepetitions, varlist_ref,perl_callback)
  1101.         SV * sess_ref
  1102. int nonrepeaters
  1103. int maxrepetitions
  1104.         SV * varlist_ref
  1105.         SV * perl_callback
  1106. PPCODE:
  1107. {
  1108.            AV *varlist;
  1109.            SV **varbind_ref;
  1110.            AV *varbind;
  1111.    I32 varlist_len;
  1112.    I32 varlist_ind;
  1113.            netsnmp_session *ss;
  1114.            netsnmp_pdu *pdu = NULL;
  1115.    oid oid_arr[MAX_OID_LEN];
  1116.    int oid_arr_len;
  1117.            SV **sess_ptr_sv;
  1118.            SV **err_str_svp;
  1119.            SV **err_num_svp;
  1120.            SV **err_ind_svp;
  1121.    char str_buf[STR_BUF_SIZE];
  1122.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  1123.    walk_context *context = NULL; /* Context for this bulkwalk */
  1124.    bulktbl *bt_entry; /* Current bulktbl/OID entry */
  1125.    int i; /* General purpose iterator  */
  1126.    int npushed; /* Number of return arrays   */
  1127.    int okay; /* Did bulkwalk complete okay */
  1128.            int best_guess;
  1129.    if (!SvROK(sess_ref) || !SvROK(varlist_ref)) {
  1130.       if (verbose)
  1131.  warn("Bad session or varlist reference!n");
  1132.       XSRETURN_UNDEF;
  1133.    }
  1134.    sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  1135.    ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  1136.    err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  1137.    err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  1138.    err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  1139.    sv_setpv(*err_str_svp, "");
  1140.    sv_setiv(*err_num_svp, 0);
  1141.    sv_setiv(*err_ind_svp, 0);
  1142.            best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  1143.    
  1144.    /* Create and initialize a new session context for this bulkwalk.
  1145.    ** This will be used to carry state between callbacks.
  1146.    */
  1147.    Newz(0x57616b6c /* "Walk" */, context, 1, walk_context);
  1148.    if (context == NULL) {
  1149.       sprintf(str_buf, "malloc(context) failed (%s)", strerror(errno));
  1150.       sv_setpv(*err_str_svp, str_buf);
  1151.       sv_setiv(*err_num_svp, SNMPERR_MALLOC);
  1152.       goto err;
  1153.    }
  1154.    /* Store the Perl callback and session reference in the context. */
  1155.    context->perl_cb  = newSVsv(perl_callback);
  1156.    context->sess_ref = newSVsv(sess_ref);
  1157.    DBPRT(3,(DBOUT "bulkwalk: sess_ref = 0x%p, sess_ptr_sv = 0x%p, ss = 0x%pn",
  1158.     sess_ref, sess_ptr_sv, ss));
  1159.            context->getlabel_f  = NO_FLAGS; /* long/numeric name flags */
  1160.            context->sprintval_f = USE_BASIC; /* Don't do fancy printing */
  1161.    context->req_oids    = NULL; /* List of oid's requested */
  1162.    context->repbase     = NULL; /* Repeaters in req_oids[] */
  1163.    context->reqbase     = NULL; /* Ptr to start of requests */
  1164.    context->nreq_oids   = 0; /* Number of oid's in list */
  1165.    context->repeaters   = 0; /* Repeater count (see below) */
  1166.    context->non_reps    = nonrepeaters; /* Non-repeater var count */
  1167.    context->max_reps    = maxrepetitions; /* Max repetition/var count */
  1168.    context->pkts_exch   = 0; /* Packets exchanged in walk */
  1169.    context->oid_total   = 0; /* OID's received during walk */
  1170.    context->oid_saved   = 0; /* OID's saved as results */
  1171.    if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
  1172.       context->getlabel_f |= USE_LONG_NAMES;
  1173.    if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
  1174.       context->getlabel_f |= USE_NUMERIC_OIDS;
  1175.    if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
  1176.       context->sprintval_f = USE_ENUMS;
  1177.    if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
  1178.       context->sprintval_f = USE_SPRINT_VALUE;
  1179.    /* Set up an array of bulktbl's to hold the original list of
  1180.    ** requested OID's.  This is used to populate the PDU's with
  1181.    ** oid values, to contain/sort the return values, and (through
  1182.    ** last_oid/last_len) to determine when the bulkwalk for each
  1183.    ** variable has completed.
  1184.    */
  1185.    varlist = (AV*) SvRV(varlist_ref);
  1186.    varlist_len = av_len(varlist) + 1; /* XXX av_len returns index of
  1187. ** last element not #elements */
  1188.    Newz(0, context->req_oids, varlist_len, bulktbl);
  1189.    if (context->req_oids == NULL) {
  1190.       sprintf(str_buf, "Newz(req_oids) failed (%s)", strerror(errno));
  1191.       if (verbose)
  1192.          warn(str_buf);
  1193.       sv_setpv(*err_str_svp, str_buf);
  1194.       sv_setiv(*err_num_svp, SNMPERR_MALLOC);
  1195.       goto err;
  1196.    }
  1197.    /* Walk through the varbind_list, parsing and copying each OID
  1198.    ** into a bulktbl slot in the req_oids array.  Bail if there's
  1199.    ** some error.  Create the initial packet to send out, which
  1200.    ** includes the non-repeaters.
  1201.    */
  1202.    DBPRT(1,(DBOUT "Building request table:n"));
  1203.    for (varlist_ind = 0; varlist_ind < varlist_len; varlist_ind++) {
  1204.       /* Get a handle on this entry in the request table. */
  1205.       bt_entry = &context->req_oids[context->nreq_oids];
  1206.       DBPRT(1,(DBOUT "  request %d: ", (int)varlist_ind));
  1207.       /* Get the request varbind from the varlist, parse it out to
  1208.       ** tag and index, and copy it to the req_oid[] array slots.
  1209.       */
  1210.       varbind_ref = av_fetch(varlist, varlist_ind, 0);
  1211.       if (!SvROK(*varbind_ref)) {
  1212.  sv_setpv(*err_str_svp, 
  1213.        (char*)snmp_api_errstring(SNMPERR_BAD_NAME));
  1214.  sv_setiv(*err_num_svp, SNMPERR_BAD_NAME);
  1215.  goto err;
  1216.       }
  1217.       varbind = (AV*) SvRV(*varbind_ref);
  1218.       __tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, "0"),
  1219. __av_elem_pv(varbind, VARBIND_IID_F, NULL),
  1220. oid_arr, &oid_arr_len, NULL, best_guess);
  1221.       if ((oid_arr_len == 0) || (oid_arr_len > MAX_OID_LEN)) {
  1222.  if (verbose)
  1223.     warn("error: bulkwalk(): unknown object ID");
  1224.  sv_setpv(*err_str_svp, 
  1225.        (char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
  1226.  sv_setiv(*err_num_svp, SNMPERR_UNKNOWN_OBJID);
  1227.  goto err;
  1228.       }
  1229.       /* Copy the now-parsed OID into the first available slot
  1230.       ** in the req_oids[] array.  Set both the req_oid (original
  1231.       ** request) and the last_oid (last requested/seen oid) to
  1232.       ** the initial value.  We build packets using last_oid (see
  1233.       ** below), so initialize last_oid to the initial request.
  1234.       */
  1235.       Copy((void *)oid_arr, (void *)bt_entry->req_oid,
  1236. oid_arr_len, oid);
  1237.       Copy((void *)oid_arr, (void *)bt_entry->last_oid,
  1238. oid_arr_len, oid);
  1239.       bt_entry->req_len  = oid_arr_len;
  1240.       bt_entry->last_len = oid_arr_len;
  1241.       /* Adjust offset to and count of repeaters.  Note non-repeater
  1242.       ** OID's in the list, if appropriate.
  1243.       */
  1244.       if (varlist_ind >= context->non_reps) {
  1245.  /* Store a pointer to the first repeater value. */
  1246.  if (context->repbase == NULL)
  1247.     context->repbase = bt_entry;
  1248.  context->repeaters ++;
  1249.       } else {
  1250.  bt_entry->norepeat = 1;
  1251.  DBPRT(1,(DBOUT "(nonrepeater) "));
  1252.       }
  1253.       /* Initialize the array in which to hold the Varbinds to be
  1254.       ** returned for the OID or subtree.
  1255.       */
  1256.       if ((bt_entry->vars = (AV*) newAV()) == NULL) {
  1257.  sv_setpv(*err_str_svp, "newAV() failed: ");
  1258.  sv_catpv(*err_str_svp, strerror(errno));
  1259.  sv_setiv(*err_num_svp, SNMPERR_MALLOC);
  1260.  goto err;
  1261.       }
  1262.       DBPRT(1,(DBOUT "%sn", snprint_objid(_debugx, sizeof(_debugx), oid_arr, oid_arr_len)));
  1263.       context->nreq_oids ++;
  1264.    }
  1265.    /* Keep track of the number of outstanding requests.  This lets us
  1266.    ** finish processing early if we're done with all requests.
  1267.    */
  1268.    context->req_remain = context->nreq_oids;
  1269.    DBPRT(1,(DBOUT "Total %d variable requests addedn", context->nreq_oids));
  1270.    /* If no good variable requests were found, return an error. */
  1271.    if (context->nreq_oids == 0) {
  1272.  sv_setpv(*err_str_svp, "No variables found in varlist");
  1273.  sv_setiv(*err_num_svp, SNMPERR_NO_VARS);
  1274.  goto err;
  1275.    }
  1276.    /* Note that this is a good context.  This allows later callbacks
  1277.    ** to ignore re-sent PDU's that correspond to completed (and hence
  1278.    ** destroyed) bulkwalk contexts.
  1279.    */
  1280.    _context_add(context);
  1281.    /* For asynchronous bulkwalk requests, all we have to do at this
  1282.    ** point is enqueue the asynchronous GETBULK request with our
  1283.    ** bulkwalk-specific callback and return.  Remember that the
  1284.    ** bulkwalk_send_pdu() function returns the reqid cast to an
  1285.    ** snmp_pdu pointer, or NULL on failure.  Return undef if the
  1286.    ** initial send fails; bulkwalk_send_pdu() takes care of setting
  1287.    ** the various error values.
  1288.    **
  1289.    ** From here, the callbacks do all the work, including sending
  1290.    ** requests for variables and handling responses.  The caller's
  1291.    ** callback will be invoked as soon as the walk completes.
  1292.    */
  1293.    if (SvTRUE(perl_callback)) {
  1294.       DBPRT(1,(DBOUT "Starting asynchronous bulkwalk...n"));
  1295.       pdu = _bulkwalk_send_pdu(context);
  1296.       if (pdu == NULL) {
  1297.  DBPRT(1,(DBOUT "Initial asynchronous send failed...n"));
  1298.  XSRETURN_UNDEF;
  1299.       }
  1300.       /* Sent okay...  Return the request ID in 'pdu' as an SvIV. */
  1301.       DBPRT(1,(DBOUT "Okay, request id is %dn", (int)pdu));
  1302. /*       XSRETURN_IV((int)pdu); */
  1303.       XPUSHs(sv_2mortal(newSViv((int)pdu)));
  1304.       XSRETURN(1);
  1305.    }
  1306.    /* For synchronous bulkwalk, we perform the basic send/receive
  1307.    ** iteration right here.  Once the walk has been completed, the
  1308.    ** bulkwalk_finish() function will push the return values onto
  1309.    ** the Perl call stack, and we return.
  1310.    */
  1311.    DBPRT(1,(DBOUT "Starting synchronous bulkwalk...n"));
  1312.    while (!(okay = _bulkwalk_done(context))) {
  1313.       /* Send a request for the next batch of variables. */
  1314.       DBPRT(1, (DBOUT "Building %s GETBULK bulkwalk PDU (%d)...n",
  1315. context->pkts_exch ? "next" : "first",
  1316. context->pkts_exch));
  1317.       pdu = _bulkwalk_send_pdu(context);
  1318.       /* If the request failed, consider the walk done. */
  1319.       if (pdu == NULL) {
  1320.  DBPRT(1,(DBOUT "bulkwalk_send_pdu() failed!n"));
  1321.  break;
  1322.       }
  1323.       /* Handle the variables in this response packet.  Break out
  1324.       ** of the loop if an error occurs or no variables are found
  1325.       ** in the response.
  1326.       */
  1327.       if ((i = _bulkwalk_recv_pdu(context, pdu)) <= 0) {
  1328.  DBPRT(2,(DBOUT "bulkwalk_recv_pdu() returned %d (error/empty)n", i));
  1329.  break;
  1330.       }
  1331.               /* Free the returned pdu.  Don't bother to do this for the async
  1332.       ** case, since the SNMP callback mechanism itself does the free
  1333.       ** for us.
  1334.       */
  1335.       snmp_free_pdu(pdu);
  1336.       /* And loop.  The call to bulkwalk_done() sets the ignore flags
  1337.       ** for any completed request subtrees.  Next time around, they
  1338.       ** won't be added to the request sent to the agent.
  1339.       */
  1340.       continue;
  1341.    }
  1342.    DBPRT(1, (DBOUT "Bulkwalk done... calling bulkwalk_finish(%s)...n",
  1343.        okay ? "okay" : "error"));
  1344.    npushed = _bulkwalk_finish(context, okay);
  1345.    DBPRT(2,(DBOUT "Returning %d values on the stack.n", npushed));
  1346.    XSRETURN(npushed);
  1347. /* Handle error cases and clean up after ourselves. */
  1348.         err:
  1349.    if (context->req_oids && context->nreq_oids) {
  1350.       bt_entry = context->req_oids;
  1351.       for (i = 0; i < context->nreq_oids; i++, bt_entry++)
  1352.  av_clear(bt_entry->vars);
  1353.    }
  1354.    if (context->req_oids)
  1355.       Safefree(context->req_oids);
  1356.    if (context)
  1357.       Safefree(context);
  1358.    if (pdu)
  1359.       snmp_free_pdu(pdu);
  1360.            XSRETURN_UNDEF;
  1361. }
  1362. int
  1363. snmp_trapV1(sess_ref,enterprise,agent,generic,specific,uptime,varlist_ref)
  1364.         SV * sess_ref
  1365.         char * enterprise
  1366.         char * agent
  1367.         int generic
  1368.         int specific
  1369.         long uptime
  1370.         SV * varlist_ref
  1371. PPCODE:
  1372. {
  1373.            AV *varlist;
  1374.            SV **varbind_ref;
  1375.            SV **varbind_val_f;
  1376.            AV *varbind;
  1377.    I32 varlist_len;
  1378.    I32 varlist_ind;
  1379.            SnmpSession *ss;
  1380.            netsnmp_pdu *pdu = NULL;
  1381.            struct tree *tp;
  1382.    oid *oid_arr;
  1383.    int oid_arr_len = MAX_OID_LEN;
  1384.            SV **sess_ptr_sv;
  1385.            SV **err_str_svp;
  1386.            SV **err_num_svp;
  1387.            SV **err_ind_svp;
  1388.            int type;
  1389.            int res;
  1390.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  1391.            int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
  1392.            struct enum_list *ep;
  1393.            int best_guess;
  1394.    
  1395.            New (0, oid_arr, MAX_OID_LEN, oid);
  1396.            if (oid_arr && SvROK(sess_ref)) {
  1397.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  1398.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  1399.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  1400.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  1401.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  1402.               sv_setpv(*err_str_svp, "");
  1403.               sv_setiv(*err_num_svp, 0);
  1404.               sv_setiv(*err_ind_svp, 0);
  1405.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  1406.       
  1407.               pdu = snmp_pdu_create(SNMP_MSG_TRAP);
  1408.               if (SvROK(varlist_ref)) {
  1409.               varlist = (AV*) SvRV(varlist_ref);
  1410.               varlist_len = av_len(varlist);
  1411.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  1412.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  1413.                  if (SvROK(*varbind_ref)) {
  1414.                     varbind = (AV*) SvRV(*varbind_ref);
  1415.                     tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, NULL),
  1416.                                  __av_elem_pv(varbind, VARBIND_IID_F, NULL),
  1417.                                  oid_arr, &oid_arr_len, &type, best_guess);
  1418.                     if (oid_arr_len == 0) {
  1419.                        if (verbose)
  1420.                         warn("error:trap: unable to determine oid for object");
  1421.                        goto err;
  1422.                     }
  1423.                     if (type == TYPE_UNKNOWN) {
  1424.                       type = __translate_appl_type(
  1425.                               __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
  1426.                       if (type == TYPE_UNKNOWN) {
  1427.                          if (verbose)
  1428.                             warn("error:trap: no type found for object");
  1429.                          goto err;
  1430.                       }
  1431.                     }
  1432.             varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
  1433.                     if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
  1434.                       for(ep = tp->enums; ep; ep = ep->next) {
  1435.                         if (varbind_val_f && SvOK(*varbind_val_f) &&
  1436.                             !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
  1437.                           sv_setiv(*varbind_val_f, ep->value);
  1438.                           break;
  1439.                         }
  1440.                       }
  1441.                     }
  1442.                     res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
  1443.                                   (varbind_val_f && SvOK(*varbind_val_f) ?
  1444.                                    SvPV(*varbind_val_f,na):NULL),
  1445.                                   (varbind_val_f && SvOK(*varbind_val_f) ?
  1446.                                    SvCUR(*varbind_val_f):0),
  1447.                                   type);
  1448.                     if(res == FAILURE) {
  1449.                         if(verbose) warn("error:trap: adding varbind");
  1450.                         goto err;
  1451.                     }
  1452.                  } /* if var_ref is ok */
  1453.               } /* for all the vars */
  1454.               }
  1455.       pdu->enterprise = (oid *)malloc( MAX_OID_LEN * sizeof(oid));
  1456.               tp = __tag2oid(enterprise,NULL, pdu->enterprise,
  1457.                              &pdu->enterprise_length, NULL, best_guess);
  1458.          if (pdu->enterprise_length == 0) {
  1459.   if (verbose) warn("error:trap:invalid enterprise id: %s", enterprise);
  1460.                   goto err;
  1461.       }
  1462.       /*  If agent is given then set the v1-TRAP specific
  1463.   agent-address field to that.  Otherwise set it to
  1464.   our address.  */
  1465.               if (agent && strlen(agent)) {
  1466.                  if (__parse_address(agent) == -1 && verbose) {
  1467.    warn("error:trap:invalid agent address: %s", agent);
  1468.    goto err;
  1469.                  } else {
  1470.    *((in_addr_t *)pdu->agent_addr) = __parse_address(agent);
  1471.  }
  1472.               } else {
  1473.                  *((in_addr_t *)pdu->agent_addr) = get_myaddr();
  1474.               }
  1475.               pdu->trap_type = generic;
  1476.               pdu->specific_type = specific;
  1477.               pdu->time = uptime;
  1478.               if (snmp_send(ss, pdu) == 0) {
  1479.          snmp_free_pdu(pdu);
  1480.               }
  1481.               XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
  1482.            } else {
  1483. err:
  1484.               XPUSHs(&sv_undef); /* no mem or bad args */
  1485.               if (pdu) snmp_free_pdu(pdu);
  1486.            }
  1487. Safefree(oid_arr);
  1488.         }
  1489. int
  1490. snmp_trapV2(sess_ref,uptime,trap_oid,varlist_ref)
  1491.         SV * sess_ref
  1492.         char * uptime
  1493.         char * trap_oid
  1494.         SV * varlist_ref
  1495. PPCODE:
  1496. {
  1497.            AV *varlist;
  1498.            SV **varbind_ref;
  1499.            SV **varbind_val_f;
  1500.            AV *varbind;
  1501.    I32 varlist_len;
  1502.    I32 varlist_ind;
  1503.            SnmpSession *ss;
  1504.            netsnmp_pdu *pdu = NULL;
  1505.            struct tree *tp;
  1506.    oid *oid_arr;
  1507.    int oid_arr_len = MAX_OID_LEN;
  1508.            SV **sess_ptr_sv;
  1509.            SV **err_str_svp;
  1510.            SV **err_num_svp;
  1511.            SV **err_ind_svp;
  1512.            int type;
  1513.            int res;
  1514.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  1515.            int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
  1516.            struct enum_list *ep;
  1517.            int best_guess;
  1518.    
  1519.            New (0, oid_arr, MAX_OID_LEN, oid);
  1520.            if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
  1521.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  1522.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  1523.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  1524.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  1525.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  1526.               sv_setpv(*err_str_svp, "");
  1527.               sv_setiv(*err_num_svp, 0);
  1528.               sv_setiv(*err_ind_svp, 0);
  1529.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  1530.       
  1531.               pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
  1532.               varlist = (AV*) SvRV(varlist_ref);
  1533.               varlist_len = av_len(varlist);
  1534.       /************************************************/
  1535.               res = __add_var_val_str(pdu, sysUpTime, SYS_UPTIME_OID_LEN,
  1536. uptime, strlen(uptime), TYPE_TIMETICKS);
  1537.               if(res == FAILURE) {
  1538.                 if(verbose) warn("error:trap v2: adding sysUpTime varbind");
  1539. goto err;
  1540.               }
  1541.       res = __add_var_val_str(pdu, snmpTrapOID, SNMP_TRAP_OID_LEN,
  1542. trap_oid ,strlen(trap_oid) ,TYPE_OBJID);
  1543.               if(res == FAILURE) {
  1544.                 if(verbose) warn("error:trap v2: adding snmpTrapOID varbind");
  1545. goto err;
  1546.               }
  1547.       /******************************************************/
  1548.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  1549.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  1550.                  if (SvROK(*varbind_ref)) {
  1551.                     varbind = (AV*) SvRV(*varbind_ref);
  1552.                     tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F,NULL),
  1553.                                  __av_elem_pv(varbind, VARBIND_IID_F,NULL),
  1554.                                  oid_arr, &oid_arr_len, &type, best_guess);
  1555.                     if (oid_arr_len == 0) {
  1556.                        if (verbose)
  1557.                         warn("error:trap v2: unable to determine oid for object");
  1558.                        goto err;
  1559.                     }
  1560.                     if (type == TYPE_UNKNOWN) {
  1561.                       type = __translate_appl_type(
  1562.                                  __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
  1563.                       if (type == TYPE_UNKNOWN) {
  1564.                          if (verbose)
  1565.                             warn("error:trap v2: no type found for object");
  1566.                          goto err;
  1567.                       }
  1568.                     }
  1569.             varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
  1570.                     if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
  1571.                       for(ep = tp->enums; ep; ep = ep->next) {
  1572.                         if (varbind_val_f && SvOK(*varbind_val_f) &&
  1573.                             !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
  1574.                           sv_setiv(*varbind_val_f, ep->value);
  1575.                           break;
  1576.                         }
  1577.                       }
  1578.                     }
  1579.                     res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
  1580.                                   (varbind_val_f && SvOK(*varbind_val_f) ?
  1581.                                    SvPV(*varbind_val_f,na):NULL),
  1582.                                   (varbind_val_f && SvOK(*varbind_val_f) ?
  1583.                                    SvCUR(*varbind_val_f):0),
  1584.                                   type);
  1585.                     if(res == FAILURE) {
  1586.                         if(verbose) warn("error:trap v2: adding varbind");
  1587.                         goto err;
  1588.                     }
  1589.                  } /* if var_ref is ok */
  1590.               } /* for all the vars */
  1591.               if (snmp_send(ss, pdu) == 0) {
  1592.          snmp_free_pdu(pdu);
  1593.               }
  1594.               XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
  1595.            } else {
  1596. err:
  1597.               XPUSHs(&sv_undef); /* no mem or bad args */
  1598.               if (pdu) snmp_free_pdu(pdu);
  1599.            }
  1600. Safefree(oid_arr);
  1601.         }
  1602. int
  1603. snmp_inform(sess_ref,uptime,trap_oid,varlist_ref,perl_callback)
  1604.         SV * sess_ref
  1605.         char * uptime
  1606.         char * trap_oid
  1607.         SV * varlist_ref
  1608.         SV * perl_callback
  1609. PPCODE:
  1610. {
  1611.            AV *varlist;
  1612.            SV **varbind_ref;
  1613.            SV **varbind_val_f;
  1614.            AV *varbind;
  1615.    I32 varlist_len;
  1616.    I32 varlist_ind;
  1617.            SnmpSession *ss;
  1618.            netsnmp_pdu *pdu = NULL;
  1619.            netsnmp_pdu *response;
  1620.            struct tree *tp;
  1621.    oid *oid_arr;
  1622.    int oid_arr_len = MAX_OID_LEN;
  1623.            snmp_xs_cb_data *xs_cb_data;
  1624.            SV **sess_ptr_sv;
  1625.            SV **err_str_svp;
  1626.            SV **err_num_svp;
  1627.            SV **err_ind_svp;
  1628.            int status = 0;
  1629.            int type;
  1630.            int res;
  1631.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  1632.            int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
  1633.            struct enum_list *ep;
  1634.            int best_guess;
  1635.    
  1636.            New (0, oid_arr, MAX_OID_LEN, oid);
  1637.            if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
  1638.               sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
  1639.       ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
  1640.               err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
  1641.               err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
  1642.               err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
  1643.               sv_setpv(*err_str_svp, "");
  1644.               sv_setiv(*err_num_svp, 0);
  1645.               sv_setiv(*err_ind_svp, 0);
  1646.               best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
  1647.       
  1648.               pdu = snmp_pdu_create(SNMP_MSG_INFORM);
  1649.               varlist = (AV*) SvRV(varlist_ref);
  1650.               varlist_len = av_len(varlist);
  1651.       /************************************************/
  1652.               res = __add_var_val_str(pdu, sysUpTime, SYS_UPTIME_OID_LEN,
  1653. uptime, strlen(uptime), TYPE_TIMETICKS);
  1654.               if(res == FAILURE) {
  1655.                 if(verbose) warn("error:inform: adding sysUpTime varbind");
  1656. goto err;
  1657.               }
  1658.       res = __add_var_val_str(pdu, snmpTrapOID, SNMP_TRAP_OID_LEN,
  1659. trap_oid ,strlen(trap_oid) ,TYPE_OBJID);
  1660.               if(res == FAILURE) {
  1661.                 if(verbose) warn("error:inform: adding snmpTrapOID varbind");
  1662. goto err;
  1663.               }
  1664.       /******************************************************/
  1665.       for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
  1666.                  varbind_ref = av_fetch(varlist, varlist_ind, 0);
  1667.                  if (SvROK(*varbind_ref)) {
  1668.                     varbind = (AV*) SvRV(*varbind_ref);
  1669.                     tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F,NULL),
  1670.                                  __av_elem_pv(varbind, VARBIND_IID_F,NULL),
  1671.                                  oid_arr, &oid_arr_len, &type, best_guess);
  1672.                     if (oid_arr_len == 0) {
  1673.                        if (verbose)
  1674.                         warn("error:inform: unable to determine oid for object");
  1675.                        goto err;
  1676.                     }
  1677.                     if (type == TYPE_UNKNOWN) {
  1678.                       type = __translate_appl_type(
  1679.                                  __av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
  1680.                       if (type == TYPE_UNKNOWN) {
  1681.                          if (verbose)
  1682.                             warn("error:inform: no type found for object");
  1683.                          goto err;
  1684.                       }
  1685.                     }
  1686.             varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
  1687.                     if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
  1688.                       for(ep = tp->enums; ep; ep = ep->next) {
  1689.                         if (varbind_val_f && SvOK(*varbind_val_f) &&
  1690.                             !strcmp(ep->label, SvPV(*varbind_val_f,na))) {
  1691.                           sv_setiv(*varbind_val_f, ep->value);
  1692.                           break;
  1693.                         }
  1694.                       }
  1695.                     }
  1696.                     res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
  1697.                                   (varbind_val_f && SvOK(*varbind_val_f) ?
  1698.                                    SvPV(*varbind_val_f,na):NULL),
  1699.                                   (varbind_val_f && SvOK(*varbind_val_f) ?
  1700.                                    SvCUR(*varbind_val_f):0),
  1701.                                   type);
  1702.                     if(res == FAILURE) {
  1703.                         if(verbose) warn("error:inform: adding varbind");
  1704.                         goto err;
  1705.                     }
  1706.                  } /* if var_ref is ok */
  1707.               } /* for all the vars */
  1708.               if (SvTRUE(perl_callback)) {
  1709.                   xs_cb_data =
  1710.                       (snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
  1711.                  xs_cb_data->perl_cb = newSVsv(perl_callback);
  1712.                  xs_cb_data->sess_ref = newRV_inc(SvRV(sess_ref));
  1713.                  status = snmp_async_send(ss, pdu, __snmp_xs_cb,
  1714.                                           (void*)xs_cb_data);
  1715.                  if (status != 0) {
  1716.                     XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
  1717.                  } else {
  1718.                     snmp_free_pdu(pdu);
  1719.                     sv_catpv(*err_str_svp,
  1720.                              (char*)snmp_api_errstring(ss->s_snmp_errno));
  1721.                     sv_setiv(*err_num_svp, ss->s_snmp_errno);
  1722.                     XPUSHs(&sv_undef);
  1723.                  }
  1724.  goto done;
  1725.               }
  1726.       status = __send_sync_pdu(ss, pdu, &response,
  1727.        NO_RETRY_NOSUCH,
  1728.                                        *err_str_svp, *err_num_svp,
  1729.                                        *err_ind_svp);
  1730.               if (response) snmp_free_pdu(response);
  1731.               if (status) {
  1732.  XPUSHs(&sv_undef);
  1733.       } else {
  1734.                  XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
  1735.               }
  1736.            } else {
  1737. err:
  1738.               XPUSHs(&sv_undef); /* no mem or bad args */
  1739.               if (pdu) snmp_free_pdu(pdu);
  1740.            }
  1741. done:
  1742. Safefree(oid_arr);
  1743.         }
  1744. char *
  1745. snmp_get_type(tag, best_guess)
  1746. char * tag
  1747.         int             best_guess
  1748. CODE:
  1749. {
  1750.    struct tree *tp  = NULL;
  1751.    static char type_str[MAX_TYPE_NAME_LEN];
  1752.            char *ret = NULL;
  1753.            if (tag && *tag) tp = __tag2oid(tag, NULL, NULL, NULL, NULL, best_guess);
  1754.            if (tp) __get_type_str(tp->type, ret = type_str);
  1755.    RETVAL = ret;
  1756. }
  1757. OUTPUT:
  1758.         RETVAL
  1759. void
  1760. snmp_dump_packet(flag)
  1761. int flag
  1762. CODE:
  1763. {
  1764.    snmp_set_dump_packet(flag);
  1765. }
  1766. char *
  1767. snmp_map_enum(tag, val, iflag, best_guess)
  1768. char * tag
  1769. char * val
  1770. int iflag
  1771.         int             best_guess
  1772. CODE:
  1773. {
  1774.    struct tree *tp  = NULL;
  1775.            struct enum_list *ep;
  1776.            char str_buf[STR_BUF_SIZE];
  1777.            int ival;
  1778.            RETVAL = NULL;
  1779.            if (tag && *tag) tp = __tag2oid(tag, NULL, NULL, NULL, NULL, best_guess);
  1780.            if (tp) {
  1781.               if (iflag) {
  1782.                  ival = atoi(val);
  1783.                  for(ep = tp->enums; ep; ep = ep->next) {
  1784.                     if (ep->value == ival) {
  1785.                        RETVAL = ep->label;
  1786.                        break;
  1787.                     }
  1788.                  }
  1789.               } else {
  1790.                  for(ep = tp->enums; ep; ep = ep->next) {
  1791.                     if (strEQ(ep->label, val)) {
  1792.                        sprintf(str_buf,"%d", ep->value);
  1793.                        RETVAL = str_buf;
  1794.                        break;
  1795.                     }
  1796.                  }
  1797.               }
  1798.            }
  1799. }
  1800. OUTPUT:
  1801.         RETVAL
  1802. #define SNMP_XLATE_MODE_OID2TAG 1
  1803. #define SNMP_XLATE_MODE_TAG2OID 0
  1804. char *
  1805. snmp_translate_obj(var,mode,use_long,auto_init,best_guess,include_module_name)
  1806. char * var
  1807. int mode
  1808. int use_long
  1809. int auto_init
  1810. int             best_guess
  1811. int include_module_name
  1812. CODE:
  1813. {
  1814.            char str_buf[STR_BUF_SIZE];
  1815.            char str_buf_temp[STR_BUF_SIZE];
  1816.            oid oid_arr[MAX_OID_LEN];
  1817.            int oid_arr_len = MAX_OID_LEN;
  1818.            char * label;
  1819.            char * iid;
  1820.            int status = FAILURE;
  1821.            int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
  1822.            struct tree *module_tree = NULL;
  1823.            char modbuf[256];
  1824.            int  old_format;   /* Current NETSNMP_DS_LIB_OID_OUTPUT_FORMAT */
  1825.            str_buf[0] = '';
  1826.            str_buf_temp[0] = '';
  1827.            /* Save old output format and set to FULL so long_names works */
  1828.            old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
  1829.            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_FULL);
  1830.       switch (mode) {
  1831.               case SNMP_XLATE_MODE_TAG2OID:
  1832. if (!__tag2oid(var, NULL, oid_arr, &oid_arr_len, NULL, best_guess)) {
  1833.    if (verbose) warn("error:snmp_translate_obj:Unknown OID %sn",var);
  1834.                 } else {
  1835.                    status = __sprint_num_objid(str_buf, oid_arr, oid_arr_len);
  1836.                 }
  1837.                 break;
  1838.              case SNMP_XLATE_MODE_OID2TAG:
  1839. oid_arr_len = 0;
  1840. __concat_oid_str(oid_arr, &oid_arr_len, var);
  1841. snprint_objid(str_buf_temp, sizeof(str_buf_temp), oid_arr, oid_arr_len);
  1842. if (!use_long) {
  1843.                   label = NULL; iid = NULL;
  1844.   if (((status=__get_label_iid(str_buf_temp,
  1845.        &label, &iid, NO_FLAGS)) == SUCCESS)
  1846.       && label) {
  1847.      strcpy(str_buf_temp, label);
  1848.      if (iid && *iid) {
  1849.        strcat(str_buf_temp, ".");
  1850.        strcat(str_buf_temp, iid);
  1851.      }
  1852.             }
  1853.         }
  1854. /* Prepend modulename:: if enabled */
  1855. if (include_module_name) {
  1856.   module_tree = get_tree (oid_arr, oid_arr_len, get_tree_head());
  1857.   if (module_tree) {
  1858.     if (strcmp(module_name(module_tree->modid, modbuf), "#-1") ) {
  1859.       strcat(str_buf, modbuf);
  1860.       strcat(str_buf, "::");
  1861.     }
  1862.     else {
  1863.       strcat(str_buf, "UNKNOWN::");
  1864.     }
  1865.   }
  1866. }
  1867. strcat(str_buf, str_buf_temp);
  1868. break;
  1869.              default:
  1870.        if (verbose) warn("snmp_translate_obj:unknown translation mode: %sn", mode);
  1871.            }
  1872.            if (*str_buf) {
  1873.               RETVAL = (char*)str_buf;
  1874.            } else {
  1875.               RETVAL = (char*)NULL;
  1876.            }
  1877.            netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, old_format);
  1878. }
  1879.         OUTPUT:
  1880.         RETVAL
  1881. void
  1882. snmp_set_replace_newer(val)
  1883. int val
  1884. CODE:
  1885. {
  1886.             netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
  1887.                                    NETSNMP_DS_LIB_MIB_REPLACE, val);
  1888. }
  1889. void
  1890. snmp_set_save_descriptions(val)
  1891. int val
  1892. CODE:
  1893. {
  1894.    snmp_set_save_descriptions(val);
  1895. }
  1896. void
  1897. snmp_set_debugging(val)
  1898. int val
  1899. CODE:
  1900. {
  1901.    snmp_set_do_debugging(val);
  1902. }
  1903. void
  1904. snmp_debug_internals(val)
  1905. int     val
  1906. CODE:
  1907. {
  1908. #ifdef DEBUGGING
  1909.    _debug_level = val;
  1910. #endif /* DEBUGGING */
  1911. }
  1912. void
  1913. snmp_mib_toggle_options(options)
  1914. char   *options
  1915. CODE:
  1916. {
  1917.    snmp_mib_toggle_options(options);
  1918. }
  1919. void
  1920. snmp_sock_cleanup()
  1921. CODE:
  1922. {
  1923.    SOCK_CLEANUP;
  1924. }
  1925. void
  1926. snmp_mainloop_finish()
  1927. CODE:
  1928. {
  1929.     mainloop_finish = 1;
  1930. }
  1931. void
  1932. snmp_main_loop(timeout_sec,timeout_usec,perl_callback)
  1933. int  timeout_sec
  1934. int  timeout_usec
  1935. SV * perl_callback
  1936. CODE:
  1937. {
  1938.         int numfds, fd_count;
  1939.         fd_set fdset;
  1940.         struct timeval time_val, *tvp;
  1941.         struct timeval last_time, *ltvp;
  1942.         struct timeval ctimeout, *ctvp;
  1943.         struct timeval interval, *itvp;
  1944.         int block;
  1945. SV *cb;
  1946.   mainloop_finish = 0;
  1947. itvp = &interval;
  1948. itvp->tv_sec = timeout_sec;
  1949. itvp->tv_usec = timeout_usec;
  1950.         ctvp = &ctimeout;
  1951.         ctvp->tv_sec = -1;
  1952.         ltvp = &last_time;
  1953.         gettimeofday(ltvp,(struct timezone*)0);
  1954. timersub(ltvp,itvp,ltvp);
  1955.         while (1) {
  1956.            numfds = 0;
  1957.            FD_ZERO(&fdset);
  1958.            block = 1;
  1959.            tvp = &time_val;
  1960.            timerclear(tvp);
  1961.            snmp_select_info(&numfds, &fdset, tvp, &block);
  1962.            __recalc_timeout(tvp,ctvp,ltvp,itvp,&block);
  1963.            # printf("pre-select: numfds = %ld, block = %ldn", numfds, block);
  1964.            if (block == 1) tvp = NULL; /* block without timeout */
  1965.            fd_count = select(numfds, &fdset, 0, 0, tvp);
  1966.            #printf("post-select: fd_count = %ld,block = %ldn",fd_count,block);
  1967.            if (fd_count > 0) {
  1968.                        dSP;
  1969.                        ENTER;
  1970.                        SAVETMPS;
  1971.               snmp_read(&fdset);
  1972.                        FREETMPS;
  1973.                        LEAVE;
  1974.            } else switch(fd_count) {
  1975.               case 0:
  1976.  SPAGAIN;
  1977.  ENTER;
  1978.  SAVETMPS;
  1979.                  snmp_timeout();
  1980.                  if (!timerisset(ctvp)) {
  1981.                     if (SvTRUE(perl_callback)) {
  1982.                        /* sv_2mortal(perl_callback); */
  1983.                        cb = __push_cb_args(perl_callback, NULL);
  1984.                        __call_callback(cb, G_DISCARD);
  1985.                        ctvp->tv_sec = -1;
  1986.                     } else {
  1987.                        FREETMPS;
  1988.                        LEAVE;
  1989.                        goto done;
  1990.                     }
  1991.                  }
  1992.                  FREETMPS;
  1993.                  LEAVE;
  1994.                  break;
  1995.               case -1:
  1996.                  if (errno == EINTR) {
  1997.                     continue;
  1998.                  } else {
  1999.                     /* snmp_set_detail(strerror(errno)); */
  2000.                     /* snmp_errno = SNMPERR_GENERR; */
  2001.                  }
  2002.               default:;
  2003.            }
  2004.    /* A call to snmp_mainloop_finish() in the callback sets the
  2005.    ** mainloop_finish flag.  Exit the loop after the callback returns.
  2006.    */
  2007.    if (mainloop_finish)
  2008.       goto done;
  2009.         }
  2010.      done:
  2011.            return;
  2012. }
  2013. void
  2014. snmp_get_select_info()
  2015. PPCODE:
  2016. {
  2017.         int numfds;
  2018.         fd_set fdset;
  2019.         struct timeval time_val, *tvp;
  2020.         int block;
  2021. int i;
  2022.         numfds = 0;
  2023.         block = 1;
  2024.         tvp = &time_val;
  2025.         FD_ZERO(&fdset);
  2026.         snmp_select_info(&numfds, &fdset, tvp, &block);
  2027. XPUSHs(sv_2mortal(newSViv(block)));
  2028. if(block){
  2029.             XPUSHs(sv_2mortal(newSViv(0)));
  2030.             XPUSHs(sv_2mortal(newSViv(0)));
  2031. } else {
  2032.             XPUSHs(sv_2mortal(newSViv(tvp->tv_sec)));
  2033.             XPUSHs(sv_2mortal(newSViv(tvp->tv_usec)));
  2034. }
  2035. if ( numfds ) {
  2036.             for(i=0; i<numfds ; i++) {
  2037.                 if(FD_ISSET(i, &fdset)){
  2038.                     XPUSHs(sv_2mortal(newSViv(i)));
  2039.                 }
  2040.             }
  2041. } else {
  2042.             XPUSHs(&sv_undef);  /* no mem or bad args */
  2043. }
  2044. }
  2045. void
  2046. snmp_read_on_fd(fd)
  2047. int fd
  2048. CODE:
  2049. {
  2050.            fd_set fdset;
  2051.            FD_ZERO(&fdset);
  2052.            FD_SET(fd, &fdset);
  2053.            snmp_read(&fdset);
  2054. }
  2055. void
  2056. snmp_check_timeout()
  2057. CODE:
  2058. {
  2059.           snmp_timeout();
  2060. }
  2061. MODULE = SNMP PACKAGE = SNMP::MIB::NODE  PREFIX = snmp_mib_node_
  2062. SV *
  2063. snmp_mib_node_TIEHASH(cl,key,tp=0)
  2064. char * cl
  2065. char * key
  2066.         IV tp
  2067. CODE:
  2068. {
  2069.             __libraries_init("perl");
  2070.            if (!tp) tp = (IV)__tag2oid(key, NULL, NULL, NULL, NULL,0);
  2071.            if (tp) {
  2072.               ST(0) = sv_newmortal();
  2073.               sv_setref_iv(ST(0), cl, tp);
  2074.            } else {
  2075.               ST(0) = &sv_undef;
  2076.            }
  2077. }
  2078. SV *
  2079. snmp_mib_node_FETCH(tp_ref, key)
  2080. SV * tp_ref
  2081. char * key
  2082. CODE:
  2083. {
  2084.    char c = *key;
  2085.    char str_buf[STR_BUF_SIZE];
  2086.            SnmpMibNode *tp = NULL, *tptmp = NULL;
  2087.            struct index_list *ip;
  2088.            struct enum_list *ep;
  2089.            struct range_list *rp;
  2090.    struct varbind_list *vp;
  2091.            struct module *mp;
  2092.            SV *child_list_aref, *next_node_href, *mib_tied_href = NULL;
  2093.    SV **nn_hrefp;
  2094.            HV *mib_hv, *enum_hv, *range_hv;
  2095.            AV *index_av, *varbind_av, *ranges_av;
  2096.            MAGIC *mg = NULL;
  2097.            if (SvROK(tp_ref)) tp = (SnmpMibNode*)SvIV((SV*)SvRV(tp_ref));
  2098.    ST(0) = sv_newmortal();
  2099.            if (tp)
  2100.    switch (c) {
  2101.       case 'a': /* access */
  2102.                  if (strncmp("access", key, strlen(key)) == 0) {
  2103.                  switch (tp->access) {
  2104.                    case MIB_ACCESS_READONLY:
  2105.                      sv_setpv(ST(0),"ReadOnly");
  2106.                      break;
  2107.                    case MIB_ACCESS_READWRITE:
  2108.                      sv_setpv(ST(0),"ReadWrite");
  2109.                      break;
  2110.                    case MIB_ACCESS_WRITEONLY:
  2111.                      sv_setpv(ST(0),"WriteOnly");
  2112.                      break;
  2113.                    case MIB_ACCESS_NOACCESS:
  2114.                      sv_setpv(ST(0),"NoAccess");
  2115.                      break;
  2116.                    case MIB_ACCESS_NOTIFY:
  2117.                      sv_setpv(ST(0),"Notify");
  2118.                      break;
  2119.                    case MIB_ACCESS_CREATE:
  2120.                      sv_setpv(ST(0),"Create");
  2121.                      break;
  2122.                    default:
  2123.                      break;
  2124.                  }
  2125.                  } else if (strncmp("augments", key, strlen(key)) == 0) {
  2126.                      sv_setpv(ST(0),tp->augments);
  2127.                  }
  2128.                  break;
  2129.          case 'c': /* children */
  2130.                  if (strncmp("children", key, strlen(key))) break;
  2131.                  child_list_aref = newRV((SV*)newAV());
  2132.                  for (tp = tp->child_list; tp; tp = tp->next_peer) {
  2133.                     mib_hv = perl_get_hv("SNMP::MIB", FALSE);
  2134.                     if (SvMAGICAL(mib_hv)) mg = mg_find((SV*)mib_hv, 'P');
  2135.                     if (mg) mib_tied_href = (SV*)mg->mg_obj;
  2136.                     next_node_href = newRV((SV*)newHV());
  2137.                     __tp_sprint_num_objid(str_buf, tp);
  2138.                     nn_hrefp = hv_fetch((HV*)SvRV(mib_tied_href),
  2139.                                         str_buf, strlen(str_buf), 1);
  2140.                     if (!SvROK(*nn_hrefp)) {
  2141.                        sv_setsv(*nn_hrefp, next_node_href);
  2142.                        ENTER ;
  2143.                        SAVETMPS ;
  2144.                        PUSHMARK(sp) ;
  2145.                        XPUSHs(SvRV(*nn_hrefp));
  2146.                        XPUSHs(sv_2mortal(newSVpv("SNMP::MIB::NODE",0)));
  2147.                        XPUSHs(sv_2mortal(newSVpv(str_buf,0)));
  2148.                        XPUSHs(sv_2mortal(newSViv((IV)tp)));
  2149.                        PUTBACK ;
  2150.                        perl_call_pv("SNMP::_tie",G_VOID);
  2151.                        /* pp_tie(ARGS); */
  2152.                        SPAGAIN ;
  2153.                        FREETMPS ;
  2154.                        LEAVE ;
  2155.                     } /* if SvROK */
  2156.                     av_push((AV*)SvRV(child_list_aref), *nn_hrefp);
  2157.                  } /* for child_list */
  2158.                  sv_setsv(ST(0), child_list_aref);
  2159.                  break;
  2160.       case 'v':
  2161.          if (strncmp("varbinds", key, strlen(key))) break;
  2162.  varbind_av = newAV();
  2163.  for (vp = tp->varbinds; vp; vp = vp->next) {
  2164.             av_push(varbind_av, newSVpv((vp->vblabel),strlen(vp->vblabel)));
  2165.  }
  2166.  sv_setsv(ST(0), newRV((SV*)varbind_av));
  2167.  break;
  2168.       case 'd': /* description */
  2169.                   if (strncmp("description", key, strlen(key))) {
  2170.                       if(!(strncmp("defaultValue",key,strlen(key)))) {
  2171.                           /* We're looking at defaultValue */
  2172.                           sv_setpv(ST(0), tp->defaultValue);
  2173.                           break;
  2174.                       } /* end if */
  2175.                   } /* end if */
  2176.           /* we must be looking at description */
  2177.                  sv_setpv(ST(0),tp->description);
  2178.                  break;
  2179.               case 'i': /* indexes */
  2180.                  if (strncmp("indexes", key, strlen(key))) break;
  2181.                  index_av = newAV();
  2182.                  if (tp->augments) {
  2183.                clear_tree_flags(get_tree_head()); 
  2184.                      tptmp = find_best_tree_node(tp->augments, get_tree_head(), NULL);
  2185.                      if (tptmp == NULL) {
  2186.                         tptmp = tp;
  2187.                      }
  2188.                  } else {
  2189.                      tptmp = tp;
  2190.                  }
  2191.                  if (tptmp)
  2192.                      for(ip=tptmp->indexes; ip != NULL; ip = ip->next) {
  2193.                          av_push(index_av,newSVpv((ip->ilabel),strlen(ip->ilabel)));
  2194.                      }
  2195.                 sv_setsv(ST(0), newRV((SV*)index_av));
  2196.                 break;
  2197.       case 'l': /* label */
  2198.                  if (strncmp("label", key, strlen(key))) break;
  2199.                  sv_setpv(ST(0),tp->label);
  2200.                  break;
  2201.       case 'm': /* moduleID */
  2202.                  if (strncmp("moduleID", key, strlen(key))) break;
  2203.                  mp = find_module(tp->modid);
  2204.                  if (mp) sv_setpv(ST(0), mp->name);
  2205.                  break;
  2206.       case 'n': /* nextNode */
  2207.                  if (strncmp("nextNode", key, strlen(key))) break;
  2208.                  tp = __get_next_mib_node(tp);
  2209.                  if (tp == NULL) {
  2210.                     sv_setsv(ST(0), &sv_undef);
  2211.                     break;
  2212.                  }
  2213.                  mib_hv = perl_get_hv("SNMP::MIB", FALSE);
  2214.                  if (SvMAGICAL(mib_hv)) mg = mg_find((SV*)mib_hv, 'P');
  2215.                  if (mg) mib_tied_href = (SV*)mg->mg_obj;
  2216.                  __tp_sprint_num_objid(str_buf, tp);
  2217.                  nn_hrefp = hv_fetch((HV*)SvRV(mib_tied_href),
  2218.                                      str_buf, strlen(str_buf), 1);
  2219.                  /* if (!SvROK(*nn_hrefp)) { */ /* bug in ucd - 2 .0.0 nodes */
  2220.                  next_node_href = newRV((SV*)newHV());
  2221.                  sv_setsv(*nn_hrefp, next_node_href);
  2222.                  ENTER ;
  2223.                  SAVETMPS ;
  2224.                  PUSHMARK(sp) ;
  2225.                  XPUSHs(SvRV(*nn_hrefp));
  2226.                  XPUSHs(sv_2mortal(newSVpv("SNMP::MIB::NODE",0)));
  2227.                  XPUSHs(sv_2mortal(newSVpv(str_buf,0)));
  2228.                  XPUSHs(sv_2mortal(newSViv((IV)tp)));
  2229.                  PUTBACK ;
  2230.                  perl_call_pv("SNMP::_tie",G_VOID);
  2231.                  /* pp_tie(ARGS); */
  2232.                  SPAGAIN ;
  2233.                  FREETMPS ;
  2234.                  LEAVE ;
  2235.                  /* } */
  2236.                  sv_setsv(ST(0), *nn_hrefp);
  2237.                  break;
  2238.       case 'o': /* objectID */
  2239.                  if (strncmp("objectID", key, strlen(key))) break;
  2240.                  __tp_sprint_num_objid(str_buf, tp);
  2241.                  sv_setpv(ST(0),str_buf);
  2242.                  break;
  2243.       case 'p': /* parent */
  2244.                  if (strncmp("parent", key, strlen(key))) break;
  2245.                  tp = tp->parent;
  2246.                  if (tp == NULL) {
  2247.                     sv_setsv(ST(0), &sv_undef);
  2248.                     break;
  2249.                  }
  2250.                  mib_hv = perl_get_hv("SNMP::MIB", FALSE);
  2251.                  if (SvMAGICAL(mib_hv)) mg = mg_find((SV*)mib_hv, 'P');
  2252.                  if (mg) mib_tied_href = (SV*)mg->mg_obj;
  2253.                  next_node_href = newRV((SV*)newHV());
  2254.                  __tp_sprint_num_objid(str_buf, tp);
  2255.                  nn_hrefp = hv_fetch((HV*)SvRV(mib_tied_href),
  2256.                                      str_buf, strlen(str_buf), 1);
  2257.                  if (!SvROK(*nn_hrefp)) {
  2258.                  sv_setsv(*nn_hrefp, next_node_href);
  2259.                  ENTER ;
  2260.                  SAVETMPS ;
  2261.                  PUSHMARK(sp) ;
  2262.                  XPUSHs(SvRV(*nn_hrefp));
  2263.                  XPUSHs(sv_2mortal(newSVpv("SNMP::MIB::NODE",0)));
  2264.                  XPUSHs(sv_2mortal(newSVpv(str_buf,0)));
  2265.                  XPUSHs(sv_2mortal(newSViv((IV)tp)));
  2266.                  PUTBACK ;
  2267.                  perl_call_pv("SNMP::_tie",G_VOID);
  2268.                  /* pp_tie(ARGS); */
  2269.                  SPAGAIN ;
  2270.                  FREETMPS ;
  2271.                  LEAVE ;
  2272.                  }
  2273.                  sv_setsv(ST(0), *nn_hrefp);
  2274.                  break;
  2275.       case 'r': /* ranges */
  2276.                  if (strncmp("reference", key, strlen(key)) == 0) {
  2277.                    sv_setpv(ST(0),tp->reference);
  2278.                    break;
  2279.                  }
  2280.                  if (strncmp("ranges", key, strlen(key))) break;
  2281.                  ranges_av = newAV();
  2282.                  for(rp=tp->ranges; rp ; rp = rp->next) {
  2283.    range_hv = newHV();
  2284.                    hv_store(range_hv, "low", strlen("low"), newSViv(rp->low), 0);
  2285.                    hv_store(range_hv, "high", strlen("high"), newSViv(rp->high), 0);
  2286.    av_push(ranges_av, newRV((SV*)range_hv));
  2287.                  }
  2288.                  sv_setsv(ST(0), newRV((SV*)ranges_av));
  2289.                  break;
  2290.       case 's': /* subID */
  2291.                  if (strncmp("subID", key, strlen(key))) {
  2292.                    if (strncmp("status", key, strlen(key))) {
  2293.                       if (strncmp("syntax", key, strlen(key))) break;
  2294.                       if (tp->tc_index >= 0) {
  2295.                          sv_setpv(ST(0), get_tc_descriptor(tp->tc_index));
  2296.                       } else {
  2297.                          __get_type_str(tp->type, str_buf);
  2298.                          sv_setpv(ST(0), str_buf);
  2299.                       }
  2300.                       break;
  2301.                    }
  2302.                    switch(tp->status) {
  2303.                      case MIB_STATUS_MANDATORY:
  2304.                        sv_setpv(ST(0),"Mandatory");
  2305.                        break;
  2306.                      case MIB_STATUS_OPTIONAL:
  2307.                        sv_setpv(ST(0),"Optional");
  2308.                        break;
  2309.                      case MIB_STATUS_OBSOLETE:
  2310.                        sv_setpv(ST(0),"Obsolete");
  2311.                        break;
  2312.                      case MIB_STATUS_DEPRECATED:
  2313.                        sv_setpv(ST(0),"Deprecated");
  2314.                        break;
  2315.      case MIB_STATUS_CURRENT:
  2316.                        sv_setpv(ST(0),"Current");
  2317.                        break;
  2318.                      default:
  2319.                        break;
  2320.                    }
  2321.                  } else {
  2322.                    sv_setiv(ST(0),(I32)tp->subid);
  2323.                  }
  2324.                  break;
  2325.       case 't': /* type */
  2326.                  if (strncmp("type", key, strlen(key))) {
  2327.                     if (strncmp("textualConvention", key, strlen(key))) break;
  2328.                     sv_setpv(ST(0), get_tc_descriptor(tp->tc_index));
  2329.                     break;
  2330.                  }
  2331.                  __get_type_str(tp->type, str_buf);
  2332.                  sv_setpv(ST(0), str_buf);
  2333.                  break;
  2334.       case 'T': /* textual convention description */
  2335.                   if (strncmp("TCDescription", key, strlen(key))) break;
  2336.                   sv_setpv(ST(0), get_tc_description(tp->tc_index));
  2337.                   break;
  2338.       case 'u': /* units */
  2339.                  if (strncmp("units", key, strlen(key))) break;
  2340.                  sv_setpv(ST(0),tp->units);
  2341.                  break;
  2342.       case 'h': /* hint */
  2343.                  if (strncmp("hint", key, strlen(key))) break;
  2344.                  sv_setpv(ST(0),tp->hint);
  2345.                  break;
  2346.       case 'e': /* enums */
  2347.                  if (strncmp("enums", key, strlen(key))) break;
  2348.                  enum_hv = newHV();
  2349.                  for(ep=tp->enums; ep != NULL; ep = ep->next) {
  2350.                    hv_store(enum_hv, ep->label, strlen(ep->label),
  2351.                                 newSViv(ep->value), 0);
  2352.                  }
  2353.                  sv_setsv(ST(0), newRV((SV*)enum_hv));
  2354.                  break;
  2355.               default:
  2356.                  break;
  2357.    }
  2358. }
  2359. MODULE = SNMP PACKAGE = SnmpSessionPtr PREFIX = snmp_session_
  2360. void
  2361. snmp_session_DESTROY(sess_ptr)
  2362. SnmpSession *sess_ptr
  2363. CODE:
  2364. {
  2365.            snmp_close( sess_ptr );
  2366. }