SNMP
view release on metacpan or search on metacpan
CODE:
{
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
if ((mib_file == NULL) || (*mib_file == '\0')) {
if (get_tree_head() == NULL) {
if (verbose) warn("snmp_read_mib: initializing MIB\n");
netsnmp_init_mib();
if (get_tree_head()) {
if (verbose) warn("done\n");
} else {
if (verbose) warn("failed\n");
}
}
} else {
if (verbose) warn("snmp_read_mib: reading MIB: %s\n", mib_file);
if (strcmp("ALL",mib_file))
read_mib(mib_file);
else
read_all_mibs();
if (get_tree_head()) {
if (verbose) warn("done\n");
} else {
if (verbose) warn("failed\n");
}
}
RETVAL = (IV)get_tree_head();
}
OUTPUT:
RETVAL
int
snmp_read_module(module)
char * module
CODE:
{
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
if (!strcmp(module,"ALL")) {
read_all_mibs();
} else {
netsnmp_read_module(module);
}
if (get_tree_head()) {
if (verbose) warn("Read %s\n", module);
} else {
if (verbose) warn("Failed reading %s\n", module);
}
RETVAL = (IV)get_tree_head();
}
OUTPUT:
RETVAL
void
snmp_set(sess_ref, varlist_ref, perl_callback)
SV * sess_ref
SV * varlist_ref
SV * perl_callback
PPCODE:
{
AV *varlist;
SV **varbind_ref;
SV **varbind_val_f;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
SnmpSession *ss;
netsnmp_pdu *pdu, *response;
struct tree *tp;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
char *tag_pv;
snmp_xs_cb_data *xs_cb_data;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int status = 0;
int type;
int res;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int use_enums;
struct enum_list *ep;
int best_guess;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
pdu = snmp_pdu_create(SNMP_MSG_SET);
varlist = (AV*) SvRV(varlist_ref);
varlist_len = av_len(varlist);
for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
varbind_ref = av_fetch(varlist, varlist_ind, 0);
if (SvROK(*varbind_ref)) {
varbind = (AV*) SvRV(*varbind_ref);
tag_pv = __av_elem_pv(varbind, VARBIND_TAG_F,NULL);
tp=__tag2oid(tag_pv,
__av_elem_pv(varbind, VARBIND_IID_F,NULL),
oid_arr, &oid_arr_len, &type, best_guess);
if (oid_arr_len==0) {
if (verbose)
warn("error: set: unknown object ID (%s)",
(tag_pv?tag_pv:"<null>"));
sv_catpv(*err_str_svp,
(char*)snmp_api_errstring(SNMPERR_UNKNOWN_OBJID));
}
}
}
res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
(varbind_val_f && SvOK(*varbind_val_f) ?
SvPV(*varbind_val_f,na):NULL),
(varbind_val_f && SvPOK(*varbind_val_f) ?
SvCUR(*varbind_val_f):0), type);
if (verbose && res == FAILURE)
warn("error: set: adding variable/value to PDU");
} /* if var_ref is ok */
} /* for all the vars */
if (SvTRUE(perl_callback)) {
xs_cb_data =
(snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
xs_cb_data->perl_cb = newSVsv(perl_callback);
xs_cb_data->sess_ref = newRV_inc(SvRV(sess_ref));
status = snmp_async_send(ss, pdu, __snmp_xs_cb,
(void*)xs_cb_data);
if (status != 0) {
XPUSHs(sv_2mortal(newSViv(status))); /* push the reqid?? */
} else {
snmp_free_pdu(pdu);
sv_catpv(*err_str_svp,
(char*)snmp_api_errstring(ss->s_snmp_errno));
sv_setiv(*err_num_svp, ss->s_snmp_errno);
XPUSHs(&sv_undef);
}
goto done;
}
status = __send_sync_pdu(ss, pdu, &response,
NO_RETRY_NOSUCH,
*err_str_svp, *err_num_svp,
*err_ind_svp);
if (response) snmp_free_pdu(response);
if (status) {
XPUSHs(&sv_undef);
} else {
XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
}
} else {
/* BUG!!! need to return an error value */
XPUSHs(&sv_undef); /* no mem or bad args */
}
done:
Safefree(oid_arr);
}
void
snmp_catch(sess_ref, perl_callback)
SV * sess_ref
SV * perl_callback
PPCODE:
{
netsnmp_session *ss;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
if (SvROK(sess_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
ss->callback = NULL;
ss->callback_magic = NULL;
if (SvTRUE(perl_callback)) {
snmp_xs_cb_data *xs_cb_data;
xs_cb_data =
(snmp_xs_cb_data*)malloc(sizeof(snmp_xs_cb_data));
xs_cb_data->perl_cb = newSVsv(perl_callback);
xs_cb_data->sess_ref = newRV_inc(SvRV(sess_ref));
# it might be more efficient to pass the varbind_ref to
# __snmp_xs_cb as part of perl_callback so it is not freed
# and reconstructed for each call
ss->callback = __snmp_xs_cb;
ss->callback_magic = xs_cb_data;
sv_2mortal(newSViv(1));
goto done;
}
}
sv_2mortal(newSViv(0));
done:
;
}
void
snmp_get(sess_ref, retry_nosuch, varlist_ref, perl_callback)
SV * sess_ref
int retry_nosuch
SV * varlist_ref
SV * perl_callback
PPCODE:
{
AV *varlist;
SV **varbind_ref;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
netsnmp_session *ss;
netsnmp_pdu *pdu, *response;
netsnmp_variable_list *vars;
struct tree *tp;
int len;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
SV *tmp_sv;
int type;
char tmp_type_str[MAX_TYPE_NAME_LEN];
snmp_xs_cb_data *xs_cb_data;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int status;
char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
size_t str_buf_len = sizeof(str_buf);
size_t out_len = 0;
int buf_over = 0;
char *label;
char *iid;
int getlabel_flag = NO_FLAGS;
int sprintval_flag = USE_BASIC;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int old_format;
SV *sv_timestamp = NULL;
int best_guess;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
getlabel_flag |= USE_LONG_NAMES;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
getlabel_flag |= USE_NUMERIC_OIDS;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
sprintval_flag = USE_ENUMS;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
sprintval_flag = USE_SPRINT_VALUE;
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
pdu = snmp_pdu_create(SNMP_MSG_GET);
varlist = (AV*) SvRV(varlist_ref);
vars->name,
vars->name_length);
str_buf[sizeof(str_buf)-1] = '\0';
if (__is_leaf(tp)) {
type = tp->type;
} else {
local_getlabel_flag |= NON_LEAF_NAME;
type = __translate_asn_type(vars->type);
}
__get_label_iid(str_buf,&label,&iid,local_getlabel_flag);
if (label) {
av_store(varbind, VARBIND_TAG_F,
newSVpv(label, strlen(label)));
} else {
av_store(varbind, VARBIND_TAG_F,
newSVpv("", 0));
}
if (iid) {
av_store(varbind, VARBIND_IID_F,
newSVpv(iid, strlen(iid)));
} else {
av_store(varbind, VARBIND_IID_F,
newSVpv("", 0));
}
__get_type_str(type, tmp_type_str);
tmp_sv = newSVpv(tmp_type_str, strlen(tmp_type_str));
av_store(varbind, VARBIND_TYPE_F, tmp_sv);
len=__snprint_value(str_buf,sizeof(str_buf),
vars,tp,type,sprintval_flag);
tmp_sv = newSVpv(str_buf, len);
av_store(varbind, VARBIND_VAL_F, tmp_sv);
if (sv_timestamp)
av_store(varbind, VARBIND_TYPE_F, sv_timestamp);
XPUSHs(sv_mortalcopy(tmp_sv));
} else {
/* Return undef for this variable. */
XPUSHs(&sv_undef);
}
}
/* Reset the library's behavior for numeric/symbolic OID's. */
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
old_format);
if (response) snmp_free_pdu(response);
} else {
XPUSHs(&sv_undef); /* no mem or bad args */
}
done:
Safefree(oid_arr);
}
void
snmp_getnext(sess_ref, varlist_ref, perl_callback)
SV * sess_ref
SV * varlist_ref
SV * perl_callback
PPCODE:
{
AV *varlist;
SV **varbind_ref;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
netsnmp_session *ss;
netsnmp_pdu *pdu, *response;
netsnmp_variable_list *vars;
struct tree *tp;
int len;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
SV *tmp_sv;
int type;
char tmp_type_str[MAX_TYPE_NAME_LEN];
snmp_xs_cb_data *xs_cb_data;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int status;
char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
size_t str_buf_len = sizeof(str_buf);
char tmp_buf_prefix[STR_BUF_SIZE];
char str_buf_prefix[STR_BUF_SIZE];
size_t out_len = 0;
int buf_over = 0;
char *label;
char *iid;
int getlabel_flag = NO_FLAGS;
int sprintval_flag = USE_BASIC;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int old_format;
SV *sv_timestamp = NULL;
int best_guess;
char *tmp_prefix_ptr;
char *st;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
getlabel_flag |= USE_LONG_NAMES;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
getlabel_flag |= USE_NUMERIC_OIDS;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
sprintval_flag = USE_ENUMS;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
sprintval_flag = USE_SPRINT_VALUE;
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
}
if (__is_leaf(tp)) {
type = tp->type;
} else {
local_getlabel_flag |= NON_LEAF_NAME;
type = __translate_asn_type(vars->type);
}
__get_label_iid(str_buf,&label,&iid,local_getlabel_flag);
if (label) {
av_store(varbind, VARBIND_TAG_F,
newSVpv(label, strlen(label)));
} else {
av_store(varbind, VARBIND_TAG_F,
newSVpv("", 0));
}
if (iid) {
av_store(varbind, VARBIND_IID_F,
newSVpv(iid, strlen(iid)));
} else {
av_store(varbind, VARBIND_IID_F,
newSVpv("", 0));
}
__get_type_str(type, tmp_type_str);
tmp_sv = newSVpv(tmp_type_str, strlen(tmp_type_str));
av_store(varbind, VARBIND_TYPE_F, tmp_sv);
len=__snprint_value(str_buf,sizeof(str_buf),
vars,tp,type,sprintval_flag);
tmp_sv = newSVpv(str_buf, len);
av_store(varbind, VARBIND_VAL_F, tmp_sv);
if (sv_timestamp)
av_store(varbind, VARBIND_TYPE_F, sv_timestamp);
XPUSHs(sv_mortalcopy(tmp_sv));
} else {
/* Return undef for this variable. */
XPUSHs(&sv_undef);
}
}
/* Reset the library's behavior for numeric/symbolic OID's. */
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
old_format);
if (response) snmp_free_pdu(response);
} else {
XPUSHs(&sv_undef); /* no mem or bad args */
}
done:
Safefree(oid_arr);
}
void
snmp_getbulk(sess_ref, nonrepeaters, maxrepetitions, varlist_ref, perl_callback)
SV * sess_ref
int nonrepeaters
int maxrepetitions
SV * varlist_ref
SV * perl_callback
PPCODE:
{
AV *varlist;
SV **varbind_ref;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
netsnmp_session *ss;
netsnmp_pdu *pdu, *response;
netsnmp_variable_list *vars;
struct tree *tp;
int len;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
SV *tmp_sv;
int type;
char tmp_type_str[MAX_TYPE_NAME_LEN];
snmp_xs_cb_data *xs_cb_data;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int status;
char str_buf[STR_BUF_SIZE], *str_bufp = str_buf;
size_t str_buf_len = sizeof(str_buf);
size_t out_len = 0;
int buf_over = 0;
char *label;
char *iid;
int getlabel_flag = NO_FLAGS;
int sprintval_flag = USE_BASIC;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int old_format;
SV *rv;
SV *sv_timestamp = NULL;
int best_guess;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseLongNames", 12, 1)))
getlabel_flag |= USE_LONG_NAMES;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseNumeric", 10, 1)))
getlabel_flag |= USE_NUMERIC_OIDS;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums", 8, 1)))
sprintval_flag = USE_ENUMS;
if (SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseSprintValue", 14, 1)))
sprintval_flag = USE_SPRINT_VALUE;
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
local_getlabel_flag |= NON_LEAF_NAME;
type = __translate_asn_type(vars->type);
}
__get_label_iid(str_buf,&label,&iid,local_getlabel_flag);
if (label) {
av_store(varbind, VARBIND_TAG_F,
newSVpv(label, strlen(label)));
} else {
av_store(varbind, VARBIND_TAG_F,
newSVpv("", 0));
}
if (iid) {
av_store(varbind, VARBIND_IID_F,
newSVpv(iid, strlen(iid)));
} else {
av_store(varbind, VARBIND_IID_F,
newSVpv("", 0));
}
__get_type_str(type, tmp_type_str);
av_store(varbind, VARBIND_TYPE_F, newSVpv(tmp_type_str,
strlen(tmp_type_str)));
len=__snprint_value(str_buf,sizeof(str_buf),
vars,tp,type,sprintval_flag);
tmp_sv = newSVpv(str_buf, len);
av_store(varbind, VARBIND_VAL_F, tmp_sv);
if (sv_timestamp)
av_store(varbind, VARBIND_TYPE_F, SvREFCNT_inc(sv_timestamp));
rv = newRV_noinc((SV *)varbind);
sv_bless(rv, gv_stashpv("SNMP::Varbind",0));
av_push(varlist, rv);
XPUSHs(sv_mortalcopy(tmp_sv));
}
} else {
XPUSHs(&sv_undef);
}
/* Reset the library's behavior for numeric/symbolic OID's. */
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_OID_OUTPUT_FORMAT,
old_format);
if (response) snmp_free_pdu(response);
} else {
XPUSHs(&sv_undef); /* no mem or bad args */
}
done:
Safefree(oid_arr);
}
void
snmp_bulkwalk(sess_ref, nonrepeaters, maxrepetitions, varlist_ref,perl_callback)
SV * sess_ref
int nonrepeaters
int maxrepetitions
SV * varlist_ref
SV * perl_callback
PPCODE:
{
AV *varlist;
SV **varbind_ref;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
netsnmp_session *ss;
netsnmp_pdu *pdu = NULL;
oid oid_arr[MAX_OID_LEN];
size_t oid_arr_len;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
char str_buf[STR_BUF_SIZE];
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
walk_context *context = NULL; /* Context for this bulkwalk */
bulktbl *bt_entry; /* Current bulktbl/OID entry */
int i; /* General purpose iterator */
int npushed; /* Number of return arrays */
int okay; /* Did bulkwalk complete okay */
int best_guess;
if (!SvROK(sess_ref) || !SvROK(varlist_ref)) {
if (verbose)
warn("bulkwalk: Bad session or varlist reference!\n");
XSRETURN_UNDEF;
}
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
/* Create and initialize a new session context for this bulkwalk.
** This will be used to carry state between callbacks.
*/
Newz(0x57616b6c /* "Walk" */, context, 1, walk_context);
if (context == NULL) {
sprintf(str_buf, "malloc(context) failed (%s)", strerror(errno));
sv_setpv(*err_str_svp, str_buf);
sv_setiv(*err_num_svp, SNMPERR_MALLOC);
goto err;
}
/* Store the Perl callback and session reference in the context. */
context->perl_cb = newSVsv(perl_callback);
context->sess_ref = newSVsv(sess_ref);
DBPRT(3,(DBOUT "bulkwalk: sess_ref = 0x%p, sess_ptr_sv = 0x%p, ss = 0x%p\n",
sess_ref, sess_ptr_sv, ss));
context->getlabel_f = NO_FLAGS; /* long/numeric name flags */
context->sprintval_f = USE_BASIC; /* Don't do fancy printing */
DBPRT(1,(DBOUT "bulkwalk_send_pdu() failed!\n"));
break;
}
/* Handle the variables in this response packet. Break out
** of the loop if an error occurs or no variables are found
** in the response.
*/
if ((i = _bulkwalk_recv_pdu(context, pdu)) <= 0) {
DBPRT(2,(DBOUT "bulkwalk_recv_pdu() returned %d (error/empty)\n", i));
goto err;
}
/* Free the returned pdu. Don't bother to do this for the async
** case, since the SNMP callback mechanism itself does the free
** for us.
*/
snmp_free_pdu(pdu);
/* And loop. The call to bulkwalk_done() sets the ignore flags
** for any completed request subtrees. Next time around, they
** won't be added to the request sent to the agent.
*/
continue;
}
DBPRT(1, (DBOUT "Bulkwalk done... calling bulkwalk_finish(%s)...\n",
okay ? "okay" : "error"));
npushed = _bulkwalk_finish(context, okay);
DBPRT(2,(DBOUT "Returning %d values on the stack.\n", npushed));
XSRETURN(npushed);
/* Handle error cases and clean up after ourselves. */
err:
if (context->req_oids && context->nreq_oids) {
bt_entry = context->req_oids;
for (i = 0; i < context->nreq_oids; i++, bt_entry++)
av_clear(bt_entry->vars);
}
if (context->req_oids)
Safefree(context->req_oids);
if (context)
Safefree(context);
if (pdu)
snmp_free_pdu(pdu);
XSRETURN_UNDEF;
}
void
snmp_trapV1(sess_ref,enterprise,agent,generic,specific,uptime,varlist_ref)
SV * sess_ref
char * enterprise
char * agent
int generic
int specific
long uptime
SV * varlist_ref
PPCODE:
{
AV *varlist;
SV **varbind_ref;
SV **varbind_val_f;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
SnmpSession *ss;
netsnmp_pdu *pdu = NULL;
struct tree *tp;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int type;
int res;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
struct enum_list *ep;
int best_guess;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
pdu = snmp_pdu_create(SNMP_MSG_TRAP);
if (SvROK(varlist_ref)) {
varlist = (AV*) SvRV(varlist_ref);
varlist_len = av_len(varlist);
for(varlist_ind = 0; varlist_ind <= varlist_len; varlist_ind++) {
varbind_ref = av_fetch(varlist, varlist_ind, 0);
if (SvROK(*varbind_ref)) {
varbind = (AV*) SvRV(*varbind_ref);
tp=__tag2oid(__av_elem_pv(varbind, VARBIND_TAG_F, NULL),
__av_elem_pv(varbind, VARBIND_IID_F, NULL),
oid_arr, &oid_arr_len, &type, best_guess);
if (oid_arr_len == 0) {
if (verbose)
warn("error:trap: unable to determine oid for object");
goto err;
}
if (type == TYPE_UNKNOWN) {
type = __translate_appl_type(
__av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
(varbind_val_f && SvOK(*varbind_val_f) ?
SvPV(*varbind_val_f,na):NULL),
(varbind_val_f && SvPOK(*varbind_val_f) ?
SvCUR(*varbind_val_f):0),
type);
if(res == FAILURE) {
if(verbose) warn("error:trap: adding varbind");
goto err;
}
} /* if var_ref is ok */
} /* for all the vars */
}
pdu->enterprise = (oid *)malloc( MAX_OID_LEN * sizeof(oid));
tp = __tag2oid(enterprise,NULL, pdu->enterprise,
&pdu->enterprise_length, NULL, best_guess);
if (pdu->enterprise_length == 0) {
if (verbose) warn("error:trap:invalid enterprise id: %s", enterprise);
goto err;
}
/* If agent is given then set the v1-TRAP specific
agent-address field to that. Otherwise set it to
our address. */
if (agent && strlen(agent)) {
if (__parse_address(agent) == -1 && verbose) {
warn("error:trap:invalid agent address: %s", agent);
goto err;
} else {
*((in_addr_t *)pdu->agent_addr) = __parse_address(agent);
}
} else {
*((in_addr_t *)pdu->agent_addr) = get_myaddr();
}
pdu->trap_type = generic;
pdu->specific_type = specific;
pdu->time = uptime;
if (snmp_send(ss, pdu) == 0) {
snmp_free_pdu(pdu);
}
XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
} else {
err:
XPUSHs(&sv_undef); /* no mem or bad args */
if (pdu) snmp_free_pdu(pdu);
}
Safefree(oid_arr);
}
void
snmp_trapV2(sess_ref,uptime,trap_oid,varlist_ref)
SV * sess_ref
char * uptime
char * trap_oid
SV * varlist_ref
PPCODE:
{
AV *varlist;
SV **varbind_ref;
SV **varbind_val_f;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
SnmpSession *ss;
netsnmp_pdu *pdu = NULL;
struct tree *tp;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int type;
int res;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
struct enum_list *ep;
int best_guess;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
varlist = (AV*) SvRV(varlist_ref);
varlist_len = av_len(varlist);
/************************************************/
res = __add_var_val_str(pdu, sysUpTime, SYS_UPTIME_OID_LEN,
uptime, strlen(uptime), TYPE_TIMETICKS);
if(res == FAILURE) {
if(verbose) warn("error:trap v2: adding sysUpTime varbind");
goto err;
}
res = __add_var_val_str(pdu, snmpTrapOID, SNMP_TRAP_OID_LEN,
trap_oid ,strlen(trap_oid) ,TYPE_OBJID);
if(res == FAILURE) {
if(verbose) warn("error:trap v2: adding snmpTrapOID varbind");
goto err;
}
/******************************************************/
if (type == TYPE_UNKNOWN) {
type = __translate_appl_type(
__av_elem_pv(varbind, VARBIND_TYPE_F, NULL));
if (type == TYPE_UNKNOWN) {
if (verbose)
warn("error:trap v2: no type found for object");
goto err;
}
}
varbind_val_f = av_fetch(varbind, VARBIND_VAL_F, 0);
if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
for(ep = tp->enums; ep; ep = ep->next) {
if (varbind_val_f && SvOK(*varbind_val_f) &&
!strcmp(ep->label, SvPV(*varbind_val_f,na))) {
sv_setiv(*varbind_val_f, ep->value);
break;
}
}
}
res = __add_var_val_str(pdu, oid_arr, oid_arr_len,
(varbind_val_f && SvOK(*varbind_val_f) ?
SvPV(*varbind_val_f,na):NULL),
(varbind_val_f && SvPOK(*varbind_val_f) ?
SvCUR(*varbind_val_f):0),
type);
if(res == FAILURE) {
if(verbose) warn("error:trap v2: adding varbind");
goto err;
}
} /* if var_ref is ok */
} /* for all the vars */
if (snmp_send(ss, pdu) == 0) {
snmp_free_pdu(pdu);
}
XPUSHs(sv_2mortal(newSVpv(ZERO_BUT_TRUE,0)));
} else {
err:
XPUSHs(&sv_undef); /* no mem or bad args */
if (pdu) snmp_free_pdu(pdu);
}
Safefree(oid_arr);
}
void
snmp_inform(sess_ref,uptime,trap_oid,varlist_ref,perl_callback)
SV * sess_ref
char * uptime
char * trap_oid
SV * varlist_ref
SV * perl_callback
PPCODE:
{
AV *varlist;
SV **varbind_ref;
SV **varbind_val_f;
AV *varbind;
I32 varlist_len;
I32 varlist_ind;
SnmpSession *ss;
netsnmp_pdu *pdu = NULL;
netsnmp_pdu *response;
struct tree *tp;
oid *oid_arr;
size_t oid_arr_len = MAX_OID_LEN;
snmp_xs_cb_data *xs_cb_data;
SV **sess_ptr_sv;
SV **err_str_svp;
SV **err_num_svp;
SV **err_ind_svp;
int status = 0;
int type;
int res;
int verbose = SvIV(perl_get_sv("SNMP::verbose", 0x01 | 0x04));
int use_enums = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"UseEnums",8,1));
struct enum_list *ep;
int best_guess;
New (0, oid_arr, MAX_OID_LEN, oid);
if (oid_arr && SvROK(sess_ref) && SvROK(varlist_ref)) {
sess_ptr_sv = hv_fetch((HV*)SvRV(sess_ref), "SessPtr", 7, 1);
ss = (SnmpSession *)SvIV((SV*)SvRV(*sess_ptr_sv));
err_str_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorStr", 8, 1);
err_num_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorNum", 8, 1);
err_ind_svp = hv_fetch((HV*)SvRV(sess_ref), "ErrorInd", 8, 1);
sv_setpv(*err_str_svp, "");
sv_setiv(*err_num_svp, 0);
sv_setiv(*err_ind_svp, 0);
best_guess = SvIV(*hv_fetch((HV*)SvRV(sess_ref),"BestGuess",9,1));
pdu = snmp_pdu_create(SNMP_MSG_INFORM);
varlist = (AV*) SvRV(varlist_ref);
varlist_len = av_len(varlist);
/************************************************/
res = __add_var_val_str(pdu, sysUpTime, SYS_UPTIME_OID_LEN,
uptime, strlen(uptime), TYPE_TIMETICKS);
if(res == FAILURE) {
if(verbose) warn("error:inform: adding sysUpTime varbind");
goto err;
}
res = __add_var_val_str(pdu, snmpTrapOID, SNMP_TRAP_OID_LEN,
trap_oid ,strlen(trap_oid) ,TYPE_OBJID);
if(res == FAILURE) {
if(verbose) warn("error:inform: adding snmpTrapOID varbind");
goto err;
}
timerclear(tvp);
snmp_select_info(&numfds, &fdset, tvp, &block);
__recalc_timeout(tvp,ctvp,ltvp,itvp,&block);
# printf("pre-select: numfds = %ld, block = %ld\n", numfds, block);
if (block == 1) tvp = NULL; /* block without timeout */
fd_count = select(numfds, &fdset, 0, 0, tvp);
#printf("post-select: fd_count = %ld,block = %ld\n",fd_count,block);
if (fd_count > 0) {
ENTER;
SAVETMPS;
snmp_read(&fdset);
FREETMPS;
LEAVE;
} else switch(fd_count) {
case 0:
SPAGAIN;
ENTER;
SAVETMPS;
snmp_timeout();
if (!timerisset(ctvp)) {
if (SvTRUE(perl_callback)) {
/* sv_2mortal(perl_callback); */
cb = __push_cb_args(perl_callback, NULL);
__call_callback(cb, G_DISCARD);
ctvp->tv_sec = -1;
} else {
FREETMPS;
LEAVE;
goto done;
}
}
FREETMPS;
LEAVE;
break;
case -1:
if (errno == EINTR) {
continue;
} else {
/* snmp_set_detail(strerror(errno)); */
/* snmp_errno = SNMPERR_GENERR; */
}
default:;
}
/* A call to snmp_mainloop_finish() in the callback sets the
** mainloop_finish flag. Exit the loop after the callback returns.
*/
if (mainloop_finish)
goto done;
}
done:
return;
}
void
snmp_get_select_info()
PPCODE:
{
int numfds;
fd_set fdset;
struct timeval time_val, *tvp;
int block;
int i;
numfds = 0;
block = 1;
tvp = &time_val;
FD_ZERO(&fdset);
snmp_select_info(&numfds, &fdset, tvp, &block);
XPUSHs(sv_2mortal(newSViv(block)));
if(block){
XPUSHs(sv_2mortal(newSViv(0)));
XPUSHs(sv_2mortal(newSViv(0)));
} else {
XPUSHs(sv_2mortal(newSViv(tvp->tv_sec)));
XPUSHs(sv_2mortal(newSViv(tvp->tv_usec)));
}
if ( numfds ) {
for(i=0; i<numfds ; i++) {
if(FD_ISSET(i, &fdset)){
XPUSHs(sv_2mortal(newSViv(i)));
}
}
} else {
XPUSHs(&sv_undef); /* no mem or bad args */
}
}
void
snmp_read_on_fd(fd)
int fd
CODE:
{
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
snmp_read(&fdset);
}
void
snmp_check_timeout()
CODE:
{
snmp_timeout();
}
MODULE = SNMP PACKAGE = SNMP::MIB::NODE PREFIX = snmp_mib_node_
SV *
snmp_mib_node_TIEHASH(cl,key,tp=0)
char * cl
char * key
IV tp
CODE:
{
( run in 1.069 second using v1.01-cache-2.11-cpan-5511b514fd6 )